acl.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <asterisk/acl.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>

Include dependency graph for acl.c:

Go to the source code of this file.

Data Structures

struct  ast_ha
struct  my_ifreq

Functions

void ast_free_ha (struct ast_ha *ha)
struct ast_haast_duplicate_ha_list (struct ast_ha *original)
struct ast_haast_append_ha (char *sense, char *stuff, struct ast_ha *path)
int ast_apply_ha (struct ast_ha *ha, struct sockaddr_in *sin)
int ast_get_ip (struct sockaddr_in *sin, char *value)
int ast_lookup_iface (char *iface, struct in_addr *address)
int ast_ouraddrfor (struct in_addr *them, struct in_addr *us)
int ast_find_ourip (struct in_addr *ourip, struct sockaddr_in bindaddr)


Function Documentation

struct ast_ha* ast_append_ha ( char *  sense,
char *  stuff,
struct ast_ha path 
) [read]

Definition at line 110 of file acl.c.

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 }

int ast_apply_ha ( struct ast_ha ha,
struct sockaddr_in *  sin 
)

Definition at line 168 of file acl.c.

00169 {
00170    /* Start optimistic */
00171    int res = AST_SENSE_ALLOW;
00172    while(ha) {
00173       char iabuf[INET_ADDRSTRLEN];
00174       char iabuf2[INET_ADDRSTRLEN];
00175       /* DEBUG */
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       /* For each rule, if this address and the netmask = the net address
00181          apply the current rule */
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 }

struct ast_ha* ast_duplicate_ha_list ( struct ast_ha original  )  [read]

Definition at line 90 of file acl.c.

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);  /* Create copy of this object */
00098       if (prev)
00099          prev->next = link;      /* Link previous to this object */
00100 
00101       if (!ret) 
00102          ret = link;    /* Save starting point */
00103 
00104       start = start->next;    /* Go to next object */
00105       prev = link;         /* Save pointer to this object */
00106    }
00107    return (ret);           /* Return start of list */
00108 }

int ast_find_ourip ( struct in_addr *  ourip,
struct sockaddr_in  bindaddr 
)

Definition at line 382 of file acl.c.

00383 {
00384    char ourhost[MAXHOSTNAMELEN]="";
00385    struct ast_hostent ahp;
00386    struct hostent *hp;
00387    struct in_addr saddr;
00388 
00389    /* just use the bind address if it is nonzero */
00390    if (ntohl(bindaddr.sin_addr.s_addr)) {
00391       memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
00392       return 0;
00393    }
00394    /* try to use our hostname */
00395    if (gethostname(ourhost, sizeof(ourhost)-1)) {
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    /* A.ROOT-SERVERS.NET. */
00405    if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
00406       return 0;
00407    return -1;
00408 }

void ast_free_ha ( struct ast_ha ha  ) 

Definition at line 58 of file acl.c.

00059 {
00060    struct ast_ha *hal;
00061    while(ha) {
00062       hal = ha;
00063       ha = ha->next;
00064       free(hal);
00065    }
00066 }

int ast_get_ip ( struct sockaddr_in *  sin,
char *  value 
)

Definition at line 189 of file acl.c.

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 }

int ast_lookup_iface ( char *  iface,
struct in_addr *  address 
)

Definition at line 204 of file acl.c.

00204                                                            {
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 }

int ast_ouraddrfor ( struct in_addr *  them,
struct in_addr *  us 
)

Definition at line 225 of file acl.c.

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; /* Protected by "routeseq_lock" mutex */
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    /* First line contains headers */
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             /* Exit loop */
00343             break;
00344          } else if (fieldnum >= 9) {
00345             /* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
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          /* Looks simple, but here is the magic */
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       /* We've already warned in subroutine */
00376       return -1;
00377    }
00378    return 0;
00379 #endif
00380 }


Generated on Wed Oct 28 17:00:48 2009 for Asterisk by  doxygen 1.5.6