1 0 stevel /* 2 8485 Peter * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel /* 6 0 stevel * Copyright (c) 1983 Regents of the University of California. 7 0 stevel * All rights reserved. The Berkeley software License Agreement 8 0 stevel * specifies the terms and conditions for redistribution. 9 0 stevel */ 10 0 stevel 11 0 stevel /* 12 0 stevel * Ifparse splits up an ifconfig command line, and was written for use 13 5978 meem * with the networking boot scripts; see $SRC/cmd/svc/shell/net_include.sh 14 0 stevel * 15 0 stevel * Ifparse can extract selected parts of the ifconfig command line, 16 0 stevel * such as failover address configuration ("ifparse -f"), or everything 17 0 stevel * except failover address configuration ("ifparse -s"). By default, 18 0 stevel * all parts of the command line are extracted (equivalent to ("ifparse -fs"). 19 0 stevel * 20 0 stevel * Examples: 21 0 stevel * 22 0 stevel * The command: 23 0 stevel * 24 0 stevel * ifparse inet 1.2.3.4 up group two addif 1.2.3.5 up addif 1.2.3.6 up 25 0 stevel * 26 0 stevel * Produces the following on standard output: 27 0 stevel * 28 0 stevel * set 1.2.3.4 up 29 0 stevel * group two 30 0 stevel * addif 1.2.3.5 up 31 0 stevel * addif 1.2.3.6 up 32 0 stevel * 33 0 stevel * The optional "set" and "destination" keywords are added to make the 34 0 stevel * output easier to process by a script or another command. 35 0 stevel * 36 0 stevel * The command: 37 0 stevel * 38 0 stevel * ifparse -f inet 1.2.3.4 -failover up group two addif 1.2.3.5 up 39 0 stevel * 40 0 stevel * Produces: 41 0 stevel * 42 0 stevel * addif 1.2.3.5 up 43 0 stevel * 44 0 stevel * Only failover address configuration has been requested. Address 45 0 stevel * 1.2.3.4 is a non-failover address, and so isn't output. 46 0 stevel * 47 0 stevel * The "failover" and "-failover" commands can occur several times for 48 0 stevel * a given logical interface. Only the last one counts. For example: 49 0 stevel * 50 0 stevel * ifparse -f inet 1.2.3.4 -failover failover -failover failover up 51 0 stevel * 52 0 stevel * Produces: 53 0 stevel * 54 0 stevel * set 1.2.3.4 -failover failover -failover failover up 55 0 stevel * 56 0 stevel * No attempt is made to clean up such "pathological" command lines, by 57 0 stevel * removing redundant "failover" and "-failover" commands. 58 0 stevel */ 59 0 stevel 60 0 stevel #include <sys/types.h> 61 0 stevel #include <stdlib.h> 62 0 stevel #include <stdio.h> 63 0 stevel #include <string.h> 64 0 stevel #include <assert.h> 65 0 stevel 66 0 stevel /* 67 0 stevel * Parser flags: 68 0 stevel * 69 0 stevel * PARSEFIXED 70 0 stevel * Command should only appear if non-failover commands 71 0 stevel * are requested. 72 0 stevel * PARSEMOVABLE 73 0 stevel * Command should only appear if failover commands are 74 0 stevel * requested. 75 0 stevel * PARSENOW 76 0 stevel * Don't buffer the command, dump it to output immediately. 77 0 stevel * PARSEADD 78 0 stevel * Indicates processing has moved on to additional 79 0 stevel * logical interfaces. 80 0 stevel * Dump the buffer to output and clear buffer contents. 81 0 stevel * PARSESET 82 0 stevel * The "set" and "destination" keywords are optional. 83 0 stevel * This flag indicates that the next address not prefixed 84 0 stevel * with a keyword will be a destination address. 85 0 stevel * PARSELOG0 86 0 stevel * Command not valid on additional logical interfaces. 87 0 stevel */ 88 0 stevel 89 0 stevel #define PARSEFIXED 0x01 90 0 stevel #define PARSEMOVABLE 0x02 91 0 stevel #define PARSENOW 0x04 92 0 stevel #define PARSEADD 0x08 93 0 stevel #define PARSESET 0x10 94 0 stevel #define PARSELOG0 0x20 95 0 stevel 96 0 stevel typedef enum { AF_UNSPEC, AF_INET, AF_INET6, AF_ANY } ac_t; 97 0 stevel 98 5978 meem #define NEXTARG (-1) /* command takes an argument */ 99 5978 meem #define OPTARG (-2) /* command takes an optional argument */ 100 0 stevel 101 0 stevel #define END_OF_TABLE (-1) 102 0 stevel 103 0 stevel /* Parsemode, the type of commands requested by the user. */ 104 0 stevel int parsemode = 0; 105 0 stevel 106 0 stevel /* Parsetype, the type of the command currently in the buffer. */ 107 0 stevel int parsetype = PARSEFIXED | PARSEMOVABLE; 108 0 stevel 109 0 stevel /* Parsebuf, pointer to the buffer. */ 110 0 stevel char *parsebuf = NULL; 111 0 stevel 112 0 stevel /* Parsebuflen, the size of the buffer area. */ 113 0 stevel unsigned parsebuflen = 0; 114 0 stevel 115 0 stevel /* Parsedumplen, the amount of the buffer currently in use. */ 116 0 stevel unsigned parsedumplen = 0; 117 0 stevel 118 0 stevel /* 119 0 stevel * Setaddr, used to decide whether an address without a keyword 120 0 stevel * prefix is a source or destination address. 121 0 stevel */ 122 0 stevel boolean_t setaddr = _B_FALSE; 123 0 stevel 124 0 stevel /* 125 0 stevel * Some ifconfig commands are only valid on the first logical interface. 126 0 stevel * As soon as an "addif" command is seen, "addint" is set. 127 0 stevel */ 128 0 stevel boolean_t addint = _B_FALSE; 129 0 stevel 130 0 stevel /* 131 0 stevel * The parser table is based on that in ifconfig. A command may or 132 5978 meem * may not have an argument, as indicated by whether NEXTARG/OPTARG is 133 5978 meem * in the second column. Some commands can only be used with certain 134 5978 meem * address families, as indicated in the third column. The fourth column 135 0 stevel * contains flags that control parser action. 136 0 stevel * 137 0 stevel * Ifparse buffers logical interface configuration commands such as "set", 138 0 stevel * "netmask" and "broadcast". This buffering continues until an "addif" 139 0 stevel * command is seen, at which point the buffer is emptied, and the process 140 0 stevel * starts again. 141 0 stevel * 142 0 stevel * Some commands do not relate to logical interface configuration and are 143 0 stevel * dumped to output as soon as they are seen, such as "group" and "standby". 144 0 stevel * 145 0 stevel */ 146 0 stevel 147 0 stevel struct cmd { 148 0 stevel char *c_name; 149 0 stevel int c_parameter; /* NEXTARG means next argv */ 150 0 stevel int c_af; /* address family restrictions */ 151 0 stevel int c_parseflags; /* parsing flags */ 152 0 stevel } cmds[] = { 153 0 stevel { "up", 0, AF_ANY, 0 }, 154 0 stevel { "down", 0, AF_ANY, 0 }, 155 0 stevel { "trailers", 0, AF_ANY, PARSENOW }, 156 0 stevel { "-trailers", 0, AF_ANY, PARSENOW }, 157 0 stevel { "arp", 0, AF_INET, PARSENOW }, 158 0 stevel { "-arp", 0, AF_INET, PARSENOW }, 159 0 stevel { "private", 0, AF_ANY, 0 }, 160 0 stevel { "-private", 0, AF_ANY, 0 }, 161 0 stevel { "router", 0, AF_ANY, PARSELOG0 }, 162 0 stevel { "-router", 0, AF_ANY, PARSELOG0 }, 163 0 stevel { "xmit", 0, AF_ANY, 0 }, 164 0 stevel { "-xmit", 0, AF_ANY, 0 }, 165 0 stevel { "-nud", 0, AF_INET6, PARSENOW }, 166 0 stevel { "nud", 0, AF_INET6, PARSENOW }, 167 0 stevel { "anycast", 0, AF_ANY, 0 }, 168 0 stevel { "-anycast", 0, AF_ANY, 0 }, 169 0 stevel { "local", 0, AF_ANY, 0 }, 170 0 stevel { "-local", 0, AF_ANY, 0 }, 171 0 stevel { "deprecated", 0, AF_ANY, 0 }, 172 0 stevel { "-deprecated", 0, AF_ANY, 0 }, 173 0 stevel { "preferred", 0, AF_INET6, 0 }, 174 0 stevel { "-preferred", 0, AF_INET6, 0 }, 175 0 stevel { "debug", 0, AF_ANY, PARSENOW }, 176 0 stevel { "verbose", 0, AF_ANY, PARSENOW }, 177 0 stevel { "netmask", NEXTARG, AF_INET, 0 }, 178 0 stevel { "metric", NEXTARG, AF_ANY, 0 }, 179 0 stevel { "mtu", NEXTARG, AF_ANY, 0 }, 180 0 stevel { "index", NEXTARG, AF_ANY, PARSELOG0 }, 181 0 stevel { "broadcast", NEXTARG, AF_INET, 0 }, 182 0 stevel { "auto-revarp", 0, AF_INET, PARSEFIXED}, 183 0 stevel { "plumb", 0, AF_ANY, PARSENOW }, 184 0 stevel { "unplumb", 0, AF_ANY, PARSENOW }, 185 8485 Peter { "ipmp", 0, AF_ANY, PARSELOG0 }, 186 0 stevel { "subnet", NEXTARG, AF_ANY, 0 }, 187 0 stevel { "token", NEXTARG, AF_INET6, PARSELOG0 }, 188 0 stevel { "tsrc", NEXTARG, AF_ANY, PARSELOG0 }, 189 0 stevel { "tdst", NEXTARG, AF_ANY, PARSELOG0 }, 190 0 stevel { "encr_auth_algs", NEXTARG, AF_ANY, PARSELOG0 }, 191 0 stevel { "encr_algs", NEXTARG, AF_ANY, PARSELOG0 }, 192 0 stevel { "auth_algs", NEXTARG, AF_ANY, PARSELOG0 }, 193 0 stevel { "addif", NEXTARG, AF_ANY, PARSEADD }, 194 0 stevel { "removeif", NEXTARG, AF_ANY, PARSELOG0 }, 195 0 stevel { "modlist", 0, AF_ANY, PARSENOW }, 196 0 stevel { "modinsert", NEXTARG, AF_ANY, PARSENOW }, 197 0 stevel { "modremove", NEXTARG, AF_ANY, PARSENOW }, 198 0 stevel { "failover", 0, AF_ANY, PARSEMOVABLE }, 199 0 stevel { "-failover", 0, AF_ANY, PARSEFIXED }, 200 0 stevel { "standby", 0, AF_ANY, PARSENOW }, 201 0 stevel { "-standby", 0, AF_ANY, PARSENOW }, 202 0 stevel { "failed", 0, AF_ANY, PARSENOW }, 203 0 stevel { "-failed", 0, AF_ANY, PARSENOW }, 204 0 stevel { "group", NEXTARG, AF_ANY, PARSELOG0 }, 205 0 stevel { "configinfo", 0, AF_ANY, PARSENOW }, 206 0 stevel { "encaplimit", NEXTARG, AF_ANY, PARSELOG0 }, 207 0 stevel { "-encaplimit", 0, AF_ANY, PARSELOG0 }, 208 0 stevel { "thoplimit", NEXTARG, AF_ANY, PARSELOG0 }, 209 0 stevel { "set", NEXTARG, AF_ANY, PARSESET }, 210 0 stevel { "destination", NEXTARG, AF_ANY, 0 }, 211 5978 meem { "zone", NEXTARG, AF_ANY, 0 }, 212 5978 meem { "-zone", 0, AF_ANY, 0 }, 213 5978 meem { "all-zones", 0, AF_ANY, 0 }, 214 5978 meem { "ether", OPTARG, AF_ANY, PARSENOW }, 215 5978 meem { "usesrc", NEXTARG, AF_ANY, PARSENOW }, 216 0 stevel { 0 /* ether addr */, 0, AF_UNSPEC, PARSELOG0 }, 217 0 stevel { 0 /* set */, 0, AF_ANY, PARSESET }, 218 0 stevel { 0 /* destination */, 0, AF_ANY, 0 }, 219 0 stevel { 0, END_OF_TABLE, END_OF_TABLE, END_OF_TABLE}, 220 0 stevel }; 221 0 stevel 222 0 stevel 223 0 stevel /* Known address families */ 224 0 stevel struct afswtch { 225 0 stevel char *af_name; 226 0 stevel short af_af; 227 0 stevel } afs[] = { 228 0 stevel { "inet", AF_INET }, 229 0 stevel { "ether", AF_UNSPEC }, 230 0 stevel { "inet6", AF_INET6 }, 231 0 stevel { 0, 0 } 232 0 stevel }; 233 0 stevel 234 0 stevel /* 235 0 stevel * Append "item" to the buffer. If there isn't enough room in the buffer, 236 0 stevel * expand it. 237 0 stevel */ 238 0 stevel static void 239 0 stevel parse_append_buf(char *item) 240 0 stevel { 241 0 stevel unsigned itemlen; 242 0 stevel unsigned newdumplen; 243 0 stevel 244 0 stevel if (item == NULL) 245 0 stevel return; 246 0 stevel 247 0 stevel itemlen = strlen(item); 248 0 stevel newdumplen = parsedumplen + itemlen; 249 0 stevel 250 0 stevel /* Expand dump buffer as needed */ 251 0 stevel if (parsebuflen < newdumplen) { 252 0 stevel if ((parsebuf = realloc(parsebuf, newdumplen)) == NULL) { 253 0 stevel perror("ifparse"); 254 0 stevel exit(1); 255 0 stevel } 256 0 stevel parsebuflen = newdumplen; 257 0 stevel } 258 0 stevel (void) memcpy(parsebuf + parsedumplen, item, itemlen); 259 0 stevel 260 0 stevel parsedumplen = newdumplen; 261 0 stevel } 262 0 stevel 263 0 stevel /* 264 0 stevel * Dump the buffer to output. 265 0 stevel */ 266 0 stevel static void 267 0 stevel parse_dump_buf(void) 268 0 stevel { 269 0 stevel /* 270 0 stevel * When parsing, a set or addif command, we may be some way into 271 0 stevel * the command before we definitely know it is movable or fixed. 272 0 stevel * If we get to the end of the command, and haven't seen a 273 0 stevel * "failover" or "-failover" flag, the command is movable. 274 0 stevel */ 275 5978 meem if (!((parsemode == PARSEFIXED) && (parsetype & PARSEMOVABLE) != 0) && 276 5978 meem (parsemode & parsetype) != 0 && parsedumplen != 0) { 277 0 stevel unsigned i; 278 0 stevel 279 0 stevel if (parsebuf[parsedumplen] == ' ') 280 0 stevel parsedumplen--; 281 0 stevel 282 0 stevel for (i = 0; i < parsedumplen; i++) 283 0 stevel (void) putchar(parsebuf[i]); 284 0 stevel 285 0 stevel (void) putchar('\n'); 286 0 stevel } 287 0 stevel /* The buffer is kept in case there is more parsing to do */ 288 0 stevel parsedumplen = 0; 289 0 stevel parsetype = PARSEFIXED | PARSEMOVABLE; 290 0 stevel } 291 0 stevel 292 0 stevel /* 293 0 stevel * Process a command. The command will either be put in the buffer, 294 0 stevel * or dumped directly to output. The current contents of the buffer 295 0 stevel * may be dumped to output. 296 0 stevel * 297 0 stevel * The buffer holds commands relating to a particular logical interface. 298 0 stevel * For example, "set", "destination", "failover", "broadcast", all relate 299 0 stevel * to a particular interface. Such commands have to be buffered until 300 0 stevel * all the "failover" and "-failover" commands for that interface have 301 0 stevel * been seen, only then will we know whether the command is movable 302 0 stevel * or not. When the "addif" command is seen, we know we are about to 303 0 stevel * start processing a new logical interface, we've seen all the 304 0 stevel * "failover" and "-failover" commands for the previous interface, and 305 0 stevel * can decide whether the buffer contents are movable or not. 306 0 stevel * 307 0 stevel */ 308 0 stevel static void 309 0 stevel parsedump(char *cmd, int param, int flags, char *arg) 310 0 stevel { 311 0 stevel char *cmdname; /* Command name */ 312 0 stevel char *cmdarg; /* Argument to command, if it takes one, or NULL */ 313 0 stevel 314 0 stevel /* 315 0 stevel * Is command only valid on logical interface 0? 316 0 stevel * If processing commands on an additional logical interface, ignore 317 0 stevel * the command. 318 0 stevel * If processing commands on logical interface 0, don't buffer the 319 0 stevel * command, dump it straight to output. 320 0 stevel */ 321 0 stevel if ((flags & PARSELOG0) != 0) { 322 0 stevel if (addint) 323 0 stevel return; 324 0 stevel flags |= PARSENOW; 325 0 stevel } 326 0 stevel 327 0 stevel /* 328 0 stevel * If processing the "addif" command, a destination address may 329 0 stevel * follow without the "destination" prefix. Add PARSESET to the 330 0 stevel * flags so that such an anonymous address is processed correctly. 331 0 stevel */ 332 0 stevel if ((flags & PARSEADD) != 0) { 333 0 stevel flags |= PARSESET; 334 0 stevel addint = _B_TRUE; 335 0 stevel } 336 0 stevel 337 0 stevel /* 338 0 stevel * Commands that must be dumped straight to output are always fixed 339 0 stevel * (non-movable) commands. 340 0 stevel * 341 0 stevel */ 342 0 stevel if ((flags & PARSENOW) != 0) 343 0 stevel flags |= PARSEFIXED; 344 0 stevel 345 0 stevel /* 346 0 stevel * Source and destination addresses do not have to be prefixed 347 0 stevel * with the keywords "set" or "destination". Ifparse always 348 0 stevel * inserts the optional keyword. 349 0 stevel */ 350 0 stevel if (cmd == NULL) { 351 0 stevel cmdarg = arg; 352 0 stevel if ((flags & PARSESET) != 0) 353 0 stevel cmdname = "set"; 354 0 stevel else if (setaddr) { 355 0 stevel cmdname = "destination"; 356 0 stevel setaddr = _B_FALSE; 357 0 stevel } else 358 0 stevel cmdname = ""; 359 0 stevel } else { 360 5978 meem cmdarg = (param == 0) ? NULL : arg; 361 0 stevel cmdname = cmd; 362 0 stevel } 363 0 stevel 364 0 stevel /* 365 0 stevel * The next address without a prefix will be a destination 366 0 stevel * address. 367 0 stevel */ 368 0 stevel if ((flags & PARSESET) != 0) 369 0 stevel setaddr = _B_TRUE; 370 0 stevel 371 0 stevel /* 372 0 stevel * Dump the command straight to output? 373 0 stevel * Only dump the command if the parse mode specified on 374 0 stevel * the command line matches the type of the command. 375 0 stevel */ 376 0 stevel if ((flags & PARSENOW) != 0) { 377 0 stevel if ((parsemode & flags) != 0) { 378 0 stevel (void) fputs(cmdname, stdout); 379 0 stevel if (cmdarg != NULL) { 380 0 stevel (void) fputc(' ', stdout); 381 0 stevel (void) fputs(cmdarg, stdout); 382 0 stevel } 383 0 stevel (void) fputc('\n', stdout); 384 0 stevel } 385 0 stevel return; 386 0 stevel } 387 0 stevel 388 0 stevel /* 389 0 stevel * Only the commands relating to a particular logical interface 390 0 stevel * are buffered. When an "addif" command is seen, processing is 391 0 stevel * about to start on a new logical interface, so dump the 392 0 stevel * buffer to output. 393 0 stevel */ 394 0 stevel if ((flags & PARSEADD) != 0) 395 0 stevel parse_dump_buf(); 396 0 stevel 397 0 stevel /* 398 0 stevel * If the command flags indicate the command is fixed or 399 0 stevel * movable, update the type of the interface in the buffer 400 0 stevel * accordingly. For example, "-failover" has the "PARSEFIXED" 401 0 stevel * flag, and the contents of the buffer are not movable if 402 0 stevel * "-failover" is seen. 403 0 stevel */ 404 0 stevel if ((flags & PARSEFIXED) != 0) 405 0 stevel parsetype &= ~PARSEMOVABLE; 406 0 stevel 407 0 stevel if ((flags & PARSEMOVABLE) != 0) 408 0 stevel parsetype &= ~PARSEFIXED; 409 0 stevel 410 0 stevel parsetype |= flags & (PARSEFIXED | PARSEMOVABLE); 411 0 stevel 412 0 stevel parse_append_buf(cmdname); 413 0 stevel 414 0 stevel if (cmdarg != NULL) { 415 0 stevel parse_append_buf(" "); 416 0 stevel parse_append_buf(cmdarg); 417 0 stevel } 418 0 stevel 419 0 stevel parse_append_buf(" "); 420 0 stevel } 421 0 stevel 422 0 stevel /* 423 0 stevel * Parse the part of the command line following the address family 424 0 stevel * specification, if any. 425 0 stevel * 426 0 stevel * This function is a modified version of the function "ifconfig" in 427 0 stevel * ifconfig.c. 428 0 stevel */ 429 0 stevel static int 430 0 stevel ifparse(int argc, char *argv[], struct afswtch *afp) 431 0 stevel { 432 5978 meem int af = afp->af_af; 433 0 stevel 434 5978 meem if (argc == 0) 435 0 stevel return (0); 436 0 stevel 437 0 stevel if (strcmp(*argv, "auto-dhcp") == 0 || strcmp(*argv, "dhcp") == 0) { 438 5978 meem if ((parsemode & PARSEFIXED) != NULL) { 439 5978 meem while (argc) { 440 5978 meem (void) fputs(*argv++, stdout); 441 5978 meem if (--argc != 0) 442 5978 meem (void) fputc(' ', stdout); 443 5978 meem else 444 5978 meem (void) fputc('\n', stdout); 445 0 stevel } 446 0 stevel } 447 5978 meem return (0); 448 0 stevel } 449 0 stevel 450 0 stevel while (argc > 0) { 451 0 stevel struct cmd *p; 452 0 stevel boolean_t found_cmd; 453 0 stevel 454 0 stevel found_cmd = _B_FALSE; 455 0 stevel for (p = cmds; ; p++) { 456 0 stevel assert(p->c_parseflags != END_OF_TABLE); 457 0 stevel if (p->c_name) { 458 0 stevel if (strcmp(*argv, p->c_name) == 0) { 459 0 stevel /* 460 0 stevel * indicate that the command was 461 0 stevel * found and check to see if 462 0 stevel * the address family is valid 463 0 stevel */ 464 0 stevel found_cmd = _B_TRUE; 465 0 stevel if (p->c_af == AF_ANY || 466 0 stevel af == p->c_af) 467 0 stevel break; 468 0 stevel } 469 0 stevel } else { 470 0 stevel if (p->c_af == AF_ANY || 471 0 stevel af == p->c_af) 472 0 stevel break; 473 0 stevel } 474 0 stevel } 475 0 stevel assert(p->c_parseflags != END_OF_TABLE); 476 0 stevel /* 477 0 stevel * If we found the keyword, but the address family 478 0 stevel * did not match spit out an error 479 0 stevel */ 480 0 stevel if (found_cmd && p->c_name == 0) { 481 0 stevel (void) fprintf(stderr, "ifparse: Operation %s not" 482 0 stevel " supported for %s\n", *argv, afp->af_name); 483 0 stevel return (1); 484 0 stevel } 485 0 stevel /* 486 0 stevel * else (no keyword found), we assume it's an address 487 0 stevel * of some sort 488 0 stevel */ 489 0 stevel if (p->c_name == 0 && setaddr) { 490 0 stevel p++; /* got src, do dst */ 491 0 stevel assert(p->c_parseflags != END_OF_TABLE); 492 0 stevel } 493 5978 meem 494 5978 meem if (p->c_parameter == NEXTARG || p->c_parameter == OPTARG) { 495 0 stevel argc--, argv++; 496 5978 meem if (argc == 0 && p->c_parameter == NEXTARG) { 497 0 stevel (void) fprintf(stderr, 498 0 stevel "ifparse: no argument for %s\n", 499 0 stevel p->c_name); 500 0 stevel return (1); 501 0 stevel } 502 0 stevel } 503 5978 meem 504 0 stevel /* 505 0 stevel * Dump the command if: 506 0 stevel * 507 0 stevel * there's no address family 508 0 stevel * restriction 509 0 stevel * OR 510 0 stevel * there is a restriction AND 511 0 stevel * the address families match 512 0 stevel */ 513 0 stevel if ((p->c_af == AF_ANY) || (af == p->c_af)) 514 5978 meem parsedump(p->c_name, p->c_parameter, p->c_parseflags, 515 5978 meem *argv); 516 0 stevel argc--, argv++; 517 0 stevel } 518 0 stevel parse_dump_buf(); 519 0 stevel 520 0 stevel return (0); 521 0 stevel } 522 0 stevel 523 0 stevel /* 524 0 stevel * Print command usage on standard error. 525 0 stevel */ 526 0 stevel static void 527 0 stevel usage(void) 528 0 stevel { 529 0 stevel (void) fprintf(stderr, 530 5978 meem "usage: ifparse [ -fs ] <addr_family> <commands>\n"); 531 0 stevel } 532 0 stevel 533 0 stevel int 534 0 stevel main(int argc, char *argv[]) 535 0 stevel { 536 0 stevel int c; 537 0 stevel struct afswtch *afp; 538 0 stevel 539 0 stevel while ((c = getopt(argc, argv, "fs")) != -1) { 540 0 stevel switch ((char)c) { 541 0 stevel case 'f': 542 0 stevel parsemode |= PARSEMOVABLE; 543 0 stevel break; 544 0 stevel case 's': 545 0 stevel parsemode |= PARSEFIXED; 546 0 stevel break; 547 0 stevel case '?': 548 0 stevel usage(); 549 0 stevel exit(1); 550 0 stevel } 551 0 stevel } 552 0 stevel 553 0 stevel if (parsemode == 0) 554 0 stevel parsemode = PARSEFIXED | PARSEMOVABLE; 555 0 stevel 556 0 stevel argc -= optind; 557 0 stevel argv += optind; 558 0 stevel 559 0 stevel afp = afs; 560 0 stevel if (argc > 0) { 561 0 stevel struct afswtch *aftp; 562 0 stevel for (aftp = afs; aftp->af_name; aftp++) { 563 0 stevel if (strcmp(aftp->af_name, *argv) == 0) { 564 0 stevel argc--; argv++; 565 0 stevel afp = aftp; 566 0 stevel break; 567 0 stevel } 568 0 stevel } 569 0 stevel } 570 0 stevel 571 0 stevel return (ifparse(argc, argv, afp)); 572 0 stevel } 573