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