Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/networking/libiproute/iptunnel.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- 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: */ 1 2 /* 2 3 * iptunnel.c "ip tunnel" … … 14 15 */ 15 16 16 #include "libbb.h"17 #include <sys/socket.h>18 #include <sys/ioctl.h>19 20 #include <string.h>21 #include <unistd.h>22 23 17 #include <netinet/ip.h> 24 25 18 #include <net/if.h> 26 19 #include <net/if_arp.h> 27 28 20 #include <asm/types.h> 29 21 #ifndef __constant_htons … … 32 24 #include <linux/if_tunnel.h> 33 25 26 #include "ip_common.h" /* #include "libbb.h" is inside */ 34 27 #include "rt_names.h" 35 28 #include "utils.h" 36 #include "ip_common.h" 37 38 29 30 31 /* Dies on error */ 39 32 static int do_ioctl_get_ifindex(char *dev) 40 33 { … … 42 35 int fd; 43 36 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); 50 40 close(fd); 51 41 return ifr.ifr_ifindex; … … 53 43 54 44 static 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)88 45 { 89 46 struct ifreq ifr; … … 91 48 int err; 92 49 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); 100 53 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 57 static char *do_ioctl_get_ifname(int idx) 105 58 { 106 59 struct ifreq ifr; … … 108 61 int err; 109 62 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); 121 66 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 70 static int do_get_ioctl(const char *basedev, struct ip_tunnel_parm *p) 126 71 { 127 72 struct ifreq ifr; … … 129 74 int err; 130 75 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)); 136 77 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); 142 80 close(fd); 143 81 return err; 144 82 } 145 83 146 static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) 147 { 84 /* Dies on error, otherwise returns 0 */ 85 static 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 */ 111 static 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 */ 129 static 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 }; 148 146 int count = 0; 149 147 char medium[IFNAMSIZ]; 148 int key; 149 150 150 memset(p, 0, sizeof(*p)); 151 151 memset(&medium, 0, sizeof(medium)); … … 154 154 p->iph.ihl = 5; 155 155 #ifndef IP_DF 156 #define IP_DF 0x4000 /* Flag: "Don't Fragment"*/156 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ 157 157 #endif 158 158 p->iph.frag_off = htons(IP_DF); 159 159 160 160 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) { 165 167 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"); 168 169 } 169 170 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) { 172 173 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"); 175 175 } 176 176 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) { 179 179 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"); 182 181 } 183 182 p->iph.protocol = IPPROTO_IPV6; 184 183 } 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) { 189 187 unsigned uval; 190 188 NEXT_ARG(); … … 195 193 else { 196 194 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\""); 199 196 } 200 197 p->i_key = p->o_key = htonl(uval); 201 198 } 202 } else if ( strcmp(*argv, "ikey") == 0) {199 } else if (key == ARG_ikey) { 203 200 unsigned uval; 204 201 NEXT_ARG(); … … 208 205 else { 209 206 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\""); 212 208 } 213 209 p->i_key = htonl(uval); 214 210 } 215 } else if ( strcmp(*argv, "okey") == 0) {211 } else if (key == ARG_okey) { 216 212 unsigned uval; 217 213 NEXT_ARG(); … … 221 217 else { 222 218 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\""); 225 220 } 226 221 p->o_key = htonl(uval); 227 222 } 228 } else if ( strcmp(*argv, "seq") == 0) {223 } else if (key == ARG_seq) { 229 224 p->i_flags |= GRE_SEQ; 230 225 p->o_flags |= GRE_SEQ; 231 } else if ( strcmp(*argv, "iseq") == 0) {226 } else if (key == ARG_iseq) { 232 227 p->i_flags |= GRE_SEQ; 233 } else if ( strcmp(*argv, "oseq") == 0) {228 } else if (key == ARG_oseq) { 234 229 p->o_flags |= GRE_SEQ; 235 } else if ( strcmp(*argv, "csum") == 0) {230 } else if (key == ARG_csum) { 236 231 p->i_flags |= GRE_CSUM; 237 232 p->o_flags |= GRE_CSUM; 238 } else if ( strcmp(*argv, "icsum") == 0) {233 } else if (key == ARG_icsum) { 239 234 p->i_flags |= GRE_CSUM; 240 } else if ( strcmp(*argv, "ocsum") == 0) {235 } else if (key == ARG_ocsum) { 241 236 p->o_flags |= GRE_CSUM; 242 } else if ( strcmp(*argv, "nopmtudisc") == 0) {237 } else if (key == ARG_nopmtudisc) { 243 238 p->iph.frag_off = 0; 244 } else if ( strcmp(*argv, "pmtudisc") == 0) {239 } else if (key == ARG_pmtudisc) { 245 240 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) 249 245 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) 253 250 p->iph.saddr = get_addr32(*argv); 254 } else if ( strcmp(*argv, "dev") == 0) {251 } else if (key == ARG_dev) { 255 252 NEXT_ARG(); 256 253 strncpy(medium, *argv, IFNAMSIZ-1); 257 } else if ( strcmp(*argv, "ttl") == 0) {254 } else if (key == ARG_ttl) { 258 255 unsigned uval; 259 256 NEXT_ARG(); 260 if (strcmp(*argv, "inherit") != 0) { 257 key = index_in_strings(keywords, *argv); 258 if (key != ARG_inherit) { 261 259 if (get_unsigned(&uval, *argv, 0)) 262 260 invarg(*argv, "TTL"); … … 265 263 p->iph.ttl = uval; 266 264 } 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) { 272 271 if (rtnl_dsfield_a2n(&uval, *argv)) 273 272 invarg(*argv, "TOS"); … … 276 275 p->iph.tos = 1; 277 276 } else { 278 if ( strcmp(*argv, "name") == 0) {277 if (key == ARG_name) { 279 278 NEXT_ARG(); 280 279 } … … 286 285 memset(&old_p, 0, sizeof(old_p)); 287 286 if (do_get_ioctl(*argv, &old_p)) 288 return -1;287 exit(1); 289 288 *p = old_p; 290 289 } 291 290 } 292 291 count++; 293 argc--; argv++;294 }295 292 argc--; 293 argv++; 294 } 296 295 297 296 if (p->iph.protocol == 0) { … … 306 305 if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { 307 306 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"); 310 308 } 311 309 } … … 313 311 if (medium[0]) { 314 312 p->link = do_ioctl_get_ifindex(medium); 315 if (p->link == 0)316 return -1;317 313 } 318 314 … … 326 322 } 327 323 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 */ 335 330 static int do_add(int cmd, int argc, char **argv) 336 331 { 337 332 struct ip_tunnel_parm p; 338 333 339 if (parse_args(argc, argv, cmd, &p) < 0) 340 return -1; 334 parse_args(argc, argv, cmd, &p); 341 335 342 336 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"); 345 338 } 346 339 … … 353 346 return do_add_ioctl(cmd, "sit0", &p); 354 347 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 */ 361 353 static int do_del(int argc, char **argv) 362 354 { 363 355 struct ip_tunnel_parm p; 364 356 365 if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0) 366 return -1; 357 parse_args(argc, argv, SIOCDELTUNNEL, &p); 367 358 368 359 switch (p.iph.protocol) { … … 376 367 return do_del_ioctl(p.name, &p); 377 368 } 378 return -1;379 369 } 380 370 … … 399 389 if (p->link) { 400 390 char *n = do_ioctl_get_ifname(p->link); 401 if (n) 391 if (n) { 402 392 printf(" dev %s ", n); 393 free(n); 394 } 403 395 } 404 396 if (p->iph.ttl) … … 409 401 SPRINT_BUF(b1); 410 402 printf(" tos"); 411 if (p->iph.tos &1)403 if (p->iph.tos & 1) 412 404 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))) 418 410 printf(" nopmtudisc"); 419 411 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) 421 413 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) 424 416 printf(" ikey %s ", s3); 425 if (p->o_flags &GRE_KEY)417 if (p->o_flags & GRE_KEY) 426 418 printf(" okey %s ", s4); 427 419 } 428 420 429 if (p->i_flags &GRE_SEQ)430 printf("% sDrop packets out of sequence.\n", _SL_);431 if (p->i_flags &GRE_CSUM)432 printf("% sChecksum in received packet is required.", _SL_);433 if (p->o_flags &GRE_SEQ)434 printf("% sSequence packets on output.", _SL_);435 if (p->o_flags &GRE_CSUM)436 printf("% sChecksum output packets.", _SL_);437 } 438 439 static intdo_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 431 static void do_tunnels_list(struct ip_tunnel_parm *p) 440 432 { 441 433 char name[IFNAMSIZ]; 442 unsigned long 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; 446 438 int type; 447 439 struct ip_tunnel_parm p1; 448 449 440 char buf[512]; 450 FILE *fp = fopen("/proc/net/dev", "r"); 441 FILE *fp = fopen_or_warn("/proc/net/dev", "r"); 442 451 443 if (fp == NULL) { 452 perror("fopen"); 453 return -1; 444 return; 454 445 } 455 446 … … 459 450 while (fgets(buf, sizeof(buf), fp) != NULL) { 460 451 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 || 463 456 (*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; 466 459 } 467 460 if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu", … … 475 468 type = do_ioctl_get_iftype(name); 476 469 if (type == -1) { 477 bb_error_msg(" Failed toget type of [%s]", name);470 bb_error_msg("cannot get type of [%s]", name); 478 471 continue; 479 472 } … … 490 483 continue; 491 484 print_tunnel(&p1); 492 p rintf("\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 */ 497 490 static int do_show(int argc, char **argv) 498 491 { … … 500 493 struct ip_tunnel_parm p; 501 494 502 if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0) 503 return -1; 495 parse_args(argc, argv, SIOCGETTUNNEL, &p); 504 496 505 497 switch (p.iph.protocol) { … … 521 513 522 514 print_tunnel(&p); 523 p rintf("\n");515 puts(""); 524 516 return 0; 525 517 } 526 518 519 /* Return value becomes exitcode. It's okay to not return at all */ 527 520 int do_iptunnel(int argc, char **argv) 528 521 { 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.