00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <pthread.h>
00017 #include <string.h>
00018 #include <sys/time.h>
00019 #include <signal.h>
00020 #include <errno.h>
00021 #include <unistd.h>
00022 #include <asterisk/acl.h>
00023 #include <asterisk/logger.h>
00024 #include <asterisk/channel.h>
00025 #include <arpa/inet.h>
00026 #include <sys/socket.h>
00027 #include <netdb.h>
00028 #include <net/if.h>
00029 #include <netinet/in_systm.h>
00030 #include <netinet/ip.h>
00031 #include <sys/ioctl.h>
00032 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
00033 #include <fcntl.h>
00034 #include <net/route.h>
00035
00036 static ast_mutex_t routeseq_lock = AST_MUTEX_INITIALIZER;
00037 #endif
00038
00039 #define AST_SENSE_DENY 0
00040 #define AST_SENSE_ALLOW 1
00041
00042 struct ast_ha {
00043
00044 struct in_addr netaddr;
00045 struct in_addr netmask;
00046 int sense;
00047 struct ast_ha *next;
00048 };
00049
00050
00051 static struct in_addr __ourip = { 0x00000000 };
00052
00053 struct my_ifreq {
00054 char ifrn_name[IFNAMSIZ];
00055 struct sockaddr_in ifru_addr;
00056 };
00057
00058 void ast_free_ha(struct ast_ha *ha)
00059 {
00060 struct ast_ha *hal;
00061 while(ha) {
00062 hal = ha;
00063 ha = ha->next;
00064 free(hal);
00065 }
00066 }
00067
00068 struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
00069 {
00070 struct ast_ha *ha = malloc(sizeof(struct ast_ha));
00071 char *nm;
00072 char tmp[256] = "";
00073 struct ast_ha *prev = NULL;
00074 struct ast_ha *ret;
00075 int x,z;
00076 unsigned int y;
00077 ret = path;
00078 while(path) {
00079 prev = path;
00080 path = path->next;
00081 }
00082 if (ha) {
00083 strncpy(tmp, stuff, sizeof(tmp) - 1);
00084 nm = strchr(tmp, '/');
00085 if (!nm)
00086 nm = "255.255.255.255";
00087 else {
00088 *nm = '\0';
00089 nm++;
00090 }
00091 if (!strchr(nm, '.')) {
00092 if ((sscanf(nm, "%i", &x) == 1) && (x >= 0) && (x <= 32)) {
00093 y = 0;
00094 for (z=0;z<x;z++) {
00095 y >>= 1;
00096 y |= 0x80000000;
00097 }
00098 ha->netmask.s_addr = htonl(y);
00099 }
00100 } else if (!inet_aton(nm, &ha->netmask)) {
00101 ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
00102 free(ha);
00103 return path;
00104 }
00105 if (!inet_aton(tmp, &ha->netaddr)) {
00106 ast_log(LOG_WARNING, "%s not a valid IP\n", tmp);
00107 free(ha);
00108 return path;
00109 }
00110 ha->netaddr.s_addr &= ha->netmask.s_addr;
00111 if (!strncasecmp(sense, "p", 1)) {
00112 ha->sense = AST_SENSE_ALLOW;
00113 } else {
00114 ha->sense = AST_SENSE_DENY;
00115 }
00116 ha->next = NULL;
00117 if (prev)
00118 prev->next = ha;
00119 else
00120 ret = ha;
00121 }
00122 return ret;
00123 }
00124
00125 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
00126 {
00127
00128 int res = AST_SENSE_ALLOW;
00129 while(ha) {
00130
00131
00132 if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
00133 res = ha->sense;
00134 ha = ha->next;
00135 }
00136 return res;
00137 }
00138
00139 int ast_get_ip(struct sockaddr_in *sin, char *value)
00140 {
00141 struct hostent *hp;
00142 hp = gethostbyname(value);
00143 if (hp) {
00144 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
00145 } else {
00146 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
00147 return -1;
00148 }
00149 return 0;
00150 }
00151
00152 int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
00153 {
00154 return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
00155 || (sin1->sin_port != sin2->sin_port));
00156 }
00157
00158
00159 int ast_lookup_iface(char *iface, struct in_addr *address) {
00160 int mysock, res = 0;
00161 struct my_ifreq ifreq;
00162
00163 memset(&ifreq, 0, sizeof(ifreq));
00164 strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
00165
00166 mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
00167 res = ioctl(mysock,SIOCGIFADDR,&ifreq);
00168
00169 close(mysock);
00170 if (res < 0) {
00171 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
00172 memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
00173 return -1;
00174 } else {
00175 memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
00176 return 0;
00177 }
00178 }
00179
00180 int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
00181 {
00182 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
00183 struct sockaddr_in *sin;
00184 struct sockaddr *sa;
00185 struct {
00186 struct rt_msghdr m_rtm;
00187 char m_space[512];
00188 } m_rtmsg;
00189 char *cp, *p = ast_strdupa(inet_ntoa(*them));
00190 int i, l, s, seq, flags;
00191 pid_t pid = getpid();
00192 static int routeseq;
00193
00194 memset(us, 0, sizeof(struct in_addr));
00195
00196 memset(&m_rtmsg, 0, sizeof(m_rtmsg));
00197 m_rtmsg.m_rtm.rtm_type = RTM_GET;
00198 m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_HOST;
00199 m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
00200 ast_mutex_lock(&routeseq_lock);
00201 seq = ++routeseq;
00202 ast_mutex_unlock(&routeseq_lock);
00203 m_rtmsg.m_rtm.rtm_seq = seq;
00204 m_rtmsg.m_rtm.rtm_addrs = RTA_IFA | RTA_DST;
00205 m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
00206 sin = (struct sockaddr_in *)m_rtmsg.m_space;
00207 sin->sin_family = AF_INET;
00208 sin->sin_len = sizeof(struct sockaddr_in);
00209 sin->sin_addr = *them;
00210
00211 if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
00212 ast_log(LOG_ERROR, "Error opening routing socket\n");
00213 return -1;
00214 }
00215 flags = fcntl(s, F_GETFL);
00216 fcntl(s, F_SETFL, flags | O_NONBLOCK);
00217 if (write(s, (char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
00218 ast_log(LOG_ERROR, "Error writing to routing socket: %s\n", strerror(errno));
00219 close(s);
00220 return -1;
00221 }
00222 do {
00223 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
00224 } while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
00225 if (l < 0) {
00226 if (errno != EAGAIN)
00227 ast_log(LOG_ERROR, "Error reading from routing socket\n");
00228 close(s);
00229 return -1;
00230 }
00231 close(s);
00232
00233 if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
00234 ast_log(LOG_ERROR, "Unsupported route socket protocol version\n");
00235 return -1;
00236 }
00237
00238 if (m_rtmsg.m_rtm.rtm_msglen != l)
00239 ast_log(LOG_WARNING, "Message length mismatch, in packet %d, returned %d\n",
00240 m_rtmsg.m_rtm.rtm_msglen, l);
00241
00242 if (m_rtmsg.m_rtm.rtm_errno) {
00243 ast_log(LOG_ERROR, "RTM_GET got %s (%d)\n",
00244 strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
00245 return -1;
00246 }
00247
00248 cp = (char *)m_rtmsg.m_space;
00249 if (m_rtmsg.m_rtm.rtm_addrs)
00250 for (i = 1; i; i <<= 1)
00251 if (m_rtmsg.m_rtm.rtm_addrs & i) {
00252 sa = (struct sockaddr *)cp;
00253 if (i == RTA_IFA && sa->sa_family == AF_INET) {
00254 sin = (struct sockaddr_in *)sa;
00255 *us = sin->sin_addr;
00256 ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, inet_ntoa(*us));
00257 return 0;
00258 }
00259 cp += sa->sa_len > 0 ?
00260 (1 + ((sa->sa_len - 1) | (sizeof(long) - 1))) :
00261 sizeof(long);
00262 }
00263
00264 ast_log(LOG_DEBUG, "No route found for address %s!\n", p);
00265 return -1;
00266 #else
00267 FILE *PROC;
00268 unsigned int remote_ip;
00269 int res = 1;
00270 char line[256];
00271 remote_ip = them->s_addr;
00272
00273 PROC = fopen("/proc/net/route","r");
00274 if (!PROC) {
00275 bzero(us,sizeof(struct in_addr));
00276 return -1;
00277 }
00278
00279 fgets(line,sizeof(line),PROC);
00280
00281 while (!feof(PROC)) {
00282 char iface[256];
00283 unsigned int dest, gateway, mask;
00284 int i,fieldnum;
00285 char *fields[40];
00286
00287 fgets(line,sizeof(line),PROC);
00288
00289 fieldnum = 0;
00290 for (i=0;i<sizeof(line);i++) {
00291 char *offset;
00292
00293 fields[fieldnum++] = line + i;
00294 offset = strchr(line + i,'\t');
00295 if (offset == NULL) {
00296
00297 break;
00298 } else if (fieldnum >= 9) {
00299
00300 break;
00301 } else {
00302 *offset = '\0';
00303 i = offset - line;
00304 }
00305 }
00306 if (fieldnum >= 8) {
00307
00308 sscanf(fields[0],"%s",iface);
00309 sscanf(fields[1],"%x",&dest);
00310 sscanf(fields[2],"%x",&gateway);
00311 sscanf(fields[7],"%x",&mask);
00312 #if 0
00313 printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
00314 #endif
00315
00316 if (((remote_ip & mask) ^ dest) == 0) {
00317 res = ast_lookup_iface(iface,us);
00318 break;
00319 }
00320 }
00321 }
00322 fclose(PROC);
00323 if (res == 1) {
00324 ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
00325 bzero(us,sizeof(struct in_addr));
00326 return -2;
00327 } else if (res) {
00328
00329 return -1;
00330 }
00331 return 0;
00332 #endif
00333 }