Annotation of embedaddon/libpdel/net/uroute.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 <netinet/if_ether.h>
                     55: #include <arpa/inet.h>
                     56: 
                     57: #include <stdio.h>
                     58: #include <stdlib.h>
                     59: #include <stdarg.h>
                     60: #include <unistd.h>
                     61: #include <assert.h>
                     62: #include <string.h>
                     63: #include <errno.h>
                     64: #include <err.h>
                     65: 
                     66: #include "structs/structs.h"
                     67: #include "structs/type/array.h"
                     68: 
                     69: #include "net/route_msg.h"
                     70: #include "net/uroute.h"
                     71: #include "util/typed_mem.h"
                     72: 
                     73: #define ROUNDUP(a) \
                     74:        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
                     75: #define ADVANCE(x, n)  ((x) += ROUNDUP((n)->sa_len))
                     76: 
                     77: #ifdef RTF_CLONING
                     78: #define WRITABLE_FLAGS (RTF_STATIC | RTF_LLINFO | RTF_REJECT | RTF_BLACKHOLE \
                     79:                            | RTF_PROTO1 | RTF_PROTO2 | RTF_CLONING \
                     80:                            | RTF_XRESOLVE | RTF_UP | RTF_GATEWAY)
                     81: #else
                     82: #define WRITABLE_FLAGS (RTF_STATIC | RTF_REJECT | RTF_BLACKHOLE \
                     83:                            | RTF_PROTO1 | RTF_PROTO2 \
                     84:                            | RTF_XRESOLVE | RTF_UP | RTF_GATEWAY)
                     85: #endif
                     86: 
                     87: struct route_flag {
                     88:        const char      *name;
                     89:        int             bit;
                     90: };
                     91: 
                     92: static const   struct route_flag route_flags[] = {
                     93: #define FLAG(x)        { #x, RTF_ ## x }
                     94:        FLAG(UP),
                     95:        FLAG(GATEWAY),
                     96:        FLAG(HOST),
                     97:        FLAG(REJECT),
                     98:        FLAG(DYNAMIC),
                     99:        FLAG(MODIFIED),
                    100:        FLAG(DONE),
                    101: #ifdef RTF_CLONING
                    102:        FLAG(CLONING),
                    103: #endif
                    104:        FLAG(XRESOLVE),
                    105: #ifdef RTF_LLINFO
                    106:        FLAG(LLINFO),
                    107: #endif
                    108:        FLAG(STATIC),
                    109:        FLAG(BLACKHOLE),
                    110:        FLAG(PROTO2),
                    111:        FLAG(PROTO1),
                    112:        FLAG(PRCLONING),
                    113: #ifdef RTF_WASCLONED
                    114:        FLAG(WASCLONED),
                    115: #endif
                    116:        FLAG(PROTO3),
                    117:        FLAG(PINNED),
                    118:        FLAG(LOCAL),
                    119:        FLAG(BROADCAST),
                    120:        FLAG(MULTICAST),
                    121: #undef FLAG
                    122:        { NULL, 0 }
                    123: };
                    124: 
                    125: /* Route structure */
                    126: struct uroute {
                    127:        int flags;
                    128:        struct sockaddr *dest;
                    129:        struct sockaddr *gateway;
                    130:        struct sockaddr *netmask;
                    131: };
                    132: 
                    133: /*
                    134:  * Internal functions
                    135:  */
                    136: static int     uroute_do_route(struct uroute *route, int sock, int type);
                    137: static const   char *uroute_sockaddr_string(const struct sockaddr *sa);
                    138: 
                    139: /*
                    140:  * Create a new route.
                    141:  */
                    142: struct uroute *
                    143: uroute_create(const struct sockaddr *dest, const struct sockaddr *gateway,
                    144:        const struct sockaddr *netmask)
                    145: {
                    146:        struct uroute *route;
                    147: 
                    148:        if (dest == NULL || gateway == NULL) {
                    149:                errno = EINVAL;
                    150:                return (NULL);
                    151:        }
                    152:        if ((route = MALLOC("uroute", sizeof(*route))) == NULL)
                    153:                return (NULL);
                    154:        memset(route, 0, sizeof(*route));
                    155:        if ((route->dest = MALLOC("uroute.dest", dest->sa_len)) == NULL)
                    156:                goto fail;
                    157:        memcpy(route->dest, dest, dest->sa_len);
                    158:        if ((route->gateway = MALLOC("uroute.gateway",
                    159:            gateway->sa_len)) == NULL)
                    160:                goto fail;
                    161:        memcpy(route->gateway, gateway, gateway->sa_len);
                    162:        if (netmask != NULL) {
                    163:                if ((route->netmask = MALLOC("uroute.netmask",
                    164:                    netmask->sa_len)) == NULL)
                    165:                        goto fail;
                    166:                memcpy(route->netmask, netmask, netmask->sa_len);
                    167:        }
                    168:        route->flags = RTF_STATIC;
                    169:        return (route);
                    170: 
                    171: fail:
                    172:        /* Clean up */
                    173:        uroute_destroy(&route);
                    174:        return (NULL);
                    175: }
                    176: 
                    177: /*
                    178:  * Free a route.
                    179:  */
                    180: void
                    181: uroute_destroy(struct uroute **routep)
                    182: {
                    183:        struct uroute *const route = *routep;
                    184: 
                    185:        if (route == NULL)
                    186:                return;
                    187:        FREE("uroute.dest", route->dest);
                    188:        FREE("uroute.gateway", route->gateway);
                    189:        FREE("uroute.netmask", route->netmask);
                    190:        FREE("uroute", route);
                    191:        *routep = NULL;
                    192: }
                    193: 
                    194: /*
                    195:  * Get the destination address.
                    196:  */
                    197: const struct sockaddr *
                    198: uroute_get_dest(struct uroute *route)
                    199: {
                    200:        return (route->dest);
                    201: }
                    202: 
                    203: /*
                    204:  * Get the gateway address.
                    205:  */
                    206: const struct sockaddr *
                    207: uroute_get_gateway(struct uroute *route)
                    208: {
                    209:        return (route->gateway);
                    210: }
                    211: 
                    212: /*
                    213:  * Get the netmask.
                    214:  *
                    215:  * Returns NULL for a host route.
                    216:  */
                    217: const struct sockaddr *
                    218: uroute_get_netmask(struct uroute *route)
                    219: {
                    220:        return (route->netmask);
                    221: }
                    222: 
                    223: /*
                    224:  * Get the flags.
                    225:  */
                    226: int
                    227: uroute_get_flags(struct uroute *route)
                    228: {
                    229:        return (route->flags);
                    230: }
                    231: 
                    232: /*
                    233:  * Set the flags.
                    234:  */
                    235: void
                    236: uroute_set_flags(struct uroute *route, int flags)
                    237: {
                    238:        route->flags = flags;
                    239: }
                    240: 
                    241: /*
                    242:  * Add route to the kernel routing table.
                    243:  */
                    244: int
                    245: uroute_add(struct uroute *route)
                    246: {
                    247:        return (uroute_do_route(route, -1, RTM_ADD));
                    248: }
                    249: 
                    250: /*
                    251:  * Delete a route.
                    252:  */
                    253: int
                    254: uroute_delete(struct uroute *route)
                    255: {
                    256:        return (uroute_do_route(route, -1, RTM_DELETE));
                    257: }
                    258: 
                    259: /*
                    260:  * Get the installed kernel route that matches the destination "dest".
                    261:  */
                    262: struct uroute *
                    263: uroute_get(const struct sockaddr *dest)
                    264: {
                    265:        struct uroute *route = NULL;
                    266:        struct route_msg *msg = NULL;
                    267:        struct route_msg **list = NULL;
                    268:        struct sockaddr_dl sdl;
                    269:        int errno_save;
                    270:        int sock = -1;
                    271:        int num = 0;
                    272:        int seq;
                    273:        int i;
                    274: 
                    275:        /* Build new route message */
                    276:        if ((msg = route_msg_create()) == NULL)
                    277:                goto fail;
                    278:        seq = route_msg_get_seq(msg);
                    279:        route_msg_set_type(msg, RTM_GET);
                    280:        if (route_msg_set_dest(msg, dest) == -1)
                    281:                goto fail;
                    282:        memset(&sdl, 0, sizeof(sdl));
                    283:        sdl.sdl_type = IFT_OTHER;
                    284:        sdl.sdl_len = 8;
                    285:        sdl.sdl_family = AF_LINK;
                    286:        if (route_msg_set_ifp(msg, (struct sockaddr *)&sdl) == -1)
                    287:                goto fail;
                    288:        route_msg_set_flags(msg, RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_STATIC);
                    289: 
                    290:        /* Send request */
                    291:        if ((sock = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
                    292:                goto fail;
                    293:        if (route_msg_send(msg, sock) == -1)
                    294:                goto fail;
                    295:        route_msg_destroy(&msg);
                    296:        msg = NULL;
                    297: 
                    298:        /* Get response */
                    299:        while (1) {
                    300: 
                    301:                /* Decode it */
                    302:                if ((num = route_msg_recv(&list, sock, TYPED_MEM_TEMP)) == -1)
                    303:                        goto fail;
                    304: 
                    305:                /* Check returned messages for a match */
                    306:                for (i = 0; i < num; i++) {
                    307:                        struct route_msg *const msg = list[i];
                    308: 
                    309:                        if (route_msg_get_pid(msg) == getpid()
                    310:                            && route_msg_get_seq(msg) == seq) {
                    311:                                if ((route = uroute_create(route_msg_get_dest(
                    312:                                    msg), route_msg_get_gateway(msg),
                    313:                                    route_msg_get_netmask(msg))) == NULL)
                    314:                                        goto fail;
                    315:                                break;
                    316:                        }
                    317:                }
                    318:                if (route != NULL)
                    319:                        break;
                    320: 
                    321:                /* Free list and try again */
                    322:                for (i = 0; i < num; i++)
                    323:                        route_msg_destroy(&list[i]);
                    324:                FREE(TYPED_MEM_TEMP, list);
                    325:                list = NULL;
                    326:        }
                    327: 
                    328: fail:
                    329:        /* Clean up and exit */
                    330:        errno_save = errno;
                    331:        if (sock != -1)
                    332:                (void)close(sock);
                    333:        if (msg != NULL)
                    334:                route_msg_destroy(&msg);
                    335:        if (list != NULL) {
                    336:                for (i = 0; i < num; i++)
                    337:                        route_msg_destroy(&list[i]);
                    338:                FREE(TYPED_MEM_TEMP, list);
                    339:        }
                    340:        errno = errno_save;
                    341:        return (route);
                    342: }
                    343: 
                    344: /*
                    345:  * Build and send a route message by type.
                    346:  */
                    347: static int
                    348: uroute_do_route(struct uroute *route, int sock, int type)
                    349: {
                    350:        struct route_msg *msg;
                    351:        int close_sock = 0;
                    352:        int r = -1;
                    353:        int flags;
                    354: 
                    355:        /* Create new route message */
                    356:        if ((msg = route_msg_create()) == NULL)
                    357:                return (-1);
                    358: 
                    359:        /* Open socket if requested */
                    360:        if (sock == -1) {
                    361:                if ((sock = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
                    362:                        goto fail;
                    363:                close_sock = 1;
                    364:        }
                    365: 
                    366:        /* Build message */
                    367:        route_msg_set_type(msg, type);
                    368:        flags = route->flags & WRITABLE_FLAGS;
                    369:        flags |= RTF_UP;
                    370:        if (route->gateway->sa_family != AF_LINK)
                    371:                flags |= RTF_GATEWAY;
                    372:        if (route->netmask == NULL)
                    373:                flags |= RTF_HOST;
                    374:        else
                    375:                flags &= ~RTF_HOST;
                    376:        route_msg_set_flags(msg, flags);
                    377:        if (route_msg_set_dest(msg, route->dest) == -1)
                    378:                goto fail;
                    379:        if (route_msg_set_gateway(msg, route->gateway) == -1)
                    380:                goto fail;
                    381:        if (route_msg_set_netmask(msg, route->netmask) == -1)
                    382:                goto fail;
                    383: 
                    384:        /* Send messsage */
                    385:        r = route_msg_send(msg, sock);
                    386: 
                    387: fail:
                    388:        /* Clean up */
                    389:        route_msg_destroy(&msg);
                    390:        if (close_sock)
                    391:                (void)close(sock);
                    392: 
                    393:        /* Done */
                    394:        return (r);
                    395: }
                    396: 
                    397: /*
                    398:  * Get the entire routing table.
                    399:  */
                    400: int
                    401: uroute_get_all(struct uroute ***listp, const char *mtype)
                    402: {
                    403:        static int oid[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0 };
                    404:        static const int noid = sizeof(oid) / sizeof(*oid);
                    405:        struct route_msg **list = NULL;
                    406:        struct uroute **routes = NULL;
                    407:        u_char *buf = NULL;
                    408:        size_t actual;
                    409:        size_t needed;
                    410:        int num = 0;
                    411:        int i;
                    412: 
                    413:        /* Get size estimate */
                    414:        if (sysctl(oid, noid, NULL, &needed, NULL, 0) < 0)
                    415:                goto fail;
                    416: 
                    417:        /* Allocate buffer for returned value */
                    418:        if ((buf = MALLOC(TYPED_MEM_TEMP, needed)) == NULL)
                    419:                goto fail;
                    420: 
                    421:        /* Get actual data */
                    422:        actual = needed;
                    423:        if (sysctl(oid, noid, buf, &actual, NULL, 0) < 0)
                    424:                goto fail;
                    425: 
                    426:        /* Decode route messages */
                    427:        if ((num = route_msg_decode(buf, actual, &list, TYPED_MEM_TEMP)) == -1)
                    428:                goto fail;
                    429: 
                    430:        /* Create routes array from route message array */
                    431:        if ((routes = MALLOC(mtype, num * sizeof(*routes))) == NULL)
                    432:                goto fail;
                    433:        memset(routes, 0, num * sizeof(*routes));
                    434:        for (i = 0; i < num; i++) {
                    435:                struct route_msg *const msg = list[i];
                    436: 
                    437:                if ((routes[i] = uroute_create(route_msg_get_dest(msg),
                    438:                    route_msg_get_gateway(msg),
                    439:                    route_msg_get_netmask(msg))) == NULL) {
                    440:                        while (i > 0)
                    441:                                uroute_destroy(&routes[--i]);
                    442:                        FREE(mtype, routes);
                    443:                        routes = NULL;
                    444:                        goto fail;
                    445:                }
                    446:                routes[i]->flags = route_msg_get_flags(msg);
                    447:        }
                    448: 
                    449: fail:
                    450:        /* Clean up and exit */
                    451:        if (buf != NULL)
                    452:                FREE(TYPED_MEM_TEMP, buf);
                    453:        if (list != NULL) {
                    454:                for (i = 0; i < num; i++)
                    455:                        route_msg_destroy(&list[i]);
                    456:                FREE(TYPED_MEM_TEMP, list);
                    457:        }
                    458:        if (routes != NULL) {
                    459:                *listp = routes;
                    460:                return (num);
                    461:        }
                    462:        return (-1);
                    463: }
                    464: 
                    465: /*
                    466:  * Print a route.
                    467:  */
                    468: void
                    469: uroute_print(struct uroute *route, FILE *fp)
                    470: {
                    471:        int didflag;
                    472:        int i;
                    473: 
                    474:        fprintf(fp, "dest %s gateway %s",
                    475:            uroute_sockaddr_string(route->dest),
                    476:            uroute_sockaddr_string(route->gateway));
                    477:        if (route->netmask != NULL) {
                    478:                fprintf(fp, " netmask %s",
                    479:                    uroute_sockaddr_string(route->netmask));
                    480:        }
                    481:        fprintf(fp, " flags=<");
                    482:        for (i = didflag = 0; route_flags[i].name != NULL; i++) {
                    483:                if ((route->flags & route_flags[i].bit) != 0) {
                    484:                        if (didflag)
                    485:                                fprintf(fp, ",");
                    486:                        didflag = 1;
                    487:                        fprintf(fp, "%s", route_flags[i].name);
                    488:                }
                    489:        }
                    490:        fprintf(fp, ">");
                    491: }
                    492: 
                    493: static const char *
                    494: uroute_sockaddr_string(const struct sockaddr *sa)
                    495: {
                    496:        static char buf[2][256];
                    497:        static int n;
                    498:        int i;
                    499: 
                    500:        n ^= 1;
                    501:        switch (sa->sa_family) {
                    502:        case AF_INET:
                    503:                strlcpy(buf[n], inet_ntoa(((struct sockaddr_in *)(void *)
                    504:                    sa)->sin_addr), sizeof(buf[n]));
                    505:                break;
                    506:        case AF_LINK:
                    507:                /* XXX implement me */
                    508:        default:
                    509:                snprintf(buf[n], sizeof(buf[n]), "{ len=%d af=%d data=[",
                    510:                    sa->sa_len, sa->sa_family);
                    511:                for (i = 2; i < sa->sa_len; i++) {
                    512:                        snprintf(buf[n] + strlen(buf[n]),
                    513:                            sizeof(buf[n]) - strlen(buf[n]),
                    514:                            " %02X", ((u_char *)sa)[i]);
                    515:                }
                    516:                strlcat(buf[n], " ] }", sizeof(buf[n]));
                    517:        }
                    518:        return (buf[n]);
                    519: }
                    520: 
                    521: 
                    522: #ifdef UROUTE_TEST
                    523: 
                    524: int
                    525: main(int ac, char **av)
                    526: {
                    527:        struct sockaddr_in dest;
                    528:        struct sockaddr_in gateway;
                    529:        struct sockaddr_in netmask;
                    530:        struct uroute *route = NULL;
                    531:        int do_netmask = 0;
                    532:        int fail = 0;
                    533:        int cmd = 0;
                    534: 
                    535:        memset(&dest, 0, sizeof(dest));
                    536:        dest.sin_family = AF_INET;
                    537:        dest.sin_len = sizeof(dest);
                    538:        memset(&gateway, 0, sizeof(gateway));
                    539:        gateway.sin_family = AF_INET;
                    540:        gateway.sin_len = sizeof(gateway);
                    541:        memset(&netmask, 0, sizeof(netmask));
                    542:        netmask.sin_family = AF_INET;
                    543:        netmask.sin_len = sizeof(netmask);
                    544: 
                    545:        av++;
                    546:        ac--;
                    547:        switch (ac) {
                    548:        case 4:
                    549:                if (inet_aton(av[3], &netmask.sin_addr))
                    550:                        ;
                    551:                else {
                    552:                        u_long haddr;
                    553: 
                    554:                        if (sscanf(av[3], "%lu", &haddr) != 1)
                    555:                                err(1, "invalid netmask \"%s\"", av[3]);
                    556:                        netmask.sin_addr.s_addr = htonl(haddr);
                    557:                }
                    558:                do_netmask = 1;
                    559:                // fall through
                    560:        case 3:
                    561:                if (!inet_aton(av[2], &gateway.sin_addr))
                    562:                        err(1, "invalid IP address \"%s\"", av[2]);
                    563:                if (!strcmp(av[0], "add"))
                    564:                        cmd = 1;
                    565:                else if (!strcmp(av[0], "delete"))
                    566:                        cmd = 2;
                    567:                else {
                    568:                        fail = 1;
                    569:                        break;
                    570:                }
                    571:                if (!inet_aton(av[1], &dest.sin_addr))
                    572:                        err(1, "invalid IP address \"%s\"", av[1]);
                    573:                if ((route = uroute_create((struct sockaddr *)&dest,
                    574:                    (struct sockaddr *)&gateway,
                    575:                    do_netmask ? (struct sockaddr *)&netmask : NULL)) == NULL)
                    576:                        err(1, "uroute_create");
                    577:                break;
                    578:        case 2:
                    579:                if (strcmp(av[0], "get") != 0) {
                    580:                        fail = 1;
                    581:                        break;
                    582:                }
                    583:                if (!inet_aton(av[1], &dest.sin_addr))
                    584:                        err(1, "invalid IP address \"%s\"", av[1]);
                    585:                break;
                    586:        case 1:
                    587:                if (strcmp(av[0], "list") != 0) {
                    588:                        fail = 1;
                    589:                        break;
                    590:                }
                    591:                // fall through
                    592:        case 0:
                    593:                cmd = 3;
                    594:                break;
                    595:        default:
                    596:                fail = 1;
                    597:                break;
                    598:        }
                    599:        if (fail) {
                    600:                fprintf(stderr, "Usage: uroute <add | delete | get | list>"
                    601:                    " [dest [ gateway [netmask] ]]\n");
                    602:                exit(1);
                    603:        }
                    604: 
                    605:        switch (cmd) {
                    606:        case 0:                         // get
                    607:                if ((route = uroute_get((struct sockaddr *)&dest)) == NULL)
                    608:                        err(1, "uroute_get");
                    609:                uroute_print(route, stdout);
                    610:                printf("\n");
                    611:                uroute_destroy(&route);
                    612:                break;
                    613:        case 1:                         // add
                    614:                if (uroute_add(route) == -1)
                    615:                        err(1, "uroute_add");
                    616:                uroute_destroy(&route);
                    617:                break;
                    618:        case 2:                         // delete
                    619:                if (uroute_delete(route) == -1)
                    620:                        err(1, "uroute_delete");
                    621:                uroute_destroy(&route);
                    622:                break;
                    623:        case 3:                         // list
                    624:            {
                    625:                struct uroute **list;
                    626:                int num;
                    627:                int i;
                    628: 
                    629:                if ((num = uroute_get_all(&list, "main")) == -1)
                    630:                        err(1, "uroute_get_all");
                    631:                for (i = 0; i < num; i++) {
                    632:                        uroute_print(list[i], stdout);
                    633:                        printf("\n");
                    634:                }
                    635:                for (i = 0; i < num; i++)
                    636:                        uroute_destroy(&list[i]);
                    637:                FREE("main", list);
                    638:                break;
                    639:            }
                    640:        default:
                    641:                assert(0);
                    642:        }
                    643: 
                    644:        /* Done */
                    645:        typed_mem_dump(stdout);
                    646:        return (0);
                    647: }
                    648: #endif
                    649: 

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