Annotation of embedaddon/pimdd/routesock.c, revision 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>