ifconfig.c revision ff550d0e264b51131fb34e9e83163b348d916640
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling * Copyright (c) 1983 Regents of the University of California.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * All rights reserved. The Berkeley software License Agreement
fa9e4066f08beec538e775443c5be79dd423fcabahrens * specifies the terms and conditions for redistribution.
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDRBITS_V4 32 /* number of bits in IPv4 address */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDRBITS_V6 128 /* number of bits in IPv6 address */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define AF_FUNC_STATUS 1 /* af_status func reports status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define AF_FUNC_CONFIGINFO 2 /* af_status func reports configinfo */
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct if_flags {
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* current interface name a praticular function is accessing */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* foreach interface saved name */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Make sure the algorithm variables hold more than the sizeof an algorithm
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in PF_KEY. (For now, more than a uint8_t.) The NO_***_?ALG indicates that
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * there was no algorithm requested, and in the ipsec_req that service should
fa9e4066f08beec538e775443c5be79dd423fcabahrens * be disabled. (E.g. if ah_aalg remains NO_AH_AALG, then AH will be
fa9e4066f08beec538e775443c5be79dd423fcabahrens * disabled on that tunnel.)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * used by setifether to create a list of interfaces to mark
fa9e4066f08beec538e775443c5be79dd423fcabahrens * down-up when changing the ethernet address of an interface
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct iface {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct iface *next; /* pointer to the next list element */
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwickstatic iface_t *logifs = NULL; /* list of logical interfaces */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic iface_t *phyif = NULL; /* physical interface */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Function prototypes for command functions.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int setverboseflag(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int set_tun_esp_auth_alg(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int set_tun_esp_encr_alg(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int set_tun_encap_limit(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int clr_tun_encap_limit(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int set_tun_hop_limit(char *arg, int64_t param);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int setnd(char *arg, int64_t param);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia#endif /* DEBUG */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Address family specific function prototypes.
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in_getaddr(char *s, struct sockaddr *saddr, int *plenp);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musantestatic void in6_getaddr(char *s, struct sockaddr *saddr, int *plenp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in6_configinfo(int force, uint64_t flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Misc support functions
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic int devfs_entry(di_node_t node, di_minor_t minor, void *arg);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void foreachinterface(void (*func)(), int argc, char *argv[],
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void ifconfig(int argc, char *argv[], int af, struct lifreq *lifrp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int ifdad(char *ifname, struct sockaddr_in6 *laddr);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic boolean_t in_getmask(struct sockaddr_in *saddr,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int in_getprefixlen(char *addr, boolean_t slash, int plen);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t in_prefixlentomask(int prefixlen, int maxlen,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void status(void);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void ifstatus(const char *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void usage(void);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int strioctl(int s, int cmd, char *buf, int buflen);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifdhcp(const char *caller, const char *ifname,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int ip_domux2fd(int *, int *, int *, int *);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int ip_plink(int, int, int, int);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int get_lun(char *);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastatic void selectifs(int argc, char *argv[], int af,
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson#define max(a, b) ((a) < (b) ? (b) : (a))
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * DHCP_EXIT_IF_FAILURE indicates that the operation failed, but if there
088f389458728c464569a5506b58070254fa4f7dahrens * are more interfaces to act on (i.e., ifconfig was invoked with -a), keep
e05725b117836db173257fae43fb0746eb857fb5bonwick * on going rather than exit with an error.
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define DHCP_IPC_MAX_WAIT 15 /* max seconds to wait to start agent */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define NEXTARG 0xffffff /* command takes an argument */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define OPTARG 0xfffffe /* command takes an optional argument */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Refer to the comments in ifconfig() on the netmask "hack" */
fa9e4066f08beec538e775443c5be79dd423fcabahrensenum { G_NETMASK_NIL, G_NETMASK_PENDING, G_NETMASK_SET }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int64_t c_parameter; /* NEXTARG means next argv */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int c_abortonfail; /* don't continue parsing args */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* for the current interface */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int c_af; /* address family restrictions */
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "trailers", -IFF_NOTRAILERS, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-trailers", IFF_NOTRAILERS, setifflags, 0, AF_ANY },
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson { "-router", -IFF_ROUTER, setifflags, 0, AF_ANY },
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick { "private", IFF_PRIVATE, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "deprecated", IFF_DEPRECATED, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-deprecated", -IFF_DEPRECATED, setifflags, 0, AF_ANY },
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick { "preferred", IFF_PREFERRED, setifflags, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-preferred", -IFF_PREFERRED, setifflags, 0, AF_INET6 },
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "auto-revarp", 0, setifrevarp, 1, AF_INET },
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "unplumb", 0, inetunplumb, 0, AF_ANY },
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson { "token", NEXTARG, setiftoken, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "encr_auth_algs", NEXTARG, set_tun_esp_auth_alg, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "encr_algs", NEXTARG, set_tun_esp_encr_alg, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "failover", -IFF_NOFAILOVER, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-failover", IFF_NOFAILOVER, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* XXX for testing SIOCT* ioctls. Remove */
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0, 0, 0, 0 },
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct if_config_cmd {
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct ni {
f1b4288b3b466065edd5eb9868399db6a4ff283evbstatic int num_ni = 0;
f1b4288b3b466065edd5eb9868399db6a4ff283evb/* End defines and structure definitions for ifconfig -a plumb */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Known address families */
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "inet", AF_INET, in_status, in_getaddr, in_configinfo },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "inet6", AF_INET6, in6_status, in6_getaddr, in6_configinfo },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0, 0, 0, 0 }
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct afswtch *afp; /* the address family being set or asked about */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Include IFF_NOXMIT, IFF_TEMPORARY and all zone interfaces */
f1b4288b3b466065edd5eb9868399db6a4ff283evb int64_t lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
f1b4288b3b466065edd5eb9868399db6a4ff283evb (void) fprintf(stderr, "%s: interface name too long\n", *argv);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(origname, name, sizeof (origname)); /* For addif */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s: Bad value for %s in %s\n", default_ip_str,
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (s < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Special interface names is any combination of these flags.
0a4e9518a44f226be6d39383330b5b1792d2f184gw * Note that due to the ifconfig syntax they have to be combined
0a4e9518a44f226be6d39383330b5b1792d2f184gw * as a single '-' option.
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -a All interfaces
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -u "up" interfaces
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -d "down" interfaces
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -D Interfaces not controlled by DHCP
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -4 IPv4 interfaces
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -6 IPv6 interfaces
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -X Turn on debug (not documented)
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -v Turn on verbose
0a4e9518a44f226be6d39383330b5b1792d2f184gw * -Z Only interfaces in caller's zone
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* One or more options */
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch ((char)c) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * -4 is not a compatable flag, therefore
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we assume they want v4compat turned off
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If they want IPv6, well then we'll assume
fa9e4066f08beec538e775443c5be79dd423fcabahrens * they don't want IPv4 compat
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s: no such interface\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens foreachinterface(ifconfig, argc, argv, af, onflags, offflags,
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For each interface, call (*func)(argc, argv, af, lifrp).
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Only call function if onflags and offflags are set or clear, respectively,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in the interfaces flags field.
f94275ce205810a201404c5f35f4cc96057022b1Adam Leventhalforeachinterface(void (*func)(), int argc, char *argv[], int af,
99653d4ee642c6528e88224f12409a5f23060994eschrock int64_t onflags, int64_t offflags, int64_t lifc_flags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Special case:
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * ifconfig -a plumb should find all network interfaces
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in the machine by traversing the devinfo tree.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Also, there is no need to SIOCGLIF* ioctls, since
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * those interfaces have already been plumbed
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look through the kernel's devinfo tree for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * network devices
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DINFOCACHE is equivalent to DINFOSUBTREE | DINFOMINOR |
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DINFOPROP | DINFOFORCE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock " check the devinfo driver.\n");
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Now, translate the linked list into
99653d4ee642c6528e88224f12409a5f23060994eschrock * a struct lifreq buffer
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick for (n = 0, lifrp = lifc.lifc_req; n < num_ni; n++, lifrp++) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick " of interfaces");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf("ifconfig: %d interfaces\n", numifs);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * We must close and recreate the socket each time
fa9e4066f08beec538e775443c5be79dd423fcabahrens * since we don't know what type of socket it is now
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (each status function may change it).
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Only service interfaces that match the on and off
fa9e4066f08beec538e775443c5be79dd423fcabahrens * flags masks.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Switch address family */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the globally defined lifreq
fa9e4066f08beec538e775443c5be79dd423fcabahrens * structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Reset global state
fa9e4066f08beec538e775443c5be79dd423fcabahrens * setaddr: Used by parser to tear apart source and dest
fa9e4066f08beec538e775443c5be79dd423fcabahrens * name and origname contain the name of the 'current'
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, lifrp->lifr_name, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "checking partial %s against %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* the func could have overwritten origname, so restore */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(treq.ifta_lifr_name, name, sizeof (treq.ifta_lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Return, we don't need to check. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Either not a tunnel (the SIOCGTUNPARAM fails on
fa9e4066f08beec538e775443c5be79dd423fcabahrens * non-tunnels), or the security flag is not set. Either
fa9e4066f08beec538e775443c5be79dd423fcabahrens * way, return.
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin (void) fprintf(stderr, "ifconfig: WARNING - tunnel with "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "only ESP and potentially no authentication.\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens * for the specified interface call (*func)(argc, argv, af, lifrp).
fa9e4066f08beec538e775443c5be79dd423fcabahrensifconfig(int argc, char *argv[], int af, struct lifreq *lifrp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argc == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(*argv, "auto-dhcp") == 0 || strcmp(*argv, "dhcp") == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * some errors are ignored in the case where
fa9e4066f08beec538e775443c5be79dd423fcabahrens * more than one interface is being operated on.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: dhcp not supported "
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin "for inet6\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The following is a "hack" to get around the existing interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens * setting mechanism. Currently, each interface attribute,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * such as address, netmask, broadcast, ... is set separately. But
fa9e4066f08beec538e775443c5be79dd423fcabahrens * sometimes two or more attributes must be set together. For
fa9e4066f08beec538e775443c5be79dd423fcabahrens * example, setting an address without a netmask does not make sense.
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin * Yet they can be set separately for IPv4 address using the current
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ifconfig(1M) syntax. The kernel then "infers" the correct netmask
fa9e4066f08beec538e775443c5be79dd423fcabahrens * using the deprecated "IP address classes." This is simply not
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The "hack" below is to go thru the whole command list looking for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the netmask command first. Then use this netmask to set the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * address. This does not provide an extensible way to accommodate
fa9e4066f08beec538e775443c5be79dd423fcabahrens * future need for setting more than one attributes together.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note that if the "netmask" command argument is a "+", we need
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to save this info and do the query after we know the address to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * be set. The reason is that if "addif" is used, the working
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface name will be changed later when the logical interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens * is created. In in_getmask(), if an address is not provided,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it will use the working interface's address to do the query.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * It will be wrong now as we don't know the logical interface's name.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ifconfig(1M) is too overloaded and the code is so convoluted
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that it is "safer" not to re-architect the code to fix the above
fa9e4066f08beec538e775443c5be79dd423fcabahrens * issue, hence this "hack." We may be better off to have a new
fa9e4066f08beec538e775443c5be79dd423fcabahrens * command with better syntax for configuring network interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens * parameters...
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Only go thru the command list once to find the netmask. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Currently, if multiple netmask commands are specified, the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * last one will be used as the final netmask. So we need
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to scan the whole list to preserve this behavior.
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (largc = argc, largv = argv; largc > 0; largc--, largv++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (--largc == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Continue the scan. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (argc > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * indicate that the command was
fa9e4066f08beec538e775443c5be79dd423fcabahrens * found and check to see if
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the address family is valid
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * If we found the keyword, but the address family
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * did not match spit out an error
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) fprintf(stderr, "ifconfig: Operation %s not"
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * else (no keyword found), we assume it's an address
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * of some sort
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick p++; /* got src, do dst */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson "ifconfig: no argument for %s\n",
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Call the function if:
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * there's no address family
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * restriction
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * we don't know the address yet
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (because we were called from
fa9e4066f08beec538e775443c5be79dd423fcabahrens * there is a restriction AND
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the address families match
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If c_func failed and we should
fa9e4066f08beec538e775443c5be79dd423fcabahrens * abort processing for this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface on failure, return
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * now rather than going on to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * process other commands for
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * the same interface.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /* Check to see if there's a security hole in the tunnel setup. */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/* ARGSUSED */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/* ARGSUSED */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * This function fills in the given lifreq's lifr_addr field based on
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * g_netmask_set.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonset_mask_lifreq(struct lifreq *lifr, struct sockaddr_storage *addr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * "+" is used as the argument to "netmask" command. Query
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * the database on the correct netmask based on the address to
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_getmask((struct sockaddr_in *)&g_netmask, _B_TRUE)) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * Set the interface address. Handles <addr>, <addr>/<n> as well as /<n>
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * syntax for setting the address, the address plus netmask, and just
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * the netmask respectively.
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick/* ARGSUSED */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (*afp->af_getaddr)(addr, (struct sockaddr *)&laddr, &prefixlen);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* Nothing there - ok */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) fprintf(stderr, "ifconfig: Bad prefix length in %s\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_prefixlentomask(prefixlen, ADDRBITS_V6,
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick "Bad prefix length: %d\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_prefixlentomask(prefixlen, ADDRBITS_V4,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick "Bad prefix length: %d\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * Just in case of funny setting of both prefix and netmask,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * prefix should override the netmask command.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Tell parser that an address was set */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* save copy of netmask to restore in case of error */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Catch set of address for AF_INET6 to perform
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * duplicate address detection. Check that the interface is
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick "setifaddr: Calling ifdad flags %llx\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ifdad(name, (struct sockaddr_in6 *)&laddr) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If setting the address and not the mask, clear any existing mask
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and the kernel will then assign the default (netmask has been set
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to 0 in this case). If setting both (either by using a prefix or
fa9e4066f08beec538e775443c5be79dd423fcabahrens * using the netmask command), set the mask first, so the address will
fa9e4066f08beec538e775443c5be79dd423fcabahrens * be interpreted correctly.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick inet_ntop(afp->af_af, addr, abuf, sizeof (abuf)));
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * Restore the netmask
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The following functions are stolen from the ipseckey(1m) program.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Perhaps they should be somewhere common, but for now, we just maintain
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * two versions. We do this because of the different semantics for which
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * algorithms we select ("requested" for ifconfig vs. "actual" for key).
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (errno != 0 || end == num || *end != '\0') {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Parse and reverse parse possible algorithm values, include numbers.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Mostly stolen from ipseckey.c. See the comments above parsenum() for why
fa9e4066f08beec538e775443c5be79dd423fcabahrens * this isn't common to ipseckey.c.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * NOTE: Static buffer in this function for the return value. Since ifconfig
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * isn't multithreaded, this isn't a huge problem.
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick#define NBUF_SIZE 20 /* Enough to print a large integer. */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwickstatic char *
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick static char numprint[128]; /* Enough to hold an algorithm name. */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Special-case 0 to return "<any-none>" */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick return ("<any-none>");
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick alg = getipsecalgbynum(alg_value, proto_num, NULL);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) strlcpy(numprint, alg->a_names[0], sizeof (numprint));
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) snprintf(numprint, sizeof (numprint), "%d", alg_value);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) fprintf(stderr, "ifconfig: Unexpected end of command "
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Special-case "none". Use strcasecmp because its length is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Since algorithms can be loaded during kernel run-time, check for
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * numeric algorithm values too.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s algorithm type %s unknown.\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwick * Actual ifconfig functions to set tunnel security properties.
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwickenum ipsec_alg_type { ESP_ENCR_ALG = 1, ESP_AUTH_ALG, AH_AUTH_ALG };
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(treq.ifta_lifr_name, name, sizeof (treq.ifta_lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror0_exit("Tunnel params on logical interfaces");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCGTUNPARAM, (caddr_t)&treq) < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "Kernel tunnel secinfo version mismatch.\n");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * If I'm just starting off this ifconfig, I want a clean slate,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * otherwise, I've captured the current tunnel security settings.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * In the case of continuation, I merely add to the settings.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ipsr->ipsr_esp_auth_alg == SADB_AALG_NONE)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Let the user specify NULL encryption implicitly. */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Will never hit DEFAULT */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSTUNPARAM, (caddr_t)&treq) < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror2_exit("set tunnel security properties",
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonset_tun_esp_encr_alg(char *addr, int64_t param)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonset_tun_esp_auth_alg(char *addr, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: revarp not possible on IPv6 interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) memcpy(&lifr.lifr_addr, &laddr, sizeof (laddr));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (*afp->af_getaddr)(addr, &subnet, &prefixlen);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: Missing prefix length in subnet %s\n", addr);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* NOTREACHED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSLIFSUBNET, (caddr_t)&lifr) < 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) printf("Setting netmask of %s to %s\n", name,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson in_getaddr(addr, (struct sockaddr *)&netmask, NULL);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) memcpy(&lifr.lifr_addr, &netmask, sizeof (netmask));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Parse '/<n>' as a netmask.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: setting prefix only supported"
e05725b117836db173257fae43fb0746eb857fb5bonwick " for address family inet or inet6\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e19302335c33c8c6e0b0b5e426fc1f6352c84b5dbonwick/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This doesn't set the broadcast address at all. Rather, it
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby * gets, then sets the interface's address, relying on the fact
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee * that resetting the address will reset the broadcast address.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens in_getaddr(addr, (struct sockaddr *)&broadaddr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_addr, &broadaddr, sizeof (broadaddr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * set interface destination address
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*afp->af_getaddr)(addr, (struct sockaddr *)&lifr.lifr_addr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Fail if '-failover' is set after a prior addif created the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * alias on a different interface. This can happen when the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface is part of an IPMP group.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: can't set -failover "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "on failed/standby/offlined interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Catch "up" transition for AF_INET6 to perform duplicate address
fa9e4066f08beec538e775443c5be79dd423fcabahrens * detection. ifdad checks if an address has been set.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (afp->af_af == AF_INET6 && !(lifr.lifr_flags & IFF_UP) &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens "setifaddr:Calling ifdad flags %llx value 0x%llx\n",
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * if the IP interface in the arguments is a logical
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface, exit with an error now.
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens " ethernet address of a logical interface\n");
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) fprintf(stderr, "ifconfig: malloc() failed\n");
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(savedname, name, sizeof (savedname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Call selectifs only for the IP interfaces that are ipv4.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * offflags == IFF_IPV6 because you should not change the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Ethernet address of an ipv6 interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens foreachinterface(selectifs, 0, (char **)NULL, 0, 0, IFF_IPV6, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If physical interface not found, exit now */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Restore */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(origname, savedname, sizeof (origname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * close and reopen the socket
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we don't know which type of socket we have now
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * mark down the logical interfaces first,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and then the physical interface
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (updownifs(logifs, 0) < 0 || updownifs(phyif, 0) < 0) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson * Change the physical address
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (dlpi_set_address(savedname, ea, maclen) == -1) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson "ifconfig: failed setting mac address on %s\n",
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson * if any interfaces were marked down before changing the
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson * ethernet address, put them up again.
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson * First the physical interface, then the logical ones.
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (updownifs(phyif, 1) < 0 || updownifs(logifs, 1) < 0) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson /* Free the memory allocated by selectifs */
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby for (current = logifs; current != NULL; current = logifs) {
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby * Print an interface's Ethernet address, if it has one.
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * Loopback interfaces and tunnels can't have MAC addresses,
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * so filter them out first.
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (fd == -1 || ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * It's possible the interface is only configured for
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * IPv6; check again with AF_INET6.
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (fd == -1 || ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1) {
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens /* Virtual interfaces don't have MAC addresses */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * We must be careful to set if_protocol based on the current
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * properties of the interface. For instance, if "ip.tun0" is
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * configured only as an IPv6 tunnel, then if_protocol must be
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * set to AF_INET6 or icfg_get_tunnel_lower() will fail and
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * we will falsely conclude that it's not a tunnel.
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(interface.if_name, ifname, sizeof (interface.if_name));
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson if (icfg_open(&handle, &interface) == ICFG_SUCCESS) {
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson if (icfg_get_tunnel_lower(handle, &protocol) == ICFG_SUCCESS) {
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson /* Tunnel op succeeded -- it's a tunnel so skip */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * static void selectifs(int argc, char *argv[], int af, struct lifreq *rp)
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * Called inside setifether() to create a list of interfaces to
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * mark down/up when changing the Ethernet address.
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * If the current interface is the physical interface passed
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens * as an argument to ifconfig, update phyif.
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * If the current interface is a logical interface associated
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * to the physical interface, add it to the logifs list.
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson/* ARGSUSED */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilsonselectifs(int argc, char *argv[], int af, struct lifreq *rp)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * savedname= name of the IP interface to which you want to
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens * change ethernet address
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * name= name of the current IP interface
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson length = max(strlen(savedname), strlen(name));
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson length = max(strlen(savedname), colonp - name);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if ((current = malloc(sizeof (iface_t))) == NULL) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante /* this is the physical interface */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* this is a logical interface */
fa9e4066f08beec538e775443c5be79dd423fcabahrens bcopy(&lifr, ¤t->lifr, sizeof (struct lifreq));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * static int updownifs(iface_t *ifs, int up)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * It takes in input a list of IP interfaces (ifs)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and a flag (up).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * It marks each interface in the list down (up = 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or up (up > 0). This is done ONLY if the IP
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface was originally up.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return values:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 0 = everything OK
fa9e4066f08beec538e775443c5be79dd423fcabahrens * -1 = problem
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (current = ifs; current != NULL; current = current->next) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Create the next unused logical interface using the original name
e05725b117836db173257fae43fb0746eb857fb5bonwick * and assign the address (and mask if '/<n>' is part of the address).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use the new logical interface for subsequent subcommands by updating
e05725b117836db173257fae43fb0746eb857fb5bonwick * the name variable.
e05725b117836db173257fae43fb0746eb857fb5bonwick * This allows syntax like:
e05725b117836db173257fae43fb0746eb857fb5bonwick * ifconfig le0 addif 109.106.86.130 netmask + up \
fa9e4066f08beec538e775443c5be79dd423fcabahrens * addif 109.106.86.131 netmask + up
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "ifconfig: addif: bad physical interface name %s\n",
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * clear so parser will interpret next address as source followed
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin * by possible dest
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*afp->af_getaddr)(str, (struct sockaddr *)&laddr, &prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Nothing there - ok */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This is a "hack" to get around the problem of SIOCLIFADDIF. The
fa9e4066f08beec538e775443c5be79dd423fcabahrens * problem is that this ioctl does not include the netmask when
fa9e4066f08beec538e775443c5be79dd423fcabahrens * adding a logical interface. This is the same problem described
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in the ifconfig() comments. To get around this problem, we first
fa9e4066f08beec538e775443c5be79dd423fcabahrens * add the logical interface with a 0 address. After that, we set
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the netmask if provided. Finally we set the interface address.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Note: no need to do DAD here since the interface isn't up yet. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Check and see if any "netmask" command is used and perform the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * necessary operation.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Only set the netmask if "netmask" command is used or a prefix is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * provided.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (g_netmask_set == G_NETMASK_SET || prefixlen >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Finally, we set the interface address. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * let parser know we got a source.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Next address, if given, should be dest
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Remove a logical interface based on its IP address. Unlike addif
fa9e4066f08beec538e775443c5be79dd423fcabahrens * there is no '/<n>' here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Verifies that the interface is down before it is removed.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: removeif: bad physical interface name %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* This can only happen if ipif_id = 0 */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "ifconfig: removeif: can't remove interface: %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If laddr is non-NULL it is used - otherwise we use the address on
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Check the address assigned to the interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Skip the check if IFF_NOLOCAL, IFF_NONUD, IFF_ANYCAST, or
fa9e4066f08beec538e775443c5be79dd423fcabahrens * IFF_LOOPBACK.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note that IFF_NONUD turns of both NUD and DAD.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifr2.lifr_flags & (IFF_NOLOCAL|IFF_LOOPBACK|IFF_NONUD|IFF_ANYCAST))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set the address token for IPv6.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens in6_getaddr(addr, (struct sockaddr *)&token, &prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Missing prefix length in subnet %s\n", addr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_addr, &token, sizeof (token));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return value: 0 on success, -1 on failure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Need to bind to a privileged port. For non-root, this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * will fail. in.mpathd verifies that only commands coming
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from privileged ports succeed so that ordinary users
fa9e4066f08beec538e775443c5be79dd423fcabahrens * can't connect and start talking to in.mpathd
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (setsockopt(s, IPPROTO_TCP, TCP_ANONPRIVBIND, &on,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (on)) < 0) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("Setting groupname %s on interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFGROUPNAME, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If the SUNW_NO_MPATHD environment variable is set then don't
fa9e4066f08beec538e775443c5be79dd423fcabahrens * bother starting up in.mpathd. See PSARC/2002/249 for the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * depressing details on this bit of stupidity.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to connect to in.mpathd using IPv4. If we succeed,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we conclude that in.mpathd is running, and quit.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* connect succeeded, mpathd is already running */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to connect to in.mpathd using IPv6. If we succeed,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we conclude that in.mpathd is running, and quit.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* connect succeeded, mpathd is already running */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in.mpathd may not be running. Start it now. If it is already
fa9e4066f08beec538e775443c5be79dd423fcabahrens * running, in.mpathd will take care of handling multiple incarnations
fa9e4066f08beec538e775443c5be79dd423fcabahrens * of itself. ifconfig only tries to optimize performance by not
fa9e4066f08beec538e775443c5be79dd423fcabahrens * starting another incarnation of in.mpathd.
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (fork()) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * To list all the modules above a given network interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((num_mods = ioctl(ipfd_lowstr, I_LIST, NULL)) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("cannot I_LIST to get the number of modules");
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin strlist.sl_modlist = malloc(sizeof (struct str_mlist) *
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(ipfd_lowstr, I_LIST, (caddr_t)&strlist) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (ip_plink(muxfd, ipfd_lowstr, arpfd_lowstr, orig_arpid));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * To insert a module to the stream of the interface. It is just a
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * wrapper. The real function is modop().
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * To remove a module from the stream of the interface. It is just a
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * wrapper. The real function is modop().
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Open a stream on /dev/udp, pop off all undesired modules (note that
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * the user may have configured autopush to add modules above or below
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * udp), and push the arp module onto raw IP.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((fd = open(udp_dev_name, O_RDWR)) == -1) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (ioctl(fd, I_PUSH, ARP_MOD_NAME) == -1) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Helper function for mod*() functions. It gets a fd to the lower IP
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * stream and I_PUNLINK's the lower stream. It also initializes the
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * global variable lifr.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int *udp_fd: (referenced) fd to /dev/udp (upper IP stream).
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int *fd: (referenced) fd to the lower IP stream.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * -1 if operation fails, 0 otherwise.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Please see the big block comment above plumb_one_device()
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * for the logic of the PLINK/PUNLINK
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyip_domux2fd(int *muxfd, int *ipfd_lowstr, int *arpfd_lowstr, int *orig_arpid)
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((ip_fd = open(ip_dev_name, O_RDWR)) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(ip_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) printf("ARP_muxid %d IP_muxid %d\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid, lifr.lifr_ip_muxid);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*muxfd = open_arp_on_udp(udp_dev_name)) == -1)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*arpfd_lowstr = ioctl(*muxfd, _I_MUXID2FD,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Some plumbing utilities set the muxid to
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * -1 or some invalid value to signify that
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * there is no arp stream. Set the muxid to 0
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * before trying to unplumb the IP stream.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * IP does not allow the IP stream to be
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * unplumbed if it sees a non-null arp muxid,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * for consistency of IP-ARP streams.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*ipfd_lowstr = ioctl(*muxfd, _I_MUXID2FD,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo any changes we made */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(*muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(*muxfd, I_PUNLINK, lifr.lifr_ip_muxid) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo any changes we made */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(*muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Helper function for mod*() functions. It I_PLINK's back the upper and
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * lower IP streams. Note that this function must be called after
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * ip_domux2fd(). In ip_domux2fd(), the global variable lifr is initialized
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * and ip_plink() needs information in lifr. So ip_domux2fd() and ip_plink()
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * must be called in pairs.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int udp_fd: fd to /dev/udp (upper IP stream).
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int fd: fd to the lower IP stream.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * -1 if operation fails, 0 otherwise.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Please see the big block comment above plumb_one_device()
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * for the logic of the PLINK/PUNLINK
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyip_plink(int muxfd, int ipfd_lowstr, int arpfd_lowstr, int orig_arpid)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy ip_muxid = ioctl(muxfd, I_PLINK, ipfd_lowstr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * If there is an arp stream, plink it. If there is no
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * arp stream, then it is possible that the plumbing
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * utility could have stored any value in the arp_muxid.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * If so, restore it from orig_arpid.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(muxfd, I_PLINK, arpfd_lowstr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (orig_arpid != 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo the changes we did in ip_domux2fd */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * The names of other core TCP/IP stack modules which cannot be removed.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * The real function to perform module insertion/removal.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * char *arg: the argument string module_name@position
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * char op: operation, either MODINSERT_OP or MODREMOVE_OP.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Before doing ip_domux2fd(), this function calls exit(1) in case of
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * error. After ip_domux2fd() is done, it returns -1 for error, 0
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int ipfd_lowstr; /* IP stream (lower stream of mux) to be plinked */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int arpfd_lowstr; /* ARP stream (lower stream of mux) to be plinked */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Need to save the original string for -a option. */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((arg_str = malloc(strlen(arg) + 1)) == NULL) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy "ifconfig: must supply a module name\n");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy mod.mod_name = strtok(arg_str, at_char);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: module name too long: %s\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Need to make sure that the core TCP/IP stack modules are not
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * removed. Otherwise, "bad" things can happen. If a module
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin * is removed and inserted back, it loses its old state. But
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * the modules above it still have the old state. E.g. IP assumes
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin * fast data path while tunnel after re-inserted assumes that it can
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * receive M_DATA only in fast data path for which it does not have
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * any state. This is a general caveat of _I_REMOVE/_I_INSERT.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (strcmp(mod.mod_name, ARP_MOD_NAME) == 0 ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy strcmp(mod.mod_name, IP_MOD_NAME) == 0 ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy strcmp(mod.mod_name, TUN6TO4_NAME) == 0)) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: cannot remove %s\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((pos_p = strtok(NULL, at_char)) == NULL) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: must supply a position\n");
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee if (ioctl(ipfd_lowstr, _I_INSERT, (caddr_t)&mod) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(ipfd_lowstr, _I_REMOVE, (caddr_t)&mod) < 0) {
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee /* Should never get to here. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ip_plink(muxfd, ipfd_lowstr, arpfd_lowstr, orig_arpid));
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick str = _link_ntoa((const unsigned char *)lifr.lifr_nd.lnr_hdw_addr,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy str, lifr.lifr_nd.lnr_hdw_len, IFT_OTHER);
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick * XXX parse phyaddr? Need syntax to fit in one argv.
e05725b117836db173257fae43fb0746eb857fb5bonwick * XXX <proto addr>/<phyaddr> ??
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick#endif /* DEBUG */
e05725b117836db173257fae43fb0746eb857fb5bonwick * Set tunnel source address
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwick * Set tunnel destination address
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwick * sets tunnels src|dst address. settaddr() expects the following:
e05725b117836db173257fae43fb0746eb857fb5bonwick * addr: Points to a printable string containing the address to be
e05725b117836db173257fae43fb0746eb857fb5bonwick * set, e.g. 129.153.128.110.
e05725b117836db173257fae43fb0746eb857fb5bonwick * fn: Pointer to a libinetcfg routine that will do the actual work.
e05725b117836db173257fae43fb0746eb857fb5bonwick * The only valid functions are icfg_set_tunnel_src and
fa9e4066f08beec538e775443c5be79dd423fcabahrens * icfg_set_tunnel_dest.
e05725b117836db173257fae43fb0746eb857fb5bonwick int (*fn)(icfg_handle_t, const struct sockaddr *, socklen_t))
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Tunnel params on logical interfaces");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Open interface. */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((rc = icfg_open(&handle, &interface)) != ICFG_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Call fn to do the real work, and close the interface. */
e05725b117836db173257fae43fb0746eb857fb5bonwick sizeof (struct sockaddr_storage));
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set tunnel encapsulation limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwick if ((sscanf(arg, "%hd", &limit) != 1) || (limit < 0) ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit("Invalid encapsulation limit");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Open interface for configuration. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit("couldn't open interface");
e05725b117836db173257fae43fb0746eb857fb5bonwick rc = icfg_set_tunnel_encaplimit(handle, (int)limit);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Could not configure tunnel encapsulation limit");
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick/* Disable encapsulation limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Tunnel params on logical interfaces");
e05725b117836db173257fae43fb0746eb857fb5bonwick /* Open interface for configuration. */
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwick (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick if (icfg_open(&handle, &interface) != ICFG_SUCCESS)
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick/* Set tunnel hop limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned short limit;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Check limit here since it's really only an 8-bit unsigned quantity.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((sscanf(arg, "%hu", &limit) != 1) || (limit > 255)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Open interface for configuration. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = icfg_set_tunnel_hoplimit(handle, (uint8_t)limit);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock Perror0_exit("Could not configure tunnel hop limit");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set zone ID */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* zone must be active */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set source address to use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Argument can be either an interface name or "none". The latter means
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that any previous selection is cleared.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rval == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Cannot specify same interface for usesrc"
fa9e4066f08beec538e775443c5be79dd423fcabahrens " group\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rval != 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("setifsrc: lifr_name %s, lifr_index %d\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCSLIFUSESRC, (caddr_t)&lifr) == -1) {
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Print the interface status line associated with `ifname'
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick * In V4 compatibility mode, we don't print the IFF_IPV4 flag or
e05725b117836db173257fae43fb0746eb857fb5bonwick * interfaces with IFF_IPV6 set.
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* don't print index or zone when in compatibility mode */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (zone_name)) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick * Find the number of interfaces that use this interfaces'
e05725b117836db173257fae43fb0746eb857fb5bonwick * address as a source address
e05725b117836db173257fae43fb0746eb857fb5bonwick /* The first pass will give the bufsize we need */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Use kernel's size + a small margin to avoid loops */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For the first pass, realloc acts like malloc */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi numifs = lifs.lifs_len / sizeof (struct lifreq);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /* Find the interface whose source address this interface uses */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) == 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) printf("\n\tusesrc %s", if_usesrc_name);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Print the status of the interface. If an address family was
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * specified, show it and it only; otherwise, show them all.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Only print the interface status if the address family matches
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * the interface family flag.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (((p->af_af == AF_INET6) && (flags & IFF_IPV4)) ||
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi ((p->af_af == AF_INET) && (flags & IFF_IPV6)))
1bc69b9cd8bf4a24b90a7093402f3ad21f3818b8Sanjeev Bagewadi * In V4 compatibility mode, don't print IFF_IPV6 interfaces.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi s = socket(SOCKET_AF(p->af_af), SOCK_DGRAM, 0);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /* set global af for use in p->af_status */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (s == -1) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Historically, 'ether' has been an address family,
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * so print it here.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Print the status of the interface in a format that can be used to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * reconfigure the interface later. Code stolen from status() above.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("configinfo: name %s flags 0x%llx af_af %d\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick /* remove LIF component */
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(phydevname, name, sizeof (phydevname));
e05725b117836db173257fae43fb0746eb857fb5bonwick * if the interface is IPv4
e05725b117836db173257fae43fb0746eb857fb5bonwick * if we have a IPv6 address family restriction return
e05725b117836db173257fae43fb0746eb857fb5bonwick * so it won't print
e05725b117836db173257fae43fb0746eb857fb5bonwick * if we are in IPv4 compatibility mode, clear out IFF_IPV4
fa9e4066f08beec538e775443c5be79dd423fcabahrens * so we don't print it.
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
e05725b117836db173257fae43fb0746eb857fb5bonwick * else if the interface is IPv6
e05725b117836db173257fae43fb0746eb857fb5bonwick * if we have a IPv4 address family restriction return
e05725b117836db173257fae43fb0746eb857fb5bonwick * or we are in IPv4 compatibiltiy mode, return.
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick if (((flags & (IFF_VIRTUAL|IFF_LOOPBACK)) != IFF_VIRTUAL) &&
e05725b117836db173257fae43fb0746eb857fb5bonwick /* don't print index when in compatibility mode */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) == 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (p != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick /* set global af for use in p->af_configinfo */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (s == -1) {
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick * Deal with versioning, for now just point
e05725b117836db173257fae43fb0746eb857fb5bonwick * an ipsec_req_t at ifta_secinfo. If versions
e05725b117836db173257fae43fb0746eb857fb5bonwick * change, something else will overlay ifta_secinfo.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_auth_alg, IPSEC_PROTO_AH));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ipsr->ipsr_esp_req & IPSEC_PREF_REQUIRED) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_esp_alg, IPSEC_PROTO_ESP));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_esp_auth_alg, IPSEC_PROTO_AH));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if ((rc = icfg_open(&handle, &interface)) != ICFG_SUCCESS)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * only print tunnel info for lun 0. If ioctl fails, assume
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * we are not a tunnel
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_get_tunnel_lower(handle, &protocol) != ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("\ttunnel: Illegal lower stream\n\t");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_get_tunnel_src(handle, (struct sockaddr *)&taddr, &socklen);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strlcpy(srcbuf, (protocol == AF_INET) ? "0.0.0.0" :
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_sockaddr_to_str(protocol, (struct sockaddr *)&taddr,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf(" tunnel src %s ", srcbuf);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_get_tunnel_dest(handle, (struct sockaddr *)&taddr, &socklen);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_sockaddr_to_str(protocol, (struct sockaddr *)&taddr,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel dst %s\n", dstbuf);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (handle->ifh_tunnel_params->ifta_flags & IFTUN_SECURITY))
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * tabbed indicates tabbed and printed. Use it tell us whether
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * to tab and that we've printed something here, so we need a
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (icfg_get_tunnel_hoplimit(handle, &hoplimit) == ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\ttunnel hop limit %d ", hoplimit);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (icfg_get_tunnel_encaplimit(handle, &encaplimit) ==
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel encapsulation limit %d",
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel encapsulation limit disabled");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia struct sockaddr_in netmask = { AF_INET };
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("in_status(%s) flags 0x%llx\n", name, flags);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* only print status for IPv4 interfaces */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* if the interface is a tunnel, print the tunnel status */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin = (struct sockaddr_in *)&lifr.lifr_addr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\tinet %s ", inet_ntoa(sin->sin_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFSUBNET");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin = (struct sockaddr_in *)&lifr.lifr_addr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin->sin_addr.s_addr != laddr->sin_addr.s_addr) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("subnet %s/%d ", inet_ntoa(sin->sin_addr),
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("Wrong family: %d\n", sin->sin_family);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFNETMASK");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia ((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFDSTADDR");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin = (struct sockaddr_in *)&lifr.lifr_dstaddr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("--> %s ", inet_ntoa(sin->sin_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If there is a groupname, print it for lun 0 alone */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) printf("in6_status(%s) flags 0x%llx\n", name, flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* if the interface is a tunnel, print the tunnel status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby !IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &laddr6->sin6_addr)) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("Wrong family: %d\n", sin6->sin6_family);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sin6 = (struct sockaddr_in6 *)&lifr.lifr_dstaddr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFTOKEN, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFLNKINFO, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby "reachretrans %u ms, maxmtu %u ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby /* If there is a groupname, print it for lun 0 alone */
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("in_configinfo(%s) flags 0x%llx\n", name, flags);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby /* only configinfo info for IPv4 interfaces */
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" addif %s ", inet_ntoa(sin->sin_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf(" subnet %s/%d ", inet_ntoa(sin->sin_addr),
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFNETMASK");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFDSTADDR");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin = (struct sockaddr_in *)&lifr.lifr_dstaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" destination %s ", inet_ntoa(sin->sin_addr));
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) printf(" netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFBRDADDR");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* If there is a groupname, print it for lun 0 alone */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* Print flags to configure */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* IFF_NOARP applies to AF_INET only */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("in6_configinfo(%s) flags 0x%llx\n", name,
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (ioctl(s, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens !IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &laddr6->sin6_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If there is a groupname, print it for lun 0 alone */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Print flags to configure */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* IFF_NONUD applies to AF_INET6 only */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* remove LIF component */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We need to plink both the arp-device stream and the arp-ip-device stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * However the muxid is stored only in IP. Plumbing 2 streams individually
fa9e4066f08beec538e775443c5be79dd423fcabahrens * is not atomic, and if ifconfig is killed, the resulting plumbing can
fa9e4066f08beec538e775443c5be79dd423fcabahrens * be inconsistent. For eg. if only the arp stream is plumbed, we have lost
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the muxid, and the half-baked plumbing can neither be unplumbed nor
fa9e4066f08beec538e775443c5be79dd423fcabahrens * replumbed, thus requiring a reboot. To avoid the above the following
fa9e4066f08beec538e775443c5be79dd423fcabahrens * scheme is used.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Ifconfig asks IP to enforce atomicity of plumbing the arp and IP streams.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This is done by pushing arp on to the mux (/dev/udp). ARP adds some
fa9e4066f08beec538e775443c5be79dd423fcabahrens * extra information in the I_PLINK and I_PUNLINK ioctls to let IP know
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that the plumbing/unplumbing has to be done atomically. Ifconfig plumbs
e05725b117836db173257fae43fb0746eb857fb5bonwick * the IP stream first, and unplumbs it last. The kernel (IP) does not
fa9e4066f08beec538e775443c5be79dd423fcabahrens * allow IP stream to be unplumbed without unplumbing arp stream. Similarly
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it does not allow arp stream to be plumbed before IP stream is plumbed.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There is no need to use SIOCSLIFMUXID, since the whole operation is atomic,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and IP uses the info in the I_PLINK message to get the muxid.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * a. STREAMS does not allow us to use /dev/ip itself as the mux. So we use
fa9e4066f08beec538e775443c5be79dd423fcabahrens * b. SIOCGLIFMUXID returns the muxid corresponding to the V4 or V6 stream
fa9e4066f08beec538e775443c5be79dd423fcabahrens * depending on the open i.e. V4 vs V6 open. So we need to use /dev/udp
fa9e4066f08beec538e775443c5be79dd423fcabahrens * c. We need to push ARP in order to get the required kernel support for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * atomic plumbings. The actual work done by ARP is explained in arp.c
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Without pushing ARP, we will still be able to plumb/unplumb. But
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it is not atomic, and is supported by the kernel for backward
fa9e4066f08beec538e775443c5be79dd423fcabahrens * compatibility for other utilities like atmifconfig etc. In this case
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick * the utility must use SIOCSLIFMUXID.
fa9e4066f08beec538e775443c5be79dd423fcabahrensplumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("plumb_one_device: ifname %s, ppa %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (diap->style == DL_STYLE2 && dlpi_detach(ip_fd, -1) < 0)
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick * Push the ARP module onto the interface stream. IP uses
fa9e4066f08beec538e775443c5be79dd423fcabahrens * this to send resolution requests up to ARP. We need to
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick * do this before the SLIFNAME ioctl is sent down because
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the interface becomes publicly known as soon as the SLIFNAME
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ioctl completes. Thus some other process trying to bring up
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the interface after SLIFNAME but before we have pushed ARP
fa9e4066f08beec538e775443c5be79dd423fcabahrens * could hang. We pop the module again later if it is not needed.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * At this point in time the kernel also allows an
fa9e4066f08beec538e775443c5be79dd423fcabahrens * override of the CANTCHANGE flags.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Set the name string and the IFF_IPV* flag */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* record the device and module names as interface name */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* set the interface name */
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (ioctl(ip_fd, SIOCSLIFNAME, (char *)&lifr) == -1) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick * This difference between the way we behave for EEXIST
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and that with other errors exists to preserve legacy
fa9e4066f08beec538e775443c5be79dd423fcabahrens * behaviour. Earlier when foreachinterface() and matcif()
fa9e4066f08beec538e775443c5be79dd423fcabahrens * were doing the duplicate interface name checks, for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * already existing interfaces, inetplumb() returned "0".
fa9e4066f08beec538e775443c5be79dd423fcabahrens * To preserve this behaviour, Perror0() and return are
fa9e4066f08beec538e775443c5be79dd423fcabahrens * called for EEXIST.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the full set of existing flags for this stream */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1)
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin /* Check if arp is not actually needed */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin * Open "/dev/udp" for use as a multiplexor to PLINK the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface stream under. We use "/dev/udp" instead of "/dev/ip"
fa9e4066f08beec538e775443c5be79dd423fcabahrens * since STREAMS will not let you PLINK a driver under itself,
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens * and "/dev/ip" is typically the driver at the bottom of
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin * the stream for tunneling interfaces.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Check if arp is not needed */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * PLINK the interface stream so that ifconfig can exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens * without tearing down the stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This interface does use ARP, so set up a separate stream
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from the interface to ARP.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note: modules specified by the user are pushed
fa9e4066f08beec538e775443c5be79dd423fcabahrens * only on the interface stream, not on the ARP stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dia.style == DL_STYLE2 && dlpi_detach(arp_fd, -1) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Tell ARP the name and unit number for this interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note that arp has no support for transparent ioctls.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * PLINK the IP and ARP streams so that ifconfig can exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens * without tearing down the stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((arp_muxid = ioctl(mux_fd, I_PLINK, arp_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If this is a physical interface then remove it.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If it is a logical interface name use SIOCLIFREMOVEIF to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * remove it. In both cases fail if it doesn't exist.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strptr != NULL || strcmp(name, LOOPBACK_IF) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Can't unplumb logical interface zero */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We used /dev/udp or udp6 to set up the mux. So we have to use
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the same now for PUNLINK also.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(mux_fd, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(mux_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We don't have a good way of knowing whether the arp stream is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * plumbed. We can't rely on IFF_NOARP because someone could
fa9e4066f08beec538e775443c5be79dd423fcabahrens * have turned it off later using "ifconfig xxx -arp".
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * Some plumbing utilities set the muxid to
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * -1 or some invalid value to signify that
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * there is no arp stream. Set the muxid to 0
0a4e9518a44f226be6d39383330b5b1792d2f184gw * before trying to unplumb the IP stream.
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * IP does not allow the IP stream to be
0a4e9518a44f226be6d39383330b5b1792d2f184gw * unplumbed if it sees a non-null arp muxid,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * for consistency of IP-ARP streams.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Some error occurred, and we need to restore
fa9e4066f08beec538e775443c5be79dd423fcabahrens * everything back to what it was.
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) ioctl(mux_fd, SIOCSLIFMUXID, (caddr_t)&lifr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If this is a physical interface then create it unless it is already
fa9e4066f08beec538e775443c5be79dd423fcabahrens * present. If it is a logical interface name use SIOCLIFADDIF to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * create and (and fail it if already exists.)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * As a special case send SIOCLIFADDIF for the loopback interface. This
fa9e4066f08beec538e775443c5be79dd423fcabahrens * is needed since there is no other notion of plumbing the loopback
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (islo && ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s already exists\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * IP can create the new logical interface on a different
fa9e4066f08beec538e775443c5be79dd423fcabahrens * physical interface in the same IPMP group. Take the new
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface into account for further operations.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("inetplumb: %s af %d\n", name, afp->af_af);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if ((dev_fd = dlpi_if_open(name, &dia, _B_FALSE)) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "%s: %s: no such interface\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "%s: %s: permission denied\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) fprintf(stderr, "%s: %s: permission denied\n",
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) snprintf(buf, sizeof (buf), "%s: %s", cmd, str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Print out error message (Perror2()) and exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * If the last argument is non-NULL allow a <addr>/<n> syntax and
fa9e4066f08beec538e775443c5be79dd423fcabahrens * pass out <n> in *plenp.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If <n> doesn't parse return BAD_ADDR as *plenp.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If no /<n> is present return NO_PREFIX as *plenp.
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getaddr(char *s, struct sockaddr *saddr, int *plenp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look for '/'<n> is plenp
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick *plenp = in_getprefixlen(str, _B_TRUE, ADDRBITS_V4);
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) fprintf(stderr, "ifconfig: %s: unexpected '/'\n", str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to catch attempts to set the broadcast address to all 1's.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
e05725b117836db173257fae43fb0746eb857fb5bonwick sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
fa9e4066f08beec538e775443c5be79dd423fcabahrens "(try again later)\n", s);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) fprintf(stderr, "ifconfig: %s: bad address\n", s);
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick * If the last argument is non-NULL allow a <addr>/<n> syntax and
fa9e4066f08beec538e775443c5be79dd423fcabahrens * pass out <n> in *plenp.
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens * If <n> doesn't parse return BAD_ADDR as *plenp.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If no /<n> is present return NO_PREFIX as *plenp.
fa9e4066f08beec538e775443c5be79dd423fcabahrensin6_getaddr(char *s, struct sockaddr *saddr, int *plenp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)saddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look for '/'<n> is plenp
0b69c2f001a429251e2d38f25aca860396551214ahrens (void) fprintf(stderr, "ifconfig: %s: unexpected '/'\n", str);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick hp = getipnodebyname(str, AF_INET6, 0, &error_num);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memcpy(&sin6->sin6_addr, hp->h_addr, hp->h_length);
fa9e4066f08beec538e775443c5be79dd423fcabahrens "(try again later)\n", s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s: bad address\n", s);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * If "slash" is zero this parses the whole string as
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * an integer. With "slash" non zero it parses the tail part as an integer.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * If it is not a valid integer this returns BAD_ADDR.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * If there is /<n> present this returns NO_PREFIX.
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getprefixlen(char *addr, boolean_t slash, int max_plen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Convert a prefix length to a mask.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Returns 1 if ok. 0 otherwise.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Assumes the mask array is zero'ed by the caller.
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (prefixlen > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < cnt; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * It has to be here and not with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * printf below because for the last one,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we don't want a comma before the ">".
fa9e4066f08beec538e775443c5be79dd423fcabahrens cnt = sizeof (if_config_cmd_tbl) / sizeof (if_config_cmd_t);
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock for (i = 0; i < cnt; i++) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Use the configured directory lookup mechanism (e.g. files/NIS/NIS+/...)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * to find the network mask. Returns true if we found one to set.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * The parameter addr_set controls whether we should get the address of
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the working interface for the netmask query. If addr_set is true,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we will use the address provided. Otherwise, we will find the working
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface's address and use it instead.
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getmask(struct sockaddr_in *saddr, boolean_t addr_set)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Read the address from the interface if it is not passed in.
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (getnetmaskbyaddr(ifaddr.sin_addr, &saddr->sin_addr) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (pp = &ni_list; (p = *pp) != NULL; pp = &(p->ni_next)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(p->ni_name, name, sizeof (p->ni_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED2 */
fa9e4066f08beec538e775443c5be79dd423fcabahrensdevfs_entry(di_node_t node, di_minor_t minor, void *arg)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens "non-alias node, ignoring\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens "alias node, using instance\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens "non-existent PPA, ignoring\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(ifname, LIFNAMSIZ, "%s%d", provider, ppa);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dhcp-related routines
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifdhcp(const char *caller, const char *ifname, int argc, char *argv[])
if (--argc <= 0) {
usage();
return (DHCP_EXIT_BADARGS);
argv++;
usage();
return (DHCP_EXIT_BADARGS);
if (timeout < 0) {
usage();
return (DHCP_EXIT_BADARGS);
usage();
return (DHCP_EXIT_BADARGS);
return (DHCP_EXIT_FAILURE);
if (is_primary)
return (DHCP_EXIT_SYSTEM);
if (error != 0) {
return (DHCP_EXIT_FAILURE);
if (error != 0) {
return (DHCP_EXIT_SUCCESS);
return (DHCP_EXIT_TIMEOUT);
return (DHCP_EXIT_IF_FAILURE);
return (DHCP_EXIT_SUCCESS);
usage(void)