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_flags = RTF_UP | RTF_HOST;
00246 m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
00247
ast_mutex_lock(&routeseq_lock);
00248 seq = ++routeseq;
00249
ast_mutex_unlock(&routeseq_lock);
00250 m_rtmsg.m_rtm.rtm_seq = seq;
00251 m_rtmsg.m_rtm.rtm_addrs = RTA_IFA | RTA_DST;
00252 m_rtmsg.m_rtm.rtm_msglen =
sizeof(
struct rt_msghdr) + sizeof(struct sockaddr_in);
00253 sin = (
struct sockaddr_in *)m_rtmsg.m_space;
00254 sin->sin_family = AF_INET;
00255 sin->sin_len =
sizeof(
struct sockaddr_in);
00256 sin->sin_addr = *them;
00257
00258
if ((
s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
00259
ast_log(
LOG_ERROR,
"Error opening routing socket\n");
00260
return -1;
00261 }
00262 flags = fcntl(
s, F_GETFL);
00263 fcntl(
s, F_SETFL, flags | O_NONBLOCK);
00264
if (write(
s, (
char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
00265
ast_log(
LOG_ERROR,
"Error writing to routing socket: %s\n", strerror(errno));
00266 close(
s);
00267
return -1;
00268 }
00269
do {
00270 l = read(
s, (
char *)&m_rtmsg,
sizeof(m_rtmsg));
00271 }
while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
00272
if (l < 0) {
00273
if (errno != EAGAIN)
00274
ast_log(
LOG_ERROR,
"Error reading from routing socket\n");
00275 close(
s);
00276
return -1;
00277 }
00278 close(
s);
00279
00280
if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
00281
ast_log(
LOG_ERROR,
"Unsupported route socket protocol version\n");
00282
return -1;
00283 }
00284
00285
if (m_rtmsg.m_rtm.rtm_msglen != l)
00286
ast_log(
LOG_WARNING,
"Message length mismatch, in packet %d, returned %d\n",
00287 m_rtmsg.m_rtm.rtm_msglen, l);
00288
00289
if (m_rtmsg.m_rtm.rtm_errno) {
00290
ast_log(
LOG_ERROR,
"RTM_GET got %s (%d)\n",
00291 strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
00292
return -1;
00293 }
00294
00295 cp = (
char *)m_rtmsg.m_space;
00296
if (m_rtmsg.m_rtm.rtm_addrs)
00297
for (i = 1; i; i <<= 1)
00298
if (m_rtmsg.m_rtm.rtm_addrs & i) {
00299 sa = (
struct sockaddr *)cp;
00300
if (i == RTA_IFA && sa->sa_family == AF_INET) {
00301 sin = (
struct sockaddr_in *)sa;
00302 *us = sin->sin_addr;
00303
ast_log(
LOG_DEBUG,
"Found route to %s, output from our address %s.\n", p,
ast_inet_ntoa(iabuf,
sizeof(iabuf), *us));
00304
return 0;
00305 }
00306 cp += sa->sa_len > 0 ?
00307 (1 + ((sa->sa_len - 1) | (
sizeof(
long) - 1))) :
00308
sizeof(
long);
00309 }
00310
00311
ast_log(
LOG_DEBUG,
"No route found for address %s!\n", p);
00312
return -1;
00313
#else
00314
FILE *PROC;
00315
unsigned int remote_ip;
00316
int res = 1;
00317
char line[256];
00318 remote_ip = them->s_addr;
00319
00320 PROC = fopen(
"/proc/net/route",
"r");
00321
if (!PROC) {
00322 bzero(us,
sizeof(
struct in_addr));
00323
return -1;
00324 }
00325
00326 fgets(line,
sizeof(line),PROC);
00327
00328
while (!feof(PROC)) {
00329
char iface[256];
00330
unsigned int dest, gateway, mask;
00331
int i,fieldnum;
00332
char *fields[40];
00333
00334 fgets(line,
sizeof(line),PROC);
00335
00336 fieldnum = 0;
00337
for (i=0;i<
sizeof(line);i++) {
00338
char *offset;
00339
00340 fields[fieldnum++] = line + i;
00341 offset = strchr(line + i,
'\t');
00342
if (offset == NULL) {
00343
00344
break;
00345 }
else if (fieldnum >= 9) {
00346
00347
break;
00348 }
else {
00349 *offset =
'\0';
00350 i = offset - line;
00351 }
00352 }
00353
if (fieldnum >= 8) {
00354
00355 sscanf(fields[0],
"%s",iface);
00356 sscanf(fields[1],
"%x",&dest);
00357 sscanf(fields[2],
"%x",&gateway);
00358 sscanf(fields[7],
"%x",&mask);
00359
#if 0
00360
{
char iabuf[INET_ADDRSTRLEN];
00361 printf(
"Addr: %s %08x Dest: %08x Mask: %08x\n",
ast_inet_ntoa(iabuf,
sizeof(iabuf), *them), remote_ip, dest, mask); }
00362
#endif
00363
00364
if (((remote_ip & mask) ^ dest) == 0) {
00365 res =
ast_lookup_iface(iface,us);
00366
break;
00367 }
00368 }
00369 }
00370 fclose(PROC);
00371
if (res == 1) {
00372
ast_log(
LOG_WARNING,
"Yikes! No default route?!!\n");
00373 bzero(us,
sizeof(
struct in_addr));
00374
return -2;
00375 }
else if (res) {
00376
00377
return -1;
00378 }
00379
return 0;
00380
#endif
00381
}