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