ifconfig: go back to using direct ioctls rather than data from getifaddrs

AF_LINK may not be the first address returned for the interface.
Technically, it *might* not even exist on the interface even though
other families do.
This is likely a driver bug if this really is the case though.

As such it's just easier to use direct ioctls rather than thump around
getifaddrs results. As it stands, the code makes a lot of getifaddrs
calls anyway, so an extra ioctl or two won't break the bank.
This commit is contained in:
roy 2020-10-14 13:37:14 +00:00
parent 7a17fd0552
commit 8b0aa988ec
3 changed files with 24 additions and 40 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ifconfig.c,v 1.247 2020/09/28 13:50:22 roy Exp $ */
/* $NetBSD: ifconfig.c,v 1.248 2020/10/14 13:37:14 roy Exp $ */
/*-
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
@ -63,7 +63,7 @@
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1983, 1993\
The Regents of the University of California. All rights reserved.");
__RCSID("$NetBSD: ifconfig.c,v 1.247 2020/09/28 13:50:22 roy Exp $");
__RCSID("$NetBSD: ifconfig.c,v 1.248 2020/10/14 13:37:14 roy Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -135,8 +135,7 @@ static int setlinkstr(prop_dictionary_t, prop_dictionary_t);
static int unsetlinkstr(prop_dictionary_t, prop_dictionary_t);
static int setifdescr(prop_dictionary_t, prop_dictionary_t);
static int unsetifdescr(prop_dictionary_t, prop_dictionary_t);
static void status(const struct sockaddr_dl *, const void *,
prop_dictionary_t, prop_dictionary_t);
static void status(prop_dictionary_t, prop_dictionary_t);
__dead static void usage(void);
static const struct kwinst ifflagskw[] = {
@ -850,9 +849,6 @@ void
printall(const char *ifname, prop_dictionary_t env0)
{
struct ifaddrs *ifap, *ifa;
struct ifreq ifr;
const struct sockaddr_dl *sdl = NULL;
const struct if_data *ifi = NULL;
prop_dictionary_t env, oenv;
int idx;
char *p;
@ -872,19 +868,8 @@ printall(const char *ifname, prop_dictionary_t env0)
p = NULL;
idx = 0;
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
memset(&ifr, 0, sizeof(ifr));
estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
if (sizeof(ifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
memcpy(&ifr.ifr_addr, ifa->ifa_addr,
ifa->ifa_addr->sa_len);
}
if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
continue;
if (ifa->ifa_addr->sa_family == AF_LINK) {
sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
ifi = (const struct if_data *)ifa->ifa_data;
}
if (p && strcmp(p, ifa->ifa_name) == 0)
continue;
if (!prop_dictionary_set_string(env, "if", ifa->ifa_name))
@ -898,8 +883,7 @@ printall(const char *ifname, prop_dictionary_t env0)
if (uflag && (ifa->ifa_flags & IFF_UP) == 0)
continue;
if (sflag && (ifi == NULL ||
ifi->ifi_link_state == LINK_STATE_DOWN))
if (sflag && carrier(env) == LINK_STATE_DOWN)
continue;
idx++;
/*
@ -912,9 +896,7 @@ printall(const char *ifname, prop_dictionary_t env0)
continue;
}
status(sdl, ifa->ifa_data, env, oenv);
sdl = NULL;
ifi = NULL;
status(env, oenv);
}
if (lflag)
printf("\n");
@ -1256,13 +1238,12 @@ print_human_bytes(bool humanize, uint64_t n)
#define MAX_PRINT_LEN 58 /* XXX need a better way to determine this! */
void
status(const struct sockaddr_dl *sdl, const void *ifa_data,
prop_dictionary_t env, prop_dictionary_t oenv)
status(prop_dictionary_t env, prop_dictionary_t oenv)
{
const struct if_data *ifi = ifa_data;
status_func_t *status_f;
statistics_func_t *statistics_f;
struct ifdatareq ifdr;
struct if_data *ifi;
struct ifreq ifr;
struct ifdrv ifdrv;
char fbuf[BUFSIZ];
@ -1351,18 +1332,16 @@ status(const struct sockaddr_dl *sdl, const void *ifa_data,
free(p);
}
media_status(sdl->sdl_type, ifi->ifi_link_state, env, oenv);
media_status(env, oenv);
if (!vflag && !zflag)
goto proto_status;
/* We already have if_data from SIOCGIFDATA in ifa_data. */
if (zflag) {
estrlcpy(ifdr.ifdr_name, ifname, sizeof(ifdr.ifdr_name));
if (prog_ioctl(s, SIOCZIFDATA, &ifdr) == -1)
err(EXIT_FAILURE, "SIOCZIFDATA");
ifi = &ifdr.ifdr_data;
}
estrlcpy(ifdr.ifdr_name, ifname, sizeof(ifdr.ifdr_name));
if (prog_ioctl(s, zflag ? SIOCZIFDATA : SIOCGIFDATA, &ifdr) == -1)
err(EXIT_FAILURE, zflag ? "SIOCZIFDATA" : "SIOCGIFDATA");
ifi = &ifdr.ifdr_data;
print_plural("\tinput: ", ifi->ifi_ipackets, "packet");
print_human_bytes(hflag, ifi->ifi_ibytes);

View File

@ -1,6 +1,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: media.c,v 1.12 2020/10/05 17:29:22 roy Exp $");
__RCSID("$NetBSD: media.c,v 1.13 2020/10/14 13:37:14 roy Exp $");
#endif /* not lint */
#include <assert.h>
@ -395,8 +395,7 @@ print_media_status(int media_type, int media_status)
}
void
media_status(int media_type, int link_state,
prop_dictionary_t env, prop_dictionary_t oenv)
media_status(prop_dictionary_t env, prop_dictionary_t oenv)
{
struct ifmediareq ifmr;
int af, i, s;
@ -416,11 +415,17 @@ media_status(int media_type, int link_state,
estrlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
if (prog_ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
struct ifdatareq ifdr = { .ifdr_data.ifi_link_state = 0 };
struct if_data *ifi = &ifdr.ifdr_data;
/*
* Interface doesn't support SIOC{G,S}IFMEDIA.
*/
if (link_state != LINK_STATE_UNKNOWN)
print_link_status(media_type, link_state);
if (direct_ioctl(env, SIOCGIFDATA, &ifdr) == -1)
err(EXIT_FAILURE, "%s: SIOCGIFDATA", __func__);
if (ifi->ifi_link_state != LINK_STATE_UNKNOWN)
print_link_status(ifi->ifi_type, ifi->ifi_link_state);
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: media.h,v 1.2 2020/09/22 14:14:17 roy Exp $ */
/* $NetBSD: media.h,v 1.3 2020/10/14 13:37:14 roy Exp $ */
#ifndef _IFCONFIG_MEDIA_H
#define _IFCONFIG_MEDIA_H
@ -11,6 +11,6 @@ extern struct pkw kwmedia;
void print_media_word(int, const char *);
void process_media_commands(prop_dictionary_t);
void media_status(int, int, prop_dictionary_t, prop_dictionary_t);
void media_status(prop_dictionary_t, prop_dictionary_t);
#endif /* _IFCONFIG_MEDIA_H */