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>