/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */ static char *INET6_sprint(struct sockaddr *sap, int numeric) { static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET6_rresolve(buff, (struct sockaddr_in6 *) sap, numeric) != 0) return (NULL); return (buff); }
/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */ static char *INET6_sprint(struct sockaddr *sap, int numeric) { static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET6_rresolve(buff, (struct sockaddr_in6 *) sap, numeric) != 0) return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff)); return (fix_v4_address(buff, &((struct sockaddr_in6 *)sap)->sin6_addr)); }
static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, const char *proto, int numeric) { const char *port_name; #if ENABLE_FEATURE_IPV6 if (addr->sa_family == AF_INET6) { INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr, (numeric & NETSTAT_NUMERIC) ? 0x0fff : 0); } else #endif { INET_rresolve(ip_port, size, (struct sockaddr_in *)addr, 0x4000 | ((numeric & NETSTAT_NUMERIC) ? 0x0fff : 0), 0xffffffff); } port_name = get_sname(htons(port), proto, numeric); if ((strlen(ip_port) + strlen(port_name)) > 22) ip_port[22 - strlen(port_name)] = '\0'; ip_port += strlen(ip_port); strcat(ip_port, ":"); strcat(ip_port, port_name); }
static void INET6_displayroutes(int noresolve) { char addr6[128], naddr6[128]; /* In addr6x, we store both 40-byte ':'-delimited ipv6 addresses. * We read the non-delimited strings into the tail of the buffer * using fscanf and then modify the buffer by shifting forward * while inserting ':'s and the nul terminator for the first string. * Hence the strings are at addr6x and addr6x+40. This generates * _much_ less code than the previous (upstream) approach. */ char addr6x[80]; char iface[16], flags[16]; int iflags, metric, refcnt, use, prefix_len, slen; struct sockaddr_in6 snaddr6; FILE *fp = bb_xfopen("/proc/net/ipv6_route", "r"); bb_printf("Kernel IPv6 routing table\n%-44s%-40s" "Flags Metric Ref Use Iface\n", "Destination", "Next Hop"); while (1) { int r; r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n", addr6x+14, &prefix_len, &slen, addr6x+40+7, &metric, &use, &refcnt, &iflags, iface); if (r != 9) { if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */ break; } ERROR: bb_error_msg_and_die("fscanf"); } /* Do the addr6x shift-and-insert changes to ':'-delimit addresses. * For now, always do this to validate the proc route format, even * if the interface is down. */ { int i = 0; char *p = addr6x+14; do { if (!*p) { if (i==40) { /* nul terminator for 1st address? */ addr6x[39] = 0; /* Fixup... need 0 instead of ':'. */ ++p; /* Skip and continue. */ continue; } goto ERROR; } addr6x[i++] = *p++; if (!((i+1)%5)) { addr6x[i++] = ':'; } } while (i < 40+28+7); } if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */ continue; } set_flags(flags, (iflags & IPV6_MASK)); r = 0; do { inet_pton(AF_INET6, addr6x + r, (struct sockaddr *) &snaddr6.sin6_addr); snaddr6.sin6_family = AF_INET6; INET6_rresolve(naddr6, sizeof(naddr6), (struct sockaddr_in6 *) &snaddr6, #if 0 (noresolve | 0x8000) /* Default instead of *. */ #else 0x0fff /* Apparently, upstream never resolves. */ #endif ); if (!r) { /* 1st pass */ snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); r += 40; } else { /* 2nd pass */ /* Print the info. */ bb_printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n", addr6, naddr6, flags, metric, refcnt, use, iface); break; } } while (1); } }
static void INET6_displayroutes(int noresolve) { char buff[256]; char iface[16], flags[16]; char addr6[128], naddr6[128]; struct sockaddr_in6 saddr6, snaddr6; int iflags, metric, refcnt, use, prefix_len, slen; int numeric; char addr6p[8][5], saddr6p[8][5], naddr6p[8][5]; FILE *fp = bb_xfopen("/proc/net/ipv6_route", "r"); flags[0] = 'U'; if (noresolve) noresolve = 0x0fff; numeric = noresolve | 0x8000; /* default instead of * */ printf("Kernel IPv6 routing table\n" "Destination " "Next Hop " "Flags Metric Ref Use Iface\n"); while (fgets(buff, sizeof(buff), fp) != NULL) { int ifl; if (sscanf(buff, "%4s%4s%4s%4s%4s%4s%4s%4s %02x " "%4s%4s%4s%4s%4s%4s%4s%4s %02x " "%4s%4s%4s%4s%4s%4s%4s%4s %08x %08x %08x %08x %s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], &prefix_len, saddr6p[0], saddr6p[1], saddr6p[2], saddr6p[3], saddr6p[4], saddr6p[5], saddr6p[6], saddr6p[7], &slen, naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3], naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7], &metric, &use, &refcnt, &iflags, iface) != 31) { bb_error_msg_and_die("Unsuported kernel route format\n"); } ifl = 1; /* parse flags */ if (!(iflags & RTF_UP)) continue; if (iflags & RTF_GATEWAY) flags[ifl++] = 'G'; if (iflags & RTF_HOST) flags[ifl++] = 'H'; if (iflags & RTF_DEFAULT) flags[ifl++] = 'D'; if (iflags & RTF_ADDRCONF) flags[ifl++] = 'A'; if (iflags & RTF_CACHE) flags[ifl++] = 'C'; flags[ifl] = 0; /* Fetch and resolve the target address. */ snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); inet_pton(AF_INET6, addr6, (struct sockaddr *) &saddr6.sin6_addr); saddr6.sin6_family = AF_INET6; INET6_rresolve(addr6, sizeof(addr6), (struct sockaddr_in6 *) &saddr6, numeric); snprintf(addr6, sizeof(addr6), "%s/%d", addr6, prefix_len); /* Fetch and resolve the nexthop address. */ snprintf(naddr6, sizeof(naddr6), "%s:%s:%s:%s:%s:%s:%s:%s", naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3], naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7]); inet_pton(AF_INET6, naddr6, (struct sockaddr *) &snaddr6.sin6_addr); snaddr6.sin6_family = AF_INET6; INET6_rresolve(naddr6, sizeof(naddr6), (struct sockaddr_in6 *) &snaddr6, numeric); /* Print the info. */ printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n", addr6, naddr6, flags, metric, refcnt, use, iface); } }
int INET6_displayroutes_array(webs_t wp) { char addr6[128], *naddr6; /* In addr6x, we store both 40-byte ':'-delimited ipv6 addresses. * We read the non-delimited strings into the tail of the buffer * using fscanf and then modify the buffer by shifting forward * while inserting ':'s and the nul terminator for the first string. * Hence the strings are at addr6x and addr6x+40. This generates * _much_ less code than the previous (upstream) approach. */ char addr6x[80]; char iface[16], flags[16]; int iflags, metric, refcnt, use, prefix_len, slen; struct sockaddr_in6 snaddr6; int ret = 0; FILE *fp = fopen("/proc/net/ipv6_route", "r"); while (1) { int r; r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n", addr6x+14, &prefix_len, &slen, addr6x+40+7, &metric, &use, &refcnt, &iflags, iface); if (r != 9) { if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */ break; } ERROR: perror("fscanf"); return ret; } /* Do the addr6x shift-and-insert changes to ':'-delimit addresses. * For now, always do this to validate the proc route format, even * if the interface is down. */ { int i = 0; char *p = addr6x+14; do { if (!*p) { if (i == 40) { /* nul terminator for 1st address? */ addr6x[39] = 0; /* Fixup... need 0 instead of ':'. */ ++p; /* Skip and continue. */ continue; } goto ERROR; } addr6x[i++] = *p++; if (!((i+1) % 5)) { addr6x[i++] = ':'; } } while (i < 40+28+7); } if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */ continue; } ipv6_set_flags(flags, (iflags & IPV6_MASK)); r = 0; do { inet_pton(AF_INET6, addr6x + r, (struct sockaddr *) &snaddr6.sin6_addr); snaddr6.sin6_family = AF_INET6; naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6, 0x0fff /* Apparently, upstream never resolves. */ ); if (!r) { /* 1st pass */ snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); r += 40; free(naddr6); } else { /* 2nd pass */ /* Print the info. */ ret += websWrite(wp, "[\"%3s\", \"%s\", \"%s\", \"%d\", \"%d\", \"%d\", \"%s\"],\n", addr6, naddr6, flags, metric, refcnt, use, iface); free(naddr6); break; } } while (1); } return ret;; }