Annotation of embedaddon/libpdel/net/uroute.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 <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>