static void tunnel_status(prop_dictionary_t env, prop_dictionary_t oenv) { char dstserv[sizeof(",65535")]; char srcserv[sizeof(",65535")]; char psrcaddr[NI_MAXHOST]; char pdstaddr[NI_MAXHOST]; const int niflag = NI_NUMERICHOST|NI_NUMERICSERV; struct if_laddrreq req; const struct afswtch *afp; psrcaddr[0] = pdstaddr[0] = '\0'; memset(&req, 0, sizeof(req)); if (direct_ioctl(env, SIOCGLIFPHYADDR, &req) == -1) return; afp = lookup_af_bynum(req.addr.ss_family); #ifdef INET6 if (req.addr.ss_family == AF_INET6) in6_fillscopeid((struct sockaddr_in6 *)&req.addr); #endif /* INET6 */ getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, psrcaddr, sizeof(psrcaddr), &srcserv[1], sizeof(srcserv) - 1, niflag); #ifdef INET6 if (req.dstaddr.ss_family == AF_INET6) in6_fillscopeid((struct sockaddr_in6 *)&req.dstaddr); #endif getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, pdstaddr, sizeof(pdstaddr), &dstserv[1], sizeof(dstserv) - 1, niflag); srcserv[0] = (strcmp(&srcserv[1], "0") == 0) ? '\0' : ','; dstserv[0] = (strcmp(&dstserv[1], "0") == 0) ? '\0' : ','; printf("\ttunnel %s %s%s --> %s%s\n", afp ? afp->af_name : "???", psrcaddr, srcserv, pdstaddr, dstserv); }
int phys_status(int s, char *ifname, char *tmp_buf, char *tmp_buf2, int buf_len, int buf2_len) { #ifdef NI_WITHSCOPEID const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; #else const int niflag = NI_NUMERICHOST; #endif struct if_laddrreq req; int dstport = 0; bzero(&req, sizeof(req)); (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); if (ioctl(s, SIOCGLIFPHYADDR, (caddr_t) &req) < 0) return(-1); if (req.addr.ss_family == AF_INET6) in6_fillscopeid((struct sockaddr_in6 *)&req.addr); if (getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, tmp_buf, buf_len, 0, 0, niflag) != 0) { printf("%% phys_status: 0/getnameinfo failure\n"); return (-1); } if (req.dstaddr.ss_family == AF_INET) { dstport = ((struct sockaddr_in *)&req.dstaddr)->sin_port; } else if (req.dstaddr.ss_family == AF_INET6) { in6_fillscopeid((struct sockaddr_in6 *) & req.dstaddr); dstport = ((struct sockaddr_in6 *)&req.dstaddr)->sin6_port; } if (getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, tmp_buf2, buf2_len, 0, 0, niflag) != 0) { printf("%% phys_status: 1/getnameinfo failure\n"); return(-1); } return(ntohs(dstport)); }
char * inet6name(struct in6_addr *in6p) { struct sockaddr_in6 sin6; char hbuf[NI_MAXHOST], *cp; static char line[50]; static char domain[MAXHOSTNAMELEN]; static int first = 1; int flags, error; if (IN6_IS_ADDR_UNSPECIFIED(in6p)) { strcpy(line, "*"); return (line); } if (first && !numeric_addr) { first = 0; if (gethostname(domain, MAXHOSTNAMELEN) == 0 && (cp = strchr(domain, '.'))) (void) strcpy(domain, cp + 1); else domain[0] = 0; } memset(&sin6, 0, sizeof(sin6)); memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p)); sin6.sin6_family = AF_INET6; /* XXX: in6p.s6_addr[2] can contain scopeid. */ in6_fillscopeid(&sin6); flags = (numeric_addr) ? NI_NUMERICHOST : 0; error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf, sizeof(hbuf), NULL, 0, flags); if (error == 0) { if ((flags & NI_NUMERICHOST) == 0 && (cp = strchr(hbuf, '.')) && !strcmp(cp + 1, domain)) *cp = 0; strcpy(line, hbuf); } else { /* XXX: this should not happen. */ sprintf(line, "%s", inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf, sizeof(ntop_buf))); } return (line); }
static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char workbuf[128]; const char *cp; if (sa == NULL) return ("null"); switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *sockin = (struct sockaddr_in *)sa; if ((sockin->sin_addr.s_addr == INADDR_ANY) && mask && ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) ==0L) cp = "default" ; else if (flags & RTF_HOST) cp = routename(sockin->sin_addr.s_addr); else if (mask) cp = netname(sockin->sin_addr.s_addr, ntohl(((struct sockaddr_in *)mask) ->sin_addr.s_addr)); else cp = netname(sockin->sin_addr.s_addr, 0L); break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; in6_fillscopeid(sa6); if (flags & RTF_HOST) cp = routename6(sa6); else if (mask) cp = netname6(sa6, &((struct sockaddr_in6 *)mask)->sin6_addr); else { cp = netname6(sa6, NULL); } break; } #endif /*INET6*/ case AF_IPX: { struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; if (ipx_nullnet(satoipx_addr(work))) cp = "default"; else cp = ipx_print(sa); break; } case AF_APPLETALK: { if (!(flags & RTF_HOST) && mask) cp = atalk_print2(sa,mask,9); else cp = atalk_print(sa,11); break; } case AF_NETGRAPH: { strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, sizeof(workbuf)); cp = workbuf; break; } case AF_LINK: { struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { (void) sprintf(workbuf, "link#%d", sdl->sdl_index); cp = workbuf; } else switch (sdl->sdl_type) { case IFT_ETHER: case IFT_L2VLAN: case IFT_BRIDGE: if (sdl->sdl_alen == ETHER_ADDR_LEN) { cp = ether_ntoa((struct ether_addr *) (sdl->sdl_data + sdl->sdl_nlen)); break; } /* FALLTHROUGH */ default: cp = link_ntoa(sdl); break; } break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = workbuf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(workbuf) - 6; cq += sprintf(cq, "(%d)", sa->sa_family); while (s < slim && cq < cqlim) { cq += sprintf(cq, " %02x", *s++); if (s < slim) cq += sprintf(cq, "%02x", *s++); } cp = workbuf; } } return (cp); }
/* * Find a server address that can be used by `caller' to contact * the local service specified by `serv_uaddr'. If `clnt_uaddr' is * non-NULL, it is used instead of `caller' as a hint suggesting * the best address (e.g. the `r_addr' field of an rpc, which * contains the rpcbind server address that the caller used). * * Returns the best server address as a malloc'd "universal address" * string which should be freed by the caller. On error, returns NULL. */ char * addrmerge(arpc_addr_t *caller, const char *serv_uaddr, const char *clnt_uaddr, const char *netid) { struct ifaddrs *ifap, *ifp = NULL, *bestif; arpc_addr_t *serv_nbp = NULL, *hint_nbp = NULL, tbuf; struct sockaddr *caller_sa, *hint_sa, *ifsa, *ifmasksa, *serv_sa; struct sockaddr_storage ss; socklen_t len; const char *hint_uaddr = NULL; char *caller_uaddr = NULL; char *ret = NULL; int err; #ifdef ND_DEBUG if (debugging) fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr, clnt_uaddr == NULL ? "NULL" : clnt_uaddr, netid); #endif caller_sa = (struct sockaddr *)caller->buf; err = ar_taddr2uaddr(rpcbind_ioctx, netid, caller, &caller_uaddr); if (err != 0) { goto freeit; } /* * Use `clnt_uaddr' as the hint if non-NULL, but ignore it if its * address family is different from that of the caller. */ hint_sa = NULL; if (clnt_uaddr != NULL) { hint_uaddr = clnt_uaddr; err = ar_uaddr2taddr(rpcbind_ioctx, netid, clnt_uaddr, &hint_nbp); if (err != 0) { goto freeit; } hint_sa = (struct sockaddr *)hint_nbp->buf; } if (hint_sa == NULL || hint_sa->sa_family != caller_sa->sa_family) { hint_uaddr = caller_uaddr; hint_sa = (struct sockaddr *)caller->buf; } #ifdef ND_DEBUG if (debugging) { fprintf(stderr, "addrmerge: hint %s\n", hint_uaddr); } #endif /* Local caller, just return the server address. */ if (strncmp(caller_uaddr, "0.0.0.0.", 8) == 0 || strncmp(caller_uaddr, "::.", 3) == 0 || caller_uaddr[0] == '/') { ret = strdup(serv_uaddr); goto freeit; } if (getifaddrs(&ifp) < 0) { goto freeit; } /* * Loop through all interfaces. For each interface, see if the * network portion of its address is equal to that of the client. * If so, we have found the interface that we want to use. */ bestif = NULL; for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { ifsa = ifap->ifa_addr; ifmasksa = ifap->ifa_netmask; if (ifsa == NULL || ifsa->sa_family != hint_sa->sa_family || !(ifap->ifa_flags & IFF_UP)) { continue; } switch (hint_sa->sa_family) { case AF_INET: /* * If the hint address matches this interface * address/netmask, then we're done. */ if (!bitmaskcmp(&SA2SINADDR(ifsa), &SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa), sizeof(struct in_addr))) { bestif = ifap; goto found; } break; case AF_INET6: /* * For v6 link local addresses, if the caller is on * a link-local address then use the scope id to see * which one. */ in6_fillscopeid(SA2SIN6(ifsa)); if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa)) && IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) && IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa))) { if (SA2SIN6(ifsa)->sin6_scope_id == SA2SIN6(caller_sa)->sin6_scope_id) { bestif = ifap; goto found; } } else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa), &SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa), sizeof(struct in6_addr))) { bestif = ifap; goto found; } break; default: continue; } /* * Remember the first possibly useful interface, preferring * "normal" to point-to-point and loopback ones. */ if (bestif == NULL || (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) && (bestif->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))) { bestif = ifap; } } if (bestif == NULL) { goto freeit; } found: /* * Construct the new address using the the address from * `bestif', and the port number from `serv_uaddr'. */ err = ar_uaddr2taddr(rpcbind_ioctx, netid, serv_uaddr, &serv_nbp); if (err != 0) { goto freeit; } serv_sa = (struct sockaddr *)serv_nbp->buf; switch (ss.ss_family) { case AF_INET: len = sizeof(struct sockaddr_in); memcpy(&ss, bestif->ifa_addr, len); SA2SIN(&ss)->sin_port = SA2SIN(serv_sa)->sin_port; break; case AF_INET6: len = sizeof(struct sockaddr_in6); memcpy(&ss, bestif->ifa_addr, len); SA2SIN6(&ss)->sin6_port = SA2SIN6(serv_sa)->sin6_port; break; default: memset(&ss, 0, sizeof(ss)); len = 0; break; } tbuf.len = len; tbuf.maxlen = sizeof(ss); tbuf.buf = (char *)&ss; err = ar_taddr2uaddr(rpcbind_ioctx, netid, &tbuf, &ret); if (err != 0) { ret = NULL; } freeit: if (caller_uaddr != NULL) { free(caller_uaddr); } if (hint_nbp != NULL) { if (hint_nbp->buf) { free(hint_nbp->buf); } free(hint_nbp); } if (serv_nbp != NULL) { if (serv_nbp->buf) { free(serv_nbp->buf); } free(serv_nbp); } if (ifp != NULL) { freeifaddrs(ifp); } #ifdef ND_DEBUG if (debugging) { fprintf(stderr, "addrmerge: returning %s\n", ret); } #endif return ret; }
static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char buf[128]; const char *cp; if (sa == NULL) return ("null"); switch(sa->sa_family) { #ifdef INET6 case AF_INET6: /* * The sa6->sin6_scope_id must be filled here because * this sockaddr is extracted from kmem(4) directly * and has KAME-specific embedded scope id in * sa6->sin6_addr.s6_addr[2]. */ in6_fillscopeid(satosin6(sa)); /* FALLTHROUGH */ #endif /*INET6*/ case AF_INET: if (flags & RTF_HOST) cp = routename(sa, numeric_addr); else if (mask) cp = netname(sa, mask); else cp = netname(sa, NULL); break; case AF_NETGRAPH: { strlcpy(buf, ((struct sockaddr_ng *)sa)->sg_data, sizeof(buf)); cp = buf; break; } case AF_LINK: { #if 0 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; /* Interface route. */ if (sdl->sdl_nlen) cp = sdl->sdl_data; else #endif cp = routename(sa, 1); break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = buf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(buf) - sizeof(" ffff"); snprintf(cq, sizeof(buf), "(%d)", sa->sa_family); cq += strlen(cq); while (s < slim && cq < cqlim) { snprintf(cq, sizeof(" ff"), " %02x", *s++); cq += strlen(cq); if (s < slim) { snprintf(cq, sizeof("ff"), "%02x", *s++); cq += strlen(cq); } } cp = buf; } } return (cp); }
int conf_ifaddrs(FILE *output, char *ifname, int flags, int af) { struct ifaddrs *ifa, *ifap; struct sockaddr_in *sin, *sinmask, *sindest; struct sockaddr_in6 *sin6, *sin6mask, *sin6dest; struct in6_ifreq ifr6; int ippntd = 0; if (getifaddrs(&ifap) != 0) { printf("%% conf: getifaddrs failed: %s\n", strerror(errno)); return(-1); } /* * Cycle through getifaddrs for interfaces with our * desired name that sport af or (AF_INET | AF_INET6). * 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) { int s; case AF_INET: if (af != AF_INET && af != 0) continue; sin = (struct sockaddr_in *)ifa->ifa_addr; if (sin->sin_addr.s_addr == INADDR_ANY) continue; sinmask = (struct sockaddr_in *)ifa->ifa_netmask; if (flags & IFF_POINTOPOINT) { sindest = (struct sockaddr_in *)ifa->ifa_dstaddr; fprintf(output, " ip %s", routename4(sin->sin_addr.s_addr)); fprintf(output, " %s", inet_ntoa(sindest->sin_addr)); } else if (flags & IFF_BROADCAST) { sindest = (struct sockaddr_in *)ifa->ifa_broadaddr; fprintf(output, " ip %s", netname4(sin->sin_addr.s_addr, sinmask)); /* * no reason to save 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)) fprintf(output, " %s", inet_ntoa(sindest->sin_addr)); } else { fprintf(output, " ip %s", netname4(sin->sin_addr.s_addr, sinmask)); } ippntd = 1; break; case AF_INET6: if (af != AF_INET6 && af != 0) continue; sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; sin6mask = (struct sockaddr_in6 *)ifa->ifa_netmask; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; if (!ipv6ll_db_compare(sin6, sin6mask, ifname)) continue; in6_fillscopeid(sin6); /* get address flags */ memset(&ifr6, 0, sizeof(ifr6)); strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); memcpy(&ifr6.ifr_addr, &sin6, sizeof(ifr6.ifr_addr)); s = socket(PF_INET6, SOCK_DGRAM, 0); if (s < 0) printf("%% conf_ifaddrs: socket: %s\n", strerror(errno)); if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) < 0) { if (errno != EADDRNOTAVAIL) printf("%% conf_ifaddrs: " \ "SIOCGIFAFLAG_IN6: %s\n", strerror(errno)); } else { /* skip autoconf addresses */ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF) continue; } if (flags & IFF_POINTOPOINT) { fprintf(output, " ip %s", routename6(sin6)); sin6dest = (struct sockaddr_in6 *)ifa->ifa_dstaddr; in6_fillscopeid(sin6dest); fprintf(output, " %s", routename6(sin6dest)); } else { fprintf(output, " ip %s", netname6(sin6, sin6mask)); } ippntd = 1; break; default: continue; } fprintf(output, "\n"); } freeifaddrs(ifap); return ippntd; }
int conf_ifaddrs(FILE *output, char *ifname, int flags, int af) { struct ifaddrs *ifa, *ifap; struct sockaddr_in *sin, *sinmask, *sindest; struct sockaddr_in6 *sin6, *sin6mask, *sin6dest; int ippntd = 0; if (getifaddrs(&ifap) != 0) { printf("%% conf: getifaddrs failed: %s\n", strerror(errno)); return(-1); } /* * Cycle through getifaddrs for interfaces with our * desired name that sport AF_INET | AF_INET6. 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: if (af != AF_INET && af != 0) continue; sin = (struct sockaddr_in *)ifa->ifa_addr; if (sin->sin_addr.s_addr == 0) continue; sinmask = (struct sockaddr_in *)ifa->ifa_netmask; if (flags & IFF_POINTOPOINT) { sindest = (struct sockaddr_in *)ifa->ifa_dstaddr; fprintf(output, " ip %s", routename4(sin->sin_addr.s_addr)); fprintf(output, " %s", inet_ntoa(sindest->sin_addr)); } else if (flags & IFF_BROADCAST) { sindest = (struct sockaddr_in *)ifa->ifa_broadaddr; fprintf(output, " ip %s", netname4(sin->sin_addr.s_addr, sinmask)); /* * no reason to save 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)) fprintf(output, " %s", inet_ntoa(sindest->sin_addr)); } else { fprintf(output, " ip %s", netname4(sin->sin_addr.s_addr, sinmask)); } ippntd = 1; break; case AF_INET6: if (af != AF_INET6 && af != 0) continue; sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; sin6mask = (struct sockaddr_in6 *)ifa->ifa_netmask; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; if (!ipv6ll_db_compare(sin6, sin6mask, ifname)) continue; in6_fillscopeid(sin6); if (flags & IFF_POINTOPOINT) { fprintf(output, " ip %s", routename6(sin6)); sin6dest = (struct sockaddr_in6 *)ifa->ifa_dstaddr; in6_fillscopeid(sin6dest); fprintf(output, " %s", routename6(sin6dest)); } else { fprintf(output, " ip %s", netname6(sin6, sin6mask)); } ippntd = 1; break; default: continue; } fprintf(output, "\n"); } freeifaddrs(ifap); return ippntd; }
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); }
char * addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr, char *netid) { struct ifaddrs *ifap, *ifp, *bestif; #ifdef INET6 struct sockaddr_in6 *servsin6, *sin6mask, *clntsin6, *ifsin6, *realsin6; struct sockaddr_in6 *newsin6; #endif struct sockaddr_in *servsin, *sinmask, *clntsin, *newsin, *ifsin; struct netbuf *serv_nbp, *clnt_nbp = NULL, tbuf; struct sockaddr *serv_sa; struct sockaddr *clnt_sa; struct sockaddr_storage ss; struct netconfig *nconf; struct sockaddr *clnt = caller->buf; char *ret = NULL; #ifdef INET6 servsin6 = ifsin6 = newsin6 = NULL; /* XXXGCC -Wuninitialized */ #endif servsin = newsin = NULL; /* XXXGCC -Wuninitialized */ #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr, clnt_uaddr, netid); #endif nconf = getnetconfigent(netid); if (nconf == NULL) return NULL; /* * Local merge, just return a duplicate. */ if (clnt_uaddr != NULL && strncmp(clnt_uaddr, "0.0.0.0.", 8) == 0) return strdup(clnt_uaddr); serv_nbp = uaddr2taddr(nconf, serv_uaddr); if (serv_nbp == NULL) return NULL; serv_sa = (struct sockaddr *)serv_nbp->buf; if (clnt_uaddr != NULL) { clnt_nbp = uaddr2taddr(nconf, clnt_uaddr); if (clnt_nbp == NULL) { free(serv_nbp); return NULL; } clnt_sa = (struct sockaddr *)clnt_nbp->buf; if (clnt_sa->sa_family == AF_LOCAL) { free(serv_nbp); free(clnt_nbp); free(clnt_sa); return strdup(serv_uaddr); } } else { clnt_sa = (struct sockaddr *) malloc(sizeof (struct sockaddr_storage)); memcpy(clnt_sa, clnt, clnt->sa_len); } if (getifaddrs(&ifp) < 0) { free(serv_nbp); free(clnt_sa); if (clnt_nbp != NULL) free(clnt_nbp); return 0; } /* * Loop through all interfaces. For each interface, see if the * network portion of its address is equal to that of the client. * If so, we have found the interface that we want to use. */ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { if (ifap->ifa_addr->sa_family != clnt->sa_family || !(ifap->ifa_flags & IFF_UP)) continue; switch (clnt->sa_family) { case AF_INET: /* * realsin: address that recvfrom gave us. * ifsin: address of interface being examined. * clntsin: address that client want us to contact * it on * servsin: local address of RPC service. * sinmask: netmask of this interface * newsin: initially a copy of clntsin, eventually * the merged address */ servsin = (struct sockaddr_in *)serv_sa; clntsin = (struct sockaddr_in *)clnt_sa; sinmask = (struct sockaddr_in *)ifap->ifa_netmask; newsin = (struct sockaddr_in *)&ss; ifsin = (struct sockaddr_in *)ifap->ifa_addr; if (!bitmaskcmp(&ifsin->sin_addr, &clntsin->sin_addr, &sinmask->sin_addr, sizeof (struct in_addr))) { goto found; } break; #ifdef INET6 case AF_INET6: /* * realsin6: address that recvfrom gave us. * ifsin6: address of interface being examined. * clntsin6: address that client want us to contact * it on * servsin6: local address of RPC service. * sin6mask: netmask of this interface * newsin6: initially a copy of clntsin, eventually * the merged address * * For v6 link local addresses, if the client contacted * us via a link-local address, and wants us to reply * to one, use the scope id to see which one. */ realsin6 = (struct sockaddr_in6 *)clnt; ifsin6 = (struct sockaddr_in6 *)ifap->ifa_addr; in6_fillscopeid(ifsin6); clntsin6 = (struct sockaddr_in6 *)clnt_sa; servsin6 = (struct sockaddr_in6 *)serv_sa; sin6mask = (struct sockaddr_in6 *)ifap->ifa_netmask; newsin6 = (struct sockaddr_in6 *)&ss; if (IN6_IS_ADDR_LINKLOCAL(&ifsin6->sin6_addr) && IN6_IS_ADDR_LINKLOCAL(&realsin6->sin6_addr) && IN6_IS_ADDR_LINKLOCAL(&clntsin6->sin6_addr)) { if (ifsin6->sin6_scope_id != realsin6->sin6_scope_id) continue; goto found; } if (!bitmaskcmp(&ifsin6->sin6_addr, &clntsin6->sin6_addr, &sin6mask->sin6_addr, sizeof (struct in6_addr))) goto found; break; #endif default: goto freeit; } } /* * Didn't find anything. Get the first possibly useful interface, * preferring "normal" interfaces to point-to-point and loopback * ones. */ bestif = NULL; for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { if (ifap->ifa_addr->sa_family != clnt->sa_family || !(ifap->ifa_flags & IFF_UP)) continue; if (!(ifap->ifa_flags & IFF_LOOPBACK) && !(ifap->ifa_flags & IFF_POINTOPOINT)) { bestif = ifap; break; } if (bestif == NULL) bestif = ifap; else if ((bestif->ifa_flags & IFF_LOOPBACK) && !(ifap->ifa_flags & IFF_LOOPBACK)) bestif = ifap; } ifap = bestif; found: switch (clnt->sa_family) { case AF_INET: memcpy(newsin, ifap->ifa_addr, clnt_sa->sa_len); newsin->sin_port = servsin->sin_port; tbuf.len = clnt_sa->sa_len; tbuf.maxlen = sizeof (struct sockaddr_storage); tbuf.buf = newsin; break; #ifdef INET6 case AF_INET6: assert(newsin6); memcpy(newsin6, ifsin6, clnt_sa->sa_len); newsin6->sin6_port = servsin6->sin6_port; tbuf.maxlen = sizeof (struct sockaddr_storage); tbuf.len = clnt_sa->sa_len; tbuf.buf = newsin6; break; #endif default: goto freeit; } if (ifap != NULL) ret = taddr2uaddr(nconf, &tbuf); freeit: freenetconfigent(nconf); free(serv_sa); free(serv_nbp); if (clnt_sa != NULL) free(clnt_sa); if (clnt_nbp != NULL) free(clnt_nbp); freeifaddrs(ifp); #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "addrmerge: returning %s\n", ret); #endif return ret; }