Annotation of embedaddon/pimdd/routesock.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *  Copyright (c) 1998 by the University of Southern California.
                      3:  *  All rights reserved.
                      4:  *
                      5:  *  Permission to use, copy, modify, and distribute this software and
                      6:  *  its documentation in source and binary forms for lawful
                      7:  *  purposes and without fee is hereby granted, provided
                      8:  *  that the above copyright notice appear in all copies and that both
                      9:  *  the copyright notice and this permission notice appear in supporting
                     10:  *  documentation, and that any documentation, advertising materials,
                     11:  *  and other materials related to such distribution and use acknowledge
                     12:  *  that the software was developed by the University of Southern
                     13:  *  California and/or Information Sciences Institute.
                     14:  *  The name of the University of Southern California may not
                     15:  *  be used to endorse or promote products derived from this software
                     16:  *  without specific prior written permission.
                     17:  *
                     18:  *  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
                     19:  *  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
                     20:  *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
                     21:  *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     22:  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
                     23:  *  NON-INFRINGEMENT.
                     24:  *
                     25:  *  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
                     26:  *  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
                     27:  *  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
                     28:  *  THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     29:  *
                     30:  *  Other copyrights might apply to parts of this software and are so
                     31:  *  noted when applicable.
                     32:  */
                     33: /*
                     34:  *  Questions concerning this software should be directed to 
                     35:  *  Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
                     36:  *
                     37:  *  $Id: routesock.c,v 1.2 1998/05/29 20:08:57 kurtw Exp $
                     38:  */
                     39: /*
                     40:  * Part of this program has been derived from mrouted.
                     41:  * The mrouted program is covered by the license in the accompanying file
                     42:  * named "LICENSE.mrouted".
                     43:  *
                     44:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
                     45:  * Leland Stanford Junior University.
                     46:  *
                     47:  */
                     48: 
                     49: #include <sys/param.h>
                     50: #include <sys/file.h>
                     51: #include "defs.h"
                     52: #include <sys/socket.h>
                     53: #include <net/route.h>
                     54: #ifdef HAVE_ROUTING_SOCKETS
                     55: #include <net/if_dl.h>
                     56: #endif
                     57: #include <arpa/inet.h>
                     58: #include <netdb.h>
                     59: #include <stdlib.h>
                     60: 
                     61: #ifdef HAVE_ROUTING_SOCKETS
                     62: union sockunion {
                     63:     struct  sockaddr sa;
                     64:     struct  sockaddr_in sin;
                     65:     struct  sockaddr_dl sdl;
                     66: } so_dst, so_ifp;
                     67: typedef union sockunion *sup;
                     68: int routing_socket;
                     69: int rtm_addrs, pid;
                     70: struct rt_metrics rt_metrics;
                     71: u_long rtm_inits;
                     72: 
                     73: /*
                     74:  * Local functions definitions.
                     75:  */
                     76: static int getmsg __P((register struct rt_msghdr *, int,
                     77:                       struct rpfctl *rpfinfo));
                     78: 
                     79: /*
                     80:  * TODO: check again!
                     81:  */
                     82: #ifdef IRIX
                     83: #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
                     84:                    : sizeof(__uint64_t))
                     85: #else
                     86: #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
                     87:                    : sizeof(long))
                     88: #endif /* IRIX */
                     89: 
                     90: #ifdef HAVE_SA_LEN
                     91: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
                     92: #else
                     93: #define ADVANCE(x, n) (x += ROUNDUP(4))   /* TODO: a hack!! */
                     94: #endif
                     95: 
                     96: /* Open and initialize the routing socket */
                     97: int
                     98: init_routesock()
                     99: {
                    100:     int off;
                    101:     
                    102:     pid = getpid();
                    103:     routing_socket = socket(PF_ROUTE, SOCK_RAW, 0);
                    104:     if (routing_socket < 0) {
                    105:        log(LOG_ERR, 0, "\nRouting socket error");
                    106:        return -1;
                    107:     }
                    108:     if (fcntl(routing_socket, F_SETFL, O_NONBLOCK) == -1){
                    109:        log(LOG_ERR, 0, "\n Routing socket error");
                    110:        return -1;
                    111:     }
                    112:     if (setsockopt(routing_socket, SOL_SOCKET,
                    113:                   SO_USELOOPBACK, (char *)&off,
                    114:                   sizeof(off)) < 0){
                    115:        log(LOG_ERR, 0 , "\n setsockopt(SO_USELOOPBACK,0)");
                    116:        return -1;
                    117:     }  
                    118:     return 0;
                    119: }
                    120: 
                    121: 
                    122: struct {
                    123:     struct  rt_msghdr m_rtm;
                    124:     char    m_space[512];
                    125: } m_rtmsg;
                    126: 
                    127: 
                    128: /* get the rpf neighbor info */
                    129: int
                    130: k_req_incoming(source, rpfp)
                    131:     u_int32 source;
                    132:     struct rpfctl *rpfp;
                    133: {
                    134:     int flags = RTF_STATIC; 
                    135:     register sup su;
                    136:     static int seq;
                    137:     int rlen;
                    138:     register char *cp = m_rtmsg.m_space;
                    139:     register int l;
                    140:     struct rpfctl rpfinfo;
                    141:        
                    142: /* TODO: a hack!!!! */
                    143: #ifdef HAVE_SA_LEN
                    144: #define NEXTADDR(w, u) \
                    145:     if (rtm_addrs & (w)) { \
                    146:        l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
                    147:     }
                    148: #else
                    149: #define NEXTADDR(w, u) \
                    150:     if (rtm_addrs & (w)) { \
                    151:        l = ROUNDUP(4); bcopy((char *)&(u), cp, l); cp += l;\
                    152:     }
                    153: #endif /* HAVE_SA_LEN */
                    154: 
                    155:     /* initialize */
                    156:     rpfp->rpfneighbor.s_addr = INADDR_ANY_N;
                    157:     rpfp->source.s_addr = source;
                    158:     
                    159:     /* check if local address or directly connected before calling the
                    160:      * routing socket
                    161:      */
                    162:     if ((rpfp->iif = find_vif_direct_local(source)) != NO_VIF) {
                    163:        rpfp->rpfneighbor.s_addr = source;
                    164:        return(TRUE);
                    165:     }       
                    166: 
                    167:     /* prepare the routing socket params */
                    168:     rtm_addrs |= RTA_DST;
                    169:     rtm_addrs |= RTA_IFP;
                    170:     su = &so_dst;
                    171:     su->sin.sin_family = AF_INET;
                    172: #ifdef HAVE_SA_LEN
                    173:     su->sin.sin_len = sizeof(struct sockaddr_in);
                    174: #endif
                    175:     su->sin.sin_addr.s_addr = source;
                    176:     if (inet_lnaof(su->sin.sin_addr) == INADDR_ANY) {
                    177:        IF_DEBUG(DEBUG_RPF)
                    178:            log(LOG_DEBUG, 0, "k_req_incoming: Invalid source %s",
                    179:                inet_fmt(source,s1));
                    180:        return(FALSE); 
                    181:     }
                    182:     so_ifp.sa.sa_family = AF_LINK;
                    183: #ifdef HAVE_SA_LEN
                    184:     so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
                    185: #endif
                    186:     flags |= RTF_UP;
                    187:     flags |= RTF_HOST;
                    188:     flags |= RTF_GATEWAY;
                    189:     errno = 0;
                    190:     bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
                    191: 
                    192: #define rtm m_rtmsg.m_rtm
                    193:     rtm.rtm_type       = RTM_GET;
                    194:     rtm.rtm_flags      = flags;
                    195:     rtm.rtm_version    = RTM_VERSION;
                    196:     rtm.rtm_seq        = ++seq;
                    197:     rtm.rtm_addrs      = rtm_addrs;
                    198:     rtm.rtm_rmx        = rt_metrics;
                    199:     rtm.rtm_inits      = rtm_inits;
                    200: 
                    201:     NEXTADDR(RTA_DST, so_dst);
                    202:     NEXTADDR(RTA_IFP, so_ifp);
                    203:     rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
                    204:     
                    205:     if ((rlen = write(routing_socket, (char *)&m_rtmsg, l)) < 0) {
                    206:        IF_DEBUG(DEBUG_RPF | DEBUG_KERN) {
                    207:            if (errno == ESRCH)
                    208:                log(LOG_DEBUG, 0,
                    209:                    "Writing to routing socket: no such route\n");
                    210:            else
                    211:                log(LOG_DEBUG, 0, "Error writing to routing socket");
                    212:        }
                    213:        return(FALSE); 
                    214:     }
                    215:     
                    216:     do {
                    217:        l = read(routing_socket, (char *)&m_rtmsg, sizeof(m_rtmsg));
                    218:     } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
                    219:     
                    220:     if (l < 0) {
                    221:        IF_DEBUG(DEBUG_RPF | DEBUG_KERN)
                    222:            log(LOG_DEBUG, 0, "Read from routing socket failed");
                    223:        return(FALSE);
                    224:     }
                    225:     
                    226:     if (getmsg(&rtm, l, &rpfinfo)){
                    227:        rpfp->rpfneighbor.s_addr = rpfinfo.rpfneighbor.s_addr;
                    228:        rpfp->iif = rpfinfo.iif;
                    229:     }
                    230: #undef rtm
                    231:     return (TRUE);
                    232: }
                    233: 
                    234: 
                    235: /*
                    236:  * Returns TRUE on success, FALSE otherwise. rpfinfo contains the result.
                    237:  */
                    238: int 
                    239: getmsg(rtm, msglen, rpfinfop)
                    240:     register struct rt_msghdr *rtm;
                    241:     int msglen;
                    242:     struct rpfctl *rpfinfop;
                    243: {
                    244:     struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
                    245:     struct sockaddr_dl *ifp = NULL;
                    246:     register struct sockaddr *sa;
                    247:     register char *cp;
                    248:     register int i;
                    249:     struct in_addr in;
                    250:     vifi_t vifi;
                    251:     struct uvif *v;
                    252:     
                    253:     if (rpfinfop == (struct rpfctl *)NULL)
                    254:        return(FALSE);
                    255:     
                    256:     in = ((struct sockaddr_in *)&so_dst)->sin_addr;
                    257:     IF_DEBUG(DEBUG_RPF)
                    258:        log(LOG_DEBUG, 0, "route to: %s", inet_fmt(in.s_addr, s1));
                    259:     cp = ((char *)(rtm + 1));
                    260:     if (rtm->rtm_addrs)
                    261:        for (i = 1; i; i <<= 1)
                    262:            if (i & rtm->rtm_addrs) {
                    263:                sa = (struct sockaddr *)cp;
                    264:                switch (i) {
                    265:                case RTA_DST:
                    266:                    dst = sa;
                    267:                    break;
                    268:                case RTA_GATEWAY:
                    269:                    gate = sa;
                    270:                    break;
                    271:                case RTA_NETMASK:
                    272:                    mask = sa;
                    273:                    break;
                    274:                case RTA_IFP:
                    275:                    if (sa->sa_family == AF_LINK &&
                    276:                        ((struct sockaddr_dl *)sa)->sdl_nlen)
                    277:                        ifp = (struct sockaddr_dl *)sa;
                    278:                    break;
                    279:                }
                    280:                ADVANCE(cp, sa);
                    281:            }
                    282:     
                    283:     if (!ifp){         /* No incoming interface */
                    284:        IF_DEBUG(DEBUG_RPF)
                    285:            log(LOG_DEBUG, 0,
                    286:                "No incoming interface for destination %s",
                    287:                inet_fmt(in.s_addr, s1));
                    288:        return(FALSE);
                    289:     }
                    290:     if (dst && mask)
                    291:        mask->sa_family = dst->sa_family;
                    292:     if (dst) {
                    293:        in = ((struct sockaddr_in *)dst)->sin_addr;
                    294:        IF_DEBUG(DEBUG_RPF)
                    295:            log(LOG_DEBUG, 0, " destination is: %s",
                    296:                inet_fmt(in.s_addr, s1));
                    297:     }
                    298:     if (gate && rtm->rtm_flags & RTF_GATEWAY) {
                    299:        in = ((struct sockaddr_in *)gate)->sin_addr;
                    300:        IF_DEBUG(DEBUG_RPF)
                    301:            log(LOG_DEBUG, 0, " gateway is: %s",
                    302:                inet_fmt(in.s_addr, s1));
                    303:        rpfinfop->rpfneighbor = in;
                    304:     }
                    305:     
                    306:     for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) 
                    307:        /* get the number of the interface by matching the name */
                    308:        if (!(strncmp(v->uv_name,ifp->sdl_data,ifp->sdl_nlen)))
                    309:            break;
                    310:     
                    311:     IF_DEBUG(DEBUG_RPF)
                    312:        log(LOG_DEBUG, 0, " iif is %d", vifi);
                    313:     
                    314:     rpfinfop->iif = vifi;
                    315:     
                    316:     if (vifi >= numvifs){
                    317:        IF_DEBUG(DEBUG_RPF)
                    318:            log(LOG_DEBUG, 0, "Invalid incoming interface for destination %s, because of invalid virtual interface", inet_fmt(in.s_addr, s1));
                    319:        return(FALSE);/* invalid iif */
                    320:     }
                    321:     
                    322:     return(TRUE);
                    323: }
                    324: 
                    325: 
                    326: #else  /* HAVE_ROUTING_SOCKETS */
                    327: 
                    328: 
                    329: /*
                    330:  * Return in rpfcinfo the incoming interface and the next hop router
                    331:  * toward source.
                    332:  */
                    333: /* TODO: check whether next hop router address is in network or host order */
                    334: int
                    335: k_req_incoming(source, rpfcinfo)
                    336:     u_int32 source;
                    337:     struct rpfctl *rpfcinfo;
                    338: {
                    339:     rpfcinfo->source.s_addr = source;
                    340:     rpfcinfo->iif = NO_VIF;     /* just initialized, will be */
                    341:     /* changed in kernel */
                    342:     rpfcinfo->rpfneighbor.s_addr = INADDR_ANY;   /* initialized */
                    343:     
                    344:     if (ioctl(udp_socket, SIOCGETRPF, (char *) rpfcinfo) < 0){
                    345:        log(LOG_ERR, errno, "ioctl SIOCGETRPF k_req_incoming");
                    346:        return(FALSE);
                    347:     }
                    348:     return (TRUE);
                    349: }
                    350: #endif /* HAVE_ROUTING_SOCKETS */
                    351: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>