ifconfig.c revision ff550d0e264b51131fb34e9e83163b348d916640
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling/*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "defs.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "strings.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "ifconfig.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <compat.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dlpi.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libdlpi.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <inet/ip.h>
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define LOOPBACK_IF "lo0"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define NONE_STR "none"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifndef ARP_MOD_NAME
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ARP_MOD_NAME "arp"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDRBITS_V4 32 /* number of bits in IPv4 address */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define ADDRBITS_V6 128 /* number of bits in IPv6 address */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define AF_FUNC_STATUS 1 /* af_status func reports status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define AF_FUNC_CONFIGINFO 2 /* af_status func reports configinfo */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct if_flags {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t iff_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *iff_name;
fa9e4066f08beec538e775443c5be79dd423fcabahrens} if_flags_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic if_flags_t if_flags_tbl[] = {
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_UP, "UP" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_BROADCAST, "BROADCAST" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_DEBUG, "DEBUG" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_LOOPBACK, "LOOPBACK" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_POINTOPOINT, "POINTOPOINT" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOTRAILERS, "NOTRAILERS" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_RUNNING, "RUNNING" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOARP, "NOARP" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_PROMISC, "PROMISC" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_ALLMULTI, "ALLMULTI" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_INTELLIGENT, "INTELLIGENT" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_MULTICAST, "MULTICAST" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_MULTI_BCAST, "MULTI_BCAST" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_UNNUMBERED, "UNNUMBERED" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_DHCPRUNNING, "DHCP" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_PRIVATE, "PRIVATE" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOXMIT, "NOXMIT" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOLOCAL, "NOLOCAL" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_DEPRECATED, "DEPRECATED" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_ADDRCONF, "ADDRCONF" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_ROUTER, "ROUTER" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NONUD, "NONUD" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_ANYCAST, "ANYCAST" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NORTEXCH, "NORTEXCH" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_IPV4, "IPv4" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_IPV6, "IPv6" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_MIPRUNNING, "MIP" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOFAILOVER, "NOFAILOVER" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_FAILED, "FAILED" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_STANDBY, "STANDBY" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_INACTIVE, "INACTIVE" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_OFFLINE, "OFFLINE" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_XRESOLV, "XRESOLV" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_COS_ENABLED, "CoS" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_PREFERRED, "PREFERRED" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_TEMPORARY, "TEMPORARY" },
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy { IFF_FIXEDMTU, "FIXEDMTU" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_VIRTUAL, "VIRTUAL"}
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct lifreq lifr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* current interface name a praticular function is accessing */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char name[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* foreach interface saved name */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char origname[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char savedname[LIFNAMSIZ]; /* For addif */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char partname[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensuid_t euid;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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.)
004388ebfdfe2ed7dfd2d153a876dfcc22d2c006casper */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define NO_AH_AALG 256
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define NO_ESP_AALG 256
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define NO_ESP_EALG 256
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * iface_t
fa9e4066f08beec538e775443c5be79dd423fcabahrens * used by setifether to create a list of interfaces to mark
fa9e4066f08beec538e775443c5be79dd423fcabahrens * down-up when changing the ethernet address of an interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct iface {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct lifreq lifr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct iface *next; /* pointer to the next list element */
fa9e4066f08beec538e775443c5be79dd423fcabahrens} iface_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwickstatic iface_t *logifs = NULL; /* list of logical interfaces */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic iface_t *phyif = NULL; /* physical interface */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrockint s;
fa9e4066f08beec538e775443c5be79dd423fcabahrensint af = AF_INET; /* default address family */
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwickint debug = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrensint all = 0; /* setifdhcp() needs to know this */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint verbose = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrensint v4compat = 0; /* Compatible printing format */
fa9e4066f08beec538e775443c5be79dd423fcabahrensboolean_t partial = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Function prototypes for command functions.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int addif(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int inetplumb(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int inetunplumb(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int removeif(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setdebugflag(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifaddr(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifbroadaddr(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifdstaddr(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifether(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifflags(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifindex(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifmetric(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifmtu(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifnetmask(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifprefixlen(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifrevarp(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifsubnet(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setiftdst(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setiftoken(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setiftsrc(char *arg, int64_t param);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int setverboseflag(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int set_tun_ah_alg(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);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int modlist(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int modinsert(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int modremove(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int setifgroupname(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int configinfo(char *arg, int64_t param);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic void print_config_flags(uint64_t flags);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic void print_flags(uint64_t flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void print_ifether(char *ifname);
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);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setzone(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int setifsrc(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int setnd(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int delnd(char *arg, int64_t param);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int getnd(char *arg, int64_t param);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia#endif /* DEBUG */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Address family specific function prototypes.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in_getaddr(char *s, struct sockaddr *saddr, int *plenp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in_status(int force, uint64_t flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in_configinfo(int force, uint64_t flags);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musantestatic void in6_getaddr(char *s, struct sockaddr *saddr, int *plenp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in6_status(int force, uint64_t flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void in6_configinfo(int force, uint64_t flags);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Misc support functions
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic int devfs_entry(di_node_t node, di_minor_t minor, void *arg);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void foreachinterface(void (*func)(), int argc, char *argv[],
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby int af, int64_t onflags, int64_t offflags,
fa9e4066f08beec538e775443c5be79dd423fcabahrens int64_t lifc_flags);
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,
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t addr_set);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int in_getprefixlen(char *addr, boolean_t slash, int plen);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t in_prefixlentomask(int prefixlen, int maxlen,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uchar_t *mask);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int settaddr(char *, int (*)(icfg_handle_t,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct sockaddr *, socklen_t));
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,
fa9e4066f08beec538e775443c5be79dd423fcabahrens int argc, char *argv[]);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int ip_domux2fd(int *, int *, int *, int *);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int ip_plink(int, int, int, int);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int modop(char *arg, char op);
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int get_lun(char *);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastatic void selectifs(int argc, char *argv[], int af,
e05725b117836db173257fae43fb0746eb857fb5bonwick struct lifreq *lifrp);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadistatic int updownifs(iface_t *ifs, int up);
e05725b117836db173257fae43fb0746eb857fb5bonwick
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson#define max(a, b) ((a) < (b) ? (b) : (a))
e05725b117836db173257fae43fb0746eb857fb5bonwick
088f389458728c464569a5506b58070254fa4f7dahrens/*
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.
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby */
e05725b117836db173257fae43fb0746eb857fb5bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define DHCP_EXIT_IF_FAILURE -1
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define DHCP_IPC_MAX_WAIT 15 /* max seconds to wait to start agent */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define NEXTARG 0xffffff /* command takes an argument */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick#define OPTARG 0xfffffe /* command takes an optional argument */
e05725b117836db173257fae43fb0746eb857fb5bonwick#define AF_ANY (-1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Refer to the comments in ifconfig() on the netmask "hack" */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define NETMASK_CMD "netmask"
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct sockaddr_storage g_netmask;
fa9e4066f08beec538e775443c5be79dd423fcabahrensenum { G_NETMASK_NIL, G_NETMASK_PENDING, G_NETMASK_SET }
fa9e4066f08beec538e775443c5be79dd423fcabahrens g_netmask_set = G_NETMASK_NIL;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastruct cmd {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia char *c_name;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int64_t c_parameter; /* NEXTARG means next argv */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int (*c_func)(char *, int64_t);
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 */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia} cmds[] = {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "up", IFF_UP, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "down", -IFF_UP, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "trailers", -IFF_NOTRAILERS, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-trailers", IFF_NOTRAILERS, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "arp", -IFF_NOARP, setifflags, 0, AF_INET },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-arp", IFF_NOARP, setifflags, 0, AF_INET },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "router", IFF_ROUTER, setifflags, 0, AF_ANY },
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson { "-router", -IFF_ROUTER, setifflags, 0, AF_ANY },
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick { "private", IFF_PRIVATE, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-private", -IFF_PRIVATE, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "xmit", -IFF_NOXMIT, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-xmit", IFF_NOXMIT, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-nud", IFF_NONUD, setifflags, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "nud", -IFF_NONUD, setifflags, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "anycast", IFF_ANYCAST, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-anycast", -IFF_ANYCAST, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "local", -IFF_NOLOCAL, setifflags, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-local", IFF_NOLOCAL, 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 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "debug", 0, setdebugflag, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "verbose", 0, setverboseflag, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { NETMASK_CMD, NEXTARG, setifnetmask, 0, AF_INET },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "metric", NEXTARG, setifmetric, 0, AF_ANY },
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson { "mtu", NEXTARG, setifmtu, 0, AF_ANY },
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick { "index", NEXTARG, setifindex, 0, AF_ANY },
0a4e9518a44f226be6d39383330b5b1792d2f184gw { "broadcast", NEXTARG, setifbroadaddr, 0, AF_INET },
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "auto-revarp", 0, setifrevarp, 1, AF_INET },
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "plumb", 0, inetplumb, 1, AF_ANY },
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia { "unplumb", 0, inetunplumb, 0, AF_ANY },
e05725b117836db173257fae43fb0746eb857fb5bonwick { "subnet", NEXTARG, setifsubnet, 0, AF_ANY },
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson { "token", NEXTARG, setiftoken, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "tsrc", NEXTARG, setiftsrc, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "tdst", NEXTARG, setiftdst, 0, AF_ANY },
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 { "auth_algs", NEXTARG, set_tun_ah_alg, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "addif", NEXTARG, addif, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "removeif", NEXTARG, removeif, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "modlist", 0, modlist, 1, AF_ANY },
1ce825d872d2e7c96109ee3b5dbb6036ae4118d7raf { "modinsert", NEXTARG, modinsert, 1, AF_ANY },
f1b4288b3b466065edd5eb9868399db6a4ff283evb { "modremove", NEXTARG, modremove, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "failover", -IFF_NOFAILOVER, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-failover", IFF_NOFAILOVER, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "standby", IFF_STANDBY, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-standby", -IFF_STANDBY, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "failed", IFF_FAILED, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-failed", -IFF_FAILED, setifflags, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "group", NEXTARG, setifgroupname, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "configinfo", 0, configinfo, 1, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "encaplimit", NEXTARG, set_tun_encap_limit, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-encaplimit", 0, clr_tun_encap_limit, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "thoplimit", NEXTARG, set_tun_hop_limit, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "getnd", NEXTARG, getnd, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "setnd", NEXTARG, setnd, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "delnd", NEXTARG, delnd, 0, AF_INET6 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* XXX for testing SIOCT* ioctls. Remove */
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "set", NEXTARG, setifaddr, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "destination", NEXTARG, setifdstaddr, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "zone", NEXTARG, setzone, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "-zone", 0, setzone, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "ether", OPTARG, setifether, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { "usesrc", NEXTARG, setifsrc, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0, setifaddr, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0, setifdstaddr, 0, AF_ANY },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0, 0, 0, 0 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct if_config_cmd {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t iff_flag;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *iff_name;
fa9e4066f08beec538e775443c5be79dd423fcabahrens} if_config_cmd_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic if_config_cmd_t if_config_cmd_tbl[] = {
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_UP, "up" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOTRAILERS, "-trailers" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_PRIVATE, "private" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOXMIT, "-xmit" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_ANYCAST, "anycast" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOLOCAL, "-local" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_DEPRECATED, "deprecated" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_NOFAILOVER, "-failover" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_STANDBY, "standby" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_FAILED, "failed" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { IFF_PREFERRED, "preferred" },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { 0, 0 },
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct ni {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char ni_name[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct ni *ni_next;
fa9e4066f08beec538e775443c5be79dd423fcabahrens} ni_t;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f1b4288b3b466065edd5eb9868399db6a4ff283evbstatic ni_t *ni_list = NULL;
f1b4288b3b466065edd5eb9868399db6a4ff283evbstatic int num_ni = 0;
f1b4288b3b466065edd5eb9868399db6a4ff283evb
f1b4288b3b466065edd5eb9868399db6a4ff283evb/* End defines and structure definitions for ifconfig -a plumb */
f1b4288b3b466065edd5eb9868399db6a4ff283evb
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Known address families */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct afswtch {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *af_name;
f1b4288b3b466065edd5eb9868399db6a4ff283evb short af_af;
f1b4288b3b466065edd5eb9868399db6a4ff283evb void (*af_status)();
f1b4288b3b466065edd5eb9868399db6a4ff283evb void (*af_getaddr)();
fa9e4066f08beec538e775443c5be79dd423fcabahrens void (*af_configinfo)();
fa9e4066f08beec538e775443c5be79dd423fcabahrens} afs[] = {
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};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct afswtch *afp; /* the address family being set or asked about */
f1b4288b3b466065edd5eb9868399db6a4ff283evb
f1b4288b3b466065edd5eb9868399db6a4ff283evbint
fa9e4066f08beec538e775443c5be79dd423fcabahrensmain(int argc, char *argv[])
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Include IFF_NOXMIT, IFF_TEMPORARY and all zone interfaces */
f1b4288b3b466065edd5eb9868399db6a4ff283evb int64_t lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
f1b4288b3b466065edd5eb9868399db6a4ff283evb char *default_ip_str;
f1b4288b3b466065edd5eb9868399db6a4ff283evb
f1b4288b3b466065edd5eb9868399db6a4ff283evb if (argc < 2) {
f1b4288b3b466065edd5eb9868399db6a4ff283evb usage();
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens argc--, argv++;
f1b4288b3b466065edd5eb9868399db6a4ff283evb if (strlen(*argv) > sizeof (name) - 1) {
f1b4288b3b466065edd5eb9868399db6a4ff283evb (void) fprintf(stderr, "%s: interface name too long\n", *argv);
f1b4288b3b466065edd5eb9868399db6a4ff283evb exit(1);
f1b4288b3b466065edd5eb9868399db6a4ff283evb }
f1b4288b3b466065edd5eb9868399db6a4ff283evb (void) strncpy(name, *argv, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens name[sizeof (name) - 1] = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(origname, name, sizeof (origname)); /* For addif */
fa9e4066f08beec538e775443c5be79dd423fcabahrens euid = geteuid();
fa9e4066f08beec538e775443c5be79dd423fcabahrens default_ip_str = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens v4compat = get_compat_flag(&default_ip_str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (v4compat == DEFAULT_PROT_BAD_VALUE) {
f1b4288b3b466065edd5eb9868399db6a4ff283evb (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s: Bad value for %s in %s\n", default_ip_str,
fa9e4066f08beec538e775443c5be79dd423fcabahrens DEFAULT_IP, INET_DEFAULT_FILE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(default_ip_str);
f1b4288b3b466065edd5eb9868399db6a4ff283evb exit(2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(default_ip_str);
e05725b117836db173257fae43fb0746eb857fb5bonwick argc--, argv++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argc > 0) {
f1b4288b3b466065edd5eb9868399db6a4ff283evb struct afswtch *myafp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (myafp = afp = afs; myafp->af_name; myafp++) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (strcmp(myafp->af_name, *argv) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens afp = myafp; argc--; argv++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
99653d4ee642c6528e88224f12409a5f23060994eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens af = lifr.lifr_addr.ss_family = afp->af_af;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (af == AF_INET6) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens v4compat = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = socket(SOCKET_AF(af), SOCK_DGRAM, 0);
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (s < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("socket");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
f1b4288b3b466065edd5eb9868399db6a4ff283evb
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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
0a4e9518a44f226be6d39383330b5b1792d2f184gw */
0a4e9518a44f226be6d39383330b5b1792d2f184gw
0a4e9518a44f226be6d39383330b5b1792d2f184gw if (name[0] == '-') {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* One or more options */
f1b4288b3b466065edd5eb9868399db6a4ff283evb int64_t onflags = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int64_t offflags = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int c;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *av[2] = { "ifconfig", name };
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens while ((c = getopt(2, av, "audDXZ46v")) != -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch ((char)c) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'a':
fa9e4066f08beec538e775443c5be79dd423fcabahrens all = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'u':
fa9e4066f08beec538e775443c5be79dd423fcabahrens onflags |= IFF_UP;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'd':
fa9e4066f08beec538e775443c5be79dd423fcabahrens offflags |= IFF_UP;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'D':
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick offflags |= IFF_DHCPRUNNING;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'X':
fa9e4066f08beec538e775443c5be79dd423fcabahrens debug += 3;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 'Z':
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifc_flags &= ~LIFC_ALLZONES;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '4':
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * -4 is not a compatable flag, therefore
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we assume they want v4compat turned off
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens v4compat = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick onflags |= IFF_IPV4;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case '6':
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If they want IPv6, well then we'll assume
fa9e4066f08beec538e775443c5be79dd423fcabahrens * they don't want IPv4 compat
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock v4compat = 0;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock onflags |= IFF_IPV6;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock break;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock case 'v':
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock verbose = 1;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock break;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock case '?':
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock usage();
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock exit(1);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock }
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock }
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if (!all) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s: no such interface\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens foreachinterface(ifconfig, argc, argv, af, onflags, offflags,
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock lifc_flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ifconfig(argc, argv, af, (struct lifreq *)NULL);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock }
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick return (0);
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick}
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockstatic void
f94275ce205810a201404c5f35f4cc96057022b1Adam Leventhalforeachinterface(void (*func)(), int argc, char *argv[], int af,
99653d4ee642c6528e88224f12409a5f23060994eschrock int64_t onflags, int64_t offflags, int64_t lifc_flags)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock{
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick int n;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *buf;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock struct lifnum lifn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct lifconf lifc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct lifreq *lifrp;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock struct lifreq lifrl; /* Local lifreq struct */
e05725b117836db173257fae43fb0746eb857fb5bonwick int numifs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned bufsize;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock ni_t *nip;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int plumball = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int save_af = af;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argc > 0 && (strcmp(*argv, "plumb") == 0)) {
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look through the kernel's devinfo tree for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * network devices
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
fa9e4066f08beec538e775443c5be79dd423fcabahrens di_node_t root;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DINFOCACHE is equivalent to DINFOSUBTREE | DINFOMINOR |
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DINFOPROP | DINFOFORCE.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: di_init failed;"
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock " check the devinfo driver.\n");
f1b4288b3b466065edd5eb9868399db6a4ff283evb exit(1);
f1b4288b3b466065edd5eb9868399db6a4ff283evb }
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, NULL,
f1b4288b3b466065edd5eb9868399db6a4ff283evb devfs_entry);
fa9e4066f08beec538e775443c5be79dd423fcabahrens di_fini(root);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Now, translate the linked list into
99653d4ee642c6528e88224f12409a5f23060994eschrock * a struct lifreq buffer
99653d4ee642c6528e88224f12409a5f23060994eschrock */
fa9e4066f08beec538e775443c5be79dd423fcabahrens bufsize = num_ni * sizeof (struct lifreq);
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((buf = malloc(bufsize)) == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("foreachinterface: malloc failed");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick lifc.lifc_family = AF_UNSPEC;
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick lifc.lifc_flags = lifc_flags;
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick lifc.lifc_len = bufsize;
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick lifc.lifc_buf = buf;
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick for (n = 0, lifrp = lifc.lifc_req; n < num_ni; n++, lifrp++) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick nip = ni_list;
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick (void) strncpy(lifrp->lifr_name, nip->ni_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick ni_list = nip->ni_next;
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(nip);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens plumball = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifn.lifn_family = AF_UNSPEC;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifn.lifn_flags = lifc_flags;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("Could not determine number"
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick " of interfaces");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick numifs = lifn.lifn_count;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (debug)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf("ifconfig: %d interfaces\n", numifs);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick bufsize = numifs * sizeof (struct lifreq);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if ((buf = malloc(bufsize)) == NULL) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0("out of memory\n");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) close(s);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick return;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifc.lifc_family = AF_UNSPEC;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifc.lifc_flags = lifc_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifc.lifc_len = bufsize;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifc.lifc_buf = buf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("SIOCGLIFCONF");
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifrp = lifc.lifc_req;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!plumball) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(s);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens af = lifrp->lifr_addr.ss_family;
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = socket(SOCKET_AF(af), SOCK_DGRAM, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s == -1) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name,
99653d4ee642c6528e88224f12409a5f23060994eschrock lifrp->lifr_name, sizeof (lifr.lifr_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock Perror0_exit("socket");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Only service interfaces that match the on and off
fa9e4066f08beec538e775443c5be79dd423fcabahrens * flags masks.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (onflags || offflags) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifrl, 0, sizeof (lifrl));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifrl.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifrp->lifr_name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("foreachinterface: SIOCGLIFFLAGS");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((lifrl.lifr_flags & onflags) != onflags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((~lifrl.lifr_flags & offflags) != offflags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!plumball) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifrl.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifrl) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * globally defined lifreq structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifrp->lifr_name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("foreachinterface: SIOCGLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifrl.lifr_addr.ss_family != af) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Switch address family */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick af = lifrl.lifr_addr.ss_family;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) close(s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = socket(SOCKET_AF(af), SOCK_DGRAM, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Perror0() assumes the name to be in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the globally defined lifreq
fa9e4066f08beec538e775443c5be79dd423fcabahrens * structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) strncpy(lifr.lifr_name,
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick lifrp->lifr_name,
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick sizeof (lifr.lifr_name));
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick Perror0_exit("socket");
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens setaddr = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, lifrp->lifr_name, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(origname, name, sizeof (origname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (partial) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "checking partial %s against %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens partname, name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strncmp(name, partname, strlen(partname)))
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*func)(argc, argv, save_af, lifrp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* the func could have overwritten origname, so restore */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, origname, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenstun_reality_check(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct iftun_req treq;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ipsec_req_t *ipsr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(treq.ifta_lifr_name, name, sizeof (treq.ifta_lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strchr(name, ':') != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Return, we don't need to check. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGTUNPARAM, (caddr_t)&treq) < 0 ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens (treq.ifta_flags & IFTUN_SECURITY) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Either not a tunnel (the SIOCGTUNPARAM fails on
fa9e4066f08beec538e775443c5be79dd423fcabahrens * non-tunnels), or the security flag is not set. Either
fa9e4066f08beec538e775443c5be79dd423fcabahrens * way, return.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ipsr = (ipsec_req_t *)&treq.ifta_secinfo;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ipsr->ipsr_esp_req != 0 &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens ipsr->ipsr_esp_auth_alg == SADB_AALG_NONE &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens ipsr->ipsr_ah_req == 0)
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin (void) fprintf(stderr, "ifconfig: WARNING - tunnel with "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "only ESP and potentially no authentication.\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * for the specified interface call (*func)(argc, argv, af, lifrp).
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensifconfig(int argc, char *argv[], int af, struct lifreq *lifrp)
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin{
fa9e4066f08beec538e775443c5be79dd423fcabahrens static boolean_t scan_netmask = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (argc == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens status();
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(*argv, "auto-dhcp") == 0 || strcmp(*argv, "dhcp") == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (af == AF_INET) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * some errors are ignored in the case where
fa9e4066f08beec538e775443c5be79dd423fcabahrens * more than one interface is being operated on.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = setifdhcp("ifconfig", name, argc, argv);
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin if (ret == DHCP_EXIT_IF_FAILURE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!all)
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(DHCP_EXIT_FAILURE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else if (ret != DHCP_EXIT_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: dhcp not supported "
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin "for inet6\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 * correct.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
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 *
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 *
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!scan_netmask && afp->af_af == AF_INET) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int largc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char **largv;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Only go thru the command list once to find the netmask. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens scan_netmask = _B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (largc = argc, largv = argv; largc > 0; largc--, largv++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(*largv, NETMASK_CMD) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (--largc == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens largv++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(*largv, "+") == 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick g_netmask_set = G_NETMASK_PENDING;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens in_getaddr(*largv, (struct sockaddr *)
fa9e4066f08beec538e775443c5be79dd423fcabahrens &g_netmask, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens g_netmask_set = G_NETMASK_SET;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Continue the scan. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (argc > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct cmd *p;
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t found_cmd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("ifconfig: argv %s\n", *argv);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens found_cmd = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (p = cmds; p->c_func; p++) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (p->c_name) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (strcmp(*argv, p->c_name) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * indicate that the command was
fa9e4066f08beec538e775443c5be79dd423fcabahrens * found and check to see if
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the address family is valid
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens found_cmd = _B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (p->c_af == AF_ANY ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens af == p->c_af)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (p->c_af == AF_ANY ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens af == p->c_af)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick /*
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * If we found the keyword, but the address family
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * did not match spit out an error
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (found_cmd && p->c_name == 0) {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) fprintf(stderr, "ifconfig: Operation %s not"
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick " supported for %s\n", *argv, afp->af_name);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick exit(1);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick }
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick /*
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * else (no keyword found), we assume it's an address
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * of some sort
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (p->c_name == 0 && setaddr)
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick p++; /* got src, do dst */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (p->c_func) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (p->c_af == AF_INET6) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson v4compat = 0;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (p->c_parameter == NEXTARG ||
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson p->c_parameter == OPTARG) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson argc--, argv++;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (argc == 0 && p->c_parameter == NEXTARG) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson (void) fprintf(stderr,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson "ifconfig: no argument for %s\n",
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson p->c_name);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson exit(1);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Call the function if:
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson *
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * there's no address family
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * restriction
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * OR
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * we don't know the address yet
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (because we were called from
fa9e4066f08beec538e775443c5be79dd423fcabahrens * main)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * OR
fa9e4066f08beec538e775443c5be79dd423fcabahrens * there is a restriction AND
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the address families match
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e05725b117836db173257fae43fb0746eb857fb5bonwick if ((p->c_af == AF_ANY) ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens (lifrp == (struct lifreq *)NULL) ||
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson (lifrp->lifr_addr.ss_family == p->c_af)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = (*p->c_func)(*argv, p->c_parameter);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (ret != 0 && p->c_abortonfail)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return;
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson argc--, argv++;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /* Check to see if there's a security hole in the tunnel setup. */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin tun_reality_check();
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/* ARGSUSED */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonstatic int
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonsetdebugflag(char *val, int64_t arg)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson{
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson debug++;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson}
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/* ARGSUSED */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonstatic int
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonsetverboseflag(char *val, int64_t arg)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson verbose++;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson}
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * This function fills in the given lifreq's lifr_addr field based on
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * g_netmask_set.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonstatic void
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonset_mask_lifreq(struct lifreq *lifr, struct sockaddr_storage *addr,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson struct sockaddr_storage *mask)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson{
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson assert(addr != NULL);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson assert(mask != NULL);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson switch (g_netmask_set) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson case G_NETMASK_SET:
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson lifr->lifr_addr = g_netmask;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson break;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson case G_NETMASK_PENDING:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
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 * be set.
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick assert(afp->af_af == AF_INET);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick g_netmask = *addr;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_getmask((struct sockaddr_in *)&g_netmask, _B_TRUE)) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifr->lifr_addr = *mask;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick g_netmask_set = G_NETMASK_NIL;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifr->lifr_addr = g_netmask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick g_netmask_set = G_NETMASK_SET;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick break;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick case G_NETMASK_NIL:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick default:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifr->lifr_addr = *mask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick break;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick}
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick/*
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 */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick/* ARGSUSED */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic int
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwicksetifaddr(char *addr, int64_t param)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick{
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick int prefixlen = 0;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_storage laddr;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_storage netmask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_in6 *sin6;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_in *sin;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_storage sav_netmask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (addr[0] == '/')
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick return (setifprefixlen(addr, 0));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (*afp->af_getaddr)(addr, (struct sockaddr *)&laddr, &prefixlen);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(&netmask, 0, sizeof (netmask));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick netmask.ss_family = afp->af_af;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick switch (prefixlen) {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick case NO_PREFIX:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* Nothing there - ok */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick break;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick case BAD_ADDR:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) fprintf(stderr, "ifconfig: Bad prefix length in %s\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick addr);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick exit(1);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick default:
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (afp->af_af == AF_INET6) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin6 = (struct sockaddr_in6 *)&netmask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_prefixlentomask(prefixlen, ADDRBITS_V6,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (uchar_t *)&sin6->sin6_addr)) {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) fprintf(stderr, "ifconfig: "
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick "Bad prefix length: %d\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick prefixlen);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick exit(1);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin = (struct sockaddr_in *)&netmask;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (!in_prefixlentomask(prefixlen, ADDRBITS_V4,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (uchar_t *)&sin->sin_addr)) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) fprintf(stderr, "ifconfig: "
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick "Bad prefix length: %d\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick prefixlen);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * Just in case of funny setting of both prefix and netmask,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * prefix should override the netmask command.
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick g_netmask_set = G_NETMASK_NIL;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Tell parser that an address was set */
fa9e4066f08beec538e775443c5be79dd423fcabahrens setaddr++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* save copy of netmask to restore in case of error */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCGLIFNETMASK");
fa9e4066f08beec538e775443c5be79dd423fcabahrens sav_netmask = lifr.lifr_addr;
e05725b117836db173257fae43fb0746eb857fb5bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Catch set of address for AF_INET6 to perform
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * duplicate address detection. Check that the interface is
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick * up.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (afp->af_af == AF_INET6) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick Perror0_exit("ifsetaddr: SIOCGLIFFLAGS");
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (lifr.lifr_flags & IFF_UP) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick (void) printf(
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick "setifaddr: Calling ifdad flags %llx\n",
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick lifr.lifr_flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ifdad(name, (struct sockaddr_in6 *)&laddr) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(3);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens set_mask_lifreq(&lifr, &laddr, &netmask);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFNETMASK");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char abuf[INET6_ADDRSTRLEN];
fa9e4066f08beec538e775443c5be79dd423fcabahrens void *addr = (afp->af_af == AF_INET) ?
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void *)&((struct sockaddr_in *)&laddr)->sin_addr :
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void *)&((struct sockaddr_in6 *)&laddr)->sin6_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) printf("Setting %s af %d addr %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_name, afp->af_af,
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick inet_ntop(afp->af_af, addr, abuf, sizeof (abuf)));
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick }
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick lifr.lifr_addr = laddr;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick lifr.lifr_addr.ss_family = afp->af_af;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick /*
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick * Restore the netmask
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick */
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick int saverr = errno;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addr = sav_netmask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick errno = saverr;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick Perror0_exit("SIOCSLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick return (0);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick}
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick/*
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).
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwickstatic ulong_t
fa9e4066f08beec538e775443c5be79dd423fcabahrensparsenum(char *num)
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick{
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick ulong_t rc;
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick char *end = NULL;
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick errno = 0;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick rc = strtoul(num, &end, 0);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (errno != 0 || end == num || *end != '\0') {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick rc = (ulong_t)-1;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick }
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick return (rc);
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick}
9af0a4dffb12fece9e4ca0a97721e6e05ca2bca9Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 *
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 */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick#define NBUF_SIZE 20 /* Enough to print a large integer. */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwickstatic char *
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwickrparsealg(uint8_t alg_value, int proto_num)
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick{
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick struct ipsecalgent *alg;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick static char numprint[128]; /* Enough to hold an algorithm name. */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Special-case 0 to return "<any-none>" */
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (alg_value == 0)
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick return ("<any-none>");
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick alg = getipsecalgbynum(alg_value, proto_num, NULL);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (alg != NULL) {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) strlcpy(numprint, alg->a_names[0], sizeof (numprint));
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick freeipsecalgent(alg);
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick } else {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) snprintf(numprint, sizeof (numprint), "%d", alg_value);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (numprint);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic uint_t
fa9e4066f08beec538e775443c5be79dd423fcabahrensparsealg(char *algname, int proto_num)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct ipsecalgent *alg;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick ulong_t invalue;
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick if (algname == NULL) {
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick (void) fprintf(stderr, "ifconfig: Unexpected end of command "
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick "line.\n");
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick /*
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * Special-case "none". Use strcasecmp because its length is
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * bound.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcasecmp("none", algname) == 0) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick return ((proto_num == IPSEC_PROTO_ESP) ?
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick NO_ESP_EALG : NO_ESP_AALG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens alg = getipsecalgbyname(algname, proto_num, NULL);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (alg != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens invalue = alg->a_alg_num;
fa9e4066f08beec538e775443c5be79dd423fcabahrens freeipsecalgent(alg);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return ((uint_t)invalue);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Since algorithms can be loaded during kernel run-time, check for
31157203d871bc0b4bc67d925b0a8424570774a1Jeff Bonwick * numeric algorithm values too.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens invalue = parsenum(algname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((invalue & (ulong_t)0xff) == invalue)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return ((uint_t)invalue);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s algorithm type %s unknown.\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (proto_num == IPSEC_PROTO_ESP) ?
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Encryption" : "Authentication", algname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwick/*
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwick * Actual ifconfig functions to set tunnel security properties.
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwick */
088f389458728c464569a5506b58070254fa4f7dahrens
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwickenum ipsec_alg_type { ESP_ENCR_ALG = 1, ESP_AUTH_ALG, AH_AUTH_ALG };
f0aa80d4da975c8ef3e34c15c60ea31e9b75f7a9bonwick
088f389458728c464569a5506b58070254fa4f7dahrensboolean_t first_set_tun = _B_TRUE;
088f389458728c464569a5506b58070254fa4f7dahrensboolean_t encr_alg_set = _B_FALSE;
088f389458728c464569a5506b58070254fa4f7dahrens
088f389458728c464569a5506b58070254fa4f7dahrensstatic int
088f389458728c464569a5506b58070254fa4f7dahrensset_tun_algs(int which_alg, int alg)
088f389458728c464569a5506b58070254fa4f7dahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct iftun_req treq;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ipsec_req_t *ipsr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(treq.ifta_lifr_name, name, sizeof (treq.ifta_lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strchr(name, ':') != NULL) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson errno = EPERM;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror0_exit("Tunnel params on logical interfaces");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCGTUNPARAM, (caddr_t)&treq) < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (errno == EOPNOTSUPP || errno == EINVAL)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror0_exit("Not a tunnel");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson else Perror0_exit("SIOCGTUNPARAM");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr = (ipsec_req_t *)&treq.ifta_secinfo;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (treq.ifta_vers != IFTUN_VERSION) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) fprintf(stderr,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "Kernel tunnel secinfo version mismatch.\n");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
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 */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (first_set_tun) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson first_set_tun = _B_FALSE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) memset(ipsr, 0, sizeof (*ipsr));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson treq.ifta_flags = IFTUN_SECURITY;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson switch (which_alg) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case ESP_ENCR_ALG:
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (alg == NO_ESP_EALG) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ipsr->ipsr_esp_auth_alg == SADB_AALG_NONE)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_req = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_alg = SADB_EALG_NONE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson encr_alg_set = _B_TRUE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_req =
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_alg = alg;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case ESP_AUTH_ALG:
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (alg == NO_ESP_AALG) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ipsr->ipsr_esp_alg == SADB_EALG_NONE ||
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_alg == SADB_EALG_NULL)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_req = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_auth_alg = SADB_AALG_NONE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_req =
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_esp_auth_alg = alg;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Let the user specify NULL encryption implicitly. */
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (ipsr->ipsr_esp_alg == SADB_EALG_NONE &&
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson !encr_alg_set)
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson ipsr->ipsr_esp_alg = SADB_EALG_NULL;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson }
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson break;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson case AH_AUTH_ALG:
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (alg == NO_AH_AALG) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson ipsr->ipsr_ah_req = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_auth_alg = SADB_AALG_NONE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_ah_req =
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ipsr->ipsr_auth_alg = alg;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Will never hit DEFAULT */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSTUNPARAM, (caddr_t)&treq) < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror2_exit("set tunnel security properties",
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson treq.ifta_lifr_name);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonset_tun_esp_encr_alg(char *addr, int64_t param)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (set_tun_algs(ESP_ENCR_ALG,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson parsealg(addr, IPSEC_PROTO_ESP)));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonset_tun_esp_auth_alg(char *addr, int64_t param)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (set_tun_algs(ESP_AUTH_ALG,
fa9e4066f08beec538e775443c5be79dd423fcabahrens parsealg(addr, IPSEC_PROTO_AH)));
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensset_tun_ah_alg(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (set_tun_algs(AH_AUTH_ALG,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson parsealg(addr, IPSEC_PROTO_AH)));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonsetifrevarp(char *arg, int64_t param)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson struct sockaddr_in laddr;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (afp->af_af == AF_INET6) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) fprintf(stderr,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: revarp not possible on IPv6 interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (doifrevarp(name, &laddr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson laddr.sin_family = AF_INET;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) memcpy(&lifr.lifr_addr, &laddr, sizeof (laddr));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFADDR");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilsonsetifsubnet(char *addr, int64_t param)
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson int prefixlen = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson struct sockaddr_storage subnet;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (*afp->af_getaddr)(addr, &subnet, &prefixlen);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson switch (prefixlen) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case NO_PREFIX:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: Missing prefix length in subnet %s\n", addr);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* NOTREACHED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case BAD_ADDR:
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) fprintf(stderr,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: Bad prefix length in %s\n", addr);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson default:
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson lifr.lifr_addr = subnet;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson lifr.lifr_addrlen = prefixlen;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (ioctl(s, SIOCSLIFSUBNET, (caddr_t)&lifr) < 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson Perror0_exit("SIOCSLIFSUBNET");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (0);
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonsetifnetmask(char *addr, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in netmask;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson assert(afp->af_af != AF_INET6);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (strcmp(addr, "+") == 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (!in_getmask(&netmask, _B_FALSE))
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) printf("Setting netmask of %s to %s\n", name,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson inet_ntoa(netmask.sin_addr));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson in_getaddr(addr, (struct sockaddr *)&netmask, NULL);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
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 Perror0_exit("SIOCSLIFNETMASK");
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Parse '/<n>' as a netmask.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/* ARGSUSED */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonsetifprefixlen(char *addr, int64_t param)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson int prefixlen;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson int af = afp->af_af;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson prefixlen = in_getprefixlen(addr, _B_TRUE,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (af == AF_INET) ? ADDRBITS_V4 : ADDRBITS_V6);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (prefixlen < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) fprintf(stderr,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "ifconfig: Bad prefix length in %s\n", addr);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson exit(1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addr.ss_family = af;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (af == AF_INET6) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!in_prefixlentomask(prefixlen, ADDRBITS_V6,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (uchar_t *)&sin6->sin6_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else if (af == AF_INET) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in *sin;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin = (struct sockaddr_in *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!in_prefixlentomask(prefixlen, ADDRBITS_V4,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (uchar_t *)&sin->sin_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: setting prefix only supported"
e05725b117836db173257fae43fb0746eb857fb5bonwick " for address family inet or inet6\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFNETMASK");
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e19302335c33c8c6e0b0b5e426fc1f6352c84b5dbonwick/* ARGSUSED */
e19302335c33c8c6e0b0b5e426fc1f6352c84b5dbonwickstatic int
e19302335c33c8c6e0b0b5e426fc1f6352c84b5dbonwicksetifbroadaddr(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick struct sockaddr_in broadaddr;
e19302335c33c8c6e0b0b5e426fc1f6352c84b5dbonwick
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens assert(afp->af_af != AF_INET6);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(addr, "+") == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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.
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(lifr.lifr_name, name,
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee sizeof (lifr.lifr_name));
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno != EADDRNOTAVAIL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCGLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCGLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens in_getaddr(addr, (struct sockaddr *)&broadaddr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_addr, &broadaddr, sizeof (broadaddr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFBRDADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFBRDADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * set interface destination address
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifdstaddr(char *addr, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*afp->af_getaddr)(addr, (struct sockaddr *)&lifr.lifr_addr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifdstaddr: SIOCSLIFDSTADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifflags(char *val, int64_t value)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int phyintlen, origphyintlen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifflags: SIOCGLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (value == IFF_NOFAILOVER) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens phyintlen = strcspn(name, ":");
fa9e4066f08beec538e775443c5be79dd423fcabahrens origphyintlen = strcspn(origname, ":");
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (phyintlen != origphyintlen ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens strncmp(name, origname, phyintlen) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: can't set -failover "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "on failed/standby/offlined interface %s\n",
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens origname);
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin exit(1);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Catch "up" transition for AF_INET6 to perform duplicate address
fa9e4066f08beec538e775443c5be79dd423fcabahrens * detection. ifdad checks if an address has been set.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (afp->af_af == AF_INET6 && !(lifr.lifr_flags & IFF_UP) &&
e05725b117836db173257fae43fb0746eb857fb5bonwick value == IFF_UP) {
0b69c2f001a429251e2d38f25aca860396551214ahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(
fa9e4066f08beec538e775443c5be79dd423fcabahrens "setifaddr:Calling ifdad flags %llx value 0x%llx\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags, value);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ifdad(name, NULL) == -1)
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (value < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens value = -value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags &= ~value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags |= value;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifflags: SIOCSLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifmetric(char *val, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_metric = atoi(val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifmetric: SIOCSLIFMETRIC");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifmtu(char *val, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_mtu = atoi(val);
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick if (ioctl(s, SIOCSLIFMTU, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifmtu: SIOCSLIFMTU");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifindex(char *val, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_index = atoi(val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFINDEX, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifindex: SIOCSLIFINDEX");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifether(char *addr, int64_t param)
b19a79ec1a527828a60c4d325ccd8dcbeb2b2e8bperrin{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uchar_t *ea;
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick iface_t *current;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int maclen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (addr == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ifstatus(name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens print_ifether(name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens phyif = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens logifs = NULL;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * if the IP interface in the arguments is a logical
fa9e4066f08beec538e775443c5be79dd423fcabahrens * interface, exit with an error now.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens if (strchr(name, ':') != NULL) {
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee (void) fprintf(stderr, "ifconfig: cannot change"
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens " ethernet address of a logical interface\n");
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens exit(1);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens }
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens ea = _link_aton(addr, &maclen);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens if (ea == NULL) {
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens if (maclen == -1)
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) fprintf(stderr,
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens "ifconfig: %s: bad address\n", addr);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens else
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) fprintf(stderr, "ifconfig: malloc() failed\n");
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(savedname, name, sizeof (savedname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens foreachinterface(selectifs, 0, (char **)NULL, 0, 0, IFF_IPV6, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If physical interface not found, exit now */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (phyif == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: interface %s not found\n", savedname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Restore */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, savedname, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(origname, savedname, sizeof (origname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * close and reopen the socket
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we don't know which type of socket we have now
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby (void) close(s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = socket(SOCKET_AF(AF_UNSPEC), SOCK_DGRAM, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s < 0) {
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens Perror0_exit("socket");
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * mark down the logical interfaces first,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and then the physical interface
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (updownifs(logifs, 0) < 0 || updownifs(phyif, 0) < 0) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante Perror0_exit("mark down interface failed");
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson }
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson /*
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson * Change the physical address
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson */
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (dlpi_set_address(savedname, ea, maclen) == -1) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson (void) fprintf(stderr,
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson "ifconfig: failed setting mac address on %s\n",
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson savedname);
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson }
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson /*
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 */
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (updownifs(phyif, 1) < 0 || updownifs(logifs, 1) < 0) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson Perror0_exit("mark down interface failed");
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson }
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson /* Free the memory allocated by selectifs */
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson free(phyif);
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby for (current = logifs; current != NULL; current = logifs) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson logifs = logifs->next;
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson free(current);
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby }
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson return (0);
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby}
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson/*
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby * Print an interface's Ethernet address, if it has one.
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson */
718d718a734e79bad0b9f8a264219b238fabaf44George Wilsonstatic void
718d718a734e79bad0b9f8a264219b238fabaf44George Wilsonprint_ifether(char *ifname)
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson{
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante int protocol;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante icfg_if_t interface;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante icfg_handle_t handle;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante int fd;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante /*
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * Loopback interfaces and tunnels can't have MAC addresses,
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * so filter them out first.
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante */
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (strcmp(ifname, LOOPBACK_IF) == 0)
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante return;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante fd = socket(AF_INET, SOCK_DGRAM, 0);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (fd == -1 || ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1) {
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson /*
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * It's possible the interface is only configured for
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante * IPv6; check again with AF_INET6.
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante */
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante (void) close(fd);
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson fd = socket(AF_INET6, SOCK_DGRAM, 0);
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (fd == -1 || ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1) {
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante (void) close(fd);
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante return;
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante }
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante }
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante (void) close(fd);
05312e2ca4a1e68606ae0db2c449aee7e7009323Mark J Musante
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens /* Virtual interfaces don't have MAC addresses */
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens if (lifr.lifr_flags & IFF_VIRTUAL)
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson return;
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson /*
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 */
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante interface.if_protocol = AF_INET;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (lifr.lifr_flags & IFF_IPV6)
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante interface.if_protocol = AF_INET6;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strncpy(interface.if_name, ifname, sizeof (interface.if_name));
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson
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 icfg_close(handle);
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson return;
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson }
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante icfg_close(handle);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante }
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson dlpi_print_address(ifname);
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson}
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson/*
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson * static void selectifs(int argc, char *argv[], int af, struct lifreq *rp)
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson *
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 */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson/* ARGSUSED */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilsonstatic void
b2d22b66bc47a107891381986ae05e32ff517d10George Wilsonselectifs(int argc, char *argv[], int af, struct lifreq *rp)
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson{
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante char *colonp;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens int length;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante iface_t *current;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante /*
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 */
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson colonp = strchr(name, ':');
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson if (colonp == NULL)
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson length = max(strlen(savedname), strlen(name));
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson else
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson length = max(strlen(savedname), colonp - name);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (strncmp(savedname, name, length) == 0) {
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens (void) strcpy(lifr.lifr_name, name);
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if (ioctl(s, SIOCGLIFFLAGS, &lifr) < 0) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante Perror0("selectifs: SIOCGLIFFLAGS");
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return;
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante }
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante if ((current = malloc(sizeof (iface_t))) == NULL) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante Perror0_exit("selectifs: malloc failed\n");
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante }
b2d22b66bc47a107891381986ae05e32ff517d10George Wilson
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (colonp == NULL) {
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante /* this is the physical interface */
4f5064b73b1cc9de1d0f1a2ae700d519d4d565dfMark J Musante phyif = current;
fa9e4066f08beec538e775443c5be79dd423fcabahrens bcopy(&lifr, &phyif->lifr, sizeof (struct lifreq));
fa9e4066f08beec538e775443c5be79dd423fcabahrens phyif->next = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* this is a logical interface */
fa9e4066f08beec538e775443c5be79dd423fcabahrens bcopy(&lifr, &current->lifr, sizeof (struct lifreq));
fa9e4066f08beec538e775443c5be79dd423fcabahrens current->next = logifs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens logifs = current;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * static int updownifs(iface_t *ifs, int up)
e05725b117836db173257fae43fb0746eb857fb5bonwick *
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 *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return values:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 0 = everything OK
fa9e4066f08beec538e775443c5be79dd423fcabahrens * -1 = problem
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic int
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrinupdownifs(iface_t *ifs, int up)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens iface_t *current;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char savename[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t orig_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (current = ifs; current != NULL; current = current->next) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (current->lifr.lifr_flags & IFF_UP) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens orig_flags = current->lifr.lifr_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!up)
fa9e4066f08beec538e775443c5be79dd423fcabahrens current->lifr.lifr_flags &= ~IFF_UP;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFFLAGS, &current->lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens save_errno = errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strcpy(savename,
fa9e4066f08beec538e775443c5be79dd423fcabahrens current->lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!up) /* restore the original flags */
fa9e4066f08beec538e775443c5be79dd423fcabahrens current->lifr.lifr_flags = orig_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
088f389458728c464569a5506b58070254fa4f7dahrens if (ret == -1) {
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) strcpy(lifr.lifr_name, savename);
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 *
e05725b117836db173257fae43fb0746eb857fb5bonwick * This allows syntax like:
e05725b117836db173257fae43fb0746eb857fb5bonwick * ifconfig le0 addif 109.106.86.130 netmask + up \
fa9e4066f08beec538e775443c5be79dd423fcabahrens * addif 109.106.86.131 netmask + up
e05725b117836db173257fae43fb0746eb857fb5bonwick */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensaddif(char *str, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int prefixlen = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_storage laddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_storage mask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, origname, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strchr(name, ':') != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "ifconfig: addif: bad physical interface name %s\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * clear so parser will interpret next address as source followed
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin * by possible dest
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens setaddr = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*afp->af_getaddr)(str, (struct sockaddr *)&laddr, &prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (prefixlen) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case NO_PREFIX:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Nothing there - ok */
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case BAD_ADDR:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Bad prefix length in %s\n", str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&mask, 0, sizeof (mask));
fa9e4066f08beec538e775443c5be79dd423fcabahrens mask.ss_family = afp->af_af;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (afp->af_af == AF_INET6) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6 = (struct sockaddr_in6 *)&mask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!in_prefixlentomask(prefixlen, ADDRBITS_V6,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (uchar_t *)&sin6->sin6_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in *sin;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin = (struct sockaddr_in *)&mask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!in_prefixlentomask(prefixlen, ADDRBITS_V4,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (uchar_t *)&sin->sin_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Bad prefix length: %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens g_netmask_set = G_NETMASK_NIL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Note: no need to do DAD here since the interface isn't up yet. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("addif: SIOCLIFADDIF");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("Created new logical interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, lifr.lifr_name, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Check and see if any "netmask" command is used and perform the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * necessary operation.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens set_mask_lifreq(&lifr, &laddr, &mask);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Only set the netmask if "netmask" command is used or a prefix is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * provided.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (g_netmask_set == G_NETMASK_SET || prefixlen >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("addif: SIOCSLIFNETMASK");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Finally, we set the interface address. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addr = laddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * let parser know we got a source.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Next address, if given, should be dest
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens setaddr++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensremoveif(char *str, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_storage laddr;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (strchr(name, ':') != NULL) {
1934e92fc930c49429ad71a8ca97340f33227e78maybee (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: removeif: bad physical interface name %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (*afp->af_getaddr)(str, &laddr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addr = laddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0) {
1934e92fc930c49429ad71a8ca97340f33227e78maybee if (errno == EBUSY) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* This can only happen if ipif_id = 0 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "ifconfig: removeif: can't remove interface: %s\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("removeif: SIOCLIFREMOVEIF");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If laddr is non-NULL it is used - otherwise we use the address on
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensifdad(char *ifname, struct sockaddr_in6 *laddr)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 testaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct lifreq lifr2; /* Avoid overriting lifr */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("ifdad(%s)\n", ifname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens assert(afp->af_af == AF_INET6);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr2.lifr_name, ifname,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr2.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr2) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("ifdad: SIOCGLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifr2.lifr_flags & (IFF_NOLOCAL|IFF_LOOPBACK|IFF_NONUD|IFF_ANYCAST))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (laddr != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens testaddr = *laddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr2) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("ifdad: SIOCGLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens testaddr = *(struct sockaddr_in6 *)&lifr2.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (IN6_IS_ADDR_UNSPECIFIED(&testaddr.sin6_addr))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (do_dad(name, &testaddr) != 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set the address token for IPv6.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetiftoken(char *addr, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int prefixlen = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 token;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens in6_getaddr(addr, (struct sockaddr *)&token, &prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (prefixlen) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case NO_PREFIX:
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Missing prefix length in subnet %s\n", addr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens case BAD_ADDR:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Bad prefix length in %s\n", addr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_addr, &token, sizeof (token));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addrlen = prefixlen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFTOKEN, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setiftoken: SIOCSLIFTOKEN");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return value: 0 on success, -1 on failure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensconnect_to_mpathd(int family)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int s;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_storage ss;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int addrlen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int on;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = socket(family, SOCK_STREAM, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (s < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("connect_to_mpathd: socket");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) bzero((char *)&ss, sizeof (ss));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ss.ss_family = family;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens on = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (setsockopt(s, IPPROTO_TCP, TCP_ANONPRIVBIND, &on,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (on)) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("connect_to_mpathd: setsockopt");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (family) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case AF_INET:
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_port = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
fa9e4066f08beec538e775443c5be79dd423fcabahrens addrlen = sizeof (struct sockaddr_in);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case AF_INET6:
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6->sin6_port = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6->sin6_addr = loopback_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens addrlen = sizeof (struct sockaddr_in6);
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin break;
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ret = bind(s, (struct sockaddr *)&ss, addrlen);
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin if (ret != 0) {
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) close(s);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (family) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case AF_INET:
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_port = htons(MPATHD_PORT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case AF_INET6:
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6->sin6_port = htons(MPATHD_PORT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = connect(s, (struct sockaddr *)&ss, addrlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifgroupname(char *grpname, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("Setting groupname %s on interface %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens grpname, name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_groupname, grpname,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_groupname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFGROUPNAME, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifgroupname: SIOCSLIFGROUPNAME");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (getenv("SUNW_NO_MPATHD") != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to connect to in.mpathd using IPv4. If we succeed,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we conclude that in.mpathd is running, and quit.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (connect_to_mpathd(AF_INET) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* connect succeeded, mpathd is already running */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to connect to in.mpathd using IPv6. If we succeed,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we conclude that in.mpathd is running, and quit.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (connect_to_mpathd(AF_INET6) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* connect succeeded, mpathd is already running */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (fork()) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case -1:
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("setifgroupname: fork");
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens case 0:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) execl(MPATHD_PATH, MPATHD_PATH, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens _exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * To list all the modules above a given network interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockmodlist(char *null, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int muxfd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ipfd_lowstr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int arpfd_lowstr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int num_mods;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct str_list strlist;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int orig_arpid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ip_domux2fd(&muxfd, &ipfd_lowstr, &arpfd_lowstr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &orig_arpid) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((num_mods = ioctl(ipfd_lowstr, I_LIST, NULL)) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("cannot I_LIST to get the number of modules");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("Listing (%d) modules above %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens num_mods, name);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock strlist.sl_nmods = num_mods;
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin strlist.sl_modlist = malloc(sizeof (struct str_mlist) *
fa9e4066f08beec538e775443c5be79dd423fcabahrens num_mods);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strlist.sl_modlist == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("cannot malloc");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(ipfd_lowstr, I_LIST, (caddr_t)&strlist) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("cannot I_LIST for module names");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < strlist.sl_nmods; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("%d %s\n", i,
fa9e4066f08beec538e775443c5be79dd423fcabahrens strlist.sl_modlist[i].l_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy free(strlist.sl_modlist);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (ip_plink(muxfd, ipfd_lowstr, arpfd_lowstr, orig_arpid));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#define MODINSERT_OP 'i'
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#define MODREMOVE_OP 'r'
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/* ARGSUSED */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiymodinsert(char *arg, int64_t param)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (modop(arg, MODINSERT_OP));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/* ARGSUSED */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiymodremove(char *arg, int64_t param)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (modop(arg, MODREMOVE_OP));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyopen_arp_on_udp(char *udp_dev_name)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int fd;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy boolean_t popped;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((fd = open(udp_dev_name, O_RDWR)) == -1) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("open", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy errno = 0;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy popped = _B_FALSE;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy while (ioctl(fd, I_POP, 0) != -1)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy popped = _B_TRUE;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (!popped) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("cannot pop", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (errno != EINVAL) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("pop", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (ioctl(fd, I_PUSH, ARP_MOD_NAME) == -1) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("arp PUSH", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (fd);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) close(fd);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
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 *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Param:
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 *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Return:
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * -1 if operation fails, 0 otherwise.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Please see the big block comment above plumb_one_device()
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * for the logic of the PLINK/PUNLINK
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyip_domux2fd(int *muxfd, int *ipfd_lowstr, int *arpfd_lowstr, int *orig_arpid)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int ip_fd;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy uint64_t flags;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy char *udp_dev_name;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy char *ip_dev_name;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *orig_arpid = 0;
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit("status: SIOCGLIFFLAGS");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy flags = lifr.lifr_flags;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (flags & IFF_IPV4) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy udp_dev_name = UDP_DEV_NAME;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy ip_dev_name = IP_DEV_NAME;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (flags & IFF_IPV6) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy udp_dev_name = UDP6_DEV_NAME;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy ip_dev_name = IP6_DEV_NAME;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((ip_fd = open(ip_dev_name, O_RDWR)) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("open", ip_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(ip_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("SIOCGLIFMUXID", ip_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (debug > 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) printf("ARP_muxid %d IP_muxid %d\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid, lifr.lifr_ip_muxid);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*muxfd = open_arp_on_udp(udp_dev_name)) == -1)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (lifr.lifr_arp_muxid != 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*arpfd_lowstr = ioctl(*muxfd, _I_MUXID2FD,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid)) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((errno == EINVAL) &&
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (flags & (IFF_NOARP | IFF_IPV6))) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *orig_arpid = lifr.lifr_arp_muxid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid = 0;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(*muxfd, SIOCSLIFMUXID,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *arpfd_lowstr = -1;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0("_I_MUXID2FD");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (ioctl(*muxfd, I_PUNLINK,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("I_PUNLINK", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *arpfd_lowstr = -1;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((*ipfd_lowstr = ioctl(*muxfd, _I_MUXID2FD,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_ip_muxid)) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0("_I_MUXID2FD");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo any changes we made */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (*orig_arpid != 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid = *orig_arpid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(*muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(*muxfd, I_PUNLINK, lifr.lifr_ip_muxid) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("I_PUNLINK", udp_dev_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo any changes we made */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (*orig_arpid != 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid = *orig_arpid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(*muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (0);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
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 *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Param:
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int udp_fd: fd to /dev/udp (upper IP stream).
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * int fd: fd to the lower IP stream.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Return:
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * -1 if operation fails, 0 otherwise.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Please see the big block comment above plumb_one_device()
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * for the logic of the PLINK/PUNLINK
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyip_plink(int muxfd, int ipfd_lowstr, int arpfd_lowstr, int orig_arpid)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int ip_muxid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy ip_muxid = ioctl(muxfd, I_PLINK, ipfd_lowstr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ip_muxid < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("I_PLINK", UDP_DEV_NAME);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (arpfd_lowstr != -1) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (ioctl(muxfd, I_PLINK, arpfd_lowstr) < 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror2("I_PLINK", UDP_DEV_NAME);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else if (orig_arpid != 0) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Undo the changes we did in ip_domux2fd */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_arp_muxid = orig_arpid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_ip_muxid = ip_muxid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) ioctl(muxfd, SIOCSLIFMUXID, (caddr_t)&lifr);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (0);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * The names of other core TCP/IP stack modules which cannot be removed.
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#ifndef TUN_NAME
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#define TUN_NAME "tun"
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#endif
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#ifndef ATUN_NAME
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#define ATUN_NAME "atun"
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#endif
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#ifndef TUN6TO4_NAME
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#define TUN6TO4_NAME "6to4tun"
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy#endif
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * The real function to perform module insertion/removal.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Param:
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * char *arg: the argument string module_name@position
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * char op: operation, either MODINSERT_OP or MODREMOVE_OP.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Return:
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 * otherwise.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiymodop(char *arg, char op)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy char *pos_p;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int muxfd;
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 struct strmodconf mod;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy char *at_char = "@";
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy char *arg_str;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy int orig_arpid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Need to save the original string for -a option. */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((arg_str = malloc(strlen(arg) + 1)) == NULL) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0("cannot malloc");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (-1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strcpy(arg_str, arg);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (*arg_str == *at_char) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy "ifconfig: must supply a module name\n");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy exit(1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy mod.mod_name = strtok(arg_str, at_char);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (strlen(mod.mod_name) > FMNAMESZ) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: module name too long: %s\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy mod.mod_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy exit(1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /*
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 */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (op == MODREMOVE_OP &&
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, TUN_NAME) == 0 ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy strcmp(mod.mod_name, ATUN_NAME) == 0 ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy strcmp(mod.mod_name, TUN6TO4_NAME) == 0)) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: cannot remove %s\n",
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy mod.mod_name);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy exit(1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((pos_p = strtok(NULL, at_char)) == NULL) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) fprintf(stderr, "ifconfig: must supply a position\n");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy exit(1);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy mod.pos = atoi(pos_p);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee if (ip_domux2fd(&muxfd, &ipfd_lowstr, &arpfd_lowstr,
e05725b117836db173257fae43fb0746eb857fb5bonwick &orig_arpid) < 0) {
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee free(arg_str);
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee }
e05725b117836db173257fae43fb0746eb857fb5bonwick switch (op) {
e05725b117836db173257fae43fb0746eb857fb5bonwick case MODINSERT_OP:
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee if (debug > 0) {
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee (void) printf("Inserting module %s at %d\n",
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee mod.mod_name, mod.pos);
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee }
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee if (ioctl(ipfd_lowstr, _I_INSERT, (caddr_t)&mod) < 0) {
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee Perror2("fail to insert module", mod.mod_name);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick break;
e05725b117836db173257fae43fb0746eb857fb5bonwick case MODREMOVE_OP:
e05725b117836db173257fae43fb0746eb857fb5bonwick if (debug > 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("Removing module %s at %d\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick mod.mod_name, mod.pos);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(ipfd_lowstr, _I_REMOVE, (caddr_t)&mod) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror2("fail to remove module", mod.mod_name);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick break;
e05725b117836db173257fae43fb0746eb857fb5bonwick default:
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee /* Should never get to here. */
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee (void) fprintf(stderr, "Unknown operation\n");
e05725b117836db173257fae43fb0746eb857fb5bonwick break;
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee }
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee free(arg_str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ip_plink(muxfd, ipfd_lowstr, arpfd_lowstr, orig_arpid));
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensgetnd(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick struct sockaddr_in6 v6addr;
e05725b117836db173257fae43fb0746eb857fb5bonwick char *str = NULL;
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens in6_getaddr(addr, &v6addr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCLIFGETND, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("SIOCLIFGETND");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick str = _link_ntoa((const unsigned char *)lifr.lifr_nd.lnr_hdw_addr,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy str, lifr.lifr_nd.lnr_hdw_len, IFT_OTHER);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if (str != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("address %s", str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" state %d/%d/%d flags %x\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_state_create,
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_state_same_lla,
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_state_diff_lla,
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_flags);
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwickdelnd(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick struct sockaddr_in6 v6addr;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick in6_getaddr(addr, &v6addr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_nd.lnr_state_create = ND_UNCHANGED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED;
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_nd.lnr_state_diff_lla = ND_UNCHANGED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_flags = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCLIFDELND, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("SIOCLIFDELND");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy return (0);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/* ARGSUSED */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiystatic int
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiysetnd(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick struct sockaddr_in6 v6addr;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
e05725b117836db173257fae43fb0746eb857fb5bonwick * XXX parse phyaddr? Need syntax to fit in one argv.
e05725b117836db173257fae43fb0746eb857fb5bonwick * XXX <proto addr>/<phyaddr> ??
e05725b117836db173257fae43fb0746eb857fb5bonwick */
fa9e4066f08beec538e775443c5be79dd423fcabahrens in6_getaddr(addr, &v6addr, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&lifr.lifr_nd.lnr_addr, &v6addr, sizeof (v6addr));
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) memset(lifr.lifr_nd.lnr_hdw_addr, 0x55,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy sizeof (lifr.lifr_nd.lnr_hdw_addr));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy lifr.lifr_nd.lnr_hdw_len = 6;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_nd.lnr_state_create = ND_STALE;
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED;
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick lifr.lifr_nd.lnr_state_diff_lla = ND_STALE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_nd.lnr_flags = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCLIFSETND, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("SIOCLIFSETND");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick#endif /* DEBUG */
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/*
e05725b117836db173257fae43fb0746eb857fb5bonwick * Set tunnel source address
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick */
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick/* ARGSUSED */
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwickstatic int
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwicksetiftsrc(char *addr, int64_t param)
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick{
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick return (settaddr(addr, icfg_set_tunnel_src));
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/*
e05725b117836db173257fae43fb0746eb857fb5bonwick * Set tunnel destination address
e05725b117836db173257fae43fb0746eb857fb5bonwick */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwicksetiftdst(char *addr, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick return (settaddr(addr, icfg_set_tunnel_dest));
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/*
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 */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwicksettaddr(char *addr,
e05725b117836db173257fae43fb0746eb857fb5bonwick int (*fn)(icfg_handle_t, const struct sockaddr *, socklen_t))
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_handle_t handle;
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_if_t interface;
e05725b117836db173257fae43fb0746eb857fb5bonwick struct sockaddr_storage laddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int lower;
e05725b117836db173257fae43fb0746eb857fb5bonwick int rc;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (strchr(name, ':') != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick errno = EPERM;
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Tunnel params on logical interfaces");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick interface.if_protocol = SOCKET_AF(af);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Open interface. */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy if ((rc = icfg_open(&handle, &interface)) != ICFG_SUCCESS)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit((char *)icfg_errmsg(rc));
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick rc = icfg_get_tunnel_lower(handle, &lower);
e05725b117836db173257fae43fb0746eb857fb5bonwick if (rc != ICFG_SUCCESS)
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit((char *)icfg_errmsg(rc));
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (lower == AF_INET) {
e05725b117836db173257fae43fb0746eb857fb5bonwick in_getaddr(addr, (struct sockaddr *)&laddr, NULL);
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
e05725b117836db173257fae43fb0746eb857fb5bonwick in6_getaddr(addr, (struct sockaddr *)&laddr, NULL);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Call fn to do the real work, and close the interface. */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick rc = (*fn)(handle, (struct sockaddr *)&laddr,
e05725b117836db173257fae43fb0746eb857fb5bonwick sizeof (struct sockaddr_storage));
fa9e4066f08beec538e775443c5be79dd423fcabahrens icfg_close(handle);
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (rc != ICFG_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit((char *)icfg_errmsg(rc));
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set tunnel encapsulation limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwickset_tun_encap_limit(char *arg, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
fa9e4066f08beec538e775443c5be79dd423fcabahrens short limit;
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_if_t interface;
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_handle_t handle;
e05725b117836db173257fae43fb0746eb857fb5bonwick int rc;
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (strchr(name, ':') != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick errno = EPERM;
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Tunnel params on logical interfaces");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
e05725b117836db173257fae43fb0746eb857fb5bonwick if ((sscanf(arg, "%hd", &limit) != 1) || (limit < 0) ||
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy (limit > 255)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = EINVAL;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit("Invalid encapsulation limit");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
e05725b117836db173257fae43fb0746eb857fb5bonwick
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy /* Open interface for configuration. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick interface.if_protocol = SOCKET_AF(af);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (icfg_open(&handle, &interface) != ICFG_SUCCESS)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy Perror0_exit("couldn't open interface");
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
e05725b117836db173257fae43fb0746eb857fb5bonwick rc = icfg_set_tunnel_encaplimit(handle, (int)limit);
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_close(handle);
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (rc != ICFG_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Could not configure tunnel encapsulation limit");
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/* Disable encapsulation limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwickclr_tun_encap_limit(char *arg, int64_t param)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_if_t interface;
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_handle_t handle;
e05725b117836db173257fae43fb0746eb857fb5bonwick int rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick if (strchr(name, ':') != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = EPERM;
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Tunnel params on logical interfaces");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick /* Open interface for configuration. */
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwick (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick interface.if_protocol = SOCKET_AF(af);
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick if (icfg_open(&handle, &interface) != ICFG_SUCCESS)
f4a724507725f215972bd6c8cdaaa33b0803e58dJeff Bonwick Perror0_exit("couldn't open interface");
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick rc = icfg_set_tunnel_encaplimit(handle, -1);
e05725b117836db173257fae43fb0746eb857fb5bonwick icfg_close(handle);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick if (rc != ICFG_SUCCESS)
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit((char *)icfg_errmsg(rc));
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/* Set tunnel hop limit. */
e05725b117836db173257fae43fb0746eb857fb5bonwick/* ARGSUSED */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic int
e05725b117836db173257fae43fb0746eb857fb5bonwickset_tun_hop_limit(char *arg, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned short limit;
fa9e4066f08beec538e775443c5be79dd423fcabahrens icfg_if_t interface;
fa9e4066f08beec538e775443c5be79dd423fcabahrens icfg_handle_t handle;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strchr(name, ':') != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = EPERM;
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Tunnel params on logical interfaces");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Check limit here since it's really only an 8-bit unsigned quantity.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((sscanf(arg, "%hu", &limit) != 1) || (limit > 255)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = EINVAL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Invalid hop limit");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Open interface for configuration. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens interface.if_protocol = SOCKET_AF(af);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (icfg_open(&handle, &interface) != ICFG_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("couldn't open interface");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = icfg_set_tunnel_hoplimit(handle, (uint8_t)limit);
fa9e4066f08beec538e775443c5be79dd423fcabahrens icfg_close(handle);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rc != ICFG_SUCCESS)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock Perror0_exit("Could not configure tunnel hop limit");
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set zone ID */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrocksetzone(char *arg, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zoneid_t zoneid = GLOBAL_ZONEID;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (param == NEXTARG) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* zone must be active */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((zoneid = getzoneidbyname(arg)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: unknown zone '%s'\n", arg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_zoneid = zoneid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCSLIFZONE, (caddr_t)&lifr) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFZONE");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Set source address to use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifsrc(char *arg, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint_t ifindex = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Argument can be either an interface name or "none". The latter means
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that any previous selection is cleared.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rval = strcmp(arg, name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rval == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: Cannot specify same interface for usesrc"
fa9e4066f08beec538e775443c5be79dd423fcabahrens " group\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rval = strcmp(arg, NONE_STR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rval != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ifindex = if_nametoindex(arg)) == 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, arg, LIFNAMSIZ);
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Could not get interface index");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_index = ifindex;
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) != 0)
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Not a valid usesrc consumer");
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_index = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (debug)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("setifsrc: lifr_name %s, lifr_index %d\n",
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_name, lifr.lifr_index);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCSLIFUSESRC, (caddr_t)&lifr) == -1) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (rval == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("Cannot reset usesrc group");
e05725b117836db173257fae43fb0746eb857fb5bonwick else
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("Could not set source interface");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Print the interface status line associated with `ifname'
e05725b117836db173257fae43fb0746eb857fb5bonwick */
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensifstatus(const char *ifname)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick uint64_t flags;
e05725b117836db173257fae43fb0746eb857fb5bonwick char if_usesrc_name[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *newbuf;
e05725b117836db173257fae43fb0746eb857fb5bonwick int n, numifs, rval = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick struct lifreq *lifrp;
e05725b117836db173257fae43fb0746eb857fb5bonwick struct lifsrcof lifs;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("status: SIOCGLIFFLAGS");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick flags = lifr.lifr_flags;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
e05725b117836db173257fae43fb0746eb857fb5bonwick * In V4 compatibility mode, we don't print the IFF_IPV4 flag or
e05725b117836db173257fae43fb0746eb857fb5bonwick * interfaces with IFF_IPV6 set.
e05725b117836db173257fae43fb0746eb857fb5bonwick */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (v4compat) {
e05725b117836db173257fae43fb0746eb857fb5bonwick flags &= ~IFF_IPV4;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & IFF_IPV6)
e05725b117836db173257fae43fb0746eb857fb5bonwick return;
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("%s: ", ifname);
e05725b117836db173257fae43fb0746eb857fb5bonwick print_flags(flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("status: SIOCGLIFMETRIC");
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifr.lifr_metric)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" metric %d", lifr.lifr_metric);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFMTU, (caddr_t)&lifr) >= 0)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" mtu %d", lifr.lifr_metric);
e05725b117836db173257fae43fb0746eb857fb5bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* don't print index or zone when in compatibility mode */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (!v4compat) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) >= 0)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" index %d", lifr.lifr_index);
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFZONE, (caddr_t)&lifr) >= 0 &&
e05725b117836db173257fae43fb0746eb857fb5bonwick lifr.lifr_zoneid != getzoneid()) {
e05725b117836db173257fae43fb0746eb857fb5bonwick char zone_name[ZONENAME_MAX];
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (getzonenamebyid(lifr.lifr_zoneid, zone_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (zone_name)) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("\n\tzone %d", lifr.lifr_zoneid);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("\n\tzone %s", zone_name);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) >= 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick lifs.lifs_ifindex = lifr.lifr_index;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
e05725b117836db173257fae43fb0746eb857fb5bonwick * Find the number of interfaces that use this interfaces'
e05725b117836db173257fae43fb0746eb857fb5bonwick * address as a source address
e05725b117836db173257fae43fb0746eb857fb5bonwick */
e05725b117836db173257fae43fb0746eb857fb5bonwick lifs.lifs_buf = NULL;
e05725b117836db173257fae43fb0746eb857fb5bonwick lifs.lifs_maxlen = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick for (;;) {
e05725b117836db173257fae43fb0746eb857fb5bonwick /* The first pass will give the bufsize we need */
e05725b117836db173257fae43fb0746eb857fb5bonwick rval = ioctl(s, SIOCGLIFSRCOF, (char *)&lifs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rval < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (lifs.lifs_buf != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick free(lifs.lifs_buf);
e05725b117836db173257fae43fb0746eb857fb5bonwick lifs.lifs_buf = NULL;
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifs.lifs_len = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifs.lifs_len <= lifs.lifs_maxlen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Use kernel's size + a small margin to avoid loops */
e05725b117836db173257fae43fb0746eb857fb5bonwick lifs.lifs_maxlen = lifs.lifs_len +
fa9e4066f08beec538e775443c5be79dd423fcabahrens 5 * sizeof (struct lifreq);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For the first pass, realloc acts like malloc */
fa9e4066f08beec538e775443c5be79dd423fcabahrens newbuf = realloc(lifs.lifs_buf, lifs.lifs_maxlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newbuf == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifs.lifs_buf != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(lifs.lifs_buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifs.lifs_buf = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi lifs.lifs_len = 0;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi break;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi lifs.lifs_buf = newbuf;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi numifs = lifs.lifs_len / sizeof (struct lifreq);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (numifs > 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi lifrp = lifs.lifs_req;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) printf("\n\tsrcof");
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi for (n = numifs; n > 0; n--, lifrp++) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) printf(" %s", lifrp->lifr_name);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (lifs.lifs_buf != NULL)
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi free(lifs.lifs_buf);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /* Find the interface whose source address this interface uses */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) == 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (lifr.lifr_index != 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (if_indextoname(lifr.lifr_index,
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if_usesrc_name) == NULL) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) printf("\n\tusesrc ifIndex %d",
1bc69b9cd8bf4a24b90a7093402f3ad21f3818b8Sanjeev Bagewadi lifr.lifr_index);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi } else {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) printf("\n\tusesrc %s", if_usesrc_name);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) putchar('\n');
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi}
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi/*
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 */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadistatic void
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadistatus(void)
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi{
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi struct afswtch *p = afp;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi uint64_t flags;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi Perror0_exit("status: SIOCGLIFFLAGS");
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi flags = lifr.lifr_flags;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /*
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Only print the interface status if the address family matches
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * the interface family flag.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (p != NULL) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (((p->af_af == AF_INET6) && (flags & IFF_IPV4)) ||
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi ((p->af_af == AF_INET) && (flags & IFF_IPV6)))
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi return;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /*
1bc69b9cd8bf4a24b90a7093402f3ad21f3818b8Sanjeev Bagewadi * In V4 compatibility mode, don't print IFF_IPV6 interfaces.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (v4compat && (flags & IFF_IPV6))
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi return;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi ifstatus(name);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (p != NULL) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (*p->af_status)(1, flags);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi } else {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi for (p = afs; p->af_name; p++) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (void) close(s);
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 af = p->af_af;
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi if (s == -1) {
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi Perror0_exit("socket");
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi (*p->af_status)(0, flags);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi /*
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * Historically, 'ether' has been an address family,
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * so print it here.
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi */
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi print_ifether(name);
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi }
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi}
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi/*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensconfiginfo(char *null, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct afswtch *p = afp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char phydevname[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char if_usesrc_name[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *cp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("status: SIOCGLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags = lifr.lifr_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("configinfo: name %s flags 0x%llx af_af %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name, flags, p != NULL ? p->af_af : -1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick /* remove LIF component */
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(phydevname, name, sizeof (phydevname));
e05725b117836db173257fae43fb0746eb857fb5bonwick cp = strchr(phydevname, ':');
e05725b117836db173257fae43fb0746eb857fb5bonwick if (cp) {
e05725b117836db173257fae43fb0746eb857fb5bonwick *cp = 0;
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick phydevname[sizeof (phydevname) - 1] = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
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 */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (flags & IFF_IPV4) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (p && p->af_af == AF_INET6)
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (v4compat)
e05725b117836db173257fae43fb0746eb857fb5bonwick flags &= ~IFF_IPV4;
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("%s inet plumb", phydevname);
e05725b117836db173257fae43fb0746eb857fb5bonwick } else if (flags & IFF_IPV6) {
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (p && p->af_af == AF_INET)
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
e05725b117836db173257fae43fb0746eb857fb5bonwick if (v4compat)
e05725b117836db173257fae43fb0746eb857fb5bonwick return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("%s inet6 plumb", phydevname);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("configinfo: SIOCGLIFMETRIC");
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (lifr.lifr_metric)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" metric %d ", lifr.lifr_metric);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick if (((flags & (IFF_VIRTUAL|IFF_LOOPBACK)) != IFF_VIRTUAL) &&
e05725b117836db173257fae43fb0746eb857fb5bonwick ioctl(s, SIOCGLIFMTU, (caddr_t)&lifr) >= 0)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" mtu %d", lifr.lifr_metric);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick /* don't print index when in compatibility mode */
e05725b117836db173257fae43fb0746eb857fb5bonwick if (!v4compat) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) >= 0)
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" index %d", lifr.lifr_index);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifr.lifr_index != 0) {
e05725b117836db173257fae43fb0746eb857fb5bonwick if (if_indextoname(lifr.lifr_index,
fa9e4066f08beec538e775443c5be79dd423fcabahrens if_usesrc_name) != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf(" usesrc %s", if_usesrc_name);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick if (p != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (*p->af_configinfo)(1, flags);
e05725b117836db173257fae43fb0746eb857fb5bonwick } else {
e05725b117836db173257fae43fb0746eb857fb5bonwick for (p = afs; p->af_name; p++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(s);
e05725b117836db173257fae43fb0746eb857fb5bonwick s = socket(SOCKET_AF(p->af_af), SOCK_DGRAM, 0);
e05725b117836db173257fae43fb0746eb857fb5bonwick /* set global af for use in p->af_configinfo */
e05725b117836db173257fae43fb0746eb857fb5bonwick af = p->af_af;
e05725b117836db173257fae43fb0746eb857fb5bonwick if (s == -1) {
e05725b117836db173257fae43fb0746eb857fb5bonwick Perror0_exit("socket");
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick (*p->af_configinfo)(0, flags);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) printf("\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick return (0);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwickstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensprint_tsec(struct iftun_req *tparams)
e05725b117836db173257fae43fb0746eb857fb5bonwick{
e05725b117836db173257fae43fb0746eb857fb5bonwick ipsec_req_t *ipsr;
e05725b117836db173257fae43fb0746eb857fb5bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("\ttunnel security settings ");
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e05725b117836db173257fae43fb0746eb857fb5bonwick assert(tparams->ifta_vers == IFTUN_VERSION);
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick ipsr = (ipsec_req_t *)(&tparams->ifta_secinfo);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ipsr->ipsr_ah_req & IPSEC_PREF_REQUIRED) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("ah (%s) ",
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_auth_alg, IPSEC_PROTO_AH));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ipsr->ipsr_esp_req & IPSEC_PREF_REQUIRED) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("esp (%s",
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_esp_alg, IPSEC_PROTO_ESP));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("/%s)",
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rparsealg(ipsr->ipsr_esp_auth_alg, IPSEC_PROTO_AH));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\n");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia}
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastatic void
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiatun_status(void)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia{
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_if_t interface;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int rc;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_handle_t handle;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int protocol;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia char srcbuf[INET6_ADDRSTRLEN];
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia char dstbuf[INET6_ADDRSTRLEN];
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia boolean_t tabbed;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia uint8_t hoplimit;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia int16_t encaplimit;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia struct sockaddr_storage taddr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia socklen_t socklen = sizeof (taddr);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(interface.if_name, name, sizeof (interface.if_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia interface.if_protocol = SOCKET_AF(af);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if ((rc = icfg_open(&handle, &interface)) != ICFG_SUCCESS)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit((char *)icfg_errmsg(rc));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /*
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 */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (strchr(name, ':') != NULL ||
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_get_tunnel_lower(handle, &protocol) != ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_close(handle);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia return;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia switch (protocol) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia case AF_INET:
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\tinet");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia break;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia case AF_INET6:
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\tinet6");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia break;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia default:
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("\ttunnel: Illegal lower stream\n\t");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia break;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_get_tunnel_src(handle, (struct sockaddr *)&taddr, &socklen);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (rc == ICFG_NOT_SET) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strlcpy(srcbuf, (protocol == AF_INET) ? "0.0.0.0" :
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia "::", sizeof (srcbuf));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else if (rc != ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit((char *)icfg_errmsg(rc));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_sockaddr_to_str(protocol, (struct sockaddr *)&taddr,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia srcbuf, sizeof (srcbuf));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (rc != ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit((char *)icfg_errmsg(rc));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf(" tunnel src %s ", srcbuf);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_get_tunnel_dest(handle, (struct sockaddr *)&taddr, &socklen);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (rc == ICFG_NOT_SET) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\n");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rc = icfg_sockaddr_to_str(protocol, (struct sockaddr *)&taddr,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia dstbuf, sizeof (dstbuf));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (rc != ICFG_SUCCESS) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit((char *)icfg_errmsg(rc));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel dst %s\n", dstbuf);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (handle->ifh_tunnel_params != NULL &&
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (handle->ifh_tunnel_params->ifta_flags & IFTUN_SECURITY))
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia print_tsec(handle->ifh_tunnel_params);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /*
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 * newline
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia tabbed = _B_FALSE;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
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 tabbed = _B_TRUE;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if ((protocol == AF_INET6) &&
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (icfg_get_tunnel_encaplimit(handle, &encaplimit) ==
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia ICFG_SUCCESS)) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (!tabbed) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\t");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia tabbed = _B_TRUE;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (encaplimit >= 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel encapsulation limit %d",
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia encaplimit);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("tunnel encapsulation limit disabled");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (tabbed)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\n");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia icfg_close(handle);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia}
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastatic void
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiain_status(int force, uint64_t flags)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia{
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia struct sockaddr_in *sin, *laddr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia struct sockaddr_in netmask = { AF_INET };
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (debug)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("in_status(%s) flags 0x%llx\n", name, flags);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* only print status for IPv4 interfaces */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (!(flags & IFF_IPV4))
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia return;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* if the interface is a tunnel, print the tunnel status */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia tun_status();
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (!(flags & IFF_NOLOCAL)) {
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 errno == ENXIO) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (!force)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia return;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) memset(&lifr.lifr_addr, 0,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sizeof (lifr.lifr_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFADDR");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
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 laddr = sin;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("\tinet ");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
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 errno == ENXIO) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (!force)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia return;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) memset(&lifr.lifr_addr, 0,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sizeof (lifr.lifr_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFSUBNET");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin = (struct sockaddr_in *)&lifr.lifr_addr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if ((flags & IFF_NOLOCAL) ||
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 lifr.lifr_addrlen);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (sin->sin_family != AF_INET) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("Wrong family: %d\n", sin->sin_family);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
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 if (errno != EADDRNOTAVAIL)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFNETMASK");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia } else
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia netmask.sin_addr =
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia ((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (flags & IFF_POINTOPOINT) {
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 if (errno == EADDRNOTAVAIL)
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) memset(&lifr.lifr_addr, 0,
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sizeof (lifr.lifr_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia else
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Perror0_exit("in_status: SIOCGLIFDSTADDR");
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sin = (struct sockaddr_in *)&lifr.lifr_dstaddr;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("--> %s ", inet_ntoa(sin->sin_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia }
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (flags & IFF_BROADCAST) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) {
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia if (errno == EADDRNOTAVAIL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("in_status: SIOCGLIFBRDADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin = (struct sockaddr_in *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sin->sin_addr.s_addr != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("broadcast %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens inet_ntoa(sin->sin_addr));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If there is a groupname, print it for lun 0 alone */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strchr(name, ':') == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(lifr.lifr_groupname, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_groupname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strlen(lifr.lifr_groupname) > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("\n\tgroupname %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_groupname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) putchar('\n');
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockin6_status(int force, uint64_t flags)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char abuf[INET6_ADDRSTRLEN];
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock struct sockaddr_in6 *sin6, *laddr6;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (debug)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) printf("in6_status(%s) flags 0x%llx\n", name, flags);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (!(flags & IFF_IPV6))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* if the interface is a tunnel, print the tunnel status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens tun_status();
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!(flags & IFF_NOLOCAL)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno == ENXIO) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!force)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("in_status6: SIOCGLIFADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("\tinet6 %s/%d ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby abuf, sizeof (abuf)),
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_addrlen);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby laddr6 = sin6;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby } else {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("\tinet6 ");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
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 errno == ENXIO) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (!force)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby return;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) memset(&lifr.lifr_addr, 0,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sizeof (lifr.lifr_addr));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby } else
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby Perror0_exit("in_status6: SIOCGLIFSUBNET");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if ((flags & IFF_NOLOCAL) ||
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby !IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &laddr6->sin6_addr)) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("subnet %s/%d ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby abuf, sizeof (abuf)),
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_addrlen);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (sin6->sin6_family != AF_INET6) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("Wrong family: %d\n", sin6->sin6_family);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (flags & IFF_POINTOPOINT) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (errno == EADDRNOTAVAIL)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) memset(&lifr.lifr_addr, 0,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sizeof (lifr.lifr_addr));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby else
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby Perror0_exit("in_status6: SIOCGLIFDSTADDR");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sin6 = (struct sockaddr_in6 *)&lifr.lifr_dstaddr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("--> %s ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby abuf, sizeof (abuf)));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (verbose) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) putchar('\n');
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) putchar('\t');
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 (errno == EADDRNOTAVAIL || errno == EINVAL)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) memset(&lifr.lifr_addr, 0,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sizeof (lifr.lifr_addr));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby else
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby Perror0_exit("in_status6: SIOCGLIFTOKEN");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby } else {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("token %s/%d ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby abuf, sizeof (abuf)),
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_addrlen);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFLNKINFO, (caddr_t)&lifr) < 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (errno != EINVAL) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby Perror0_exit("in_status6: SIOCGLIFLNKINFO");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby } else {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("maxhops %u, reachtime %u ms, "
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby "reachretrans %u ms, maxmtu %u ",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_ifinfo.lir_maxhops,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_ifinfo.lir_reachtime,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_ifinfo.lir_reachretrans,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_ifinfo.lir_maxmtu);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby /* If there is a groupname, print it for lun 0 alone */
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (strchr(name, ':') == NULL) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) memset(lifr.lifr_groupname, 0,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sizeof (lifr.lifr_groupname));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (strlen(lifr.lifr_groupname) > 0) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("\n\tgroupname %s",
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby lifr.lifr_groupname);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) putchar('\n');
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby}
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirbystatic void
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirbyin_configinfo(int force, uint64_t flags)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby{
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby struct sockaddr_in *sin, *laddr;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby struct sockaddr_in netmask = { AF_INET };
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (debug)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) printf("in_configinfo(%s) flags 0x%llx\n", name, flags);
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby /* only configinfo info for IPv4 interfaces */
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (!(flags & IFF_IPV4))
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby return;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (!(flags & IFF_NOLOCAL)) {
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 ||
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby errno == ENXIO) {
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby if (!force)
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby return;
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby (void) memset(&lifr.lifr_addr, 0,
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby sizeof (lifr.lifr_addr));
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby } else
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby Perror0_exit("in_configinfo: SIOCGLIFADDR");
5c987a37e6561d090231fb3c10ba9f6ea995f34dChris Kirby }
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin = (struct sockaddr_in *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (get_lun(name) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" addif %s ", inet_ntoa(sin->sin_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" set %s ", inet_ntoa(sin->sin_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens laddr = sin;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno == ENXIO) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!force)
e05725b117836db173257fae43fb0746eb857fb5bonwick return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFSUBNET");
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock sin = (struct sockaddr_in *)&lifr.lifr_addr;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((flags & IFF_NOLOCAL) ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_addr.s_addr != laddr->sin_addr.s_addr) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf(" subnet %s/%d ", inet_ntoa(sin->sin_addr),
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addrlen);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (errno != EADDRNOTAVAIL)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFNETMASK");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick } else
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick netmask.sin_addr =
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (flags & IFF_POINTOPOINT) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (errno == EADDRNOTAVAIL)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(&lifr.lifr_addr, 0,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sizeof (lifr.lifr_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick else
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFDSTADDR");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin = (struct sockaddr_in *)&lifr.lifr_dstaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" destination %s ", inet_ntoa(sin->sin_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) printf(" netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (flags & IFF_BROADCAST) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (errno == EADDRNOTAVAIL)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(&lifr.lifr_addr, 0,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sizeof (lifr.lifr_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick else
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror0_exit("in_configinfo: SIOCGLIFBRDADDR");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin = (struct sockaddr_in *)&lifr.lifr_addr;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (sin->sin_addr.s_addr != 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf(" broadcast %s ",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick inet_ntoa(sin->sin_addr));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* If there is a groupname, print it for lun 0 alone */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (get_lun(name) == 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memset(lifr.lifr_groupname, 0,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sizeof (lifr.lifr_groupname));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (strlen(lifr.lifr_groupname) > 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf(" group %s ",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifr.lifr_groupname);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* Print flags to configure */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick print_config_flags(flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick /* IFF_NOARP applies to AF_INET only */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (flags & IFF_NOARP) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) printf("-arp ");
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic void
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickin6_configinfo(int force, uint64_t flags)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick{
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick char abuf[INET6_ADDRSTRLEN];
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick struct sockaddr_in6 *sin6, *laddr6;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("in6_configinfo(%s) flags 0x%llx\n", name,
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick flags);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!(flags & IFF_IPV6))
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson return;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!(flags & IFF_NOLOCAL)) {
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 ||
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick errno == ENXIO) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (!force)
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson return;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) memset(&lifr.lifr_addr, 0,
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson sizeof (lifr.lifr_addr));
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson } else
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson Perror0_exit("in6_configinfo: SIOCGLIFADDR");
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson }
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (get_lun(name) != 0) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) printf(" addif %s/%d ",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson abuf, sizeof (abuf)),
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick lifr.lifr_addrlen);
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson } else {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson (void) printf(" set %s/%d ",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick abuf, sizeof (abuf)),
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick lifr.lifr_addrlen);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens laddr6 = sin6;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
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 errno == ENXIO) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (!force)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("in6_configinfo: SIOCGLIFSUBNET");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((flags & IFF_NOLOCAL) ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens !IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &laddr6->sin6_addr)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" subnet %s/%d ",
fa9e4066f08beec538e775443c5be79dd423fcabahrens inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens abuf, sizeof (abuf)),
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addrlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & IFF_POINTOPOINT) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("in6_configinfo: SIOCGLIFDSTADDR");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin6 = (struct sockaddr_in6 *)&lifr.lifr_dstaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" destination %s ",
fa9e4066f08beec538e775443c5be79dd423fcabahrens inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens abuf, sizeof (abuf)));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFTOKEN, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EADDRNOTAVAIL || errno == EINVAL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0,
e05725b117836db173257fae43fb0746eb857fb5bonwick sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
088f389458728c464569a5506b58070254fa4f7dahrens Perror0_exit("in6_configinfo: SIOCGLIFTOKEN");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
088f389458728c464569a5506b58070254fa4f7dahrens sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" token %s/%d ",
fa9e4066f08beec538e775443c5be79dd423fcabahrens inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens abuf, sizeof (abuf)),
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_addrlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* If there is a groupname, print it for lun 0 alone */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (get_lun(name) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(lifr.lifr_groupname, 0,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr.lifr_groupname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFGROUPNAME, (caddr_t)&lifr) >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strlen(lifr.lifr_groupname) > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(" group %s ",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_groupname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Print flags to configure */
fa9e4066f08beec538e775443c5be79dd423fcabahrens print_config_flags(flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* IFF_NONUD applies to AF_INET6 only */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & IFF_NONUD) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("-nud ");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_lun(char *rsrc)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens char resource[LIFNAMSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *cp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strcpy(resource, rsrc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* remove LIF component */
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp = strchr(resource, ':');
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (cp) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens cp++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (atoi(cp));
e05725b117836db173257fae43fb0746eb857fb5bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 *
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 *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * a. STREAMS does not allow us to use /dev/ip itself as the mux. So we use
fa9e4066f08beec538e775443c5be79dd423fcabahrens * /dev/udp[6].
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 * or /dev/udp6.
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensplumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int arp_fd = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int arp_muxid = -1, ip_muxid;
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick int mux_fd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *udp_dev_name;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dlpi_if_attr_t dia;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("plumb_one_device: ifname %s, ppa %d\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens diap->ifname, diap->ppa);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (diap->style == DL_STYLE2 && dlpi_detach(ip_fd, -1) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("dlpi_detach");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
d80c45e0f58fa434ba37259ea2e2b12e0380c19abonwick if (ioctl(ip_fd, I_PUSH, IP_MOD_NAME) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2_exit("I_PUSH", IP_MOD_NAME);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(ip_fd, I_PUSH, ARP_MOD_NAME) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2_exit("I_PUSH", ARP_MOD_NAME);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set IFF_IPV4/IFF_IPV6 flags.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * At this point in time the kernel also allows an
fa9e4066f08beec538e775443c5be79dd423fcabahrens * override of the CANTCHANGE flags.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_name[0] = '\0';
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock Perror0_exit("plumb_one_device: SIOCGLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Set the name string and the IFF_IPV* flag */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (af == AF_INET6) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags |= IFF_IPV6;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick lifr.lifr_flags |= IFF_IPV4;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_flags &= ~IFF_IPV6;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* record the device and module names as interface name */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock lifr.lifr_ppa = diap->ppa;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* set the interface name */
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (ioctl(ip_fd, SIOCSLIFNAME, (char *)&lifr) == -1) {
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick if (errno != EEXIST)
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick Perror0_exit("SIOCSLIFNAME for ip");
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("SIOCSLIFNAME for ip");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the full set of existing flags for this stream */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1)
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin Perror0_exit("plumb_one_device: SIOCFLIFFLAGS");
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("plumb_one_device: %s got flags: \n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens print_flags(lifr.lifr_flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) putchar('\n');
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin /* Check if arp is not actually needed */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) {
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (ioctl(ip_fd, I_POP, 0) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2_exit("I_POP", ARP_MOD_NAME);
3a57275a335306e90136ebd00a4689fe0ee72519ck }
6365109ded948bd19a48c186a43ed08bd46a26adVictor Latushkin
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (af == AF_INET6)
fa9e4066f08beec538e775443c5be79dd423fcabahrens udp_dev_name = UDP6_DEV_NAME;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens udp_dev_name = UDP_DEV_NAME;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(EXIT_FAILURE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Check if arp is not needed */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * PLINK the interface stream so that ifconfig can exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens * without tearing down the stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("I_PLINK for ip");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(mux_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This interface does use ARP, so set up a separate stream
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from the interface to ARP.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note: modules specified by the user are pushed
fa9e4066f08beec538e775443c5be79dd423fcabahrens * only on the interface stream, not on the ARP stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("plumb_one_device: ifname: %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens diap->ifname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens arp_fd = dlpi_if_open(diap->ifname, &dia, _B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dia.style == DL_STYLE2 && dlpi_detach(arp_fd, -1) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("dlpi_detach");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2_exit("I_PUSH", ARP_MOD_NAME);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Tell ARP the name and unit number for this interface.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Note that arp has no support for transparent ioctls.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strioctl(arp_fd, SIOCSLIFNAME, (char *)&lifr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (lifr)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno != EEXIST)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("SIOCSLIFNAME for arp");
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0("SIOCSLIFNAME for arp");
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(arp_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(mux_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * PLINK the IP and ARP streams so that ifconfig can exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens * without tearing down the stream.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("I_PLINK for ip");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((arp_muxid = ioctl(mux_fd, I_PLINK, arp_fd)) == -1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) ioctl(mux_fd, I_PUNLINK, ip_muxid);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick Perror0_exit("I_PLINK for arp");
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick }
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (debug)
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) printf("arp muxid = %d\n", arp_muxid);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) close(arp_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(mux_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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.
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensinetunplumb(char *arg, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ip_muxid, arp_muxid;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick int mux_fd;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick char *udp_dev_name;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick char *strptr;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick uint64_t flags;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick boolean_t changed_arp_muxid = _B_FALSE;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick int save_errno;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens strptr = strchr(name, ':');
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strptr != NULL || strcmp(name, LOOPBACK_IF) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Can't unplumb logical interface zero */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strptr != NULL && strcmp(strptr, ":0") == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: unplumb:"
fa9e4066f08beec538e775443c5be79dd423fcabahrens " Cannot unplumb %s: Invalid interface\n", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("unplumb: SIOCLIFREMOVEIF");
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (afp->af_af == AF_INET6)
fa9e4066f08beec538e775443c5be79dd423fcabahrens udp_dev_name = UDP6_DEV_NAME;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens udp_dev_name = UDP_DEV_NAME;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1)
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(EXIT_FAILURE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(mux_fd, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("unplumb: SIOCGLIFFLAGS");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens flags = lifr.lifr_flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(mux_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("unplumb: SIOCGLIFMUXID");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens arp_muxid = lifr.lifr_arp_muxid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ip_muxid = lifr.lifr_ip_muxid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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".
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick */
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (arp_muxid != 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if (debug)
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) printf("arp_muxid %d\n", arp_muxid);
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick if ((errno == EINVAL) &&
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (flags & (IFF_NOARP | IFF_IPV6))) {
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson /*
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.
0a4e9518a44f226be6d39383330b5b1792d2f184gw */
0a4e9518a44f226be6d39383330b5b1792d2f184gw lifr.lifr_arp_muxid = 0;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) ioctl(mux_fd, SIOCSLIFMUXID,
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (caddr_t)&lifr);
0a4e9518a44f226be6d39383330b5b1792d2f184gw changed_arp_muxid = _B_TRUE;
0a4e9518a44f226be6d39383330b5b1792d2f184gw } else {
0a4e9518a44f226be6d39383330b5b1792d2f184gw Perror0("I_PUNLINK for arp");
0a4e9518a44f226be6d39383330b5b1792d2f184gw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("ip_muxid %d\n", ip_muxid);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(mux_fd, I_PUNLINK, ip_muxid) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (changed_arp_muxid) {
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Some error occurred, and we need to restore
fa9e4066f08beec538e775443c5be79dd423fcabahrens * everything back to what it was.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens save_errno = errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_arp_muxid = arp_muxid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens lifr.lifr_ip_muxid = ip_muxid;
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) ioctl(mux_fd, SIOCSLIFMUXID, (caddr_t)&lifr);
e05725b117836db173257fae43fb0746eb857fb5bonwick errno = save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror0_exit("I_PUNLINK for ip");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) close(mux_fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensinetplumb(char *arg, int64_t param)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *strptr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int dev_fd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dlpi_if_attr_t dia;
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t islo;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick strptr = strchr(name, ':');
e05725b117836db173257fae43fb0746eb857fb5bonwick islo = (strcmp(name, LOOPBACK_IF) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strptr != NULL || islo) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&lifr, 0, sizeof (lifr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (islo && ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) >= 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s already exists\n", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno == EEXIST) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "ifconfig: %s already exists\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2_exit("plumb: SIOCLIFADDIF", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(name, lifr.lifr_name, sizeof (name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("inetplumb: %s af %d\n", name, afp->af_af);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if ((dev_fd = dlpi_if_open(name, &dia, _B_FALSE)) < 0) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick Perror2_exit("plumb", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens plumb_one_device(&dia, dev_fd, afp->af_af);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia (void) close(dev_fd);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia return (0);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia}
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiavoid
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. CorreiaPerror0(char *cmd)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens save_errno = errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: ");
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case ENXIO:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "%s: %s: no such interface\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmd, lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EPERM:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "%s: %s: permission denied\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmd, lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EEXIST:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "%s: %s: already exists\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick cmd, lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens default: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char buf[BUFSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(buf, sizeof (buf), "%s: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmd, lifr.lifr_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens perror(buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwickvoid
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwickPerror0_exit(char *cmd)
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwick{
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwick Perror0(cmd);
0e34b6a7bff4918432f0aa6b1dfaf73ac9df45b1bonwick exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensPerror2(char *cmd, char *str)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens save_errno = errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: ");
fa9e4066f08beec538e775443c5be79dd423fcabahrens errno = save_errno;
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
0a4e9518a44f226be6d39383330b5b1792d2f184gw
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick case ENXIO:
0a4e9518a44f226be6d39383330b5b1792d2f184gw (void) fprintf(stderr, "%s: %s: no such interface\n",
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick cmd, str);
0a4e9518a44f226be6d39383330b5b1792d2f184gw break;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick case EPERM:
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) fprintf(stderr, "%s: %s: permission denied\n",
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick cmd, str);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick break;
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick default: {
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick char buf[BUFSIZ];
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick (void) snprintf(buf, sizeof (buf), "%s: %s", cmd, str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens perror(buf);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick}
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Print out error message (Perror2()) and exit
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensPerror2_exit(char *cmd, char *str)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens Perror2(cmd, str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NOTREACHED */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getaddr(char *s, struct sockaddr *saddr, int *plenp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct hostent *hp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct netent *np;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char str[BUFSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error_num;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(str, s, sizeof (str));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look for '/'<n> is plenp
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (plenp != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *cp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick *plenp = in_getprefixlen(str, _B_TRUE, ADDRBITS_V4);
e05725b117836db173257fae43fb0746eb857fb5bonwick if (*plenp == BAD_ADDR)
e05725b117836db173257fae43fb0746eb857fb5bonwick return;
e05725b117836db173257fae43fb0746eb857fb5bonwick cp = strchr(str, '/');
e05725b117836db173257fae43fb0746eb857fb5bonwick if (cp != NULL)
e05725b117836db173257fae43fb0746eb857fb5bonwick *cp = '\0';
e05725b117836db173257fae43fb0746eb857fb5bonwick } else if (strchr(str, '/') != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) fprintf(stderr, "ifconfig: %s: unexpected '/'\n", str);
e05725b117836db173257fae43fb0746eb857fb5bonwick exit(1);
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick (void) memset(sin, 0, sizeof (*sin));
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try to catch attempts to set the broadcast address to all 1's.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (strcmp(str, "255.255.255.255") == 0 ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens (strtoul(str, (char **)NULL, 0) == 0xffffffffUL)) {
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee sin->sin_family = AF_INET;
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee sin->sin_addr.s_addr = 0xffffffff;
e05725b117836db173257fae43fb0746eb857fb5bonwick return;
e05725b117836db173257fae43fb0746eb857fb5bonwick }
e05725b117836db173257fae43fb0746eb857fb5bonwick
e05725b117836db173257fae43fb0746eb857fb5bonwick hp = getipnodebyname(str, AF_INET, 0, &error_num);
4d31c452acf5d10173fb57db4d33ab750d0fd1c8maybee if (hp) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_family = hp->h_addrtype;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
fa9e4066f08beec538e775443c5be79dd423fcabahrens freehostent(hp);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens np = getnetbyname(str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (np) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens sin->sin_family = np->n_addrtype;
e05725b117836db173257fae43fb0746eb857fb5bonwick sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
e05725b117836db173257fae43fb0746eb857fb5bonwick return;
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin }
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin if (error_num == TRY_AGAIN) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s: bad address "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "(try again later)\n", s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) fprintf(stderr, "ifconfig: %s: bad address\n", s);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick/*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensin6_getaddr(char *s, struct sockaddr *saddr, int *plenp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)saddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct hostent *hp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char str[BUFSIZ];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error_num;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(str, s, sizeof (str));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e05725b117836db173257fae43fb0746eb857fb5bonwick /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Look for '/'<n> is plenp
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (plenp != NULL) {
e05725b117836db173257fae43fb0746eb857fb5bonwick char *cp;
e05725b117836db173257fae43fb0746eb857fb5bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens *plenp = in_getprefixlen(str, _B_TRUE, ADDRBITS_V6);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*plenp == BAD_ADDR)
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson return;
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson cp = strchr(str, '/');
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson if (cp != NULL)
718d718a734e79bad0b9f8a264219b238fabaf44George Wilson *cp = '\0';
e05725b117836db173257fae43fb0746eb857fb5bonwick } else if (strchr(str, '/') != NULL) {
0b69c2f001a429251e2d38f25aca860396551214ahrens (void) fprintf(stderr, "ifconfig: %s: unexpected '/'\n", str);
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) memset(sin6, 0, sizeof (*sin6));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick hp = getipnodebyname(str, AF_INET6, 0, &error_num);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick if (hp) {
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick sin6->sin6_family = hp->h_addrtype;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick (void) memcpy(&sin6->sin6_addr, hp->h_addr, hp->h_length);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick freehostent(hp);
8ad4d6dd86f5bc65fb3afa566c8133f3bac21648Jeff Bonwick return;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error_num == TRY_AGAIN) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s: bad address "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "(try again later)\n", s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "ifconfig: %s: bad address\n", s);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens exit(1);
e05725b117836db173257fae43fb0746eb857fb5bonwick}
e05725b117836db173257fae43fb0746eb857fb5bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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 *
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.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correiastatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getprefixlen(char *addr, boolean_t slash, int max_plen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int prefixlen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *str, *end;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (slash) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str = strchr(addr, '/');
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (str == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (NO_PREFIX);
fa9e4066f08beec538e775443c5be79dd423fcabahrens str++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else
fa9e4066f08beec538e775443c5be79dd423fcabahrens str = addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen = strtol(str, &end, 10);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (prefixlen < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (BAD_ADDR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (str == end)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (BAD_ADDR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (max_plen != 0 && max_plen < prefixlen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (BAD_ADDR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (prefixlen < 0 || prefixlen > maxlen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (prefixlen > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (prefixlen >= 8) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *mask++ = 0xFF;
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen -= 8;
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens *mask |= 1 << (8 - prefixlen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefixlen--;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (1);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson}
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic void
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimhprint_flags(uint64_t flags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t first = _B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int cnt, i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("flags=%llx", flags);
fa9e4066f08beec538e775443c5be79dd423fcabahrens cnt = sizeof (if_flags_tbl) / sizeof (if_flags_t);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < cnt; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & if_flags_tbl[i].iff_value) {
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson if (first) {
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson (void) printf("<");
fa9e4066f08beec538e775443c5be79dd423fcabahrens first = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
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 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(",");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("%s", if_flags_tbl[i].iff_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!first)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf(">");
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensprint_config_flags(uint64_t flags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int cnt, i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens cnt = sizeof (if_config_cmd_tbl) / sizeof (if_config_cmd_t);
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock for (i = 0; i < cnt; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flags & if_config_cmd_tbl[i].iff_flag) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) printf("%s ", if_config_cmd_tbl[i].iff_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
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 *
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t
fa9e4066f08beec538e775443c5be79dd423fcabahrensin_getmask(struct sockaddr_in *saddr, boolean_t addr_set)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ecc2d604e885a75cc75e647b5641af99d5a6f4a6bonwick struct sockaddr_in ifaddr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Read the address from the interface if it is not passed in.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!addr_set) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (errno != EADDRNOTAVAIL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "Need net number for "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "mask\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (_B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ifaddr = *((struct sockaddr_in *)&lifr.lifr_addr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ifaddr.sin_addr = saddr->sin_addr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (getnetmaskbyaddr(ifaddr.sin_addr, &saddr->sin_addr) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens saddr->sin_family = AF_INET;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (_B_TRUE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (_B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensstrioctl(int s, int cmd, char *buf, int buflen)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct strioctl ioc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) memset(&ioc, 0, sizeof (ioc));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ioc.ic_cmd = cmd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ioc.ic_timout = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ioc.ic_len = buflen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ioc.ic_dp = buf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ioctl(s, I_STR, (char *)&ioc));
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensadd_ni(char *name)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens ni_t **pp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ni_t *p;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (pp = &ni_list; (p = *pp) != NULL; pp = &(p->ni_next)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(p->ni_name, name) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "'%s' is a duplicate\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson }
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson }
d6e555bdd793b8bc8fe57d5f12c3d69c813d0661George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "adding '%s'\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((p = malloc(sizeof (ni_t))) == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(p->ni_name, name, sizeof (p->ni_name));
004388ebfdfe2ed7dfd2d153a876dfcc22d2c006casper p->ni_next = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *pp = p;
fa9e4066f08beec538e775443c5be79dd423fcabahrens num_ni++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
5ad820458efd0fdb914baff9c1447c22b819fa23nd
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED2 */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensdevfs_entry(di_node_t node, di_minor_t minor, void *arg)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *provider;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int fd;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint_t ppa;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dl_info_ack_t dlia;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char ifname[LIFNAMSIZ];
5ad820458efd0fdb914baff9c1447c22b819fa23nd
fa9e4066f08beec538e775443c5be79dd423fcabahrens provider = di_minor_name(minor);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strlen(provider) > LIFNAMSIZ)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (DI_WALK_CONTINUE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fprintf(stderr, "provider = %s\n", provider);
5ad820458efd0fdb914baff9c1447c22b819fa23nd
5ad820458efd0fdb914baff9c1447c22b819fa23nd if ((fd = dlpi_open(provider)) < 0)
5ad820458efd0fdb914baff9c1447c22b819fa23nd return (DI_WALK_CONTINUE);
5ad820458efd0fdb914baff9c1447c22b819fa23nd
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fprintf(stderr, "getting DL_INFO_ACK\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto done;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dlia.dl_provider_style == DL_STYLE1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fprintf(stderr, "provider is DL_STYLE1\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens add_ni(provider);
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto done;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fprintf(stderr, "provider is DL_STYLE2\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (di_minor_type(minor) != DDM_ALIAS) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "non-alias node, ignoring\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto done;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "alias node, using instance\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens ppa = di_instance(node);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dlpi_attach(fd, -1, ppa) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (debug > 2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "non-existent PPA, ignoring\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens goto done;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(ifname, LIFNAMSIZ, "%s%d", provider, ppa);
fa9e4066f08beec538e775443c5be79dd423fcabahrens add_ni(ifname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensdone:
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) dlpi_close(fd);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (DI_WALK_CONTINUE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dhcp-related routines
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetifdhcp(const char *caller, const char *ifname, int argc, char *argv[])
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dhcp_ipc_request_t *request;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dhcp_ipc_reply_t *reply = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int timeout = DHCP_IPC_WAIT_DEFAULT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dhcp_ipc_type_t type = DHCP_START;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t is_primary = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens boolean_t started = _B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (argv++; --argc > 0; argv++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strcmp(*argv, "primary") == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens is_primary = _B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
if (strcmp(*argv, "wait") == 0) {
if (--argc <= 0) {
usage();
return (DHCP_EXIT_BADARGS);
}
argv++;
if (strcmp(*argv, "forever") == 0) {
timeout = DHCP_IPC_WAIT_FOREVER;
continue;
}
if (sscanf(*argv, "%d", &timeout) != 1) {
usage();
return (DHCP_EXIT_BADARGS);
}
if (timeout < 0) {
usage();
return (DHCP_EXIT_BADARGS);
}
continue;
}
type = dhcp_string_to_request(*argv);
if (type == -1) {
usage();
return (DHCP_EXIT_BADARGS);
}
}
/*
* Only try to start agent on start or inform; in all other cases it
* has to already be running for anything to make sense.
*/
if (type == DHCP_START || type == DHCP_INFORM) {
if (dhcp_start_agent(DHCP_IPC_MAX_WAIT) == -1) {
(void) fprintf(stderr, "%s: unable to start %s\n",
caller, DHCP_AGENT_PATH);
return (DHCP_EXIT_FAILURE);
}
started = _B_TRUE;
}
if (is_primary)
type = type | DHCP_PRIMARY;
request = dhcp_ipc_alloc_request(type, ifname, NULL, 0, DHCP_TYPE_NONE);
if (request == NULL) {
(void) fprintf(stderr, "%s: out of memory\n", caller);
return (DHCP_EXIT_SYSTEM);
}
error = dhcp_ipc_make_request(request, &reply, timeout);
if (error != 0) {
free(request);
/*
* Re-map connect error to not under control if we didn't try a
* start operation, as this has to be true and results in a
* clearer message, not to mention preserving compatibility
* with the days when we always started dhcpagent for every
* request.
*/
if (error == DHCP_IPC_E_CONNECT && !started)
error = DHCP_IPC_E_UNKIF;
(void) fprintf(stderr, "%s: %s: %s\n", caller, ifname,
dhcp_ipc_strerror(error));
return (DHCP_EXIT_FAILURE);
}
error = reply->return_code;
if (error != 0) {
free(request);
free(reply);
if (error == DHCP_IPC_E_TIMEOUT && timeout == 0)
return (DHCP_EXIT_SUCCESS);
(void) fprintf(stderr, "%s: %s: %s\n", caller, ifname,
dhcp_ipc_strerror(error));
if (error == DHCP_IPC_E_TIMEOUT)
return (DHCP_EXIT_TIMEOUT);
else
return (DHCP_EXIT_IF_FAILURE);
}
if (DHCP_IPC_CMD(type) == DHCP_STATUS) {
(void) printf("%s", dhcp_status_hdr_string());
(void) printf("%s", dhcp_status_reply_to_string(reply));
}
free(request);
free(reply);
return (DHCP_EXIT_SUCCESS);
}
static void
usage(void)
{
(void) fprintf(stderr,
"usage: ifconfig <interface> | -a[ 4 | 6 | D ][ u | d ][ Z ]\n");
(void) fprintf(stderr, "%s",
"\t[ <addr_family> ]\n"
"\t[ <address>[/<prefix_length>] [ <dest_address> ] ]\n"
"\t[ set [ <address>][/<prefix_length>] ]"
" [ <address>/<prefix_length>] ]\n"
"\t[ destination <dest_address> ]\n"
"\t[ addif <address>[/<prefix_length>]"
" [ <dest_address> ] ]\n"
"\t[ removeif <address>[/<prefix_length>] ]\n"
"\t[ arp | -arp ]\n"
"\t[ auto-revarp ]\n"
"\t[ broadcast <broad_addr> ]\n"
"\t[ index <if_index> ]\n"
"\t[ metric <n> ] [ mtu <n> ]\n"
"\t[ netmask <mask> ]\n"
"\t[ plumb ] [ unplumb ]\n"
"\t[ preferred | -preferred ]\n"
"\t[ private | -private ]\n"
"\t[ local | -local ]\n"
"\t[ router | -router ]\n"
"\t[ subnet <subnet_address>]\n"
"\t[ trailers | -trailers ]\n"
"\t[ token <address>/<prefix_length> ]\n"
"\t[ tsrc <tunnel_src_address> ]\n"
"\t[ tdst <tunnel_dest_address> ]\n"
"\t[ auth_algs <tunnel_AH_authentication_algorithm> ]\n"
"\t[ encr_algs <tunnel_ESP_encryption_algorithm> ]\n"
"\t[ encr_auth_algs <tunnel_ESP_authentication_algorithm> ]\n"
"\t[ up ] [ down ]\n"
"\t[ xmit | -xmit ]\n"
"\t[ modlist ]\n"
"\t[ modinsert <module_name@position> ]\n"
"\t[ modremove <module_name@position> ]\n"
"\t[ group <groupname>] | [ group \"\"]\n"
"\t[ deprecated | -deprecated ]\n"
"\t[ standby | -standby ]\n"
"\t[ failover | -failover ]\n"
"\t[ zone <zonename> | -zone ]\n"
"\t[ usesrc <interface> ]\n");
(void) fprintf(stderr, "or\n");
(void) fprintf(stderr,
"\tifconfig <interface> | -a[ 4 | 6 | D ] [ u | d ]\n");
(void) fprintf(stderr, "%s", "\tauto-dhcp | dhcp\n"
"\t[ wait <time> | forever ]\n\t[ primary ]\n"
"\tstart | drop | ping | release | status | inform\n");
}