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