2 * Asterisk -- A telephony toolkit for Linux.
4 * Various sorts of access control
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
22 #include <asterisk/acl.h>
23 #include <asterisk/logger.h>
24 #include <arpa/inet.h>
25 #include <sys/socket.h>
28 #include <netinet/in_systm.h>
29 #include <netinet/ip.h>
30 #include <sys/ioctl.h>
32 #define AST_SENSE_DENY 0
33 #define AST_SENSE_ALLOW 1
36 /* Host access rule */
37 struct in_addr netaddr;
38 struct in_addr netmask;
43 /* Default IP - if not otherwise set, don't breathe garbage */
44 static struct in_addr __ourip = { (in_addr_t)0x00000000 };
47 char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
48 struct sockaddr_in ifru_addr;
51 void ast_free_ha(struct ast_ha *ha)
61 struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
63 struct ast_ha *ha = malloc(sizeof(struct ast_ha));
65 struct ast_ha *prev = NULL;
75 strsep(&stringp, "/");
76 nm = strsep(&stringp, "/");
78 nm = "255.255.255.255";
79 if (!inet_aton(stuff, &ha->netaddr)) {
80 ast_log(LOG_WARNING, "%s not a valid IP\n", stuff);
84 if (!inet_aton(nm, &ha->netmask)) {
85 ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
89 ha->netaddr.s_addr &= ha->netmask.s_addr;
90 if (!strncasecmp(sense, "p", 1)) {
91 ha->sense = AST_SENSE_ALLOW;
93 ha->sense = AST_SENSE_DENY;
104 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
106 /* Start optimistic */
107 int res = AST_SENSE_ALLOW;
109 /* For each rule, if this address and the netmask = the net address
110 apply the current rule */
111 if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
118 int ast_get_ip(struct sockaddr_in *sin, char *value)
121 hp = gethostbyname(value);
123 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
125 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
131 int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
133 return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
134 || (sin1->sin_port != sin2->sin_port));
137 /* iface is the interface (e.g. eth0); address is the return value */
138 int ast_lookup_iface(char *iface, struct in_addr *address) {
140 struct my_ifreq ifreq;
142 memset(&ifreq, 0, sizeof(ifreq));
143 strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
145 mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
146 res = ioctl(mysock,SIOCGIFADDR,&ifreq);
150 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
151 strncpy((char *)address,(char *)&__ourip,sizeof(__ourip));
154 strncpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
159 int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
162 unsigned int remote_ip;
165 remote_ip = them->s_addr;
167 PROC = fopen("/proc/net/route","r");
169 bzero(us,sizeof(struct in_addr));
172 /* First line contains headers */
173 fgets(line,sizeof(line),PROC);
175 while (!feof(PROC)) {
177 unsigned int dest, gateway, mask;
181 fgets(line,sizeof(line),PROC);
184 for (i=0;i<sizeof(line);i++) {
187 fields[fieldnum++] = line + i;
188 offset = strchr(line + i,'\t');
189 if (offset == NULL) {
192 } else if (fieldnum >= 9) {
193 /* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
201 sscanf(fields[0],"%s",iface);
202 sscanf(fields[1],"%x",&dest);
203 sscanf(fields[2],"%x",&gateway);
204 sscanf(fields[7],"%x",&mask);
206 printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
208 /* Looks simple, but here is the magic */
209 if (((remote_ip & mask) ^ dest) == 0) {
210 res = ast_lookup_iface(iface,us);
216 ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
217 bzero(us,sizeof(struct in_addr));
220 /* We've already warned in subroutine */