Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (17 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/networking/libiproute/iptunnel.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * iptunnel.c          "ip tunnel"
     
    1415 */
    1516
    16 #include "libbb.h"
    17 #include <sys/socket.h>
    18 #include <sys/ioctl.h>
    19 
    20 #include <string.h>
    21 #include <unistd.h>
    22 
    2317#include <netinet/ip.h>
    24 
    2518#include <net/if.h>
    2619#include <net/if_arp.h>
    27 
    2820#include <asm/types.h>
    2921#ifndef __constant_htons
     
    3224#include <linux/if_tunnel.h>
    3325
     26#include "ip_common.h"  /* #include "libbb.h" is inside */
    3427#include "rt_names.h"
    3528#include "utils.h"
    36 #include "ip_common.h"
    37 
    38 
     29
     30
     31/* Dies on error */
    3932static int do_ioctl_get_ifindex(char *dev)
    4033{
     
    4235    int fd;
    4336
    44     strcpy(ifr.ifr_name, dev);
    45     fd = socket(AF_INET, SOCK_DGRAM, 0);
    46     if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
    47         bb_perror_msg("ioctl");
    48         return 0;
    49     }
     37    strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
     38    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     39    xioctl(fd, SIOCGIFINDEX, &ifr);
    5040    close(fd);
    5141    return ifr.ifr_ifindex;
     
    5343
    5444static int do_ioctl_get_iftype(char *dev)
    55 {
    56     struct ifreq ifr;
    57     int fd;
    58 
    59     strcpy(ifr.ifr_name, dev);
    60     fd = socket(AF_INET, SOCK_DGRAM, 0);
    61     if (ioctl(fd, SIOCGIFHWADDR, &ifr)) {
    62         bb_perror_msg("ioctl");
    63         return -1;
    64     }
    65     close(fd);
    66     return ifr.ifr_addr.sa_family;
    67 }
    68 
    69 
    70 static char *do_ioctl_get_ifname(int idx)
    71 {
    72     static struct ifreq ifr;
    73     int fd;
    74 
    75     ifr.ifr_ifindex = idx;
    76     fd = socket(AF_INET, SOCK_DGRAM, 0);
    77     if (ioctl(fd, SIOCGIFNAME, &ifr)) {
    78         bb_perror_msg("ioctl");
    79         return NULL;
    80     }
    81     close(fd);
    82     return ifr.ifr_name;
    83 }
    84 
    85 
    86 
    87 static int do_get_ioctl(char *basedev, struct ip_tunnel_parm *p)
    8845{
    8946    struct ifreq ifr;
     
    9148    int err;
    9249
    93     strcpy(ifr.ifr_name, basedev);
    94     ifr.ifr_ifru.ifru_data = (void*)p;
    95     fd = socket(AF_INET, SOCK_DGRAM, 0);
    96     err = ioctl(fd, SIOCGETTUNNEL, &ifr);
    97     if (err) {
    98         bb_perror_msg("ioctl");
    99     }
     50    strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
     51    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     52    err = ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr);
    10053    close(fd);
    101     return err;
    102 }
    103 
    104 static int do_add_ioctl(int cmd, char *basedev, struct ip_tunnel_parm *p)
     54    return err ? -1 : ifr.ifr_addr.sa_family;
     55}
     56
     57static char *do_ioctl_get_ifname(int idx)
    10558{
    10659    struct ifreq ifr;
     
    10861    int err;
    10962
    110     if (cmd == SIOCCHGTUNNEL && p->name[0]) {
    111         strcpy(ifr.ifr_name, p->name);
    112     } else {
    113         strcpy(ifr.ifr_name, basedev);
    114     }
    115     ifr.ifr_ifru.ifru_data = (void*)p;
    116     fd = socket(AF_INET, SOCK_DGRAM, 0);
    117     err = ioctl(fd, cmd, &ifr);
    118     if (err) {
    119         bb_perror_msg("ioctl");
    120     }
     63    ifr.ifr_ifindex = idx;
     64    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     65    err = ioctl_or_warn(fd, SIOCGIFNAME, &ifr);
    12166    close(fd);
    122     return err;
    123 }
    124 
    125 static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p)
     67    return err ? NULL : xstrndup(ifr.ifr_name, sizeof(ifr.ifr_name));
     68}
     69
     70static int do_get_ioctl(const char *basedev, struct ip_tunnel_parm *p)
    12671{
    12772    struct ifreq ifr;
     
    12974    int err;
    13075
    131     if (p->name[0]) {
    132         strcpy(ifr.ifr_name, p->name);
    133     } else {
    134         strcpy(ifr.ifr_name, basedev);
    135     }
     76    strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name));
    13677    ifr.ifr_ifru.ifru_data = (void*)p;
    137     fd = socket(AF_INET, SOCK_DGRAM, 0);
    138     err = ioctl(fd, SIOCDELTUNNEL, &ifr);
    139     if (err) {
    140         bb_perror_msg("ioctl");
    141     }
     78    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     79    err = ioctl_or_warn(fd, SIOCGETTUNNEL, &ifr);
    14280    close(fd);
    14381    return err;
    14482}
    14583
    146 static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
    147 {
     84/* Dies on error, otherwise returns 0 */
     85static int do_add_ioctl(int cmd, const char *basedev, struct ip_tunnel_parm *p)
     86{
     87    struct ifreq ifr;
     88    int fd;
     89
     90    if (cmd == SIOCCHGTUNNEL && p->name[0]) {
     91        strncpy(ifr.ifr_name, p->name, sizeof(ifr.ifr_name));
     92    } else {
     93        strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name));
     94    }
     95    ifr.ifr_ifru.ifru_data = (void*)p;
     96    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     97#if ENABLE_IOCTL_HEX2STR_ERROR
     98    /* #define magic will turn ioctl# into string */
     99    if (cmd == SIOCCHGTUNNEL)
     100        xioctl(fd, SIOCCHGTUNNEL, &ifr);
     101    else
     102        xioctl(fd, SIOCADDTUNNEL, &ifr);
     103#else
     104    xioctl(fd, cmd, &ifr);
     105#endif
     106    close(fd);
     107    return 0;
     108}
     109
     110/* Dies on error, otherwise returns 0 */
     111static int do_del_ioctl(const char *basedev, struct ip_tunnel_parm *p)
     112{
     113    struct ifreq ifr;
     114    int fd;
     115
     116    if (p->name[0]) {
     117        strncpy(ifr.ifr_name, p->name, sizeof(ifr.ifr_name));
     118    } else {
     119        strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name));
     120    }
     121    ifr.ifr_ifru.ifru_data = (void*)p;
     122    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     123    xioctl(fd, SIOCDELTUNNEL, &ifr);
     124    close(fd);
     125    return 0;
     126}
     127
     128/* Dies on error */
     129static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
     130{
     131    static const char keywords[] ALIGN1 =
     132        "mode\0""ipip\0""ip/ip\0""gre\0""gre/ip\0""sit\0""ipv6/ip\0"
     133        "key\0""ikey\0""okey\0""seq\0""iseq\0""oseq\0"
     134        "csum\0""icsum\0""ocsum\0""nopmtudisc\0""pmtudisc\0"
     135        "remote\0""any\0""local\0""dev\0"
     136        "ttl\0""inherit\0""tos\0""dsfield\0"
     137        "name\0";
     138    enum {
     139        ARG_mode, ARG_ipip, ARG_ip_ip, ARG_gre, ARG_gre_ip, ARG_sit, ARG_ip6_ip,
     140        ARG_key, ARG_ikey, ARG_okey, ARG_seq, ARG_iseq, ARG_oseq,
     141        ARG_csum, ARG_icsum, ARG_ocsum, ARG_nopmtudisc, ARG_pmtudisc,
     142        ARG_remote, ARG_any, ARG_local, ARG_dev,
     143        ARG_ttl, ARG_inherit, ARG_tos, ARG_dsfield,
     144        ARG_name
     145    };
    148146    int count = 0;
    149147    char medium[IFNAMSIZ];
     148    int key;
     149
    150150    memset(p, 0, sizeof(*p));
    151151    memset(&medium, 0, sizeof(medium));
     
    154154    p->iph.ihl = 5;
    155155#ifndef IP_DF
    156 #define IP_DF       0x4000      /* Flag: "Don't Fragment"   */
     156#define IP_DF 0x4000  /* Flag: "Don't Fragment" */
    157157#endif
    158158    p->iph.frag_off = htons(IP_DF);
    159159
    160160    while (argc > 0) {
    161         if (strcmp(*argv, "mode") == 0) {
    162             NEXT_ARG();
    163             if (strcmp(*argv, "ipip") == 0 ||
    164                 strcmp(*argv, "ip/ip") == 0) {
     161        key = index_in_strings(keywords, *argv);
     162        if (key == ARG_mode) {
     163            NEXT_ARG();
     164            key = index_in_strings(keywords, *argv);
     165            if (key == ARG_ipip ||
     166                key == ARG_ip_ip) {
    165167                if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
    166                     bb_error_msg("You managed to ask for more than one tunnel mode.");
    167                     exit(-1);
     168                    bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
    168169                }
    169170                p->iph.protocol = IPPROTO_IPIP;
    170             } else if (strcmp(*argv, "gre") == 0 ||
    171                    strcmp(*argv, "gre/ip") == 0) {
     171            } else if (key == ARG_gre ||
     172                   key == ARG_gre_ip) {
    172173                if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) {
    173                     bb_error_msg("You managed to ask for more than one tunnel mode.");
    174                     exit(-1);
     174                    bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
    175175                }
    176176                p->iph.protocol = IPPROTO_GRE;
    177             } else if (strcmp(*argv, "sit") == 0 ||
    178                    strcmp(*argv, "ipv6/ip") == 0) {
     177            } else if (key == ARG_sit ||
     178                   key == ARG_ip6_ip) {
    179179                if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
    180                     bb_error_msg("You managed to ask for more than one tunnel mode.");
    181                     exit(-1);
     180                    bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
    182181                }
    183182                p->iph.protocol = IPPROTO_IPV6;
    184183            } else {
    185                 bb_error_msg("Cannot guess tunnel mode.");
    186                 exit(-1);
    187             }
    188         } else if (strcmp(*argv, "key") == 0) {
     184                bb_error_msg_and_die("cannot guess tunnel mode");
     185            }
     186        } else if (key == ARG_key) {
    189187            unsigned uval;
    190188            NEXT_ARG();
     
    195193            else {
    196194                if (get_unsigned(&uval, *argv, 0)<0) {
    197                     bb_error_msg("invalid value of \"key\"");
    198                     exit(-1);
     195                    bb_error_msg_and_die("invalid value of \"key\"");
    199196                }
    200197                p->i_key = p->o_key = htonl(uval);
    201198            }
    202         } else if (strcmp(*argv, "ikey") == 0) {
     199        } else if (key == ARG_ikey) {
    203200            unsigned uval;
    204201            NEXT_ARG();
     
    208205            else {
    209206                if (get_unsigned(&uval, *argv, 0)<0) {
    210                     bb_error_msg("invalid value of \"ikey\"");
    211                     exit(-1);
     207                    bb_error_msg_and_die("invalid value of \"ikey\"");
    212208                }
    213209                p->i_key = htonl(uval);
    214210            }
    215         } else if (strcmp(*argv, "okey") == 0) {
     211        } else if (key == ARG_okey) {
    216212            unsigned uval;
    217213            NEXT_ARG();
     
    221217            else {
    222218                if (get_unsigned(&uval, *argv, 0)<0) {
    223                     bb_error_msg("invalid value of \"okey\"");
    224                     exit(-1);
     219                    bb_error_msg_and_die("invalid value of \"okey\"");
    225220                }
    226221                p->o_key = htonl(uval);
    227222            }
    228         } else if (strcmp(*argv, "seq") == 0) {
     223        } else if (key == ARG_seq) {
    229224            p->i_flags |= GRE_SEQ;
    230225            p->o_flags |= GRE_SEQ;
    231         } else if (strcmp(*argv, "iseq") == 0) {
     226        } else if (key == ARG_iseq) {
    232227            p->i_flags |= GRE_SEQ;
    233         } else if (strcmp(*argv, "oseq") == 0) {
     228        } else if (key == ARG_oseq) {
    234229            p->o_flags |= GRE_SEQ;
    235         } else if (strcmp(*argv, "csum") == 0) {
     230        } else if (key == ARG_csum) {
    236231            p->i_flags |= GRE_CSUM;
    237232            p->o_flags |= GRE_CSUM;
    238         } else if (strcmp(*argv, "icsum") == 0) {
     233        } else if (key == ARG_icsum) {
    239234            p->i_flags |= GRE_CSUM;
    240         } else if (strcmp(*argv, "ocsum") == 0) {
     235        } else if (key == ARG_ocsum) {
    241236            p->o_flags |= GRE_CSUM;
    242         } else if (strcmp(*argv, "nopmtudisc") == 0) {
     237        } else if (key == ARG_nopmtudisc) {
    243238            p->iph.frag_off = 0;
    244         } else if (strcmp(*argv, "pmtudisc") == 0) {
     239        } else if (key == ARG_pmtudisc) {
    245240            p->iph.frag_off = htons(IP_DF);
    246         } else if (strcmp(*argv, "remote") == 0) {
    247             NEXT_ARG();
    248             if (strcmp(*argv, "any"))
     241        } else if (key == ARG_remote) {
     242            NEXT_ARG();
     243            key = index_in_strings(keywords, *argv);
     244            if (key == ARG_any)
    249245                p->iph.daddr = get_addr32(*argv);
    250         } else if (strcmp(*argv, "local") == 0) {
    251             NEXT_ARG();
    252             if (strcmp(*argv, "any"))
     246        } else if (key == ARG_local) {
     247            NEXT_ARG();
     248            key = index_in_strings(keywords, *argv);
     249            if (key == ARG_any)
    253250                p->iph.saddr = get_addr32(*argv);
    254         } else if (strcmp(*argv, "dev") == 0) {
     251        } else if (key == ARG_dev) {
    255252            NEXT_ARG();
    256253            strncpy(medium, *argv, IFNAMSIZ-1);
    257         } else if (strcmp(*argv, "ttl") == 0) {
     254        } else if (key == ARG_ttl) {
    258255            unsigned uval;
    259256            NEXT_ARG();
    260             if (strcmp(*argv, "inherit") != 0) {
     257            key = index_in_strings(keywords, *argv);
     258            if (key != ARG_inherit) {
    261259                if (get_unsigned(&uval, *argv, 0))
    262260                    invarg(*argv, "TTL");
     
    265263                p->iph.ttl = uval;
    266264            }
    267         } else if (strcmp(*argv, "tos") == 0 ||
    268                matches(*argv, "dsfield") == 0) {
    269             __u32 uval;
    270             NEXT_ARG();
    271             if (strcmp(*argv, "inherit") != 0) {
     265        } else if (key == ARG_tos ||
     266               key == ARG_dsfield) {
     267            uint32_t uval;
     268            NEXT_ARG();
     269            key = index_in_strings(keywords, *argv);
     270            if (key != ARG_inherit) {
    272271                if (rtnl_dsfield_a2n(&uval, *argv))
    273272                    invarg(*argv, "TOS");
     
    276275                p->iph.tos = 1;
    277276        } else {
    278             if (strcmp(*argv, "name") == 0) {
     277            if (key == ARG_name) {
    279278                NEXT_ARG();
    280279            }
     
    286285                memset(&old_p, 0, sizeof(old_p));
    287286                if (do_get_ioctl(*argv, &old_p))
    288                     return -1;
     287                    exit(1);
    289288                *p = old_p;
    290289            }
    291290        }
    292291        count++;
    293         argc--; argv++;
    294     }
    295 
     292        argc--;
     293        argv++;
     294    }
    296295
    297296    if (p->iph.protocol == 0) {
     
    306305    if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) {
    307306        if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) {
    308             bb_error_msg("Keys are not allowed with ipip and sit.");
    309             return -1;
     307            bb_error_msg_and_die("keys are not allowed with ipip and sit");
    310308        }
    311309    }
     
    313311    if (medium[0]) {
    314312        p->link = do_ioctl_get_ifindex(medium);
    315         if (p->link == 0)
    316             return -1;
    317313    }
    318314
     
    326322    }
    327323    if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) {
    328         bb_error_msg("Broadcast tunnel requires a source address.");
    329         return -1;
    330     }
    331     return 0;
    332 }
    333 
    334 
     324        bb_error_msg_and_die("broadcast tunnel requires a source address");
     325    }
     326}
     327
     328
     329/* Return value becomes exitcode. It's okay to not return at all */
    335330static int do_add(int cmd, int argc, char **argv)
    336331{
    337332    struct ip_tunnel_parm p;
    338333
    339     if (parse_args(argc, argv, cmd, &p) < 0)
    340         return -1;
     334    parse_args(argc, argv, cmd, &p);
    341335
    342336    if (p.iph.ttl && p.iph.frag_off == 0) {
    343         bb_error_msg("ttl != 0 and noptmudisc are incompatible");
    344         return -1;
     337        bb_error_msg_and_die("ttl != 0 and noptmudisc are incompatible");
    345338    }
    346339
     
    353346        return do_add_ioctl(cmd, "sit0", &p);
    354347    default:
    355         bb_error_msg("cannot determine tunnel mode (ipip, gre or sit)");
    356         return -1;
    357     }
    358     return -1;
    359 }
    360 
     348        bb_error_msg_and_die("cannot determine tunnel mode (ipip, gre or sit)");
     349    }
     350}
     351
     352/* Return value becomes exitcode. It's okay to not return at all */
    361353static int do_del(int argc, char **argv)
    362354{
    363355    struct ip_tunnel_parm p;
    364356
    365     if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0)
    366         return -1;
     357    parse_args(argc, argv, SIOCDELTUNNEL, &p);
    367358
    368359    switch (p.iph.protocol) {
     
    376367        return do_del_ioctl(p.name, &p);
    377368    }
    378     return -1;
    379369}
    380370
     
    399389    if (p->link) {
    400390        char *n = do_ioctl_get_ifname(p->link);
    401         if (n)
     391        if (n) {
    402392            printf(" dev %s ", n);
     393            free(n);
     394        }
    403395    }
    404396    if (p->iph.ttl)
     
    409401        SPRINT_BUF(b1);
    410402        printf(" tos");
    411         if (p->iph.tos&1)
     403        if (p->iph.tos & 1)
    412404            printf(" inherit");
    413         if (p->iph.tos&~1)
    414             printf("%c%s ", p->iph.tos&1 ? '/' : ' ',
    415                    rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1)));
    416     }
    417     if (!(p->iph.frag_off&htons(IP_DF)))
     405        if (p->iph.tos & ~1)
     406            printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
     407                   rtnl_dsfield_n2a(p->iph.tos & ~1, b1, sizeof(b1)));
     408    }
     409    if (!(p->iph.frag_off & htons(IP_DF)))
    418410        printf(" nopmtudisc");
    419411
    420     if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
     412    if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
    421413        printf(" key %s", s3);
    422     else if ((p->i_flags|p->o_flags)&GRE_KEY) {
    423         if (p->i_flags&GRE_KEY)
     414    else if ((p->i_flags | p->o_flags) & GRE_KEY) {
     415        if (p->i_flags & GRE_KEY)
    424416            printf(" ikey %s ", s3);
    425         if (p->o_flags&GRE_KEY)
     417        if (p->o_flags & GRE_KEY)
    426418            printf(" okey %s ", s4);
    427419    }
    428420
    429     if (p->i_flags&GRE_SEQ)
    430         printf("%s  Drop packets out of sequence.\n", _SL_);
    431     if (p->i_flags&GRE_CSUM)
    432         printf("%s  Checksum in received packet is required.", _SL_);
    433     if (p->o_flags&GRE_SEQ)
    434         printf("%s  Sequence packets on output.", _SL_);
    435     if (p->o_flags&GRE_CSUM)
    436         printf("%s  Checksum output packets.", _SL_);
    437 }
    438 
    439 static int do_tunnels_list(struct ip_tunnel_parm *p)
     421    if (p->i_flags & GRE_SEQ)
     422        printf("%c  Drop packets out of sequence.\n", _SL_);
     423    if (p->i_flags & GRE_CSUM)
     424        printf("%c  Checksum in received packet is required.", _SL_);
     425    if (p->o_flags & GRE_SEQ)
     426        printf("%c  Sequence packets on output.", _SL_);
     427    if (p->o_flags & GRE_CSUM)
     428        printf("%c  Checksum output packets.", _SL_);
     429}
     430
     431static void do_tunnels_list(struct ip_tunnel_parm *p)
    440432{
    441433    char name[IFNAMSIZ];
    442     unsigned long  rx_bytes, rx_packets, rx_errs, rx_drops,
    443     rx_fifo, rx_frame,
    444     tx_bytes, tx_packets, tx_errs, tx_drops,
    445     tx_fifo, tx_colls, tx_carrier, rx_multi;
     434    unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
     435        rx_fifo, rx_frame,
     436        tx_bytes, tx_packets, tx_errs, tx_drops,
     437        tx_fifo, tx_colls, tx_carrier, rx_multi;
    446438    int type;
    447439    struct ip_tunnel_parm p1;
    448 
    449440    char buf[512];
    450     FILE *fp = fopen("/proc/net/dev", "r");
     441    FILE *fp = fopen_or_warn("/proc/net/dev", "r");
     442
    451443    if (fp == NULL) {
    452         perror("fopen");
    453         return -1;
     444        return;
    454445    }
    455446
     
    459450    while (fgets(buf, sizeof(buf), fp) != NULL) {
    460451        char *ptr;
    461         buf[sizeof(buf) - 1] = 0;
    462         if ((ptr = strchr(buf, ':')) == NULL ||
     452
     453        /*buf[sizeof(buf) - 1] = 0; - fgets is safe anyway */
     454        ptr = strchr(buf, ':');
     455        if (ptr == NULL ||
    463456            (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
    464             bb_error_msg("Wrong format of /proc/net/dev. Sorry.");
    465             return -1;
     457            bb_error_msg("wrong format of /proc/net/dev");
     458            return;
    466459        }
    467460        if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
     
    475468        type = do_ioctl_get_iftype(name);
    476469        if (type == -1) {
    477             bb_error_msg("Failed to get type of [%s]", name);
     470            bb_error_msg("cannot get type of [%s]", name);
    478471            continue;
    479472        }
     
    490483            continue;
    491484        print_tunnel(&p1);
    492         printf("\n");
    493     }
    494     return 0;
    495 }
    496 
     485        puts("");
     486    }
     487}
     488
     489/* Return value becomes exitcode. It's okay to not return at all */
    497490static int do_show(int argc, char **argv)
    498491{
     
    500493    struct ip_tunnel_parm p;
    501494
    502     if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
    503         return -1;
     495    parse_args(argc, argv, SIOCGETTUNNEL, &p);
    504496
    505497    switch (p.iph.protocol) {
     
    521513
    522514    print_tunnel(&p);
    523     printf("\n");
     515    puts("");
    524516    return 0;
    525517}
    526518
     519/* Return value becomes exitcode. It's okay to not return at all */
    527520int do_iptunnel(int argc, char **argv)
    528521{
    529     if (argc > 0) {
    530         if (matches(*argv, "add") == 0)
    531             return do_add(SIOCADDTUNNEL, argc-1, argv+1);
    532         if (matches(*argv, "change") == 0)
    533             return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
    534         if (matches(*argv, "del") == 0)
    535             return do_del(argc-1, argv+1);
    536         if (matches(*argv, "show") == 0 ||
    537             matches(*argv, "lst") == 0 ||
    538             matches(*argv, "list") == 0)
    539             return do_show(argc-1, argv+1);
    540     } else
    541         return do_show(0, NULL);
    542 
    543     bb_error_msg("Command \"%s\" is unknown.", *argv);
    544     exit(-1);
    545 }
     522    static const char keywords[] ALIGN1 =
     523        "add\0""change\0""delete\0""show\0""list\0""lst\0";
     524    enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst };
     525    int key;
     526
     527    if (argc) {
     528        key = index_in_substrings(keywords, *argv);
     529        if (key < 0)
     530            bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     531        --argc;
     532        ++argv;
     533        if (key == ARG_add)
     534            return do_add(SIOCADDTUNNEL, argc, argv);
     535        if (key == ARG_change)
     536            return do_add(SIOCCHGTUNNEL, argc, argv);
     537        if (key == ARG_del)
     538            return do_del(argc, argv);
     539    }
     540    return do_show(argc, argv);
     541}
Note: See TracChangeset for help on using the changeset viewer.