Changeset View
Changeset View
Standalone View
Standalone View
ifconfig.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#include <net/route.h> | #include <net/route.h> | ||||
/* IP */ | /* IP */ | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <fnmatch.h> | |||||
#include <ifaddrs.h> | #include <ifaddrs.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#ifdef JAIL | #ifdef JAIL | ||||
#include <jail.h> | #include <jail.h> | ||||
#endif | #endif | ||||
Show All 26 Lines | |||||
int supmedia = 0; | int supmedia = 0; | ||||
int printkeys = 0; /* Print keying material for interfaces. */ | int printkeys = 0; /* Print keying material for interfaces. */ | ||||
int exit_code = 0; | int exit_code = 0; | ||||
/* Formatter Strings */ | /* Formatter Strings */ | ||||
char *f_inet, *f_inet6, *f_ether, *f_addr; | char *f_inet, *f_inet6, *f_ether, *f_addr; | ||||
static bool group_member(const char *ifname, const char *match, | |||||
const char *nomatch); | |||||
static int ifconfig(int argc, char *const *argv, int iscreate, | static int ifconfig(int argc, char *const *argv, int iscreate, | ||||
const struct afswtch *afp); | const struct afswtch *afp); | ||||
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, | static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, | ||||
struct ifaddrs *ifa); | struct ifaddrs *ifa); | ||||
static void tunnel_status(int s); | static void tunnel_status(int s); | ||||
static _Noreturn void usage(void); | static _Noreturn void usage(void); | ||||
static int getifflags(const char *ifname, int us); | static int getifflags(const char *ifname, int us); | ||||
▲ Show 20 Lines • Show All 281 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
const struct afswtch *afp = NULL; | const struct afswtch *afp = NULL; | ||||
int ifindex; | int ifindex; | ||||
struct ifaddrs *ifap, *sifap, *ifa; | struct ifaddrs *ifap, *sifap, *ifa; | ||||
struct ifreq paifr; | struct ifreq paifr; | ||||
const struct sockaddr_dl *sdl; | const struct sockaddr_dl *sdl; | ||||
char options[1024], *cp, *envformat, *namecp = NULL; | char options[1024], *cp, *envformat, *namecp = NULL; | ||||
struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); | struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); | ||||
struct ifa_order_elt *cur, *tmp; | struct ifa_order_elt *cur, *tmp; | ||||
const char *ifname; | const char *ifname, *matchgroup, *nogroup; | ||||
struct option *p; | struct option *p; | ||||
size_t iflen; | size_t iflen; | ||||
int flags; | int flags; | ||||
all = downonly = uponly = namesonly = noload = verbose = 0; | all = downonly = uponly = namesonly = noload = verbose = 0; | ||||
f_inet = f_inet6 = f_ether = f_addr = NULL; | f_inet = f_inet6 = f_ether = f_addr = NULL; | ||||
matchgroup = nogroup = NULL; | |||||
envformat = getenv("IFCONFIG_FORMAT"); | envformat = getenv("IFCONFIG_FORMAT"); | ||||
if (envformat != NULL) | if (envformat != NULL) | ||||
setformat(envformat); | setformat(envformat); | ||||
/* | /* | ||||
* Ensure we print interface name when expected to, | * Ensure we print interface name when expected to, | ||||
* even if we terminate early due to error. | * even if we terminate early due to error. | ||||
*/ | */ | ||||
atexit(printifnamemaybe); | atexit(printifnamemaybe); | ||||
/* Parse leading line options */ | /* Parse leading line options */ | ||||
strlcpy(options, "f:adklmnuv", sizeof(options)); | strlcpy(options, "G:adf:klmnuv", sizeof(options)); | ||||
for (p = opts; p != NULL; p = p->next) | for (p = opts; p != NULL; p = p->next) | ||||
strlcat(options, p->opt, sizeof(options)); | strlcat(options, p->opt, sizeof(options)); | ||||
while ((c = getopt(argc, argv, options)) != -1) { | while ((c = getopt(argc, argv, options)) != -1) { | ||||
switch (c) { | switch (c) { | ||||
case 'a': /* scan all interfaces */ | case 'a': /* scan all interfaces */ | ||||
all++; | all++; | ||||
break; | break; | ||||
case 'd': /* restrict scan to "down" interfaces */ | case 'd': /* restrict scan to "down" interfaces */ | ||||
downonly++; | downonly++; | ||||
break; | break; | ||||
case 'f': | case 'f': | ||||
if (optarg == NULL) | if (optarg == NULL) | ||||
usage(); | usage(); | ||||
setformat(optarg); | setformat(optarg); | ||||
break; | break; | ||||
case 'G': | |||||
if (optarg == NULL || all == 0) | |||||
usage(); | |||||
nogroup = optarg; | |||||
break; | |||||
case 'k': | case 'k': | ||||
printkeys++; | printkeys++; | ||||
break; | break; | ||||
case 'l': /* scan interface names only */ | case 'l': /* scan interface names only */ | ||||
namesonly++; | namesonly++; | ||||
break; | break; | ||||
case 'm': /* show media choices in status */ | case 'm': /* show media choices in status */ | ||||
supmedia = 1; | supmedia = 1; | ||||
break; | break; | ||||
case 'n': /* suppress module loading */ | case 'n': /* suppress module loading */ | ||||
noload++; | noload++; | ||||
break; | break; | ||||
case 'u': /* restrict scan to "up" interfaces */ | case 'u': /* restrict scan to "up" interfaces */ | ||||
uponly++; | uponly++; | ||||
break; | break; | ||||
case 'v': | case 'v': | ||||
verbose++; | verbose++; | ||||
break; | break; | ||||
case 'g': | |||||
if (all) { | |||||
if (optarg == NULL) | |||||
usage(); | |||||
matchgroup = optarg; | |||||
break; | |||||
} | |||||
/* FALLTHROUGH */ | |||||
default: | default: | ||||
for (p = opts; p != NULL; p = p->next) | for (p = opts; p != NULL; p = p->next) | ||||
if (p->opt[0] == c) { | if (p->opt[0] == c) { | ||||
p->cb(optarg); | p->cb(optarg); | ||||
break; | break; | ||||
} | } | ||||
if (p == NULL) | if (p == NULL) | ||||
usage(); | usage(); | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | for (ifa = sifap; ifa; ifa = ifa->ifa_next) { | ||||
cp = ifa->ifa_name; | cp = ifa->ifa_name; | ||||
if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0) | if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0) | ||||
continue; | continue; | ||||
if (downonly && (ifa->ifa_flags & IFF_UP) != 0) | if (downonly && (ifa->ifa_flags & IFF_UP) != 0) | ||||
continue; | continue; | ||||
if (uponly && (ifa->ifa_flags & IFF_UP) == 0) | if (uponly && (ifa->ifa_flags & IFF_UP) == 0) | ||||
continue; | continue; | ||||
if (!group_member(ifa->ifa_name, matchgroup, nogroup)) | |||||
continue; | |||||
/* | /* | ||||
* Are we just listing the interfaces? | * Are we just listing the interfaces? | ||||
*/ | */ | ||||
if (namesonly) { | if (namesonly) { | ||||
if (namecp == cp) | if (namecp == cp) | ||||
continue; | continue; | ||||
if (afp != NULL) { | if (afp != NULL) { | ||||
/* special case for "ether" address family */ | /* special case for "ether" address family */ | ||||
Show All 26 Lines | #endif | ||||
} | } | ||||
if (namesonly) | if (namesonly) | ||||
printf("\n"); | printf("\n"); | ||||
freeifaddrs(ifap); | freeifaddrs(ifap); | ||||
done: | done: | ||||
freeformat(); | freeformat(); | ||||
exit(exit_code); | exit(exit_code); | ||||
} | |||||
/* | |||||
* Returns true if an interface should be listed because any its groups | |||||
* matches shell pattern "match" and none of groups matches pattern "nomatch". | |||||
* If any pattern is NULL, corresponding condition is skipped. | |||||
*/ | |||||
static bool | |||||
group_member(const char *ifname, const char *match, const char *nomatch) | |||||
{ | |||||
static int sock = -1; | |||||
struct ifgroupreq ifgr; | |||||
struct ifg_req *ifg; | |||||
int len; | |||||
bool matched, nomatched; | |||||
/* Sanity checks. */ | |||||
if (match == NULL && nomatch == NULL) | |||||
return (true); | |||||
if (ifname == NULL) | |||||
return (false); | |||||
memset(&ifgr, 0, sizeof(ifgr)); | |||||
strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); | |||||
/* The socket is opened once. Let _exit() close it. */ | |||||
if (sock == -1) { | |||||
sock = socket(AF_LOCAL, SOCK_DGRAM, 0); | |||||
if (sock == -1) | |||||
errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__); | |||||
} | |||||
/* Determine amount of memory for the list of groups. */ | |||||
if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { | |||||
if (errno == EINVAL || errno == ENOTTY) | |||||
return (false); | |||||
else | |||||
errx(1, "%s: SIOCGIFGROUP", __func__); | |||||
} | |||||
/* Obtain the list of groups. */ | |||||
len = ifgr.ifgr_len; | |||||
ifgr.ifgr_groups = | |||||
(struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg)); | |||||
if (ifgr.ifgr_groups == NULL) | |||||
errx(1, "%s: no memory", __func__); | |||||
if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) | |||||
errx(1, "%s: SIOCGIFGROUP", __func__); | |||||
/* Perform matching. */ | |||||
matched = false; | |||||
nomatched = true; | |||||
for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) { | |||||
len -= sizeof(struct ifg_req); | |||||
if (match) | |||||
matched |= !fnmatch(match, ifg->ifgrq_group, 0); | |||||
if (nomatch) | |||||
nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0); | |||||
} | |||||
if (match && !nomatch) | |||||
return (matched); | |||||
if (!match && nomatch) | |||||
return (nomatched); | |||||
return (matched && nomatched); | |||||
} | } | ||||
static struct afswtch *afs = NULL; | static struct afswtch *afs = NULL; | ||||
void | void | ||||
af_register(struct afswtch *p) | af_register(struct afswtch *p) | ||||
{ | { | ||||
p->af_next = afs; | p->af_next = afs; | ||||
▲ Show 20 Lines • Show All 938 Lines • Show Last 20 Lines |