File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / routesock.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:58:55 2017 UTC (7 years ago) by misho
Branches: pimdd, MAIN
CVS tags: v0_2_1p0, v0_2_1, HEAD
pimdd-dense 0.2.1.0_2

    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.1.1.1 2017/06/12 07:58:55 misho 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>