File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / net / route_msg.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 4 months ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    1: 
    2: /*
    3:  * Copyright (c) 2001-2002 Packet Design, LLC.
    4:  * All rights reserved.
    5:  * 
    6:  * Subject to the following obligations and disclaimer of warranty,
    7:  * use and redistribution of this software, in source or object code
    8:  * forms, with or without modifications are expressly permitted by
    9:  * Packet Design; provided, however, that:
   10:  * 
   11:  *    (i)  Any and all reproductions of the source or object code
   12:  *         must include the copyright notice above and the following
   13:  *         disclaimer of warranties; and
   14:  *    (ii) No rights are granted, in any manner or form, to use
   15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
   16:  *         on advertising, endorsements, or otherwise except as such
   17:  *         appears in the above copyright notice or in the software.
   18:  * 
   19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
   20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
   21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
   22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
   23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
   24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
   25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
   26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
   27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
   28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
   29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
   30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
   31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
   32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
   33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
   35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
   36:  * THE POSSIBILITY OF SUCH DAMAGE.
   37:  *
   38:  * Author: Archie Cobbs <archie@freebsd.org>
   39:  */
   40: 
   41: #include <sys/types.h>
   42: #include <sys/param.h>
   43: #include <sys/socket.h>
   44: #include <sys/sysctl.h>
   45: #include <sys/sockio.h>
   46: #include <sys/ioctl.h>
   47: 
   48: #include <net/if.h>
   49: #include <net/if_dl.h>
   50: #include <net/if_types.h>
   51: #include <net/route.h>
   52: 
   53: #include <netinet/in.h>
   54: #include <arpa/inet.h>
   55: 
   56: #include <stdio.h>
   57: #include <stdlib.h>
   58: #include <stddef.h>
   59: #include <stdarg.h>
   60: #include <unistd.h>
   61: #include <string.h>
   62: #include <assert.h>
   63: #include <errno.h>
   64: #include <time.h>
   65: 
   66: #include "structs/structs.h"
   67: #include "structs/type/array.h"
   68: 
   69: #include "util/typed_mem.h"
   70: #include "net/route_msg.h"
   71: 
   72: #define ROUNDUP(a) \
   73: 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
   74: #define ADVANCE(x, n)	((x) += ROUNDUP((n)->sa_len))
   75: 
   76: struct route_msg {
   77: 	int		type;		/* message type */
   78: 	int		index;		/* index for associated ifp */
   79: 	int		flags;		/* flags, incl. kern & msg, e.g. DONE */
   80: 	pid_t		pid;		/* for sender to identify action */
   81: 	int		seq;		/* for sender to identify action */
   82: 	int		error;		/* why failed */
   83: 	struct sockaddr	*dest;		/* destination sockaddr */
   84: 	struct sockaddr	*gateway;	/* gateway sockaddr */
   85: 	struct sockaddr	*netmask;	/* netmask sockaddr */
   86: 	struct sockaddr	*genmask;	/* genmask sockaddr */
   87: 	struct sockaddr	*ifp;		/* interface name sockaddr */
   88: 	struct sockaddr	*ifa;		/* interface addr sockaddr */
   89: 	struct sockaddr	*author;	/* author of redirect sockaddr */
   90: 	struct sockaddr	*brd;		/* for NEWADDR, broadcast or p2p dest */
   91: };
   92: 
   93: /*
   94:  * Internal variables
   95:  */
   96: 
   97: /* List of sockaddr's in a route message from the kernel */
   98: struct msg_sock {
   99: 	const char	*name;
  100: 	u_int		offset;
  101: };
  102: 
  103: static const	struct msg_sock msg_socks[] = {
  104: 	{ "dest",	offsetof(struct route_msg, dest)	},
  105: 	{ "gateway",	offsetof(struct route_msg, gateway)	},
  106: 	{ "netmask",	offsetof(struct route_msg, netmask)	},
  107: 	{ "genmask",	offsetof(struct route_msg, genmask)	},
  108: 	{ "ifp",	offsetof(struct route_msg, ifp)		},
  109: 	{ "ifa",	offsetof(struct route_msg, ifa)		},
  110: 	{ "author",	offsetof(struct route_msg, author)	},
  111: 	{ "brd",	offsetof(struct route_msg, brd)		},
  112: 	{ NULL, 0 }
  113: };
  114: 
  115: static int	prev_seq;		/* last used sequence number */
  116: 
  117: /*
  118:  * Internal functions
  119:  */
  120: static int	route_msg_set_sa(struct route_msg *msg,
  121: 			const char *name, const struct sockaddr *sa);
  122: 
  123: /*
  124:  * Create a new route message.
  125:  */
  126: struct route_msg *
  127: route_msg_create(void)
  128: {
  129: 	struct route_msg *msg;
  130: 
  131: 	if ((msg = MALLOC("route_msg", sizeof(*msg))) == NULL)
  132: 		return (NULL);
  133: 	memset(msg, 0, sizeof(*msg));
  134: 	msg->seq = ++prev_seq;				/* XXX not atomic */
  135: 	msg->pid = getpid();
  136: 	return (msg);
  137: }
  138: 
  139: /*
  140:  * Destroy a routing message.
  141:  */
  142: void
  143: route_msg_destroy(struct route_msg **msgp)
  144: {
  145: 	struct route_msg *const msg = *msgp;
  146: 
  147: 	if (msg == NULL)
  148: 		return;
  149: 	FREE("route_msg.dest", msg->dest);
  150: 	FREE("route_msg.gateway", msg->gateway);
  151: 	FREE("route_msg.netmask", msg->netmask);
  152: 	FREE("route_msg.genmask", msg->genmask);
  153: 	FREE("route_msg.ifp", msg->ifp);
  154: 	FREE("route_msg.ifa", msg->ifa);
  155: 	FREE("route_msg.author", msg->author);
  156: 	FREE("route_msg.brd", msg->brd);
  157: 	FREE("route_msg", msg);
  158: 	*msgp = NULL;
  159: }
  160: 
  161: /*
  162:  * Get message type.
  163:  */
  164: int
  165: route_msg_get_type(struct route_msg *msg)
  166: {
  167: 	return (msg->type);
  168: }
  169: 
  170: /*
  171:  * Set message type.
  172:  */
  173: void
  174: route_msg_set_type(struct route_msg *msg, int type)
  175: {
  176: 	msg->type = type;
  177: }
  178: 
  179: /*
  180:  * Get message index.
  181:  */
  182: int
  183: route_msg_get_index(struct route_msg *msg)
  184: {
  185: 	return (msg->index);
  186: }
  187: 
  188: /*
  189:  * Set message index.
  190:  */
  191: void
  192: route_msg_set_index(struct route_msg *msg, int index)
  193: {
  194: 	msg->index = index;
  195: }
  196: 
  197: /*
  198:  * Get message flags.
  199:  */
  200: int
  201: route_msg_get_flags(struct route_msg *msg)
  202: {
  203: 	return (msg->flags);
  204: }
  205: 
  206: /*
  207:  * Set message flags.
  208:  */
  209: void
  210: route_msg_set_flags(struct route_msg *msg, int flags)
  211: {
  212: 	msg->flags = flags;
  213: }
  214: 
  215: /*
  216:  * Get message error code.
  217:  */
  218: int
  219: route_msg_get_error(struct route_msg *msg)
  220: {
  221: 	return (msg->error);
  222: }
  223: 
  224: /*
  225:  * Get message process ID.
  226:  */
  227: pid_t
  228: route_msg_get_pid(struct route_msg *msg)
  229: {
  230: 	return (msg->pid);
  231: }
  232: 
  233: /*
  234:  * Get message sequence number.
  235:  */
  236: int
  237: route_msg_get_seq(struct route_msg *msg)
  238: {
  239: 	return (msg->seq);
  240: }
  241: 
  242: /*
  243:  * Get message destination.
  244:  */
  245: const struct sockaddr *
  246: route_msg_get_dest(struct route_msg *msg)
  247: {
  248: 	return (msg->dest);
  249: }
  250: 
  251: /*
  252:  * Set message destination.
  253:  */
  254: int
  255: route_msg_set_dest(struct route_msg *msg, const struct sockaddr *dest)
  256: {
  257: 	return (route_msg_set_sa(msg, "dest", dest));
  258: }
  259: 
  260: /*
  261:  * Get message gateway.
  262:  */
  263: const struct sockaddr *
  264: route_msg_get_gateway(struct route_msg *msg)
  265: {
  266: 	return (msg->gateway);
  267: }
  268: 
  269: /*
  270:  * Set message gateway.
  271:  */
  272: int
  273: route_msg_set_gateway(struct route_msg *msg, const struct sockaddr *gateway)
  274: {
  275: 	return (route_msg_set_sa(msg, "gateway", gateway));
  276: }
  277: 
  278: /*
  279:  * Get message netmask.
  280:  */
  281: const struct sockaddr *
  282: route_msg_get_netmask(struct route_msg *msg)
  283: {
  284: 	return (msg->netmask);
  285: }
  286: 
  287: /*
  288:  * Set message netmask.
  289:  */
  290: int
  291: route_msg_set_netmask(struct route_msg *msg, const struct sockaddr *netmask)
  292: {
  293: 	return (route_msg_set_sa(msg, "netmask", netmask));
  294: }
  295: 
  296: /*
  297:  * Get message cloning netmask.
  298:  */
  299: const struct sockaddr *
  300: route_msg_get_genmask(struct route_msg *msg)
  301: {
  302: 	return (msg->genmask);
  303: }
  304: 
  305: /*
  306:  * Set message cloning netmask.
  307:  */
  308: int
  309: route_msg_set_genmask(struct route_msg *msg, const struct sockaddr *genmask)
  310: {
  311: 	return (route_msg_set_sa(msg, "genmask", genmask));
  312: }
  313: 
  314: /*
  315:  * Get message interface name.
  316:  */
  317: const struct sockaddr *
  318: route_msg_get_ifp(struct route_msg *msg)
  319: {
  320: 	return (msg->ifp);
  321: }
  322: 
  323: /*
  324:  * Set message interface name.
  325:  */
  326: int
  327: route_msg_set_ifp(struct route_msg *msg, const struct sockaddr *ifp)
  328: {
  329: 	return (route_msg_set_sa(msg, "ifp", ifp));
  330: }
  331: 
  332: /*
  333:  * Get message interface address.
  334:  */
  335: const struct sockaddr *
  336: route_msg_get_ifa(struct route_msg *msg)
  337: {
  338: 	return (msg->ifa);
  339: }
  340: 
  341: /*
  342:  * Set message interface address.
  343:  */
  344: int
  345: route_msg_set_ifa(struct route_msg *msg, const struct sockaddr *ifa)
  346: {
  347: 	return (route_msg_set_sa(msg, "ifa", ifa));
  348: }
  349: 
  350: /*
  351:  * Get message author of the redirect message.
  352:  */
  353: const struct sockaddr *
  354: route_msg_get_author(struct route_msg *msg)
  355: {
  356: 	return (msg->author);
  357: }
  358: 
  359: /*
  360:  * Set message author of the redirect message.
  361:  */
  362: int
  363: route_msg_set_author(struct route_msg *msg, const struct sockaddr *author)
  364: {
  365: 	return (route_msg_set_sa(msg, "author", author));
  366: }
  367: 
  368: /*
  369:  * Get message broadcast or point-to-point destination address.
  370:  */
  371: const struct sockaddr *
  372: route_msg_get_brd(struct route_msg *msg)
  373: {
  374: 	return (msg->brd);
  375: }
  376: 
  377: /*
  378:  * Set message broadcast or point-to-point destination address.
  379:  */
  380: int
  381: route_msg_set_brd(struct route_msg *msg, const struct sockaddr *brd)
  382: {
  383: 	return (route_msg_set_sa(msg, "brd", brd));
  384: }
  385: 
  386: /*
  387:  * Set one of the struct sockaddr fields.
  388:  */
  389: static int
  390: route_msg_set_sa(struct route_msg *msg,
  391: 	const char *name, const struct sockaddr *sa)
  392: {
  393: 	struct sockaddr *copy;
  394: 	struct sockaddr **sp;
  395: 	char buf[32];
  396: 	int i;
  397: 
  398: 	for (i = 0; msg_socks[i].name != NULL
  399: 	    && strcmp(name, msg_socks[i].name) != 0; i++);
  400: 	assert(msg_socks[i].name != NULL);
  401: 	sp = (struct sockaddr **)(void *)((u_char *)msg + msg_socks[i].offset);
  402: 	snprintf(buf, sizeof(buf), "route_msg.%s", name);
  403: 	if (sa != NULL) {
  404: 		if ((copy = MALLOC(buf, sa->sa_len)) == NULL)
  405: 			return (-1);
  406: 		memcpy(copy, sa, sa->sa_len);
  407: 	} else
  408: 		copy = NULL;
  409: 	FREE(buf, *sp);
  410: 	*sp = copy;
  411: 	return (0);
  412: }
  413: 
  414: /*
  415:  * Decode one or more routing messages from raw socket data.
  416:  *
  417:  * Returns the number of decoded messages, or -1 for error.
  418:  * The array of struct route_msg pointers is returned in *listp,
  419:  * in an array allocated with memory type 'mtype'.
  420:  */
  421: int
  422: route_msg_decode(const u_char *data, size_t dlen,
  423: 	struct route_msg ***listp, const char *mtype)
  424: {
  425: 	struct route_msg **list;
  426: 	struct rt_msghdr rtm;
  427: 	int posn;
  428: 	int num;
  429: 	int i;
  430: 
  431: 	/* Count number of messages */
  432: 	for (num = posn = 0; posn < dlen; num++, posn += rtm.rtm_msglen) {
  433: 		if (dlen - posn < sizeof(rtm)) {
  434: 			errno = EINVAL;
  435: 			return (-1);
  436: 		}
  437: 		memcpy(&rtm, data + posn, sizeof(rtm.rtm_msglen));
  438: 		if (rtm.rtm_msglen < sizeof(rtm)) {
  439: 			errno = EINVAL;
  440: 			return (-1);
  441: 		}
  442: 	}
  443: 
  444: 	/* Allocate list */
  445: 	if ((list = MALLOC(mtype, num * sizeof(*list))) == NULL)
  446: 		return (-1);
  447: 	memset(list, 0, num * sizeof(*list));
  448: 
  449: 	/* Decode each message */
  450: 	for (i = posn = 0; i < num; i++, posn += rtm.rtm_msglen) {
  451: 		int posn2;
  452: 		int j;
  453: 
  454: 		/* Create new route_msg object */
  455: 		if ((list[i] = route_msg_create()) == NULL)
  456: 			goto fail;
  457: 
  458: 		/* Copy fields from route message header */
  459: 		memcpy(&rtm, data + posn, sizeof(rtm));
  460: 		list[i]->type = rtm.rtm_type;
  461: 		list[i]->index = rtm.rtm_index;
  462: 		list[i]->flags = rtm.rtm_flags;
  463: 		list[i]->pid = rtm.rtm_pid;
  464: 		list[i]->seq = rtm.rtm_seq;
  465: 		list[i]->error = rtm.rtm_errno;
  466: 
  467: 		/* Create struct sockaddr's from each appended sockaddr */
  468: 		for (posn2 = posn + sizeof(rtm), j = 0;
  469: 		    msg_socks[j].name != NULL; j++) {
  470: 			const struct sockaddr *const sa
  471: 			    = (struct sockaddr *)(data + posn2);
  472: 
  473: 			if ((rtm.rtm_addrs & (1 << j)) == 0)
  474: 				continue;
  475: 			if (sa->sa_len != 0) {
  476: 				if (route_msg_set_sa(list[i],
  477: 				    msg_socks[j].name, sa) == -1)
  478: 					goto fail;
  479: 			}
  480: 			ADVANCE(posn2, sa);
  481: 		}
  482: 	}
  483: 
  484: 	/* Done */
  485: 	*listp = list;
  486: 	return (num);
  487: 
  488: fail:
  489: 	/* Cleanup after failure */
  490: 	for (i = 0; i < num; i++)
  491: 		route_msg_destroy(&list[i]);
  492: 	FREE(mtype, list);
  493: 	return (-1);
  494: }
  495: 
  496: /*
  497:  * Encode a route message into raw binary form.
  498:  *
  499:  * Returns the total encoded length, or -1 for error.
  500:  */
  501: int
  502: route_msg_encode(const struct route_msg *msg, u_char *data, size_t dlen)
  503: {
  504: 	struct rt_msghdr rtm;
  505: 	int totalLen;
  506: 	int i;
  507: 
  508: 	/* Prepare header */
  509: 	if ((totalLen = sizeof(rtm)) > dlen) {
  510: 		errno = EMSGSIZE;
  511: 		return (-1);
  512: 	}
  513: 	memset(&rtm, 0, sizeof(rtm));
  514: 	rtm.rtm_version = RTM_VERSION;
  515: 	rtm.rtm_type = msg->type;
  516: 	rtm.rtm_index = msg->index;
  517: 	rtm.rtm_flags = msg->flags;
  518: 	rtm.rtm_pid = msg->pid;
  519: 	rtm.rtm_seq = msg->seq;
  520: 	rtm.rtm_errno = msg->error;
  521: 
  522: 	/* Append struct sockaddr's */
  523: 	for (i = 0; msg_socks[i].name != NULL; i++) {
  524: 		struct sockaddr *const sa = *((struct sockaddr **)(void *)
  525: 		    ((u_char *)msg + msg_socks[i].offset));
  526: 		int len;
  527: 
  528: 		if (sa == NULL)
  529: 			continue;
  530: 		rtm.rtm_addrs |= (1 << i);
  531: 		len = ROUNDUP(sa->sa_len);
  532: 		if (totalLen + len > dlen) {
  533: 			errno = EMSGSIZE;
  534: 			return (-1);
  535: 		}
  536: 		memcpy(data + totalLen, sa, sa->sa_len);
  537: 		memset(data + totalLen + sa->sa_len, 0, len - sa->sa_len);
  538: 		totalLen += len;
  539: 	}
  540: 
  541: 	/* Copy in completed header */
  542: 	rtm.rtm_msglen = totalLen;
  543: 	memcpy(data, &rtm, sizeof(rtm));
  544: 
  545: 	/* Done */
  546: 	return (totalLen);
  547: }
  548: 
  549: /*
  550:  * Send a route message to a socket.
  551:  */
  552: int
  553: route_msg_send(struct route_msg *msg, int sock)
  554: {
  555: 	u_char buf[512];
  556: 	int count;
  557: 	int elen;
  558: 	int r;
  559: 
  560: 	if ((elen = route_msg_encode(msg, buf, sizeof(buf))) == -1)
  561: 		return (-1);
  562: 	for (count = 0; count < 32; count++) {
  563: 		if ((r = send(sock, buf, elen, 0)) >= 0)
  564: 			return (0);
  565: 		switch (errno) {
  566: 		case ENETUNREACH:
  567: 		case ESRCH:
  568: 			break;
  569: 		default:
  570: 			return (-1);
  571: 		}
  572: 	}
  573: 	return (-1);
  574: }
  575: 
  576: /*
  577:  * Receive route messages from a socket.
  578:  */
  579: int
  580: route_msg_recv(struct route_msg ***listp, int sock, const char *mtype)
  581: {
  582: 	u_char buf[512];
  583: 	int r;
  584: 
  585: 	/* Read next raw message array */
  586: 	if ((r = recv(sock, buf, sizeof(buf), 0)) < 0)
  587: 		return (-1);
  588: 
  589: 	/* Decode it */
  590: 	return (route_msg_decode(buf, r, listp, mtype));
  591: }
  592: 
  593: /*
  594:  * Print route message as a string.
  595:  */
  596: void
  597: route_msg_print(struct route_msg *msg, FILE *fp)
  598: {
  599: 	const char *typestr = NULL;
  600: 
  601: 	fprintf(fp, "type=");
  602: 	switch (msg->type) {
  603: 	case RTM_ADD:		typestr = "ADD"; break;
  604: 	case RTM_DELETE:	typestr = "DELETE"; break;
  605: 	case RTM_CHANGE:	typestr = "CHANGE"; break;
  606: 	case RTM_GET:		typestr = "GET"; break;
  607: 	case RTM_LOSING:	typestr = "LOSING"; break;
  608: 	case RTM_REDIRECT:	typestr = "REDIRECT"; break;
  609: 	case RTM_MISS:		typestr = "MISS"; break;
  610: 	case RTM_LOCK:		typestr = "LOCK"; break;
  611: 	case RTM_OLDADD:	typestr = "OLDADD"; break;
  612: 	case RTM_OLDDEL:	typestr = "OLDDEL"; break;
  613: 	case RTM_RESOLVE:	typestr = "RESOLVE"; break;
  614: 	case RTM_NEWADDR:	typestr = "NEWADDR"; break;
  615: 	case RTM_DELADDR:	typestr = "DELADDR"; break;
  616: 	case RTM_IFINFO:	typestr = "IFINFO"; break;
  617: 	case RTM_NEWMADDR:	typestr = "NEWMADDR"; break;
  618: 	case RTM_DELMADDR:	typestr = "DELMADDR"; break;
  619: 	default:
  620: 		fprintf(fp, "%d", msg->type);
  621: 		break;
  622: 	}
  623: 	if (typestr != NULL)
  624: 		fprintf(fp, "%s", typestr);
  625: 	fprintf(fp, " index=%d flags=0x%x pid=%lu seq=%d errno=%d",
  626: 	    msg->index, msg->flags, (u_long)msg->pid, msg->seq, msg->error);
  627: 	if (msg->dest != NULL)
  628: 		fprintf(fp, " dest=%p", msg->dest);
  629: 	if (msg->gateway != NULL)
  630: 		fprintf(fp, " gateway=%p", msg->gateway);
  631: 	if (msg->netmask != NULL)
  632: 		fprintf(fp, " netmask=%p", msg->netmask);
  633: 	if (msg->genmask != NULL)
  634: 		fprintf(fp, " genmask=%p", msg->genmask);
  635: 	if (msg->ifp != NULL)
  636: 		fprintf(fp, " ifp=%p", msg->ifp);
  637: 	if (msg->ifa != NULL)
  638: 		fprintf(fp, " ifa=%p", msg->ifa);
  639: 	if (msg->author != NULL)
  640: 		fprintf(fp, " author=%p", msg->author);
  641: 	if (msg->brd != NULL)
  642: 		fprintf(fp, " brd=%p", msg->brd);
  643: 	fflush(fp);
  644: }
  645: 

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