Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

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>

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)
ast_haast_duplicate_ha_list (struct ast_ha *original)
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)


Function Documentation

struct ast_ha* ast_append_ha char *    sense,
char *    stuff,
struct ast_ha   path
 

Definition at line 110 of file acl.c.

References ast_log(), AST_SENSE_ALLOW, AST_SENSE_DENY, free, LOG_DEBUG, LOG_WARNING, malloc, ast_ha::netaddr, ast_ha::netmask, ast_ha::next, and ast_ha::sense.

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.

References ast_inet_ntoa(), ast_log(), AST_SENSE_ALLOW, LOG_DEBUG, ast_ha::netaddr, ast_ha::netmask, ast_ha::next, and ast_ha::sense.

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
 

Definition at line 90 of file acl.c.

References ast_ha::next.

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 }

void ast_free_ha struct ast_ha   ha
 

Definition at line 58 of file acl.c.

References free, and ast_ha::next.

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.

References ast_gethostbyname(), ast_log(), and LOG_WARNING.

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.

References ast_log(), my_ifreq::ifrn_name, my_ifreq::ifru_addr, and LOG_WARNING.

Referenced by ast_ouraddrfor().

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.

References ast_inet_ntoa(), ast_log(), ast_lookup_iface(), ast_mutex_lock, ast_mutex_unlock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and s.

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


Generated on Thu Oct 28 11:32:58 2004 for Asterisk by doxygen1.2.15