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