/* * Check to see whether the interface could be started. If the IFF_RUNNING * flag is set, then we're in good shape. Otherwise, wireless interfaces are * special: we'll attempt to connect to an Access Point as part of the start-up * procedure, and IFF_RUNNING won't be present until that's done, so assume * that all wireless interfaces are good to go. This is just an optimization; * we could start everything. */ static boolean_t is_startable(struct interface *ifp) { ifp->if_flags = get_ifflags(ifp->if_name, ifp->if_family); if (ifp->if_flags & IFF_RUNNING) return (B_TRUE); return (ifp->if_type == IF_WIRELESS); }
/* * Returns the interface structure upon success. Returns NULL and sets * errno upon error. */ struct interface * add_interface(sa_family_t family, const char *name, uint64_t flags) { struct interface *i; libnwam_interface_type_t iftype; if (name == NULL) return (NULL); dprintf("add_interface: found interface %s", name); if (family == AF_INET6) { /* * we don't track IPv6 interfaces separately from their * v4 counterparts; a link either has v4 only, or both * v4 and v6, so we only maintain a v4 interface struct. */ dprintf("not adding v6 interface for %s", name); return (NULL); } else if (family != AF_INET) { /* * the classic "shouldn't happen"... */ dprintf("not adding af %d interface for %s", family, name); return (NULL); } if ((iftype = find_if_type(name)) == IF_TUN) { /* * for now, we're ignoring tunnel interfaces (we expect * them to be entirely manipulated by higher layer profile * activation/deactivation scripts) */ dprintf("%s is a tunnel interface; ignoring", name); return (NULL); } if ((i = calloc(1, sizeof (*i))) == NULL) { dprintf("add_interface: malloc failed"); return (NULL); } (void) strlcpy(i->if_name, name, sizeof (i->if_name)); i->if_family = family; i->if_type = iftype; i->if_flags = flags == 0 ? get_ifflags(name, family) : flags; dprintf("added interface %s of type %s af %d; is %savailable", i->if_name, if_type_str(i->if_type), i->if_family, (i->if_flags & IFF_RUNNING) ? "" : "not "); interface_list_insert(i); if (iftype == IF_WIRELESS) add_wireless_if(name); return (i); }
int intflags(char *ifname, int ifs, int argc, char **argv) { int set, value, flags; if (NO_ARG(argv[0])) { set = 0; argv++; argc--; } else set = 1; if (isprefix(argv[0], "debug")) { /* debug */ value = IFF_DEBUG; } else if (isprefix(argv[0], "shutdown")) { /* shutdown */ value = -IFF_UP; } else if (isprefix(argv[0], "arp")) { /* arp */ value = -IFF_NOARP; } else { printf("%% intflags: Internal error\n"); return(0); } flags = get_ifflags(ifname, ifs); if (value < 0) { /* * Idea from ifconfig. If value is negative then * we just reverse the operation. (e.g. 'shutdown' is * the opposite of the IFF_UP flag) */ if (set) { value = -value; flags &= ~value; } else { value = -value; flags |= value; } } else if (value > 0) { if (set) flags |= value; else flags &= ~value; } else { printf("%% intflags: value internal error\n"); } set_ifflags(ifname, ifs, flags); return(0); }
/* ARGSUSED */ static int do_unplumb_if(icfg_if_t *intf, void *arg) { uint64_t flags = get_ifflags(intf->if_name, intf->if_protocol); /* We don't touch loopback interface. */ if (flags & IFF_LOOPBACK) return (ICFG_SUCCESS); (void) start_child(IFCONFIG, intf->if_name, intf->if_protocol == AF_INET6 ? "inet6" : "inet", "unplumb", NULL); return (ICFG_SUCCESS); }
/* ARGSUSED */ static int do_add_interface(icfg_if_t *intf, void *arg) { uint64_t flags = get_ifflags(intf->if_name, intf->if_protocol); /* We don't touch loopback interface. */ if (flags & IFF_LOOPBACK) return (ICFG_SUCCESS); /* If adding fails, just ignore that interface... */ (void) add_interface(intf->if_protocol, intf->if_name, flags); return (ICFG_SUCCESS); }
/* * Called only in the main thread * * For IPv6, unplumbing the link local interface causes dhcp and ndpd to remove * other addresses they have added. We watch for routing socket events on the * IPv4 interface, which is always enabled, so no need to keep IPv6 around on a * switch. */ void clear_cached_address(const char *ifname) { struct interface *ifp; uint64_t ifflags; if ((ifp = get_interface(ifname)) == NULL) { dprintf("clear_cached_address: can't find interface struct " "for %s", ifname); (void) start_child(IFCONFIG, ifname, "inet6", "unplumb", NULL); return; } if (ifp->if_v6onlink) (void) start_child(IFCONFIG, ifname, "inet6", "unplumb", NULL); ifflags = get_ifflags(ifname, AF_INET); if ((ifflags & IFF_UP) && !(ifflags & IFF_RUNNING)) zero_out_v4addr(ifname); ifp->if_ipv4addr = INADDR_ANY; ifp->if_lflags &= ~IF_DHCPFLAGS; }
/* * Walker function used to start info gathering of each interface. Caller * holds ifs_lock. */ void start_if_info_collect(struct interface *ifp, void *arg) { int retv; pthread_attr_t attr; /* * In certain cases we need to refresh the cached flags value as * it may be stale. Notably, we can miss a DL_NOTE_LINK_DOWN * event after we initialize interfaces before the routing thread * is launched. */ if (arg != NULL) ifp->if_flags = get_ifflags(ifp->if_name, ifp->if_family); /* * Only if the cable of the wired interface is * plugged in, start gathering info from it. */ if (!is_startable(ifp)) { dprintf("not gathering info on %s; not running", ifp->if_name); return; } /* * This is a "fresh start" for the interface, so clear old DHCP flags. */ ifp->if_lflags &= ~IF_DHCPFLAGS; (void) pthread_attr_init(&attr); (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if ((retv = pthread_create(&ifp->if_thr, &attr, gather_interface_info, ifp)) != 0) { syslog(LOG_ERR, "create interface gathering thread: %s", strerror(retv)); exit(EXIT_FAILURE); } else { dprintf("interface info thread for %s: %d", ifp->if_name, ifp->if_thr); } }
/* Called only in the main thread */ void takedowninterface(const char *ifname, libnwam_diag_cause_t cause) { uint64_t flags; struct interface *ifp; dprintf("takedowninterface(%s, %d)", ifname, (int)cause); if ((ifp = get_interface(ifname)) == NULL) { dprintf("takedowninterface: can't find interface struct for %s", ifname); } flags = get_ifflags(ifname, AF_INET); if (flags & IFF_DHCPRUNNING) { /* * We generally prefer doing a release, as that tells the * server that it can relinquish the lease, whereas drop is * just a client-side operation. But if we never came up, * release will fail, because dhcpagent does not allow an * interface without a lease to release, so we have to drop in * that case. So try release first, then fall back to drop. */ if (start_child(IFCONFIG, ifname, "dhcp", "wait", "2", "release", NULL) != 0) { (void) start_child(IFCONFIG, ifname, "dhcp", "wait", "2", "drop", NULL); } } else { if (flags & IFF_UP) (void) start_child(IFCONFIG, ifname, "down", NULL); /* need to unset a statically configured addr */ (void) start_child(IFCONFIG, ifname, "0.0.0.0", "netmask", "0", "broadcast", "0.0.0.0", NULL); } if (ifp == NULL || ifp->if_v6onlink) { /* * Unplumbing the link local interface causes dhcp and ndpd to * remove other addresses they have added. */ (void) start_child(IFCONFIG, ifname, "inet6", "unplumb", NULL); } if (ifp == NULL || ifp->if_up_attempted) report_interface_down(ifname, cause); if (ifp != NULL) { /* We're no longer expecting the interface to be up */ ifp->if_flags = flags & ~IFF_UP; if (ifp->if_type == IF_WIRELESS) { /* and if it's wireless, it's not running, either */ ifp->if_flags &= ~IFF_RUNNING; disconnect_wlan(ifp->if_name); } dprintf("takedown interface, zero cached ip address"); ifp->if_lflags &= ~IF_DHCPSTARTED & ~IF_DHCPACQUIRED; ifp->if_ipv4addr = INADDR_ANY; ifp->if_up_attempted = B_FALSE; } }
/* * Returns SUCCESS if the interface is successfully brought up, * FAILURE if bringup fails, or WAITING if we'll need to wait on the GUI to run. * Called only in the main thread or a thread holding machine_lock. */ return_vals_t bringupinterface(const char *ifname, const char *host, const char *ipv6addr, boolean_t ipv6onlink) { struct interface *intf; intf = get_interface(ifname); if (intf == NULL) { syslog(LOG_ERR, "could not bring up interface %s: not in list", ifname); return (FAILURE); } /* check current state; no point going on if flags are 0 */ if ((intf->if_flags = get_ifflags(ifname, intf->if_family)) == 0) { dprintf("bringupinterface(%s): get_ifflags() returned 0", ifname); return (FAILURE); } if (intf->if_type == IF_WIRELESS) { switch (handle_wireless_lan(ifname)) { case WAITING: intf->if_up_attempted = B_TRUE; return (WAITING); case FAILURE: syslog(LOG_INFO, "Could not connect to any WLAN, not " "bringing %s up", ifname); return (FAILURE); } } intf->if_up_attempted = B_TRUE; /* physical level must now be up; bail out if not */ intf->if_flags = get_ifflags(ifname, intf->if_family); if (!(intf->if_flags & IFF_RUNNING)) { dprintf("bringupinterface(%s): physical layer down", ifname); return (FAILURE); } /* * If the link layer profile says that we want v6 then plumb it and * bring it up; if there's a static address, configure it as well. */ if (ipv6onlink) { dprintf("bringupinterface: configuring ipv6"); (void) start_child(IFCONFIG, ifname, "inet6", "plumb", "up", NULL); if (ipv6addr) { (void) start_child(IFCONFIG, ifname, "inet6", "addif", ipv6addr, "up", NULL); } } intf->if_v6onlink = ipv6onlink; if (strcmp(host, "dhcp") == 0) { start_dhcp(intf); } else { (void) start_child(IFCONFIG, ifname, host, NULL); (void) start_child(IFCONFIG, ifname, "up", NULL); } syslog(LOG_DEBUG, "brought up %s", ifname); return (SUCCESS); }
int show_int(int argc, char **argv) { struct ifaddrs *ifap, *ifa; struct if_nameindex *ifn_list, *ifnp; struct ifreq ifr, ifrdesc; struct if_data if_data; struct sockaddr_in sin, sin2, sin3; struct timeval tv; struct vlanreq vreq; short tmp; int ifs, br, flags, days, hours, mins, pntd; int ippntd = 0; time_t c; char *type, *lladdr, *ifname = NULL; const char *carp; char tmp_str[512], tmp_str2[512], ifdescr[IFDESCRSIZE]; if (argc == 3) ifname = argv[2]; /* * Show all interfaces when no ifname specified. */ if (ifname == NULL) { if ((ifn_list = if_nameindex()) == NULL) { printf("%% show_int: if_nameindex failed\n"); return 1; } for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { char *args[] = { NULL, NULL, ifnp->if_name }; show_int(3, args); } if_freenameindex(ifn_list); return(0); } else if (!is_valid_ifname(ifname)) { printf("%% interface %s not found\n", ifname); return(1); } if ((ifs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("%% show_int: %s\n", strerror(errno)); return(1); } if (!(br = is_bridge(ifs, (char *)ifname))) br = 0; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); /* * Show up/down status and last change time */ flags = get_ifflags(ifname, ifs); ifr.ifr_data = (caddr_t)&if_data; if (ioctl(ifs, SIOCGIFDATA, (caddr_t)&ifr) < 0) { printf("%% show_int: SIOCGIFDATA: %s\n", strerror(errno)); close(ifs); return(1); } printf("%% %s", ifname); /* description */ memset(&ifrdesc, 0, sizeof(ifrdesc)); strlcpy(ifrdesc.ifr_name, ifname, sizeof(ifrdesc.ifr_name)); ifrdesc.ifr_data = (caddr_t)&ifdescr; if (ioctl(ifs, SIOCGIFDESCR, &ifrdesc) == 0 && strlen(ifrdesc.ifr_data)) printf(" (%s)", ifrdesc.ifr_data); putchar('\n'); printf(" %s is %s", br ? "Bridge" : "Interface", flags & IFF_UP ? "up" : "down"); if (if_lastchange.tv_sec) { gettimeofday(&tv, (struct timezone *)0); c = difftime(tv.tv_sec, if_lastchange.tv_sec); days = c / SECSPERDAY; c %= SECSPERDAY; hours = c / SECSPERHOUR; c %= SECSPERHOUR; mins = c / SECSPERMIN; c %= SECSPERMIN; printf(" (last change "); if (days) printf("%id ", days); printf("%02i:%02i:%02i)", hours, mins, c); } printf(", protocol is %s", flags & IFF_RUNNING ? "up" : "down"); printf("\n"); type = iftype(if_type); printf(" Interface type %s", type); if (flags & IFF_BROADCAST) printf(" (Broadcast)"); else if (flags & IFF_POINTOPOINT) printf(" (PointToPoint)"); if ((lladdr = get_hwdaddr(ifname)) != NULL) printf(", hardware address %s", lladdr); printf("\n"); media_status(ifs, ifname, " Media type "); /* * Print interface IP address, and broadcast or * destination if available. But, don't print broadcast * if it is what we would expect given the ip and netmask! */ if (getifaddrs(&ifap) != 0) { printf("%% show_int: getifaddrs failed: %s\n", strerror(errno)); return(1); } /* * Cycle through getifaddrs for interfaces with our * desired name that sport AF_INET, print the IP and * related information. */ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (strncmp(ifname, ifa->ifa_name, IFNAMSIZ)) continue; if (ifa->ifa_addr->sa_family != AF_INET) continue; memcpy(&sin, ifa->ifa_addr, sizeof(struct sockaddr_in)); memcpy(&sin2, ifa->ifa_netmask, sizeof(struct sockaddr_in)); if (sin.sin_addr.s_addr == 0 || sin2.sin_addr.s_addr == 0) continue; if (!ippntd) printf(" Internet address"); printf("%s %s", ippntd ? "," : "", netname4(sin.sin_addr.s_addr, &sin2)); ippntd = 1; if (flags & IFF_POINTOPOINT) { memcpy(&sin3, ifa->ifa_dstaddr, sizeof(struct sockaddr_in)); printf(" (Destination %s)", inet_ntoa(sin3.sin_addr)); } else if (flags & IFF_BROADCAST) { memcpy(&sin3, ifa->ifa_broadaddr, sizeof(struct sockaddr_in)); /* * no reason to show the broadcast addr * if it is standard (this should always * be true unless someone has messed up their * network or they are playing around...) */ if (ntohl(sin3.sin_addr.s_addr) != in4_brdaddr(sin.sin_addr.s_addr, sin2.sin_addr.s_addr)) printf(" (Broadcast %s)", inet_ntoa(sin3.sin_addr)); } } if (ippntd) { ippntd = 0; printf("\n"); } freeifaddrs(ifap); if (!br) { if (phys_status(ifs, ifname, tmp_str, tmp_str2, sizeof(tmp_str), sizeof(tmp_str2)) > 0) printf(" Tunnel source %s destination %s\n", tmp_str, tmp_str2); if ((carp = carp_state(ifs, ifname)) != NULL) printf(" CARP state %s\n", carp); /* * Display MTU, line rate, and ALTQ token rate info * (if available) */ printf(" MTU %u bytes", if_mtu); if (if_baudrate) printf(", Line Rate %qu %s\n", MBPS(if_baudrate) ? MBPS(if_baudrate) : if_baudrate / 1000, MBPS(if_baudrate) ? "Mbps" : "Kbps"); else printf("\n"); memset(&vreq, 0, sizeof(struct vlanreq)); ifr.ifr_data = (caddr_t)&vreq; if (ioctl(ifs, SIOCGETVLAN, (caddr_t)&ifr) != -1) if(vreq.vlr_tag || (vreq.vlr_parent[0] != '\0')) printf(" 802.1Q vlan tag %d, parent %s\n", vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? "<none>" : vreq.vlr_parent); } if (get_nwinfo(ifname, tmp_str, sizeof(tmp_str), NWID) != NULL) { printf(" SSID %s", tmp_str); if(get_nwinfo(ifname, tmp_str, sizeof(tmp_str), NWKEY) != NULL) printf(", key %s", tmp_str); if ((tmp = get_nwinfo(ifname, tmp_str, sizeof(tmp_str), POWERSAVE) != NULL)) printf(", powersaving (%s ms)\n", tmp_str); printf("\n"); } /* * Display remaining info from if_data structure */ printf(" %qu packets input, %qu bytes, %qu errors, %qu drops\n", if_ipackets, if_ibytes, if_ierrors, if_iqdrops); printf(" %qu packets output, %qu bytes, %qu errors, %qu unsupported\n", if_opackets, if_obytes, if_oerrors, if_noproto); if (if_ibytes && if_ipackets && (if_ibytes / if_ipackets) >= ETHERMIN) { /* < ETHERMIN means byte counter probably rolled over */ printf(" %qu input", if_ibytes / if_ipackets); pntd = 1; } else pntd = 0; if (if_obytes && if_opackets && (if_obytes / if_opackets) >= ETHERMIN) { /* < ETHERMIN means byte counter probably rolled over */ printf("%s%qu output", pntd ? ", " : " ", if_obytes / if_opackets); pntd = 1; } if (pntd) printf(" (average bytes/packet)\n"); switch(if_type) { /* * These appear to be the only interface types to increase collision * count in the OpenBSD 3.2 kernel. */ case IFT_ETHER: case IFT_SLIP: case IFT_PROPVIRTUAL: case IFT_IEEE80211: printf(" %qu collisions\n", if_collisions); break; default: break; } if(verbose) { if (flags) { printf(" Flags:\n "); bprintf(stdout, flags, ifnetflags); printf("\n"); } if (br) { if ((tmp = bridge_list(ifs, ifname, " ", tmp_str, sizeof(tmp_str), SHOW_STPSTATE))) { printf(" STP member state%s:\n", tmp > 1 ? "s" : ""); printf("%s", tmp_str); } bridge_addrs(ifs, ifname, " ", " "); } media_supported(ifs, ifname, " ", " "); } close(ifs); return(0); }
int intip(char *ifname, int ifs, int argc, char **argv) { int set, alias, flags, argcmax; ip_t ip; struct in_addr destbcast; struct ifaliasreq addreq, ridreq; struct sockaddr_in *sin; char *msg, *cmdname; memset(&addreq, 0, sizeof(addreq)); memset(&ridreq, 0, sizeof(ridreq)); if (NO_ARG(argv[0])) { set = 0; argc--; argv++; } else set = 1; /* * We use this function for ip and alias setup since they are * the same thing. */ if (isprefix(argv[0], "alias")) { alias = 1; cmdname = "alias"; } else if (isprefix(argv[0], "ip")) { alias = 0; cmdname = "ip"; } else { printf("%% intip: Internal error\n"); return 0; } argc--; argv++; flags = get_ifflags(ifname, ifs); if (flags & IFF_POINTOPOINT) { argcmax = 2; msg = "destination"; } else if (flags & IFF_BROADCAST) { argcmax = 2; msg = "broadcast"; } else { argcmax = 1; msg = NULL; } if (argc < 1 || argc > argcmax) { printf("%% %s <address>/<bits> %s%s%s\n", cmdname, msg ? "[" : "", msg ? msg : "", msg ? "]" : ""); printf("%% %s <address>/<netmask> %s%s%s\n", cmdname, msg ? "[" : "", msg ? msg : "", msg ? "]" : ""); printf("%% no %s <address>[/bits]\n", cmdname); printf("%% no %s <address>[/netmask]\n", cmdname); return(0); } /* ignore 'address' keyword, don't print error */ if (isprefix(argv[0], "address")) { argc--; argv++; } if (isprefix(argv[0], "dhcp")) { char *args[] = { PKILL, "dhclient", ifname, '\0' }; char leasefile[sizeof(LEASEPREFIX)+1+IFNAMSIZ]; if (set) cmdarg(DHCLIENT, ifname); else { cmdargs(PKILL, args); snprintf(leasefile, sizeof(leasefile), "%s.%s", LEASEPREFIX, ifname); rmtemp(leasefile); } return(0); } ip = parse_ip(argv[0], NO_NETMASK); if (ip.family == 0) /* bad IP specified */ return(0); if (ip.bitlen == -1) { printf("%% Netmask not specified\n"); return(0); } if (argc == 2) if (!inet_aton(argv[1], &destbcast)) { printf("%% Invalid %s address\n", msg); return(0); } strlcpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); strlcpy(ridreq.ifra_name, ifname, sizeof(ridreq.ifra_name)); if (!set) { sin = (struct sockaddr_in *)&ridreq.ifra_addr; sin->sin_len = sizeof(ridreq.ifra_addr); sin->sin_family = AF_INET; sin->sin_addr.s_addr = ip.addr.sin.s_addr; } if (!alias || !set) { /* * Here we remove the top IP on the interface before we * might add another one, or we delete the specified IP. */ if (ioctl(ifs, SIOCDIFADDR, &ridreq) < 0) if (!set) printf("%% intip: SIOCDIFADDR: %s\n", strerror(errno)); } if (set) { sin = (struct sockaddr_in *)&addreq.ifra_addr; sin->sin_family = AF_INET; sin->sin_len = sizeof(addreq.ifra_addr); sin->sin_addr.s_addr = ip.addr.sin.s_addr; sin = (struct sockaddr_in *)&addreq.ifra_mask; sin->sin_family = AF_INET; sin->sin_len = sizeof(addreq.ifra_mask); sin->sin_addr.s_addr = htonl(0xffffffff << (32 - ip.bitlen)); if (argc == 2) { sin = (struct sockaddr_in *)&addreq.ifra_dstaddr; sin->sin_family = AF_INET; sin->sin_len = sizeof(addreq.ifra_dstaddr); sin->sin_addr.s_addr = destbcast.s_addr; } if (ioctl(ifs, SIOCAIFADDR, &addreq) < 0) printf("%% intip: SIOCAIFADDR: %s\n", strerror(errno)); } return(0); }
int intlink(char *ifname, int ifs, int argc, char **argv) { const char *errmsg = NULL; int set, i, flags, value = 0; if (NO_ARG(argv[0])) { set = 0; argv++; argc--; } else set = 1; argv++; argc--; if ((set && argc < 1) || argc > 3) { printf("%% link <012>\n"); printf("%% no link [012]\n"); return(0); } flags = get_ifflags(ifname, ifs); if (!set && argc == 0) { /* * just 'no link' was specified. so we remove all flags */ flags &= ~IFF_LINK0 & ~IFF_LINK1 & ~IFF_LINK2; } else for (i = 0; i < argc; i++) { int a; a = strtonum(argv[i], 0, 2, &errmsg); if (errmsg) { printf("%% Invalid link flag %s: %s\n", argv[i], errmsg); return(0); } switch(a) { case 0: value = IFF_LINK0; break; case 1: value = IFF_LINK1; break; case 2: value = IFF_LINK2; break; } if (set) flags |= value; else flags &= ~value; } set_ifflags(ifname, ifs, flags); return(0); }
int show_int(int argc, char **argv) { struct ifaddrs *ifap, *ifa; struct if_nameindex *ifn_list, *ifnp; struct ifreq ifr, ifrdesc; struct if_data if_data; struct sockaddr_in *sin = NULL, *sinmask = NULL, *sindest; struct sockaddr_in6 *sin6 = NULL, *sin6mask = NULL, *sin6dest; struct timeval tv; short tmp; int ifs, br, flags, days, hours, mins, pntd; int ippntd = 0; int physrt, physttl; time_t c; char *type, *lladdr, *ifname = NULL; char tmp_str[512], tmp_str2[512], ifdescr[IFDESCRSIZE]; if (argc == 3) ifname = argv[2]; /* * Show all interfaces when no ifname specified. */ if (ifname == NULL) { if ((ifn_list = if_nameindex()) == NULL) { printf("%% show_int: if_nameindex failed\n"); return 0; } for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { char *args[] = { NULL, NULL, ifnp->if_name }; show_int(3, args); } if_freenameindex(ifn_list); return(0); } else if (!is_valid_ifname(ifname)) { printf("%% interface %s not found\n", ifname); return(1); } if ((ifs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("%% show_int: %s\n", strerror(errno)); return(1); } if (!(br = is_bridge(ifs, (char *)ifname))) br = 0; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); /* * Show up/down status and last change time */ flags = get_ifflags(ifname, ifs); ifr.ifr_data = (caddr_t)&if_data; if (ioctl(ifs, SIOCGIFDATA, (caddr_t)&ifr) < 0) { printf("%% show_int: SIOCGIFDATA: %s\n", strerror(errno)); close(ifs); return(1); } printf("%% %s", ifname); /* description */ memset(&ifrdesc, 0, sizeof(ifrdesc)); strlcpy(ifrdesc.ifr_name, ifname, sizeof(ifrdesc.ifr_name)); ifrdesc.ifr_data = (caddr_t)&ifdescr; if (ioctl(ifs, SIOCGIFDESCR, &ifrdesc) == 0 && strlen(ifrdesc.ifr_data)) printf(" (%s)", ifrdesc.ifr_data); putchar('\n'); printf(" %s is %s", br ? "Bridge" : "Interface", flags & IFF_UP ? "up" : "down"); if (if_data.ifi_lastchange.tv_sec) { gettimeofday(&tv, (struct timezone *)0); c = difftime(tv.tv_sec, if_data.ifi_lastchange.tv_sec); days = c / (24 * 60 * 60); c %= (24 * 60 * 60); hours = c / (60 * 60); c %= (60 * 60); mins = c / 60; c %= 60; printf(" (last change "); if (days) printf("%id ", days); printf("%02i:%02i:%02i)", hours, mins, (int)c); } printf(", protocol is %s", flags & IFF_RUNNING ? "up" : "down"); printf("\n"); type = iftype(if_data.ifi_type); printf(" Interface type %s", type); if (flags & IFF_BROADCAST) printf(" (Broadcast)"); else if (flags & IFF_POINTOPOINT) printf(" (PointToPoint)"); if ((lladdr = get_hwdaddr(ifname)) != NULL) printf(", hardware address %s", lladdr); printf("\n"); show_trunk(ifs, ifname); media_status(ifs, ifname, " Media type "); /* * Print interface IP address, and broadcast or * destination if available. But, don't print broadcast * if it is what we would expect given the ip and netmask! */ if (getifaddrs(&ifap) != 0) { printf("%% show_int: getifaddrs failed: %s\n", strerror(errno)); return(1); } /* * Cycle through getifaddrs for interfaces with our * desired name that sport AF_INET, print the IP and * related information. */ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (strncmp(ifname, ifa->ifa_name, IFNAMSIZ)) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: sin = (struct sockaddr_in *)ifa->ifa_addr; sinmask = (struct sockaddr_in *)ifa->ifa_netmask; if (sin->sin_addr.s_addr == INADDR_ANY) continue; break; case AF_INET6: sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; sin6mask = (struct sockaddr_in6 *)ifa->ifa_netmask; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; in6_fillscopeid(sin6); break; default: continue; } if (!ippntd) printf(" Internet address"); printf("%s %s", ippntd ? "," : "", ifa->ifa_addr->sa_family == AF_INET ? netname4(sin->sin_addr.s_addr, sinmask) : netname6(sin6, sin6mask)); ippntd = 1; switch (ifa->ifa_addr->sa_family) { case AF_INET: if (flags & IFF_POINTOPOINT) { sindest = (struct sockaddr_in *) ifa->ifa_dstaddr; printf(" (Destination %s)", routename4(sindest->sin_addr.s_addr)); } else if (flags & IFF_BROADCAST) { sindest = (struct sockaddr_in *) ifa->ifa_broadaddr; /* * no reason to show the broadcast addr * if it is standard (this should always * be true unless someone has messed up their * network or they are playing around...) */ if (ntohl(sindest->sin_addr.s_addr) != in4_brdaddr(sin->sin_addr.s_addr, sinmask->sin_addr.s_addr) && ntohl(sindest->sin_addr.s_addr) != INADDR_ANY) printf(" (Broadcast %s)", inet_ntoa(sindest->sin_addr)); } break; case AF_INET6: if (flags & IFF_POINTOPOINT) { sin6dest = (struct sockaddr_in6 *) ifa->ifa_dstaddr; in6_fillscopeid(sin6dest); printf(" (Destination %s)", routename6(sin6dest)); } break; default: printf(" unknown"); break; } } if (ippntd) { printf("\n"); } freeifaddrs(ifap); if (!br) { if (phys_status(ifs, ifname, tmp_str, tmp_str2, sizeof(tmp_str), sizeof(tmp_str2)) > 0) { printf(" Tunnel source %s destination %s", tmp_str, tmp_str2); if (((physrt = get_physrtable(ifs, ifname)) != 0)) printf(" destination rdomain %i", physrt); if (((physttl = get_physttl(ifs, ifname)) != 0)) printf(" ttl %i", physttl); printf("\n"); } carp_state(ifs, ifname); printf(" "); show_vnet_parent(ifs, ifname); if (ioctl(ifs, SIOCGIFRDOMAIN, (caddr_t)&ifr) != -1) printf(" rdomain %d,", ifr.ifr_rdomainid); /* * Display MTU, line rate */ printf(" MTU %u bytes", if_data.ifi_mtu); if (ioctl(ifs, SIOCGIFHARDMTU, (caddr_t)&ifr) != -1) { if (ifr.ifr_hardmtu) printf(" (hardmtu %u)", ifr.ifr_hardmtu); } if (if_data.ifi_baudrate) printf(", Line Rate %qu %s", MBPS(if_data.ifi_baudrate) ? MBPS(if_data.ifi_baudrate) : if_data.ifi_baudrate / 1000, MBPS(if_data.ifi_baudrate) ? "Mbps" : "Kbps"); printf("\n"); } if (get_nwinfo(ifname, tmp_str, sizeof(tmp_str), NWID) != 0) { printf(" SSID %s", tmp_str); if(get_nwinfo(ifname, tmp_str, sizeof(tmp_str), NWKEY) != 0) printf(", key %s", tmp_str); if ((tmp = get_nwinfo(ifname, tmp_str, sizeof(tmp_str), POWERSAVE)) != 0) printf(", powersaving (%s ms)\n", tmp_str); printf("\n"); } /* * Display remaining info from if_data structure */ printf(" %qu packets input, %qu bytes, %qu errors, %qu drops\n", if_data.ifi_ipackets, if_data.ifi_ibytes, if_data.ifi_ierrors, if_data.ifi_iqdrops); printf(" %qu packets output, %qu bytes, %qu errors, %qu unsupported\n", if_data.ifi_opackets, if_data.ifi_obytes, if_data.ifi_oerrors, if_data.ifi_noproto); if (if_data.ifi_ibytes && if_data.ifi_ipackets && (if_data.ifi_ibytes / if_data.ifi_ipackets) >= ETHERMIN) { /* < ETHERMIN means byte counter probably rolled over */ printf(" %qu input", if_data.ifi_ibytes / if_data.ifi_ipackets); pntd = 1; } else pntd = 0; if (if_data.ifi_obytes && if_data.ifi_opackets && (if_data.ifi_obytes / if_data.ifi_opackets) >= ETHERMIN) { /* < ETHERMIN means byte counter probably rolled over */ printf("%s%qu output", pntd ? ", " : " ", if_data.ifi_obytes / if_data.ifi_opackets); pntd = 1; } if (pntd) printf(" (average bytes/packet)\n"); switch(if_data.ifi_type) { /* * These appear to be the only interface types to increase collision * count in the OpenBSD 3.2 kernel. */ case IFT_ETHER: case IFT_SLIP: case IFT_PROPVIRTUAL: case IFT_IEEE80211: printf(" %qu collisions\n", if_data.ifi_collisions); break; default: break; } if(verbose) { if (flags) { printf(" Flags:\n "); bprintf(stdout, flags, ifnetflags); printf("\n"); } printifhwfeatures(ifs, ifname); if (br) { if ((tmp = bridge_list(ifs, ifname, " ", tmp_str, sizeof(tmp_str), SHOW_STPSTATE))) { printf(" STP member state%s:\n", tmp > 1 ? "s" : ""); printf("%s", tmp_str); } bridge_addrs(ifs, ifname, " ", " "); } media_supported(ifs, ifname, " ", " "); } close(ifs); return(0); }
int intip(char *ifname, int ifs, int argc, char **argv) { int s, set, flags, argcmax; char *msg, *cmdname; ip_t ip; /* ipv4 structures */ struct in_addr in4dest; struct ifaliasreq ip4req; /* ipv6 structures */ struct in6_addr in6dest; struct in6_aliasreq ip6req; if (NO_ARG(argv[0])) { set = 0; argc--; argv++; } else set = 1; /* * We use this function for ip and alias setup since they are * the same thing. */ if (isprefix(argv[0], "alias")) { cmdname = "alias"; } else if (isprefix(argv[0], "ip")) { cmdname = "ip"; } else { printf("%% intip: Internal error\n"); return 0; } argc--; argv++; flags = get_ifflags(ifname, ifs); if (flags & IFF_POINTOPOINT) { argcmax = 2; msg = "destination"; } else if (flags & IFF_BROADCAST) { argcmax = 2; msg = "broadcast"; } else { argcmax = 1; msg = NULL; } if (argc < 1 || argc > argcmax) { printf("%% %s <address>/<bits> %s%s%s\n", cmdname, msg ? "[" : "", msg ? msg : "", msg ? "]" : ""); printf("%% %s <address>/<netmask> %s%s%s\n", cmdname, msg ? "[" : "", msg ? msg : "", msg ? "]" : ""); printf("%% no %s <address>[/bits]\n", cmdname); printf("%% no %s <address>[/netmask]\n", cmdname); return(0); } /* ignore 'address' keyword, don't print error */ if (isprefix(argv[0], "address")) { argc--; argv++; } if (isprefix(argv[0], "dhcp")) { char *args[] = { PKILL, "dhclient", ifname, '\0' }; char *args_set[] = { DHCLIENT, ifname, '\0' }; char leasefile[sizeof(LEASEPREFIX)+1+IFNAMSIZ]; if (set) cmdargs(DHCLIENT, args_set); else { cmdargs(PKILL, args); snprintf(leasefile, sizeof(leasefile), "%s.%s", LEASEPREFIX, ifname); rmtemp(leasefile); } return(0); } memset(&ip, 0, sizeof(ip)); parse_ip_pfx(argv[0], NO_NETMASK, &ip); if (ip.family == 0) /* bad IP specified */ return(0); if (set && !(flags & IFF_POINTOPOINT) && ip.bitlen == -1) { printf("%% Netmask not specified\n"); return(0); } if (ip.bitlen == -1) { /* * No netmask specified, set the field at 0. * The kernel mostly ignores netmask for PTP interfaces, * but won't allow anything less than a /128 for an IPv6 * PTP interface. */ if (!(flags & IFF_POINTOPOINT)) ip.bitlen = 0; else if (ip.family == AF_INET) ip.bitlen = 32; else if (ip.family == AF_INET6) ip.bitlen = 128; } switch(ip.family) { case AF_INET: memset(&in4dest, 0, sizeof(in4dest)); if (argc == 2 && !inet_pton(AF_INET, argv[1], &in4dest)) { printf("%% Invalid %s address\n", msg); return(0); } memset(&ip4req, 0, sizeof(ip4req)); pack_ifaliasreq(&ip4req, &ip, &in4dest, ifname); /* do it */ if (ioctl(ifs, set ? SIOCAIFADDR : SIOCDIFADDR, &ip4req) < 0) printf("%% intip: SIOC%sIFADDR: %s\n", set ? "A" : "D", strerror(errno)); break; case AF_INET6: memset(&in6dest, 0, sizeof(in6dest)); if (argc == 2 && parse_ipv6(argv[1], &in6dest) != 0) { printf("%% Invalid destination address %s\n", argv[1]); return(0); } memset(&ip6req, 0, sizeof(ip6req)); pack_in6aliasreq(&ip6req, &ip, &in6dest, ifname); /* get inet6 socket */ s = socket(PF_INET6, SOCK_DGRAM, 0); if (s < 0) { printf("%% socket failed: %s\n", strerror(errno)); return(0); } /* turn on inet6 */ addaf(ifname, AF_INET6, ifs); /* do it */ if (ioctl(s, set ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6, &ip6req) < 0) { if (!set && errno == EADDRNOTAVAIL) printf("%% IP address not found on %s\n", ifname); else printf("%% intip: SIOC%sIFADDR_IN6: %s\n", set ? "A" : "D", strerror(errno)); } else { ipv6ll_db_store( (struct sockaddr_in6 *)&ip6req.ifra_addr, (struct sockaddr_in6 *)&ip6req.ifra_prefixmask, set ? DB_X_ENABLE : DB_X_REMOVE, ifname); } close(s); break; default: printf("%% unknown address family: %d\n", ip.family); break; } return(0); }