Version 0.2.0 from FTP
[asterisk/asterisk.git] / acl.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Various sorts of access control
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <pthread.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <signal.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <asterisk/acl.h>
23 #include <asterisk/logger.h>
24 #include <arpa/inet.h>
25 #include <sys/socket.h>
26 #include <netdb.h>
27
28 #define AST_SENSE_DENY                  0
29 #define AST_SENSE_ALLOW                 1
30
31 struct ast_ha {
32         /* Host access rule */
33         struct in_addr netaddr;
34         struct in_addr netmask;
35         int sense;
36         struct ast_ha *next;
37 };
38
39 void ast_free_ha(struct ast_ha *ha)
40 {
41         struct ast_ha *hal;
42         while(ha) {
43                 hal = ha;
44                 ha = ha->next;
45                 free(hal);
46         }
47 }
48
49 struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
50 {
51         struct ast_ha *ha = malloc(sizeof(struct ast_ha));
52         char *nm;
53         struct ast_ha *prev = NULL;
54         struct ast_ha *ret;
55         ret = path;
56         while(path) {
57                 prev = path;
58                 path = path->next;
59         }
60         if (ha) {
61                 strtok(stuff, "/");
62                 nm = strtok(NULL, "/");
63                 if (!nm)
64                         nm = "255.255.255.255";
65                 if (!inet_aton(stuff, &ha->netaddr)) {
66                         ast_log(LOG_WARNING, "%s not a valid IP\n", stuff);
67                         free(ha);
68                         return NULL;
69                 }
70                 if (!inet_aton(nm, &ha->netmask)) {
71                         ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
72                         free(ha);
73                         return NULL;
74                 }
75                 ha->netaddr.s_addr &= ha->netmask.s_addr;
76                 if (!strncasecmp(sense, "p", 1)) {
77                         ha->sense = AST_SENSE_ALLOW;
78                 } else {
79                         ha->sense = AST_SENSE_DENY;
80                 }
81                 ha->next = NULL;
82                 if (prev)
83                         prev->next = ha;
84                 else
85                         ret = ha;
86         }
87         return NULL;
88 }
89
90 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
91 {
92         /* Start optimistic */
93         int res = AST_SENSE_ALLOW;
94         while(ha) {
95                 /* For each rule, if this address and the netmask = the net address
96                    apply the current rule */
97                 if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
98                         res = ha->sense;
99                 ha = ha->next;
100         }
101         return res;
102 }
103
104 int ast_get_ip(struct sockaddr_in *sin, char *value)
105 {
106         struct hostent *hp;
107         hp = gethostbyname(value);
108         if (hp) {
109                 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
110         } else {
111                 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
112                 return -1;
113         }
114         return 0;
115 }
116