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>