1b1d757bcSAlan Somers /* 2b1d757bcSAlan Somers * Copyright (c) 2017, Spectra Logic Corporation 3b1d757bcSAlan Somers * All rights reserved. 4b1d757bcSAlan Somers * 5b1d757bcSAlan Somers * Redistribution and use in source and binary forms, with or without modification, 6b1d757bcSAlan Somers * are permitted provided that the following conditions are met: 7b1d757bcSAlan Somers * 8b1d757bcSAlan Somers * 1. Redistributions of source code must retain the above copyright notice, 9b1d757bcSAlan Somers * thislist of conditions and the following disclaimer. 10b1d757bcSAlan Somers * 11b1d757bcSAlan Somers * 2. Redistributions in binary form must reproduce the above copyright notice, 12b1d757bcSAlan Somers * this list of conditions and the following disclaimer in the documentation and/or 13b1d757bcSAlan Somers * other materials provided with the distribution. 14b1d757bcSAlan Somers * 15b1d757bcSAlan Somers * 16b1d757bcSAlan Somers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17b1d757bcSAlan Somers * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18b1d757bcSAlan Somers * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19b1d757bcSAlan Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20b1d757bcSAlan Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b1d757bcSAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22b1d757bcSAlan Somers * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23b1d757bcSAlan Somers * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24b1d757bcSAlan Somers * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25b1d757bcSAlan Somers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b1d757bcSAlan Somers * 27b1d757bcSAlan Somers * $FreeBSD$ 28b1d757bcSAlan Somers */ 29b1d757bcSAlan Somers 30b1d757bcSAlan Somers #include <sys/param.h> 31b1d757bcSAlan Somers #include <sys/ioctl.h> 32b1d757bcSAlan Somers #include <sys/socket.h> 33b1d757bcSAlan Somers 34b1d757bcSAlan Somers #include <arpa/inet.h> 35b1d757bcSAlan Somers #include <net/ethernet.h> 36b1d757bcSAlan Somers #include <net/if.h> 37b1d757bcSAlan Somers #include <net/if_dl.h> 38b1d757bcSAlan Somers #include <net/if_lagg.h> 39b1d757bcSAlan Somers #include <net/if_media.h> 40b1d757bcSAlan Somers #include <net/if_types.h> 41b1d757bcSAlan Somers #include <netinet/in.h> 42b1d757bcSAlan Somers #include <netinet/ip_carp.h> 43b1d757bcSAlan Somers #include <netinet6/in6_var.h> 44b1d757bcSAlan Somers #include <netinet6/nd6.h> 45b1d757bcSAlan Somers 46b1d757bcSAlan Somers #include <err.h> 47b1d757bcSAlan Somers #include <errno.h> 48b1d757bcSAlan Somers #include <ifaddrs.h> 49b1d757bcSAlan Somers #include <netdb.h> 50b1d757bcSAlan Somers #include <stdio.h> 51b1d757bcSAlan Somers #include <stdlib.h> 52b1d757bcSAlan Somers #include <string.h> 53b1d757bcSAlan Somers #include <libifconfig.h> 54b1d757bcSAlan Somers 55b1d757bcSAlan Somers static const char *carp_states[] = { CARP_STATES }; 56b1d757bcSAlan Somers 57b1d757bcSAlan Somers static void 58b1d757bcSAlan Somers print_carp(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 59b1d757bcSAlan Somers { 60b1d757bcSAlan Somers struct carpreq carpr[CARP_MAXVHID]; 61b1d757bcSAlan Somers int i; 62b1d757bcSAlan Somers 63b1d757bcSAlan Somers if (ifconfig_carp_get_info(lifh, ifa->ifa_name, carpr, CARP_MAXVHID)) { 64b1d757bcSAlan Somers return; /* Probably not configured on this interface */ 65b1d757bcSAlan Somers } 66b1d757bcSAlan Somers for (i = 0; i < carpr[0].carpr_count; i++) { 67b1d757bcSAlan Somers printf("\tcarp: %s vhid %d advbase %d advskew %d", 68b1d757bcSAlan Somers carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, 69b1d757bcSAlan Somers carpr[i].carpr_advbase, carpr[i].carpr_advskew); 70b1d757bcSAlan Somers printf("\n"); 71b1d757bcSAlan Somers } 72b1d757bcSAlan Somers } 73b1d757bcSAlan Somers 74b1d757bcSAlan Somers static void 75b1d757bcSAlan Somers print_inet4_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 76b1d757bcSAlan Somers { 77b1d757bcSAlan Somers struct ifconfig_inet_addr addr; 78b1d757bcSAlan Somers char addr_buf[NI_MAXHOST]; 79b1d757bcSAlan Somers 80b1d757bcSAlan Somers if (ifconfig_inet_get_addrinfo(lifh, ifa->ifa_name, ifa, &addr) != 0) { 81b1d757bcSAlan Somers return; 82b1d757bcSAlan Somers } 83b1d757bcSAlan Somers 84b1d757bcSAlan Somers inet_ntop(AF_INET, &addr.sin->sin_addr, addr_buf, sizeof(addr_buf)); 85b1d757bcSAlan Somers printf("\tinet %s", addr_buf); 86b1d757bcSAlan Somers 87b1d757bcSAlan Somers if (addr.dst) { 88b1d757bcSAlan Somers printf(" --> %s", inet_ntoa(addr.dst->sin_addr)); 89b1d757bcSAlan Somers } 90b1d757bcSAlan Somers 91b1d757bcSAlan Somers printf(" netmask 0x%x ", ntohl(addr.netmask->sin_addr.s_addr)); 92b1d757bcSAlan Somers 93b1d757bcSAlan Somers if ((addr.broadcast != NULL) && 94b1d757bcSAlan Somers (addr.broadcast->sin_addr.s_addr != 0)) { 95b1d757bcSAlan Somers printf("broadcast %s ", inet_ntoa(addr.broadcast->sin_addr)); 96b1d757bcSAlan Somers } 97b1d757bcSAlan Somers 98b1d757bcSAlan Somers if (addr.vhid != 0) { 99b1d757bcSAlan Somers printf("vhid %d ", addr.vhid); 100b1d757bcSAlan Somers } 101b1d757bcSAlan Somers printf("\n"); 102b1d757bcSAlan Somers } 103b1d757bcSAlan Somers 104b1d757bcSAlan Somers static void 105b1d757bcSAlan Somers print_inet6_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 106b1d757bcSAlan Somers { 107b1d757bcSAlan Somers struct ifconfig_inet6_addr addr; 108b1d757bcSAlan Somers char addr_buf[NI_MAXHOST]; 109b1d757bcSAlan Somers struct timespec now; 110b1d757bcSAlan Somers 111b1d757bcSAlan Somers /* Print the address */ 112b1d757bcSAlan Somers if (ifconfig_inet6_get_addrinfo(lifh, ifa->ifa_name, ifa, &addr) != 0) { 113b1d757bcSAlan Somers err(1, "ifconfig_inet6_get_addrinfo"); 114b1d757bcSAlan Somers } 115b1d757bcSAlan Somers if (0 != getnameinfo((struct sockaddr *)addr.sin6, addr.sin6->sin6_len, 116b1d757bcSAlan Somers addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST)) { 117b1d757bcSAlan Somers inet_ntop(AF_INET6, &addr.sin6->sin6_addr, addr_buf, 118b1d757bcSAlan Somers sizeof(addr_buf)); 119b1d757bcSAlan Somers } 120b1d757bcSAlan Somers printf("\tinet6 %s", addr_buf); 121b1d757bcSAlan Somers 122b1d757bcSAlan Somers if (addr.dstin6) { 123b1d757bcSAlan Somers inet_ntop(AF_INET6, addr.dstin6, addr_buf, sizeof(addr_buf)); 124b1d757bcSAlan Somers printf(" --> %s", addr_buf); 125b1d757bcSAlan Somers } 126b1d757bcSAlan Somers 127b1d757bcSAlan Somers /* Print the netmask */ 128b1d757bcSAlan Somers printf(" prefixlen %d ", addr.prefixlen); 129b1d757bcSAlan Somers 130b1d757bcSAlan Somers /* Print the scopeid*/ 131b1d757bcSAlan Somers if (addr.sin6->sin6_scope_id) { 132b1d757bcSAlan Somers printf("scopeid 0x%x ", addr.sin6->sin6_scope_id); 133b1d757bcSAlan Somers } 134b1d757bcSAlan Somers 135b1d757bcSAlan Somers /* Print the flags */ 136b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_ANYCAST) != 0) { 137b1d757bcSAlan Somers printf("anycast "); 138b1d757bcSAlan Somers } 139b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_TENTATIVE) != 0) { 140b1d757bcSAlan Somers printf("tentative "); 141b1d757bcSAlan Somers } 142b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_DUPLICATED) != 0) { 143b1d757bcSAlan Somers printf("duplicated "); 144b1d757bcSAlan Somers } 145b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_DETACHED) != 0) { 146b1d757bcSAlan Somers printf("detached "); 147b1d757bcSAlan Somers } 148b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_DEPRECATED) != 0) { 149b1d757bcSAlan Somers printf("deprecated "); 150b1d757bcSAlan Somers } 151b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_AUTOCONF) != 0) { 152b1d757bcSAlan Somers printf("autoconf "); 153b1d757bcSAlan Somers } 154b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_TEMPORARY) != 0) { 155b1d757bcSAlan Somers printf("temporary "); 156b1d757bcSAlan Somers } 157b1d757bcSAlan Somers if ((addr.flags & IN6_IFF_PREFER_SOURCE) != 0) { 158b1d757bcSAlan Somers printf("prefer_source "); 159b1d757bcSAlan Somers } 160b1d757bcSAlan Somers 161b1d757bcSAlan Somers /* Print the lifetimes */ 162b1d757bcSAlan Somers clock_gettime(CLOCK_MONOTONIC_FAST, &now); 163b1d757bcSAlan Somers if (addr.lifetime.ia6t_preferred || addr.lifetime.ia6t_expire) { 164b1d757bcSAlan Somers printf("pltime "); 165b1d757bcSAlan Somers if (addr.lifetime.ia6t_preferred) { 166b1d757bcSAlan Somers printf("%ld ", MAX(0l, 167b1d757bcSAlan Somers addr.lifetime.ia6t_preferred - now.tv_sec)); 168b1d757bcSAlan Somers } else { 169b1d757bcSAlan Somers printf("infty "); 170b1d757bcSAlan Somers } 171b1d757bcSAlan Somers 172b1d757bcSAlan Somers printf("vltime "); 173b1d757bcSAlan Somers if (addr.lifetime.ia6t_expire) { 174b1d757bcSAlan Somers printf("%ld ", MAX(0l, 175b1d757bcSAlan Somers addr.lifetime.ia6t_expire - now.tv_sec)); 176b1d757bcSAlan Somers } else { 177b1d757bcSAlan Somers printf("infty "); 178b1d757bcSAlan Somers } 179b1d757bcSAlan Somers } 180b1d757bcSAlan Somers 181b1d757bcSAlan Somers /* Print the vhid */ 182b1d757bcSAlan Somers if (addr.vhid != 0) { 183b1d757bcSAlan Somers printf("vhid %d ", addr.vhid); 184b1d757bcSAlan Somers } 185b1d757bcSAlan Somers printf("\n"); 186b1d757bcSAlan Somers } 187b1d757bcSAlan Somers 188b1d757bcSAlan Somers static void 189b1d757bcSAlan Somers print_link_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 190b1d757bcSAlan Somers { 191b1d757bcSAlan Somers char addr_buf[NI_MAXHOST]; 192b1d757bcSAlan Somers struct sockaddr_dl *sdl; 193b1d757bcSAlan Somers int n; 194b1d757bcSAlan Somers 195b1d757bcSAlan Somers sdl = (struct sockaddr_dl *)ifa->ifa_addr; 196b1d757bcSAlan Somers if ((sdl != NULL) && (sdl->sdl_alen > 0)) { 197b1d757bcSAlan Somers if (((sdl->sdl_type == IFT_ETHER) || 198b1d757bcSAlan Somers (sdl->sdl_type == IFT_L2VLAN) || 199b1d757bcSAlan Somers (sdl->sdl_type == IFT_BRIDGE)) && 200b1d757bcSAlan Somers (sdl->sdl_alen == ETHER_ADDR_LEN)) { 201b1d757bcSAlan Somers ether_ntoa_r((struct ether_addr *)LLADDR(sdl), 202b1d757bcSAlan Somers addr_buf); 203b1d757bcSAlan Somers printf("\tether %s\n", addr_buf); 204b1d757bcSAlan Somers } else { 205b1d757bcSAlan Somers n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; 206b1d757bcSAlan Somers 207b1d757bcSAlan Somers printf("\tlladdr %s\n", link_ntoa(sdl) + n); 208b1d757bcSAlan Somers } 209b1d757bcSAlan Somers } 210b1d757bcSAlan Somers } 211b1d757bcSAlan Somers 212b1d757bcSAlan Somers static void 213b1d757bcSAlan Somers print_ifaddr(ifconfig_handle_t *lifh, struct ifaddrs *ifa, void *udata __unused) 214b1d757bcSAlan Somers { 215b1d757bcSAlan Somers switch (ifa->ifa_addr->sa_family) { 216b1d757bcSAlan Somers case AF_INET: 217b1d757bcSAlan Somers print_inet4_addr(lifh, ifa); 218b1d757bcSAlan Somers break; 219b1d757bcSAlan Somers case AF_INET6: 220b1d757bcSAlan Somers 221b1d757bcSAlan Somers /* 222b1d757bcSAlan Somers * printing AF_INET6 status requires calling SIOCGIFAFLAG_IN6 223b1d757bcSAlan Somers * and SIOCGIFALIFETIME_IN6. TODO: figure out the best way to 224b1d757bcSAlan Somers * do that from within libifconfig 225b1d757bcSAlan Somers */ 226b1d757bcSAlan Somers print_inet6_addr(lifh, ifa); 227b1d757bcSAlan Somers break; 228b1d757bcSAlan Somers case AF_LINK: 229b1d757bcSAlan Somers print_link_addr(lifh, ifa); 230b1d757bcSAlan Somers break; 231b1d757bcSAlan Somers case AF_LOCAL: 232b1d757bcSAlan Somers case AF_UNSPEC: 233b1d757bcSAlan Somers default: 234b1d757bcSAlan Somers /* TODO */ 235b1d757bcSAlan Somers break; 236b1d757bcSAlan Somers } 237b1d757bcSAlan Somers } 238b1d757bcSAlan Somers 239b1d757bcSAlan Somers static void 240b1d757bcSAlan Somers print_nd6(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 241b1d757bcSAlan Somers { 242b1d757bcSAlan Somers struct in6_ndireq nd; 243b1d757bcSAlan Somers 244b1d757bcSAlan Somers if (ifconfig_get_nd6(lifh, ifa->ifa_name, &nd) == 0) { 245b1d757bcSAlan Somers printf("\tnd6 options=%x\n", nd.ndi.flags); 246b1d757bcSAlan Somers } else { 247b1d757bcSAlan Somers err(1, "Failed to get nd6 options"); 248b1d757bcSAlan Somers } 249b1d757bcSAlan Somers } 250b1d757bcSAlan Somers 251b1d757bcSAlan Somers static void 252b1d757bcSAlan Somers print_fib(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 253b1d757bcSAlan Somers { 254b1d757bcSAlan Somers int fib; 255b1d757bcSAlan Somers 256b1d757bcSAlan Somers if (ifconfig_get_fib(lifh, ifa->ifa_name, &fib) == 0) { 257b1d757bcSAlan Somers printf("\tfib: %d\n", fib); 258b1d757bcSAlan Somers } else { 259b1d757bcSAlan Somers err(1, "Failed to get interface FIB"); 260b1d757bcSAlan Somers } 261b1d757bcSAlan Somers } 262b1d757bcSAlan Somers 263b1d757bcSAlan Somers static void 264b1d757bcSAlan Somers print_lagg(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 265b1d757bcSAlan Somers { 266b1d757bcSAlan Somers struct lagg_protos lpr[] = LAGG_PROTOS; 267b1d757bcSAlan Somers struct ifconfig_lagg_status *ls; 268b1d757bcSAlan Somers struct lacp_opreq *lp; 269b1d757bcSAlan Somers const char *proto = "<unknown>"; 270b1d757bcSAlan Somers int i; 271b1d757bcSAlan Somers 272b1d757bcSAlan Somers if (ifconfig_lagg_get_lagg_status(lifh, ifa->ifa_name, &ls) < 0) { 273b1d757bcSAlan Somers if (ifconfig_err_errno(lifh) == EINVAL) { 274b1d757bcSAlan Somers return; 275b1d757bcSAlan Somers } 276b1d757bcSAlan Somers err(1, "Failed to get interface lagg status"); 277b1d757bcSAlan Somers } 278b1d757bcSAlan Somers 279b1d757bcSAlan Somers /* First print the proto */ 280b1d757bcSAlan Somers for (i = 0; i < nitems(lpr); i++) { 281b1d757bcSAlan Somers if (ls->ra->ra_proto == lpr[i].lpr_proto) { 282b1d757bcSAlan Somers proto = lpr[i].lpr_name; 283b1d757bcSAlan Somers break; 284b1d757bcSAlan Somers } 285b1d757bcSAlan Somers } 286b1d757bcSAlan Somers printf("\tlaggproto %s", proto); 287b1d757bcSAlan Somers 288b1d757bcSAlan Somers /* Now print the lagg hash */ 289b1d757bcSAlan Somers if (ls->rf->rf_flags & LAGG_F_HASHMASK) { 290b1d757bcSAlan Somers const char *sep = ""; 291b1d757bcSAlan Somers 292b1d757bcSAlan Somers printf(" lagghash "); 293b1d757bcSAlan Somers if (ls->rf->rf_flags & LAGG_F_HASHL2) { 294b1d757bcSAlan Somers printf("%sl2", sep); 295b1d757bcSAlan Somers sep = ","; 296b1d757bcSAlan Somers } 297b1d757bcSAlan Somers if (ls->rf->rf_flags & LAGG_F_HASHL3) { 298b1d757bcSAlan Somers printf("%sl3", sep); 299b1d757bcSAlan Somers sep = ","; 300b1d757bcSAlan Somers } 301b1d757bcSAlan Somers if (ls->rf->rf_flags & LAGG_F_HASHL4) { 302b1d757bcSAlan Somers printf("%sl4", sep); 303b1d757bcSAlan Somers sep = ","; 304b1d757bcSAlan Somers } 305b1d757bcSAlan Somers } 306b1d757bcSAlan Somers putchar('\n'); 307b1d757bcSAlan Somers printf("\tlagg options:\n"); 308b1d757bcSAlan Somers printf("\t\tflags=%x", ls->ro->ro_opts); 309b1d757bcSAlan Somers putchar('\n'); 310b1d757bcSAlan Somers printf("\t\tflowid_shift: %d\n", ls->ro->ro_flowid_shift); 311b1d757bcSAlan Somers if (ls->ra->ra_proto == LAGG_PROTO_ROUNDROBIN) { 312b1d757bcSAlan Somers printf("\t\trr_limit: %d\n", ls->ro->ro_bkt); 313b1d757bcSAlan Somers } 314b1d757bcSAlan Somers printf("\tlagg statistics:\n"); 315b1d757bcSAlan Somers printf("\t\tactive ports: %d\n", ls->ro->ro_active); 316b1d757bcSAlan Somers printf("\t\tflapping: %u\n", ls->ro->ro_flapping); 317b1d757bcSAlan Somers for (i = 0; i < ls->ra->ra_ports; i++) { 318b1d757bcSAlan Somers lp = (struct lacp_opreq *)&ls->ra->ra_port[i].rp_lacpreq; 319b1d757bcSAlan Somers printf("\tlaggport: %s ", ls->ra->ra_port[i].rp_portname); 320b1d757bcSAlan Somers printf("flags=%x", ls->ra->ra_port[i].rp_flags); 321b1d757bcSAlan Somers if (ls->ra->ra_proto == LAGG_PROTO_LACP) { 322b1d757bcSAlan Somers printf(" state=%x", lp->actor_state); 323b1d757bcSAlan Somers } 324b1d757bcSAlan Somers putchar('\n'); 325b1d757bcSAlan Somers } 326b1d757bcSAlan Somers 327b1d757bcSAlan Somers printf("\n"); 328b1d757bcSAlan Somers ifconfig_lagg_free_lagg_status(ls); 329b1d757bcSAlan Somers } 330b1d757bcSAlan Somers 331b1d757bcSAlan Somers static void 332b1d757bcSAlan Somers print_laggport(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 333b1d757bcSAlan Somers { 334b1d757bcSAlan Somers struct lagg_reqport rp; 335b1d757bcSAlan Somers 336b1d757bcSAlan Somers if (ifconfig_lagg_get_laggport_status(lifh, ifa->ifa_name, &rp) < 0) { 337b1d757bcSAlan Somers if ((ifconfig_err_errno(lifh) == EINVAL) || 338b1d757bcSAlan Somers (ifconfig_err_errno(lifh) == ENOENT)) { 339b1d757bcSAlan Somers return; 340b1d757bcSAlan Somers } else { 341b1d757bcSAlan Somers err(1, "Failed to get lagg port status"); 342b1d757bcSAlan Somers } 343b1d757bcSAlan Somers } 344b1d757bcSAlan Somers 345b1d757bcSAlan Somers printf("\tlaggdev: %s\n", rp.rp_ifname); 346b1d757bcSAlan Somers } 347b1d757bcSAlan Somers 348b1d757bcSAlan Somers static void 349b1d757bcSAlan Somers print_groups(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 350b1d757bcSAlan Somers { 351b1d757bcSAlan Somers struct ifgroupreq ifgr; 352b1d757bcSAlan Somers struct ifg_req *ifg; 353b1d757bcSAlan Somers int len; 354b1d757bcSAlan Somers int cnt = 0; 355b1d757bcSAlan Somers 356b1d757bcSAlan Somers if (ifconfig_get_groups(lifh, ifa->ifa_name, &ifgr) != 0) { 357b1d757bcSAlan Somers err(1, "Failed to get groups"); 358b1d757bcSAlan Somers } 359b1d757bcSAlan Somers 360b1d757bcSAlan Somers ifg = ifgr.ifgr_groups; 361b1d757bcSAlan Somers len = ifgr.ifgr_len; 362b1d757bcSAlan Somers for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 363b1d757bcSAlan Somers len -= sizeof(struct ifg_req); 364b1d757bcSAlan Somers if (strcmp(ifg->ifgrq_group, "all")) { 365b1d757bcSAlan Somers if (cnt == 0) { 366b1d757bcSAlan Somers printf("\tgroups: "); 367b1d757bcSAlan Somers } 368b1d757bcSAlan Somers cnt++; 369b1d757bcSAlan Somers printf("%s ", ifg->ifgrq_group); 370b1d757bcSAlan Somers } 371b1d757bcSAlan Somers } 372b1d757bcSAlan Somers if (cnt) { 373b1d757bcSAlan Somers printf("\n"); 374b1d757bcSAlan Somers } 375b1d757bcSAlan Somers 376b1d757bcSAlan Somers free(ifgr.ifgr_groups); 377b1d757bcSAlan Somers } 378b1d757bcSAlan Somers 379b1d757bcSAlan Somers static void 380b1d757bcSAlan Somers print_media(ifconfig_handle_t *lifh, struct ifaddrs *ifa) 381b1d757bcSAlan Somers { 382b1d757bcSAlan Somers int i; 383b1d757bcSAlan Somers 384b1d757bcSAlan Somers /* Outline: 385b1d757bcSAlan Somers * 1) Determine whether the iface supports SIOGIFMEDIA or SIOGIFXMEDIA 386b1d757bcSAlan Somers * 2) Get the full media list 387b1d757bcSAlan Somers * 3) Print the current media word 388b1d757bcSAlan Somers * 4) Print the active media word, if different 389b1d757bcSAlan Somers * 5) Print the status 390b1d757bcSAlan Somers * 6) Print the supported media list 391b1d757bcSAlan Somers * 392b1d757bcSAlan Somers * How to print the media word: 393b1d757bcSAlan Somers * 1) Get the top-level interface type and description 394b1d757bcSAlan Somers * 2) Print the subtype 395b1d757bcSAlan Somers * 3) For current word only, print the top type, if it exists 396b1d757bcSAlan Somers * 4) Print options list 397b1d757bcSAlan Somers * 5) Print the instance, if there is one 398b1d757bcSAlan Somers * 399b1d757bcSAlan Somers * How to get the top-level interface type 400b1d757bcSAlan Somers * 1) Shift ifmw right by 0x20 and index into IFM_TYPE_DESCRIPTIONS 401b1d757bcSAlan Somers * 402b1d757bcSAlan Somers * How to get the top-level interface subtype 403b1d757bcSAlan Somers * 1) Shift ifmw right by 0x20, index into ifmedia_types_to_subtypes 404b1d757bcSAlan Somers * 2) Iterate through the resulting table's subtypes table, ignoring 405b1d757bcSAlan Somers * aliases. Iterate through the resulting ifmedia_description 406b1d757bcSAlan Somers * tables, finding an entry with the right media subtype 407b1d757bcSAlan Somers */ 408b1d757bcSAlan Somers struct ifmediareq *ifmr; 409b1d757bcSAlan Somers 410b1d757bcSAlan Somers if (ifconfig_media_get_mediareq(lifh, ifa->ifa_name, &ifmr) != 0) { 411b1d757bcSAlan Somers if (ifconfig_err_errtype(lifh) != OK) { 412b1d757bcSAlan Somers err(1, "Failed to get media info"); 413b1d757bcSAlan Somers } else { 414b1d757bcSAlan Somers return; /* Interface doesn't support media info */ 415b1d757bcSAlan Somers } 416b1d757bcSAlan Somers } 417b1d757bcSAlan Somers 418b1d757bcSAlan Somers printf("\tmedia: %s %s", ifconfig_media_get_type(ifmr->ifm_current), 419b1d757bcSAlan Somers ifconfig_media_get_subtype(ifmr->ifm_current)); 420b1d757bcSAlan Somers if (ifmr->ifm_active != ifmr->ifm_current) { 421*c4ba4aa5SRyan Moeller const char **options; 422*c4ba4aa5SRyan Moeller 423b1d757bcSAlan Somers printf(" (%s", ifconfig_media_get_subtype(ifmr->ifm_active)); 424*c4ba4aa5SRyan Moeller options = ifconfig_media_get_options(ifmr->ifm_active); 425*c4ba4aa5SRyan Moeller if (options != NULL && options[0] != NULL) { 426*c4ba4aa5SRyan Moeller printf(" <%s", options[0]); 427*c4ba4aa5SRyan Moeller for (size_t i = 1; options[i] != NULL; ++i) 428*c4ba4aa5SRyan Moeller printf(",%s", options[i]); 429*c4ba4aa5SRyan Moeller printf(">)\n"); 430b1d757bcSAlan Somers } else { 431b1d757bcSAlan Somers printf(")\n"); 432b1d757bcSAlan Somers } 433*c4ba4aa5SRyan Moeller free(options); 434b1d757bcSAlan Somers } else { 435b1d757bcSAlan Somers printf("\n"); 436b1d757bcSAlan Somers } 437b1d757bcSAlan Somers 438b1d757bcSAlan Somers if (ifmr->ifm_status & IFM_AVALID) { 439b1d757bcSAlan Somers printf("\tstatus: %s\n", 440b1d757bcSAlan Somers ifconfig_media_get_status(ifmr)); 441b1d757bcSAlan Somers } 442b1d757bcSAlan Somers 443b1d757bcSAlan Somers printf("\tsupported media:\n"); 444b1d757bcSAlan Somers for (i = 0; i < ifmr->ifm_count; i++) { 445*c4ba4aa5SRyan Moeller const char **options; 446*c4ba4aa5SRyan Moeller 447b1d757bcSAlan Somers printf("\t\tmedia %s", 448b1d757bcSAlan Somers ifconfig_media_get_subtype(ifmr->ifm_ulist[i])); 449*c4ba4aa5SRyan Moeller options = ifconfig_media_get_options(ifmr->ifm_ulist[i]); 450*c4ba4aa5SRyan Moeller if (options != NULL && options[0] != NULL) { 451*c4ba4aa5SRyan Moeller printf(" mediaopt %s", options[0]); 452*c4ba4aa5SRyan Moeller for (size_t i = 1; options[i] != NULL; ++i) 453*c4ba4aa5SRyan Moeller printf(",%s", options[i]); 454*c4ba4aa5SRyan Moeller printf("\n"); 455b1d757bcSAlan Somers } else { 456b1d757bcSAlan Somers printf("\n"); 457b1d757bcSAlan Somers } 458*c4ba4aa5SRyan Moeller free(options); 459b1d757bcSAlan Somers } 460b1d757bcSAlan Somers free(ifmr); 461b1d757bcSAlan Somers } 462b1d757bcSAlan Somers 463b1d757bcSAlan Somers static void 464b1d757bcSAlan Somers print_iface(ifconfig_handle_t *lifh, struct ifaddrs *ifa, void *udata __unused) 465b1d757bcSAlan Somers { 466b1d757bcSAlan Somers int metric, mtu; 467b1d757bcSAlan Somers char *description = NULL; 468b1d757bcSAlan Somers struct ifconfig_capabilities caps; 469b1d757bcSAlan Somers struct ifstat ifs; 470b1d757bcSAlan Somers 471b1d757bcSAlan Somers printf("%s: flags=%x ", ifa->ifa_name, ifa->ifa_flags); 472b1d757bcSAlan Somers 473b1d757bcSAlan Somers if (ifconfig_get_metric(lifh, ifa->ifa_name, &metric) == 0) { 474b1d757bcSAlan Somers printf("metric %d ", metric); 475b1d757bcSAlan Somers } else { 476b1d757bcSAlan Somers err(1, "Failed to get interface metric"); 477b1d757bcSAlan Somers } 478b1d757bcSAlan Somers 479b1d757bcSAlan Somers if (ifconfig_get_mtu(lifh, ifa->ifa_name, &mtu) == 0) { 480b1d757bcSAlan Somers printf("mtu %d\n", mtu); 481b1d757bcSAlan Somers } else { 482b1d757bcSAlan Somers err(1, "Failed to get interface MTU"); 483b1d757bcSAlan Somers } 484b1d757bcSAlan Somers 485b1d757bcSAlan Somers if (ifconfig_get_description(lifh, ifa->ifa_name, &description) == 0) { 486b1d757bcSAlan Somers printf("\tdescription: %s\n", description); 487b1d757bcSAlan Somers } 488b1d757bcSAlan Somers 489b1d757bcSAlan Somers if (ifconfig_get_capability(lifh, ifa->ifa_name, &caps) == 0) { 490b1d757bcSAlan Somers if (caps.curcap != 0) { 491b1d757bcSAlan Somers printf("\toptions=%x\n", caps.curcap); 492b1d757bcSAlan Somers } 493b1d757bcSAlan Somers if (caps.reqcap != 0) { 494b1d757bcSAlan Somers printf("\tcapabilities=%x\n", caps.reqcap); 495b1d757bcSAlan Somers } 496b1d757bcSAlan Somers } else { 497b1d757bcSAlan Somers err(1, "Failed to get interface capabilities"); 498b1d757bcSAlan Somers } 499b1d757bcSAlan Somers 500b1d757bcSAlan Somers ifconfig_foreach_ifaddr(lifh, ifa, print_ifaddr, NULL); 501b1d757bcSAlan Somers 502b1d757bcSAlan Somers /* This paragraph is equivalent to ifconfig's af_other_status funcs */ 503b1d757bcSAlan Somers print_nd6(lifh, ifa); 504b1d757bcSAlan Somers print_media(lifh, ifa); 505b1d757bcSAlan Somers print_groups(lifh, ifa); 506b1d757bcSAlan Somers print_fib(lifh, ifa); 507b1d757bcSAlan Somers print_carp(lifh, ifa); 508b1d757bcSAlan Somers print_lagg(lifh, ifa); 509b1d757bcSAlan Somers print_laggport(lifh, ifa); 510b1d757bcSAlan Somers 511b1d757bcSAlan Somers if (ifconfig_get_ifstatus(lifh, ifa->ifa_name, &ifs) == 0) { 512b1d757bcSAlan Somers printf("%s", ifs.ascii); 513b1d757bcSAlan Somers } 514b1d757bcSAlan Somers 515b1d757bcSAlan Somers free(description); 516b1d757bcSAlan Somers } 517b1d757bcSAlan Somers 518b1d757bcSAlan Somers int 519b1d757bcSAlan Somers main(int argc, char *argv[]) 520b1d757bcSAlan Somers { 521b1d757bcSAlan Somers ifconfig_handle_t *lifh; 522b1d757bcSAlan Somers 523b1d757bcSAlan Somers if (argc != 1) { 524b1d757bcSAlan Somers errx(1, "Usage: example_status"); 525b1d757bcSAlan Somers } 526b1d757bcSAlan Somers 527b1d757bcSAlan Somers lifh = ifconfig_open(); 528b1d757bcSAlan Somers if (lifh == NULL) { 529b1d757bcSAlan Somers errx(1, "Failed to open libifconfig handle."); 530b1d757bcSAlan Somers } 531b1d757bcSAlan Somers 532b1d757bcSAlan Somers if (ifconfig_foreach_iface(lifh, print_iface, NULL) != 0) { 533b1d757bcSAlan Somers err(1, "Failed to get interfaces"); 534b1d757bcSAlan Somers } 535b1d757bcSAlan Somers 536b1d757bcSAlan Somers ifconfig_close(lifh); 537b1d757bcSAlan Somers lifh = NULL; 538b1d757bcSAlan Somers return (-1); 539b1d757bcSAlan Somers } 540