From owner-svn-src-all@FreeBSD.ORG Mon Feb 2 13:03:05 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 8CF7E9DA; Mon, 2 Feb 2015 13:03:05 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 780C0BD; Mon, 2 Feb 2015 13:03:05 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t12D355u059545; Mon, 2 Feb 2015 13:03:05 GMT (envelope-from vsevolod@FreeBSD.org) Received: (from vsevolod@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t12D35Nf059543; Mon, 2 Feb 2015 13:03:05 GMT (envelope-from vsevolod@FreeBSD.org) Message-Id: <201502021303.t12D35Nf059543@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: vsevolod set sender to vsevolod@FreeBSD.org using -f From: Vsevolod Stakhov Date: Mon, 2 Feb 2015 13:03:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r278080 - head/sbin/ifconfig X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Feb 2015 13:03:05 -0000 Author: vsevolod (ports committer) Date: Mon Feb 2 13:03:04 2015 New Revision: 278080 URL: https://svnweb.freebsd.org/changeset/base/278080 Log: Reorganize the list of addresses associated with an interface and group them based on the address family. This should help to recognize interfaces with multiple AF (e.g. ipv4 and ipv6) with many aliases or additional addresses. The order of addresses inside a single group is strictly preserved. Improve the scope_id output for AF_INET6 families, as the current approach uses hexadecimal string that is basically the ID of an interface, whilst this information is already depicted by getnameinfo(3) call. Therefore, now ifconfig just prints the scope of address as it is defined in 2.4 of RFC 2373. PR: 197270 Approved by: bapt MFC after: 2 weeks Modified: head/sbin/ifconfig/af_inet6.c head/sbin/ifconfig/ifconfig.c Modified: head/sbin/ifconfig/af_inet6.c ============================================================================== --- head/sbin/ifconfig/af_inet6.c Mon Feb 2 12:48:13 2015 (r278079) +++ head/sbin/ifconfig/af_inet6.c Mon Feb 2 13:03:04 2015 (r278080) @@ -167,6 +167,33 @@ setip6eui64(const char *cmd, int dummy _ } static void +in6_print_scope(uint8_t *a) +{ + const char *sname = NULL; + uint16_t val; + + val = (a[0] << 4) + ((a[1] & 0xc0) >> 4); + + if ((val & 0xff0) == 0xff0) + sname = "Multicast"; + else { + switch(val) { + case 0xfe8: + sname = "Link"; + break; + case 0xfec: + sname = "Site"; + break; + default: + sname = "Global"; + break; + } + } + + printf("scope: %s ", sname); +} + +static void in6_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_in6 *sin, null_sin; @@ -257,9 +284,7 @@ in6_status(int s __unused, const struct if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0) printf("prefer_source "); - if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id) - printf("scopeid 0x%x ", - ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id); + in6_print_scope((uint8_t *)&((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_addr); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { printf("pltime "); Modified: head/sbin/ifconfig/ifconfig.c ============================================================================== --- head/sbin/ifconfig/ifconfig.c Mon Feb 2 12:48:13 2015 (r278079) +++ head/sbin/ifconfig/ifconfig.c Mon Feb 2 13:03:04 2015 (r278080) @@ -47,6 +47,7 @@ static const char rcsid[] = #include #include #include +#include #include #include @@ -110,6 +111,15 @@ static void af_other_status(int); static struct option *opts = NULL; +struct ifa_order_elt { + int if_order; + int af_orders[255]; + struct ifaddrs *ifa; + TAILQ_ENTRY(ifa_order_elt) link; +}; + +TAILQ_HEAD(ifa_queue, ifa_order_elt); + void opt_register(struct option *p) { @@ -141,16 +151,162 @@ usage(void) exit(1); } +static int +calcorders(struct ifaddrs *ifa, struct ifa_queue *q) +{ + unsigned int ord, af, ifa_ord; + struct ifaddrs *prev; + struct ifa_order_elt *cur; + + prev = NULL; + cur = NULL; + ord = 0; + ifa_ord = 0; + + while (ifa != NULL) { + if (prev == NULL || strcmp(ifa->ifa_name, prev->ifa_name) != 0) { + cur = calloc(1, sizeof(*cur)); + + if (cur == NULL) + return (-1); + + TAILQ_INSERT_TAIL(q, cur, link); + cur->if_order = ifa_ord ++; + cur->ifa = ifa; + ord = 0; + } + + if (ifa->ifa_addr) { + af = ifa->ifa_addr->sa_family; + + if (af < sizeof(cur->af_orders) / sizeof(cur->af_orders[0]) && + cur->af_orders[af] == 0) + cur->af_orders[af] = ++ord; + } + prev = ifa; + ifa = ifa->ifa_next; + } + + return (0); +} + +static int +cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) +{ + int ret; + unsigned int af1, af2; + struct ifa_order_elt *cur, *e1, *e2; + + e1 = e2 = NULL; + + ret = strcmp(a->ifa_name, b->ifa_name); + if (ret != 0) { + /* We need to find elements corresponding to these different names */ + TAILQ_FOREACH(cur, q, link) { + if (e1 && e2) + break; + + if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) + e1 = cur; + else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0) + e2 = cur; + } + + if (!e1 || !e2) + return (0); + else + return (e1->if_order - e2->if_order); + + } else if (a->ifa_addr != NULL && b->ifa_addr != NULL) { + TAILQ_FOREACH(cur, q, link) { + if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) { + e1 = cur; + break; + } + } + + if (!e1) + return (0); + + af1 = a->ifa_addr->sa_family; + af2 = b->ifa_addr->sa_family; + + if (af1 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0]) && + af2 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0])) + return (e1->af_orders[af2] - e1->af_orders[af1]); + } + + return (0); +} + +static struct ifaddrs * +sortifaddrs(struct ifaddrs *list, + int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), + struct ifa_queue *q) +{ + + struct ifaddrs *right, *temp, *last, *result, *next, *tail; + + right = list; + temp = list; + last = list; + result = NULL; + next = NULL; + tail = NULL; + + if (!list || !list->ifa_next) + return (list); + + while (temp && temp->ifa_next) { + last = right; + right = right->ifa_next; + temp = temp->ifa_next->ifa_next; + } + + last->ifa_next = NULL; + + list = sortifaddrs(list, compare, q); + right = sortifaddrs(right, compare, q); + + while (list || right) { + + if (!right) { + next = list; + list = list->ifa_next; + } else if (!list) { + next = right; + right = right->ifa_next; + } else if (compare(list, right, q) <= 0) { + next = list; + list = list->ifa_next; + } else { + next = right; + right = right->ifa_next; + } + + if (!result) + result = next; + else + tail->ifa_next = next; + + tail = next; + } + + return (result); +} + int main(int argc, char *argv[]) { int c, all, namesonly, downonly, uponly; const struct afswtch *afp = NULL; int ifindex; - struct ifaddrs *ifap, *ifa; + struct ifaddrs *ifap, *sifap, *ifa; struct ifreq paifr; const struct sockaddr_dl *sdl; char options[1024], *cp, *namecp = NULL; + struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); + struct ifa_order_elt *cur, *tmp; const char *ifname; struct option *p; size_t iflen; @@ -285,9 +441,19 @@ main(int argc, char *argv[]) if (getifaddrs(&ifap) != 0) err(EXIT_FAILURE, "getifaddrs"); + cp = NULL; + + if (calcorders(ifap, &q) != 0) + err(EXIT_FAILURE, "calcorders"); + + sifap = sortifaddrs(ifap, cmpifaddrs, &q); + + TAILQ_FOREACH_SAFE(cur, &q, link, tmp) + free(cur); + ifindex = 0; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + for (ifa = sifap; ifa; ifa = ifa->ifa_next) { memset(&paifr, 0, sizeof(paifr)); strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {