17c478bd9Sstevel@tonic-gate /* 2*e11c3f44Smeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate /* 67c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 77c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 87c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 97c478bd9Sstevel@tonic-gate */ 107c478bd9Sstevel@tonic-gate 117c478bd9Sstevel@tonic-gate /* 127c478bd9Sstevel@tonic-gate * Ifparse splits up an ifconfig command line, and was written for use 13f7d61273Smeem * with the networking boot scripts; see $SRC/cmd/svc/shell/net_include.sh 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * Ifparse can extract selected parts of the ifconfig command line, 167c478bd9Sstevel@tonic-gate * such as failover address configuration ("ifparse -f"), or everything 177c478bd9Sstevel@tonic-gate * except failover address configuration ("ifparse -s"). By default, 187c478bd9Sstevel@tonic-gate * all parts of the command line are extracted (equivalent to ("ifparse -fs"). 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * Examples: 217c478bd9Sstevel@tonic-gate * 227c478bd9Sstevel@tonic-gate * The command: 237c478bd9Sstevel@tonic-gate * 247c478bd9Sstevel@tonic-gate * ifparse inet 1.2.3.4 up group two addif 1.2.3.5 up addif 1.2.3.6 up 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Produces the following on standard output: 277c478bd9Sstevel@tonic-gate * 287c478bd9Sstevel@tonic-gate * set 1.2.3.4 up 297c478bd9Sstevel@tonic-gate * group two 307c478bd9Sstevel@tonic-gate * addif 1.2.3.5 up 317c478bd9Sstevel@tonic-gate * addif 1.2.3.6 up 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * The optional "set" and "destination" keywords are added to make the 347c478bd9Sstevel@tonic-gate * output easier to process by a script or another command. 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * The command: 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * ifparse -f inet 1.2.3.4 -failover up group two addif 1.2.3.5 up 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate * Produces: 417c478bd9Sstevel@tonic-gate * 427c478bd9Sstevel@tonic-gate * addif 1.2.3.5 up 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * Only failover address configuration has been requested. Address 457c478bd9Sstevel@tonic-gate * 1.2.3.4 is a non-failover address, and so isn't output. 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * The "failover" and "-failover" commands can occur several times for 487c478bd9Sstevel@tonic-gate * a given logical interface. Only the last one counts. For example: 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * ifparse -f inet 1.2.3.4 -failover failover -failover failover up 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * Produces: 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * set 1.2.3.4 -failover failover -failover failover up 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * No attempt is made to clean up such "pathological" command lines, by 577c478bd9Sstevel@tonic-gate * removing redundant "failover" and "-failover" commands. 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include <sys/types.h> 617c478bd9Sstevel@tonic-gate #include <stdlib.h> 627c478bd9Sstevel@tonic-gate #include <stdio.h> 637c478bd9Sstevel@tonic-gate #include <string.h> 647c478bd9Sstevel@tonic-gate #include <assert.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * Parser flags: 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * PARSEFIXED 707c478bd9Sstevel@tonic-gate * Command should only appear if non-failover commands 717c478bd9Sstevel@tonic-gate * are requested. 727c478bd9Sstevel@tonic-gate * PARSEMOVABLE 737c478bd9Sstevel@tonic-gate * Command should only appear if failover commands are 747c478bd9Sstevel@tonic-gate * requested. 757c478bd9Sstevel@tonic-gate * PARSENOW 767c478bd9Sstevel@tonic-gate * Don't buffer the command, dump it to output immediately. 777c478bd9Sstevel@tonic-gate * PARSEADD 787c478bd9Sstevel@tonic-gate * Indicates processing has moved on to additional 797c478bd9Sstevel@tonic-gate * logical interfaces. 807c478bd9Sstevel@tonic-gate * Dump the buffer to output and clear buffer contents. 817c478bd9Sstevel@tonic-gate * PARSESET 827c478bd9Sstevel@tonic-gate * The "set" and "destination" keywords are optional. 837c478bd9Sstevel@tonic-gate * This flag indicates that the next address not prefixed 847c478bd9Sstevel@tonic-gate * with a keyword will be a destination address. 857c478bd9Sstevel@tonic-gate * PARSELOG0 867c478bd9Sstevel@tonic-gate * Command not valid on additional logical interfaces. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #define PARSEFIXED 0x01 907c478bd9Sstevel@tonic-gate #define PARSEMOVABLE 0x02 917c478bd9Sstevel@tonic-gate #define PARSENOW 0x04 927c478bd9Sstevel@tonic-gate #define PARSEADD 0x08 937c478bd9Sstevel@tonic-gate #define PARSESET 0x10 947c478bd9Sstevel@tonic-gate #define PARSELOG0 0x20 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate typedef enum { AF_UNSPEC, AF_INET, AF_INET6, AF_ANY } ac_t; 977c478bd9Sstevel@tonic-gate 98f7d61273Smeem #define NEXTARG (-1) /* command takes an argument */ 99f7d61273Smeem #define OPTARG (-2) /* command takes an optional argument */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #define END_OF_TABLE (-1) 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* Parsemode, the type of commands requested by the user. */ 1047c478bd9Sstevel@tonic-gate int parsemode = 0; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* Parsetype, the type of the command currently in the buffer. */ 1077c478bd9Sstevel@tonic-gate int parsetype = PARSEFIXED | PARSEMOVABLE; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* Parsebuf, pointer to the buffer. */ 1107c478bd9Sstevel@tonic-gate char *parsebuf = NULL; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* Parsebuflen, the size of the buffer area. */ 1137c478bd9Sstevel@tonic-gate unsigned parsebuflen = 0; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* Parsedumplen, the amount of the buffer currently in use. */ 1167c478bd9Sstevel@tonic-gate unsigned parsedumplen = 0; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Setaddr, used to decide whether an address without a keyword 1207c478bd9Sstevel@tonic-gate * prefix is a source or destination address. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate boolean_t setaddr = _B_FALSE; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * Some ifconfig commands are only valid on the first logical interface. 1267c478bd9Sstevel@tonic-gate * As soon as an "addif" command is seen, "addint" is set. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate boolean_t addint = _B_FALSE; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * The parser table is based on that in ifconfig. A command may or 132f7d61273Smeem * may not have an argument, as indicated by whether NEXTARG/OPTARG is 133f7d61273Smeem * in the second column. Some commands can only be used with certain 134f7d61273Smeem * address families, as indicated in the third column. The fourth column 1357c478bd9Sstevel@tonic-gate * contains flags that control parser action. 1367c478bd9Sstevel@tonic-gate * 1377c478bd9Sstevel@tonic-gate * Ifparse buffers logical interface configuration commands such as "set", 1387c478bd9Sstevel@tonic-gate * "netmask" and "broadcast". This buffering continues until an "addif" 1397c478bd9Sstevel@tonic-gate * command is seen, at which point the buffer is emptied, and the process 1407c478bd9Sstevel@tonic-gate * starts again. 1417c478bd9Sstevel@tonic-gate * 1427c478bd9Sstevel@tonic-gate * Some commands do not relate to logical interface configuration and are 1437c478bd9Sstevel@tonic-gate * dumped to output as soon as they are seen, such as "group" and "standby". 1447c478bd9Sstevel@tonic-gate * 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate struct cmd { 1487c478bd9Sstevel@tonic-gate char *c_name; 1497c478bd9Sstevel@tonic-gate int c_parameter; /* NEXTARG means next argv */ 1507c478bd9Sstevel@tonic-gate int c_af; /* address family restrictions */ 1517c478bd9Sstevel@tonic-gate int c_parseflags; /* parsing flags */ 1527c478bd9Sstevel@tonic-gate } cmds[] = { 1537c478bd9Sstevel@tonic-gate { "up", 0, AF_ANY, 0 }, 1547c478bd9Sstevel@tonic-gate { "down", 0, AF_ANY, 0 }, 1557c478bd9Sstevel@tonic-gate { "trailers", 0, AF_ANY, PARSENOW }, 1567c478bd9Sstevel@tonic-gate { "-trailers", 0, AF_ANY, PARSENOW }, 1577c478bd9Sstevel@tonic-gate { "arp", 0, AF_INET, PARSENOW }, 1587c478bd9Sstevel@tonic-gate { "-arp", 0, AF_INET, PARSENOW }, 1597c478bd9Sstevel@tonic-gate { "private", 0, AF_ANY, 0 }, 1607c478bd9Sstevel@tonic-gate { "-private", 0, AF_ANY, 0 }, 1617c478bd9Sstevel@tonic-gate { "router", 0, AF_ANY, PARSELOG0 }, 1627c478bd9Sstevel@tonic-gate { "-router", 0, AF_ANY, PARSELOG0 }, 1637c478bd9Sstevel@tonic-gate { "xmit", 0, AF_ANY, 0 }, 1647c478bd9Sstevel@tonic-gate { "-xmit", 0, AF_ANY, 0 }, 1657c478bd9Sstevel@tonic-gate { "-nud", 0, AF_INET6, PARSENOW }, 1667c478bd9Sstevel@tonic-gate { "nud", 0, AF_INET6, PARSENOW }, 1677c478bd9Sstevel@tonic-gate { "anycast", 0, AF_ANY, 0 }, 1687c478bd9Sstevel@tonic-gate { "-anycast", 0, AF_ANY, 0 }, 1697c478bd9Sstevel@tonic-gate { "local", 0, AF_ANY, 0 }, 1707c478bd9Sstevel@tonic-gate { "-local", 0, AF_ANY, 0 }, 1717c478bd9Sstevel@tonic-gate { "deprecated", 0, AF_ANY, 0 }, 1727c478bd9Sstevel@tonic-gate { "-deprecated", 0, AF_ANY, 0 }, 1737c478bd9Sstevel@tonic-gate { "preferred", 0, AF_INET6, 0 }, 1747c478bd9Sstevel@tonic-gate { "-preferred", 0, AF_INET6, 0 }, 1757c478bd9Sstevel@tonic-gate { "debug", 0, AF_ANY, PARSENOW }, 1767c478bd9Sstevel@tonic-gate { "verbose", 0, AF_ANY, PARSENOW }, 1777c478bd9Sstevel@tonic-gate { "netmask", NEXTARG, AF_INET, 0 }, 1787c478bd9Sstevel@tonic-gate { "metric", NEXTARG, AF_ANY, 0 }, 1797c478bd9Sstevel@tonic-gate { "mtu", NEXTARG, AF_ANY, 0 }, 1807c478bd9Sstevel@tonic-gate { "index", NEXTARG, AF_ANY, PARSELOG0 }, 1817c478bd9Sstevel@tonic-gate { "broadcast", NEXTARG, AF_INET, 0 }, 1827c478bd9Sstevel@tonic-gate { "auto-revarp", 0, AF_INET, PARSEFIXED}, 1837c478bd9Sstevel@tonic-gate { "plumb", 0, AF_ANY, PARSENOW }, 1847c478bd9Sstevel@tonic-gate { "unplumb", 0, AF_ANY, PARSENOW }, 185*e11c3f44Smeem { "ipmp", 0, AF_ANY, PARSELOG0 }, 1867c478bd9Sstevel@tonic-gate { "subnet", NEXTARG, AF_ANY, 0 }, 1877c478bd9Sstevel@tonic-gate { "token", NEXTARG, AF_INET6, PARSELOG0 }, 1887c478bd9Sstevel@tonic-gate { "tsrc", NEXTARG, AF_ANY, PARSELOG0 }, 1897c478bd9Sstevel@tonic-gate { "tdst", NEXTARG, AF_ANY, PARSELOG0 }, 1907c478bd9Sstevel@tonic-gate { "encr_auth_algs", NEXTARG, AF_ANY, PARSELOG0 }, 1917c478bd9Sstevel@tonic-gate { "encr_algs", NEXTARG, AF_ANY, PARSELOG0 }, 1927c478bd9Sstevel@tonic-gate { "auth_algs", NEXTARG, AF_ANY, PARSELOG0 }, 1937c478bd9Sstevel@tonic-gate { "addif", NEXTARG, AF_ANY, PARSEADD }, 1947c478bd9Sstevel@tonic-gate { "removeif", NEXTARG, AF_ANY, PARSELOG0 }, 1957c478bd9Sstevel@tonic-gate { "modlist", 0, AF_ANY, PARSENOW }, 1967c478bd9Sstevel@tonic-gate { "modinsert", NEXTARG, AF_ANY, PARSENOW }, 1977c478bd9Sstevel@tonic-gate { "modremove", NEXTARG, AF_ANY, PARSENOW }, 1987c478bd9Sstevel@tonic-gate { "failover", 0, AF_ANY, PARSEMOVABLE }, 1997c478bd9Sstevel@tonic-gate { "-failover", 0, AF_ANY, PARSEFIXED }, 2007c478bd9Sstevel@tonic-gate { "standby", 0, AF_ANY, PARSENOW }, 2017c478bd9Sstevel@tonic-gate { "-standby", 0, AF_ANY, PARSENOW }, 2027c478bd9Sstevel@tonic-gate { "failed", 0, AF_ANY, PARSENOW }, 2037c478bd9Sstevel@tonic-gate { "-failed", 0, AF_ANY, PARSENOW }, 2047c478bd9Sstevel@tonic-gate { "group", NEXTARG, AF_ANY, PARSELOG0 }, 2057c478bd9Sstevel@tonic-gate { "configinfo", 0, AF_ANY, PARSENOW }, 2067c478bd9Sstevel@tonic-gate { "encaplimit", NEXTARG, AF_ANY, PARSELOG0 }, 2077c478bd9Sstevel@tonic-gate { "-encaplimit", 0, AF_ANY, PARSELOG0 }, 2087c478bd9Sstevel@tonic-gate { "thoplimit", NEXTARG, AF_ANY, PARSELOG0 }, 2097c478bd9Sstevel@tonic-gate { "set", NEXTARG, AF_ANY, PARSESET }, 2107c478bd9Sstevel@tonic-gate { "destination", NEXTARG, AF_ANY, 0 }, 211f7d61273Smeem { "zone", NEXTARG, AF_ANY, 0 }, 212f7d61273Smeem { "-zone", 0, AF_ANY, 0 }, 213f7d61273Smeem { "all-zones", 0, AF_ANY, 0 }, 214f7d61273Smeem { "ether", OPTARG, AF_ANY, PARSENOW }, 215f7d61273Smeem { "usesrc", NEXTARG, AF_ANY, PARSENOW }, 2167c478bd9Sstevel@tonic-gate { 0 /* ether addr */, 0, AF_UNSPEC, PARSELOG0 }, 2177c478bd9Sstevel@tonic-gate { 0 /* set */, 0, AF_ANY, PARSESET }, 2187c478bd9Sstevel@tonic-gate { 0 /* destination */, 0, AF_ANY, 0 }, 2197c478bd9Sstevel@tonic-gate { 0, END_OF_TABLE, END_OF_TABLE, END_OF_TABLE}, 2207c478bd9Sstevel@tonic-gate }; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* Known address families */ 2247c478bd9Sstevel@tonic-gate struct afswtch { 2257c478bd9Sstevel@tonic-gate char *af_name; 2267c478bd9Sstevel@tonic-gate short af_af; 2277c478bd9Sstevel@tonic-gate } afs[] = { 2287c478bd9Sstevel@tonic-gate { "inet", AF_INET }, 2297c478bd9Sstevel@tonic-gate { "ether", AF_UNSPEC }, 2307c478bd9Sstevel@tonic-gate { "inet6", AF_INET6 }, 2317c478bd9Sstevel@tonic-gate { 0, 0 } 2327c478bd9Sstevel@tonic-gate }; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * Append "item" to the buffer. If there isn't enough room in the buffer, 2367c478bd9Sstevel@tonic-gate * expand it. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate static void 2397c478bd9Sstevel@tonic-gate parse_append_buf(char *item) 2407c478bd9Sstevel@tonic-gate { 2417c478bd9Sstevel@tonic-gate unsigned itemlen; 2427c478bd9Sstevel@tonic-gate unsigned newdumplen; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (item == NULL) 2457c478bd9Sstevel@tonic-gate return; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate itemlen = strlen(item); 2487c478bd9Sstevel@tonic-gate newdumplen = parsedumplen + itemlen; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* Expand dump buffer as needed */ 2517c478bd9Sstevel@tonic-gate if (parsebuflen < newdumplen) { 2527c478bd9Sstevel@tonic-gate if ((parsebuf = realloc(parsebuf, newdumplen)) == NULL) { 2537c478bd9Sstevel@tonic-gate perror("ifparse"); 2547c478bd9Sstevel@tonic-gate exit(1); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate parsebuflen = newdumplen; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate (void) memcpy(parsebuf + parsedumplen, item, itemlen); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate parsedumplen = newdumplen; 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * Dump the buffer to output. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate static void 2677c478bd9Sstevel@tonic-gate parse_dump_buf(void) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * When parsing, a set or addif command, we may be some way into 2717c478bd9Sstevel@tonic-gate * the command before we definitely know it is movable or fixed. 2727c478bd9Sstevel@tonic-gate * If we get to the end of the command, and haven't seen a 2737c478bd9Sstevel@tonic-gate * "failover" or "-failover" flag, the command is movable. 2747c478bd9Sstevel@tonic-gate */ 275f7d61273Smeem if (!((parsemode == PARSEFIXED) && (parsetype & PARSEMOVABLE) != 0) && 276f7d61273Smeem (parsemode & parsetype) != 0 && parsedumplen != 0) { 2777c478bd9Sstevel@tonic-gate unsigned i; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate if (parsebuf[parsedumplen] == ' ') 2807c478bd9Sstevel@tonic-gate parsedumplen--; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate for (i = 0; i < parsedumplen; i++) 2837c478bd9Sstevel@tonic-gate (void) putchar(parsebuf[i]); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate (void) putchar('\n'); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate /* The buffer is kept in case there is more parsing to do */ 2887c478bd9Sstevel@tonic-gate parsedumplen = 0; 2897c478bd9Sstevel@tonic-gate parsetype = PARSEFIXED | PARSEMOVABLE; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * Process a command. The command will either be put in the buffer, 2947c478bd9Sstevel@tonic-gate * or dumped directly to output. The current contents of the buffer 2957c478bd9Sstevel@tonic-gate * may be dumped to output. 2967c478bd9Sstevel@tonic-gate * 2977c478bd9Sstevel@tonic-gate * The buffer holds commands relating to a particular logical interface. 2987c478bd9Sstevel@tonic-gate * For example, "set", "destination", "failover", "broadcast", all relate 2997c478bd9Sstevel@tonic-gate * to a particular interface. Such commands have to be buffered until 3007c478bd9Sstevel@tonic-gate * all the "failover" and "-failover" commands for that interface have 3017c478bd9Sstevel@tonic-gate * been seen, only then will we know whether the command is movable 3027c478bd9Sstevel@tonic-gate * or not. When the "addif" command is seen, we know we are about to 3037c478bd9Sstevel@tonic-gate * start processing a new logical interface, we've seen all the 3047c478bd9Sstevel@tonic-gate * "failover" and "-failover" commands for the previous interface, and 3057c478bd9Sstevel@tonic-gate * can decide whether the buffer contents are movable or not. 3067c478bd9Sstevel@tonic-gate * 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate static void 3097c478bd9Sstevel@tonic-gate parsedump(char *cmd, int param, int flags, char *arg) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate char *cmdname; /* Command name */ 3127c478bd9Sstevel@tonic-gate char *cmdarg; /* Argument to command, if it takes one, or NULL */ 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Is command only valid on logical interface 0? 3167c478bd9Sstevel@tonic-gate * If processing commands on an additional logical interface, ignore 3177c478bd9Sstevel@tonic-gate * the command. 3187c478bd9Sstevel@tonic-gate * If processing commands on logical interface 0, don't buffer the 3197c478bd9Sstevel@tonic-gate * command, dump it straight to output. 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate if ((flags & PARSELOG0) != 0) { 3227c478bd9Sstevel@tonic-gate if (addint) 3237c478bd9Sstevel@tonic-gate return; 3247c478bd9Sstevel@tonic-gate flags |= PARSENOW; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * If processing the "addif" command, a destination address may 3297c478bd9Sstevel@tonic-gate * follow without the "destination" prefix. Add PARSESET to the 3307c478bd9Sstevel@tonic-gate * flags so that such an anonymous address is processed correctly. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate if ((flags & PARSEADD) != 0) { 3337c478bd9Sstevel@tonic-gate flags |= PARSESET; 3347c478bd9Sstevel@tonic-gate addint = _B_TRUE; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * Commands that must be dumped straight to output are always fixed 3397c478bd9Sstevel@tonic-gate * (non-movable) commands. 3407c478bd9Sstevel@tonic-gate * 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate if ((flags & PARSENOW) != 0) 3437c478bd9Sstevel@tonic-gate flags |= PARSEFIXED; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * Source and destination addresses do not have to be prefixed 3477c478bd9Sstevel@tonic-gate * with the keywords "set" or "destination". Ifparse always 3487c478bd9Sstevel@tonic-gate * inserts the optional keyword. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate if (cmd == NULL) { 3517c478bd9Sstevel@tonic-gate cmdarg = arg; 3527c478bd9Sstevel@tonic-gate if ((flags & PARSESET) != 0) 3537c478bd9Sstevel@tonic-gate cmdname = "set"; 3547c478bd9Sstevel@tonic-gate else if (setaddr) { 3557c478bd9Sstevel@tonic-gate cmdname = "destination"; 3567c478bd9Sstevel@tonic-gate setaddr = _B_FALSE; 3577c478bd9Sstevel@tonic-gate } else 3587c478bd9Sstevel@tonic-gate cmdname = ""; 3597c478bd9Sstevel@tonic-gate } else { 360f7d61273Smeem cmdarg = (param == 0) ? NULL : arg; 3617c478bd9Sstevel@tonic-gate cmdname = cmd; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * The next address without a prefix will be a destination 3667c478bd9Sstevel@tonic-gate * address. 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate if ((flags & PARSESET) != 0) 3697c478bd9Sstevel@tonic-gate setaddr = _B_TRUE; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * Dump the command straight to output? 3737c478bd9Sstevel@tonic-gate * Only dump the command if the parse mode specified on 3747c478bd9Sstevel@tonic-gate * the command line matches the type of the command. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate if ((flags & PARSENOW) != 0) { 3777c478bd9Sstevel@tonic-gate if ((parsemode & flags) != 0) { 3787c478bd9Sstevel@tonic-gate (void) fputs(cmdname, stdout); 3797c478bd9Sstevel@tonic-gate if (cmdarg != NULL) { 3807c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 3817c478bd9Sstevel@tonic-gate (void) fputs(cmdarg, stdout); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate return; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * Only the commands relating to a particular logical interface 3907c478bd9Sstevel@tonic-gate * are buffered. When an "addif" command is seen, processing is 3917c478bd9Sstevel@tonic-gate * about to start on a new logical interface, so dump the 3927c478bd9Sstevel@tonic-gate * buffer to output. 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate if ((flags & PARSEADD) != 0) 3957c478bd9Sstevel@tonic-gate parse_dump_buf(); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * If the command flags indicate the command is fixed or 3997c478bd9Sstevel@tonic-gate * movable, update the type of the interface in the buffer 4007c478bd9Sstevel@tonic-gate * accordingly. For example, "-failover" has the "PARSEFIXED" 4017c478bd9Sstevel@tonic-gate * flag, and the contents of the buffer are not movable if 4027c478bd9Sstevel@tonic-gate * "-failover" is seen. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate if ((flags & PARSEFIXED) != 0) 4057c478bd9Sstevel@tonic-gate parsetype &= ~PARSEMOVABLE; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if ((flags & PARSEMOVABLE) != 0) 4087c478bd9Sstevel@tonic-gate parsetype &= ~PARSEFIXED; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate parsetype |= flags & (PARSEFIXED | PARSEMOVABLE); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate parse_append_buf(cmdname); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate if (cmdarg != NULL) { 4157c478bd9Sstevel@tonic-gate parse_append_buf(" "); 4167c478bd9Sstevel@tonic-gate parse_append_buf(cmdarg); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate parse_append_buf(" "); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Parse the part of the command line following the address family 4247c478bd9Sstevel@tonic-gate * specification, if any. 4257c478bd9Sstevel@tonic-gate * 4267c478bd9Sstevel@tonic-gate * This function is a modified version of the function "ifconfig" in 4277c478bd9Sstevel@tonic-gate * ifconfig.c. 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate static int 4307c478bd9Sstevel@tonic-gate ifparse(int argc, char *argv[], struct afswtch *afp) 4317c478bd9Sstevel@tonic-gate { 432f7d61273Smeem int af = afp->af_af; 4337c478bd9Sstevel@tonic-gate 434f7d61273Smeem if (argc == 0) 4357c478bd9Sstevel@tonic-gate return (0); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (strcmp(*argv, "auto-dhcp") == 0 || strcmp(*argv, "dhcp") == 0) { 4387c478bd9Sstevel@tonic-gate if ((parsemode & PARSEFIXED) != NULL) { 4397c478bd9Sstevel@tonic-gate while (argc) { 4407c478bd9Sstevel@tonic-gate (void) fputs(*argv++, stdout); 4417c478bd9Sstevel@tonic-gate if (--argc != 0) 4427c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 4437c478bd9Sstevel@tonic-gate else 4447c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate return (0); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate while (argc > 0) { 4517c478bd9Sstevel@tonic-gate struct cmd *p; 4527c478bd9Sstevel@tonic-gate boolean_t found_cmd; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate found_cmd = _B_FALSE; 4557c478bd9Sstevel@tonic-gate for (p = cmds; ; p++) { 4567c478bd9Sstevel@tonic-gate assert(p->c_parseflags != END_OF_TABLE); 4577c478bd9Sstevel@tonic-gate if (p->c_name) { 4587c478bd9Sstevel@tonic-gate if (strcmp(*argv, p->c_name) == 0) { 4597c478bd9Sstevel@tonic-gate /* 4607c478bd9Sstevel@tonic-gate * indicate that the command was 4617c478bd9Sstevel@tonic-gate * found and check to see if 4627c478bd9Sstevel@tonic-gate * the address family is valid 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate found_cmd = _B_TRUE; 4657c478bd9Sstevel@tonic-gate if (p->c_af == AF_ANY || 4667c478bd9Sstevel@tonic-gate af == p->c_af) 4677c478bd9Sstevel@tonic-gate break; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate } else { 4707c478bd9Sstevel@tonic-gate if (p->c_af == AF_ANY || 4717c478bd9Sstevel@tonic-gate af == p->c_af) 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate assert(p->c_parseflags != END_OF_TABLE); 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * If we found the keyword, but the address family 4787c478bd9Sstevel@tonic-gate * did not match spit out an error 4797c478bd9Sstevel@tonic-gate */ 4807c478bd9Sstevel@tonic-gate if (found_cmd && p->c_name == 0) { 4817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ifparse: Operation %s not" 4827c478bd9Sstevel@tonic-gate " supported for %s\n", *argv, afp->af_name); 4837c478bd9Sstevel@tonic-gate return (1); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate /* 4867c478bd9Sstevel@tonic-gate * else (no keyword found), we assume it's an address 4877c478bd9Sstevel@tonic-gate * of some sort 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate if (p->c_name == 0 && setaddr) { 4907c478bd9Sstevel@tonic-gate p++; /* got src, do dst */ 4917c478bd9Sstevel@tonic-gate assert(p->c_parseflags != END_OF_TABLE); 4927c478bd9Sstevel@tonic-gate } 493f7d61273Smeem 494f7d61273Smeem if (p->c_parameter == NEXTARG || p->c_parameter == OPTARG) { 4957c478bd9Sstevel@tonic-gate argc--, argv++; 496f7d61273Smeem if (argc == 0 && p->c_parameter == NEXTARG) { 4977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4987c478bd9Sstevel@tonic-gate "ifparse: no argument for %s\n", 4997c478bd9Sstevel@tonic-gate p->c_name); 5007c478bd9Sstevel@tonic-gate return (1); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate } 503f7d61273Smeem 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * Dump the command if: 5067c478bd9Sstevel@tonic-gate * 5077c478bd9Sstevel@tonic-gate * there's no address family 5087c478bd9Sstevel@tonic-gate * restriction 5097c478bd9Sstevel@tonic-gate * OR 5107c478bd9Sstevel@tonic-gate * there is a restriction AND 5117c478bd9Sstevel@tonic-gate * the address families match 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate if ((p->c_af == AF_ANY) || (af == p->c_af)) 514f7d61273Smeem parsedump(p->c_name, p->c_parameter, p->c_parseflags, 515f7d61273Smeem *argv); 5167c478bd9Sstevel@tonic-gate argc--, argv++; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate parse_dump_buf(); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate return (0); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * Print command usage on standard error. 5257c478bd9Sstevel@tonic-gate */ 5267c478bd9Sstevel@tonic-gate static void 5277c478bd9Sstevel@tonic-gate usage(void) 5287c478bd9Sstevel@tonic-gate { 5297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5307c478bd9Sstevel@tonic-gate "usage: ifparse [ -fs ] <addr_family> <commands>\n"); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate int 5347c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate int c; 5377c478bd9Sstevel@tonic-gate struct afswtch *afp; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "fs")) != -1) { 5407c478bd9Sstevel@tonic-gate switch ((char)c) { 5417c478bd9Sstevel@tonic-gate case 'f': 5427c478bd9Sstevel@tonic-gate parsemode |= PARSEMOVABLE; 5437c478bd9Sstevel@tonic-gate break; 5447c478bd9Sstevel@tonic-gate case 's': 5457c478bd9Sstevel@tonic-gate parsemode |= PARSEFIXED; 5467c478bd9Sstevel@tonic-gate break; 5477c478bd9Sstevel@tonic-gate case '?': 5487c478bd9Sstevel@tonic-gate usage(); 5497c478bd9Sstevel@tonic-gate exit(1); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (parsemode == 0) 5547c478bd9Sstevel@tonic-gate parsemode = PARSEFIXED | PARSEMOVABLE; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate argc -= optind; 5577c478bd9Sstevel@tonic-gate argv += optind; 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate afp = afs; 5607c478bd9Sstevel@tonic-gate if (argc > 0) { 5617c478bd9Sstevel@tonic-gate struct afswtch *aftp; 5627c478bd9Sstevel@tonic-gate for (aftp = afs; aftp->af_name; aftp++) { 5637c478bd9Sstevel@tonic-gate if (strcmp(aftp->af_name, *argv) == 0) { 5647c478bd9Sstevel@tonic-gate argc--; argv++; 5657c478bd9Sstevel@tonic-gate afp = aftp; 5667c478bd9Sstevel@tonic-gate break; 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate return (ifparse(argc, argv, afp)); 5727c478bd9Sstevel@tonic-gate } 573