Annotation of embedaddon/libpdel/net/route_msg.c, revision 1.1
1.1 ! misho 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>