10f66f451Sopenharmony_ci/* netstat.c - Display Linux networking subsystem. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2012 Ranjan Kumar <ranjankumar.bth@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * Not in SUSv4. 70f66f451Sopenharmony_ci * 80f66f451Sopenharmony_ciUSE_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN)) 90f66f451Sopenharmony_ciconfig NETSTAT 100f66f451Sopenharmony_ci bool "netstat" 110f66f451Sopenharmony_ci default y 120f66f451Sopenharmony_ci help 130f66f451Sopenharmony_ci usage: netstat [-pWrxwutneal] 140f66f451Sopenharmony_ci 150f66f451Sopenharmony_ci Display networking information. Default is netstat -tuwx 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci -r Routing table 180f66f451Sopenharmony_ci -a All sockets (not just connected) 190f66f451Sopenharmony_ci -l Listening server sockets 200f66f451Sopenharmony_ci -t TCP sockets 210f66f451Sopenharmony_ci -u UDP sockets 220f66f451Sopenharmony_ci -w Raw sockets 230f66f451Sopenharmony_ci -x Unix sockets 240f66f451Sopenharmony_ci -e Extended info 250f66f451Sopenharmony_ci -n Don't resolve names 260f66f451Sopenharmony_ci -W Wide display 270f66f451Sopenharmony_ci -p Show PID/program name of sockets 280f66f451Sopenharmony_ci*/ 290f66f451Sopenharmony_ci 300f66f451Sopenharmony_ci#define FOR_netstat 310f66f451Sopenharmony_ci#include "toys.h" 320f66f451Sopenharmony_ci#include <net/route.h> 330f66f451Sopenharmony_ci 340f66f451Sopenharmony_ciGLOBALS( 350f66f451Sopenharmony_ci struct num_cache *inodes; 360f66f451Sopenharmony_ci int wpad; 370f66f451Sopenharmony_ci); 380f66f451Sopenharmony_ci 390f66f451Sopenharmony_ci// convert address into text format. 400f66f451Sopenharmony_cistatic void addr2str(int af, void *addr, unsigned port, char *buf, int len, 410f66f451Sopenharmony_ci char *proto) 420f66f451Sopenharmony_ci{ 430f66f451Sopenharmony_ci int pos, count; 440f66f451Sopenharmony_ci struct servent *ser = 0; 450f66f451Sopenharmony_ci 460f66f451Sopenharmony_ci // Convert to numeric address 470f66f451Sopenharmony_ci if (!inet_ntop(af, addr, buf, 256)) { 480f66f451Sopenharmony_ci *buf = 0; 490f66f451Sopenharmony_ci 500f66f451Sopenharmony_ci return; 510f66f451Sopenharmony_ci } 520f66f451Sopenharmony_ci buf[len] = 0; 530f66f451Sopenharmony_ci pos = strlen(buf); 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci // If there's no port number, it's a local :* binding, nothing to look up. 560f66f451Sopenharmony_ci if (!port) { 570f66f451Sopenharmony_ci if (len-pos<2) pos = len-2; 580f66f451Sopenharmony_ci strcpy(buf+pos, ":*"); 590f66f451Sopenharmony_ci 600f66f451Sopenharmony_ci return; 610f66f451Sopenharmony_ci } 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_n)) { 640f66f451Sopenharmony_ci struct addrinfo hints, *result, *rp; 650f66f451Sopenharmony_ci char cut[4]; 660f66f451Sopenharmony_ci 670f66f451Sopenharmony_ci memset(&hints, 0, sizeof(struct addrinfo)); 680f66f451Sopenharmony_ci hints.ai_family = af; 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci if (!getaddrinfo(buf, NULL, &hints, &result)) { 710f66f451Sopenharmony_ci socklen_t sock_len = (af == AF_INET) ? sizeof(struct sockaddr_in) 720f66f451Sopenharmony_ci : sizeof(struct sockaddr_in6); 730f66f451Sopenharmony_ci 740f66f451Sopenharmony_ci // We assume that a failing getnameinfo dosn't stomp "buf" here. 750f66f451Sopenharmony_ci for (rp = result; rp; rp = rp->ai_next) 760f66f451Sopenharmony_ci if (!getnameinfo(rp->ai_addr, sock_len, buf, 256, 0, 0, 0)) break; 770f66f451Sopenharmony_ci freeaddrinfo(result); 780f66f451Sopenharmony_ci buf[len] = 0; 790f66f451Sopenharmony_ci pos = strlen(buf); 800f66f451Sopenharmony_ci } 810f66f451Sopenharmony_ci 820f66f451Sopenharmony_ci // Doesn't understand proto "tcp6", so truncate 830f66f451Sopenharmony_ci memcpy(cut, proto, 3); 840f66f451Sopenharmony_ci cut[3] = 0; 850f66f451Sopenharmony_ci ser = getservbyport(htons(port), cut); 860f66f451Sopenharmony_ci } 870f66f451Sopenharmony_ci 880f66f451Sopenharmony_ci // Append :service 890f66f451Sopenharmony_ci count = snprintf(0, 0, ":%u", port); 900f66f451Sopenharmony_ci if (ser) { 910f66f451Sopenharmony_ci count = snprintf(0, 0, ":%s", ser->s_name); 920f66f451Sopenharmony_ci // sheer paranoia 930f66f451Sopenharmony_ci if (count>=len) { 940f66f451Sopenharmony_ci count = len-1; 950f66f451Sopenharmony_ci ser->s_name[count] = 0; 960f66f451Sopenharmony_ci } 970f66f451Sopenharmony_ci } 980f66f451Sopenharmony_ci if (len-pos<count) pos = len-count; 990f66f451Sopenharmony_ci if (ser) sprintf(buf+pos, ":%s", ser->s_name); 1000f66f451Sopenharmony_ci else sprintf(buf+pos, ":%u", port); 1010f66f451Sopenharmony_ci} 1020f66f451Sopenharmony_ci 1030f66f451Sopenharmony_ci// Display info for tcp/udp/raw 1040f66f451Sopenharmony_cistatic void show_ip(char *fname) 1050f66f451Sopenharmony_ci{ 1060f66f451Sopenharmony_ci char *ss_state = "UNKNOWN", buf[12], *s, *label = strrchr(fname, '/')+1; 1070f66f451Sopenharmony_ci char *state_label[] = {"", "ESTABLISHED", "SYN_SENT", "SYN_RECV", "FIN_WAIT1", 1080f66f451Sopenharmony_ci "FIN_WAIT2", "TIME_WAIT", "CLOSE", "CLOSE_WAIT", 1090f66f451Sopenharmony_ci "LAST_ACK", "LISTEN", "CLOSING", "UNKNOWN"}; 1100f66f451Sopenharmony_ci struct passwd *pw; 1110f66f451Sopenharmony_ci FILE *fp = fopen(fname, "r"); 1120f66f451Sopenharmony_ci 1130f66f451Sopenharmony_ci if (!fp) { 1140f66f451Sopenharmony_ci perror_msg("'%s'", fname); 1150f66f451Sopenharmony_ci return; 1160f66f451Sopenharmony_ci } 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_ci if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. 1190f66f451Sopenharmony_ci 1200f66f451Sopenharmony_ci while (fgets(toybuf, sizeof(toybuf), fp)) { 1210f66f451Sopenharmony_ci char lip[256], rip[256]; 1220f66f451Sopenharmony_ci union { 1230f66f451Sopenharmony_ci struct {unsigned u; unsigned char b[4];} i4; 1240f66f451Sopenharmony_ci struct {struct {unsigned a, b, c, d;} u; unsigned char b[16];} i6; 1250f66f451Sopenharmony_ci } laddr, raddr; 1260f66f451Sopenharmony_ci unsigned lport, rport, state, txq, rxq, num, uid, nitems; 1270f66f451Sopenharmony_ci unsigned long inode; 1280f66f451Sopenharmony_ci 1290f66f451Sopenharmony_ci // Try ipv6, then try ipv4 1300f66f451Sopenharmony_ci nitems = sscanf(toybuf, 1310f66f451Sopenharmony_ci " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x %*X:%*X %*X %d %*d %ld", 1320f66f451Sopenharmony_ci &num, &laddr.i6.u.a, &laddr.i6.u.b, &laddr.i6.u.c, 1330f66f451Sopenharmony_ci &laddr.i6.u.d, &lport, &raddr.i6.u.a, &raddr.i6.u.b, 1340f66f451Sopenharmony_ci &raddr.i6.u.c, &raddr.i6.u.d, &rport, &state, &txq, &rxq, 1350f66f451Sopenharmony_ci &uid, &inode); 1360f66f451Sopenharmony_ci 1370f66f451Sopenharmony_ci if (nitems!=16) { 1380f66f451Sopenharmony_ci nitems = sscanf(toybuf, 1390f66f451Sopenharmony_ci " %d: %x:%x %x:%x %x %x:%x %*X:%*X %*X %d %*d %ld", 1400f66f451Sopenharmony_ci &num, &laddr.i4.u, &lport, &raddr.i4.u, &rport, &state, &txq, 1410f66f451Sopenharmony_ci &rxq, &uid, &inode); 1420f66f451Sopenharmony_ci 1430f66f451Sopenharmony_ci if (nitems!=10) continue; 1440f66f451Sopenharmony_ci nitems = AF_INET; 1450f66f451Sopenharmony_ci } else nitems = AF_INET6; 1460f66f451Sopenharmony_ci 1470f66f451Sopenharmony_ci // Should we display this? (listening or all or TCP/UDP/RAW) 1480f66f451Sopenharmony_ci if (!((toys.optflags & FLAG_l) && (!rport && (state & 0xA))) 1490f66f451Sopenharmony_ci && !(toys.optflags & FLAG_a) && !(rport & (0x10 | 0x20 | 0x40))) 1500f66f451Sopenharmony_ci continue; 1510f66f451Sopenharmony_ci 1520f66f451Sopenharmony_ci addr2str(nitems, &laddr, lport, lip, TT.wpad, label); 1530f66f451Sopenharmony_ci addr2str(nitems, &raddr, rport, rip, TT.wpad, label); 1540f66f451Sopenharmony_ci 1550f66f451Sopenharmony_ci // Display data 1560f66f451Sopenharmony_ci s = label; 1570f66f451Sopenharmony_ci if (strstart(&s, "tcp")) { 1580f66f451Sopenharmony_ci int sz = ARRAY_LEN(state_label); 1590f66f451Sopenharmony_ci if (!state || state >= sz) state = sz-1; 1600f66f451Sopenharmony_ci ss_state = state_label[state]; 1610f66f451Sopenharmony_ci } else if (strstart(&s, "udp")) { 1620f66f451Sopenharmony_ci if (state == 1) ss_state = state_label[state]; 1630f66f451Sopenharmony_ci else if (state == 7) ss_state = ""; 1640f66f451Sopenharmony_ci } else if (strstart(&s, "raw")) sprintf(ss_state = buf, "%u", state); 1650f66f451Sopenharmony_ci 1660f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_n) && (pw = bufgetpwuid(uid))) 1670f66f451Sopenharmony_ci snprintf(toybuf, sizeof(toybuf), "%s", pw->pw_name); 1680f66f451Sopenharmony_ci else snprintf(toybuf, sizeof(toybuf), "%d", uid); 1690f66f451Sopenharmony_ci 1700f66f451Sopenharmony_ci printf("%-6s%6d%7d ", label, rxq, txq); 1710f66f451Sopenharmony_ci printf("%*.*s %*.*s ", -TT.wpad, TT.wpad, lip, -TT.wpad, TT.wpad, rip); 1720f66f451Sopenharmony_ci printf("%-11s", ss_state); 1730f66f451Sopenharmony_ci if ((toys.optflags & FLAG_e)) printf(" %-10s %-11ld", toybuf, inode); 1740f66f451Sopenharmony_ci if ((toys.optflags & FLAG_p)) { 1750f66f451Sopenharmony_ci struct num_cache *nc = get_num_cache(TT.inodes, inode); 1760f66f451Sopenharmony_ci 1770f66f451Sopenharmony_ci printf(" %s", nc ? nc->data : "-"); 1780f66f451Sopenharmony_ci } 1790f66f451Sopenharmony_ci xputc('\n'); 1800f66f451Sopenharmony_ci } 1810f66f451Sopenharmony_ci fclose(fp); 1820f66f451Sopenharmony_ci} 1830f66f451Sopenharmony_ci 1840f66f451Sopenharmony_cistatic void show_unix_sockets(void) 1850f66f451Sopenharmony_ci{ 1860f66f451Sopenharmony_ci char *types[] = {"","STREAM","DGRAM","RAW","RDM","SEQPACKET","DCCP","PACKET"}, 1870f66f451Sopenharmony_ci *states[] = {"","LISTENING","CONNECTING","CONNECTED","DISCONNECTING"}, 1880f66f451Sopenharmony_ci *s, *ss; 1890f66f451Sopenharmony_ci unsigned long refcount, flags, type, state, inode; 1900f66f451Sopenharmony_ci FILE *fp = xfopen("/proc/net/unix", "r"); 1910f66f451Sopenharmony_ci 1920f66f451Sopenharmony_ci if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. 1930f66f451Sopenharmony_ci 1940f66f451Sopenharmony_ci while (fgets(toybuf, sizeof(toybuf), fp)) { 1950f66f451Sopenharmony_ci unsigned offset = 0; 1960f66f451Sopenharmony_ci 1970f66f451Sopenharmony_ci // count = 6 or 7 (first field ignored, sockets don't always have filenames) 1980f66f451Sopenharmony_ci if (6<sscanf(toybuf, "%*p: %lX %*X %lX %lX %lX %lu %n", 1990f66f451Sopenharmony_ci &refcount, &flags, &type, &state, &inode, &offset)) 2000f66f451Sopenharmony_ci continue; 2010f66f451Sopenharmony_ci 2020f66f451Sopenharmony_ci // Linux exports only SO_ACCEPTCON since 2.3.15pre3 in 1999, but let's 2030f66f451Sopenharmony_ci // filter in case they add more someday. 2040f66f451Sopenharmony_ci flags &= 1<<16; 2050f66f451Sopenharmony_ci 2060f66f451Sopenharmony_ci // Only show unconnected listening sockets with -a 2070f66f451Sopenharmony_ci if (state==1 && flags && !(toys.optflags&FLAG_a)) continue; 2080f66f451Sopenharmony_ci 2090f66f451Sopenharmony_ci if (type==10) type = 7; // move SOCK_PACKET into line 2100f66f451Sopenharmony_ci if (type>ARRAY_LEN(types)) type = 0; 2110f66f451Sopenharmony_ci if (state>ARRAY_LEN(states) || (state==1 && !flags)) state = 0; 2120f66f451Sopenharmony_ci sprintf(toybuf, "[ %s]", flags ? "ACC " : ""); 2130f66f451Sopenharmony_ci 2140f66f451Sopenharmony_ci printf("unix %-6ld %-11s %-10s %-13s %8lu ", 2150f66f451Sopenharmony_ci refcount, toybuf, types[type], states[state], inode); 2160f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) { 2170f66f451Sopenharmony_ci struct num_cache *nc = get_num_cache(TT.inodes, inode); 2180f66f451Sopenharmony_ci 2190f66f451Sopenharmony_ci printf("%-19.19s", nc ? nc->data : "-"); 2200f66f451Sopenharmony_ci } 2210f66f451Sopenharmony_ci 2220f66f451Sopenharmony_ci if (offset) { 2230f66f451Sopenharmony_ci if ((ss = strrchr(s = toybuf+offset, '\n'))) *ss = 0; 2240f66f451Sopenharmony_ci printf("%s", s); 2250f66f451Sopenharmony_ci } 2260f66f451Sopenharmony_ci xputc('\n'); 2270f66f451Sopenharmony_ci } 2280f66f451Sopenharmony_ci 2290f66f451Sopenharmony_ci fclose(fp); 2300f66f451Sopenharmony_ci} 2310f66f451Sopenharmony_ci 2320f66f451Sopenharmony_cistatic int scan_pids(struct dirtree *node) 2330f66f451Sopenharmony_ci{ 2340f66f451Sopenharmony_ci char *s = toybuf+256; 2350f66f451Sopenharmony_ci struct dirent *entry; 2360f66f451Sopenharmony_ci DIR *dp; 2370f66f451Sopenharmony_ci int pid, dirfd; 2380f66f451Sopenharmony_ci 2390f66f451Sopenharmony_ci if (!node->parent) return DIRTREE_RECURSE; 2400f66f451Sopenharmony_ci if (!(pid = atol(node->name))) return 0; 2410f66f451Sopenharmony_ci 2420f66f451Sopenharmony_ci sprintf(toybuf, "/proc/%d/cmdline", pid); 2430f66f451Sopenharmony_ci if (!(readfile(toybuf, toybuf, 256))) return 0; 2440f66f451Sopenharmony_ci 2450f66f451Sopenharmony_ci sprintf(s, "%d/fd", pid); 2460f66f451Sopenharmony_ci if (-1==(dirfd = openat(dirtree_parentfd(node), s, O_RDONLY))) return 0; 2470f66f451Sopenharmony_ci if (!(dp = fdopendir(dirfd))) { 2480f66f451Sopenharmony_ci close(dirfd); 2490f66f451Sopenharmony_ci 2500f66f451Sopenharmony_ci return 0; 2510f66f451Sopenharmony_ci } 2520f66f451Sopenharmony_ci 2530f66f451Sopenharmony_ci while ((entry = readdir(dp))) { 2540f66f451Sopenharmony_ci s = toybuf+256; 2550f66f451Sopenharmony_ci if (!readlinkat0(dirfd, entry->d_name, s, sizeof(toybuf)-256)) continue; 2560f66f451Sopenharmony_ci // Can the "[0000]:" happen in a modern kernel? 2570f66f451Sopenharmony_ci if (strstart(&s, "socket:[") || strstart(&s, "[0000]:")) { 2580f66f451Sopenharmony_ci long long ll = atoll(s); 2590f66f451Sopenharmony_ci 2600f66f451Sopenharmony_ci sprintf(s, "%d/%s", pid, getbasename(toybuf)); 2610f66f451Sopenharmony_ci add_num_cache(&TT.inodes, ll, s, strlen(s)+1); 2620f66f451Sopenharmony_ci } 2630f66f451Sopenharmony_ci } 2640f66f451Sopenharmony_ci closedir(dp); 2650f66f451Sopenharmony_ci 2660f66f451Sopenharmony_ci return 0; 2670f66f451Sopenharmony_ci} 2680f66f451Sopenharmony_ci 2690f66f451Sopenharmony_ci/* 2700f66f451Sopenharmony_ci * extract inet4 route info from /proc/net/route file and display it. 2710f66f451Sopenharmony_ci */ 2720f66f451Sopenharmony_cistatic void display_routes(void) 2730f66f451Sopenharmony_ci{ 2740f66f451Sopenharmony_ci static const char flagchars[] = "GHRDMDAC"; 2750f66f451Sopenharmony_ci static const unsigned flagarray[] = { 2760f66f451Sopenharmony_ci RTF_GATEWAY, RTF_HOST, RTF_REINSTATE, RTF_DYNAMIC, RTF_MODIFIED 2770f66f451Sopenharmony_ci }; 2780f66f451Sopenharmony_ci unsigned dest, gate, mask; 2790f66f451Sopenharmony_ci int flags, ref, use, metric, mss, win, irtt; 2800f66f451Sopenharmony_ci char *out = toybuf, *flag_val; 2810f66f451Sopenharmony_ci char iface[64]={0}; 2820f66f451Sopenharmony_ci FILE *fp = xfopen("/proc/net/route", "r"); 2830f66f451Sopenharmony_ci 2840f66f451Sopenharmony_ci if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header. 2850f66f451Sopenharmony_ci 2860f66f451Sopenharmony_ci printf("Kernel IP routing table\n" 2870f66f451Sopenharmony_ci "Destination\tGateway \tGenmask \tFlags %s Iface\n", 2880f66f451Sopenharmony_ci !(toys.optflags&FLAG_e) ? " MSS Window irtt" : "Metric Ref Use"); 2890f66f451Sopenharmony_ci 2900f66f451Sopenharmony_ci while (fgets(toybuf, sizeof(toybuf), fp)) { 2910f66f451Sopenharmony_ci char *destip = 0, *gateip = 0, *maskip = 0; 2920f66f451Sopenharmony_ci 2930f66f451Sopenharmony_ci if (11 != sscanf(toybuf, "%63s%x%x%X%d%d%d%x%d%d%d", iface, &dest, 2940f66f451Sopenharmony_ci &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt)) 2950f66f451Sopenharmony_ci break; 2960f66f451Sopenharmony_ci 2970f66f451Sopenharmony_ci // skip down interfaces. 2980f66f451Sopenharmony_ci if (!(flags & RTF_UP)) continue; 2990f66f451Sopenharmony_ci 3000f66f451Sopenharmony_ci// TODO /proc/net/ipv6_route 3010f66f451Sopenharmony_ci 3020f66f451Sopenharmony_ci if (dest) { 3030f66f451Sopenharmony_ci if (inet_ntop(AF_INET, &dest, out, 16)) destip = out; 3040f66f451Sopenharmony_ci } else destip = (toys.optflags&FLAG_n) ? "0.0.0.0" : "default"; 3050f66f451Sopenharmony_ci out += 16; 3060f66f451Sopenharmony_ci 3070f66f451Sopenharmony_ci if (gate) { 3080f66f451Sopenharmony_ci if (inet_ntop(AF_INET, &gate, out, 16)) gateip = out; 3090f66f451Sopenharmony_ci } else gateip = (toys.optflags&FLAG_n) ? "0.0.0.0" : "*"; 3100f66f451Sopenharmony_ci out += 16; 3110f66f451Sopenharmony_ci 3120f66f451Sopenharmony_ci// TODO /24 3130f66f451Sopenharmony_ci //For Mask 3140f66f451Sopenharmony_ci if (inet_ntop(AF_INET, &mask, out, 16)) maskip = out; 3150f66f451Sopenharmony_ci else maskip = "?"; 3160f66f451Sopenharmony_ci out += 16; 3170f66f451Sopenharmony_ci 3180f66f451Sopenharmony_ci //Get flag Values 3190f66f451Sopenharmony_ci flag_val = out; 3200f66f451Sopenharmony_ci *out++ = 'U'; 3210f66f451Sopenharmony_ci for (dest = 0; dest < ARRAY_LEN(flagarray); dest++) 3220f66f451Sopenharmony_ci if (flags&flagarray[dest]) *out++ = flagchars[dest]; 3230f66f451Sopenharmony_ci *out = 0; 3240f66f451Sopenharmony_ci if (flags & RTF_REJECT) *flag_val = '!'; 3250f66f451Sopenharmony_ci 3260f66f451Sopenharmony_ci printf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, maskip, flag_val); 3270f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_e)) 3280f66f451Sopenharmony_ci printf("%5d %-5d %6d %s\n", mss, win, irtt, iface); 3290f66f451Sopenharmony_ci else printf("%-6d %-2d %7d %s\n", metric, ref, use, iface); 3300f66f451Sopenharmony_ci } 3310f66f451Sopenharmony_ci 3320f66f451Sopenharmony_ci fclose(fp); 3330f66f451Sopenharmony_ci} 3340f66f451Sopenharmony_ci 3350f66f451Sopenharmony_civoid netstat_main(void) 3360f66f451Sopenharmony_ci{ 3370f66f451Sopenharmony_ci int tuwx = FLAG_t|FLAG_u|FLAG_w|FLAG_x; 3380f66f451Sopenharmony_ci char *type = "w/o"; 3390f66f451Sopenharmony_ci 3400f66f451Sopenharmony_ci TT.wpad = (toys.optflags&FLAG_W) ? 51 : 23; 3410f66f451Sopenharmony_ci if (!(toys.optflags&(FLAG_r|tuwx))) toys.optflags |= tuwx; 3420f66f451Sopenharmony_ci if (toys.optflags & FLAG_r) display_routes(); 3430f66f451Sopenharmony_ci if (!(toys.optflags&tuwx)) return; 3440f66f451Sopenharmony_ci 3450f66f451Sopenharmony_ci if (toys.optflags & FLAG_a) type = "established and"; 3460f66f451Sopenharmony_ci else if (toys.optflags & FLAG_l) type = "only"; 3470f66f451Sopenharmony_ci 3480f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) dirtree_read("/proc", scan_pids); 3490f66f451Sopenharmony_ci 3500f66f451Sopenharmony_ci if (toys.optflags&(FLAG_t|FLAG_u|FLAG_w)) { 3510f66f451Sopenharmony_ci printf("Active %s (%s servers)\n", "Internet connections", type); 3520f66f451Sopenharmony_ci printf("Proto Recv-Q Send-Q %*s %*s State ", -TT.wpad, "Local Address", 3530f66f451Sopenharmony_ci -TT.wpad, "Foreign Address"); 3540f66f451Sopenharmony_ci if (toys.optflags & FLAG_e) printf(" User Inode "); 3550f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) printf(" PID/Program Name"); 3560f66f451Sopenharmony_ci xputc('\n'); 3570f66f451Sopenharmony_ci 3580f66f451Sopenharmony_ci if (toys.optflags & FLAG_t) { 3590f66f451Sopenharmony_ci show_ip("/proc/net/tcp"); 3600f66f451Sopenharmony_ci show_ip("/proc/net/tcp6"); 3610f66f451Sopenharmony_ci } 3620f66f451Sopenharmony_ci if (toys.optflags & FLAG_u) { 3630f66f451Sopenharmony_ci show_ip("/proc/net/udp"); 3640f66f451Sopenharmony_ci show_ip("/proc/net/udp6"); 3650f66f451Sopenharmony_ci } 3660f66f451Sopenharmony_ci if (toys.optflags & FLAG_w) { 3670f66f451Sopenharmony_ci show_ip("/proc/net/raw"); 3680f66f451Sopenharmony_ci show_ip("/proc/net/raw6"); 3690f66f451Sopenharmony_ci } 3700f66f451Sopenharmony_ci } 3710f66f451Sopenharmony_ci 3720f66f451Sopenharmony_ci if (toys.optflags & FLAG_x) { 3730f66f451Sopenharmony_ci printf("Active %s (%s servers)\n", "UNIX domain sockets", type); 3740f66f451Sopenharmony_ci 3750f66f451Sopenharmony_ci printf("Proto RefCnt Flags\t Type\t State\t %s Path\n", 3760f66f451Sopenharmony_ci (toys.optflags&FLAG_p) ? "PID/Program Name" : "I-Node"); 3770f66f451Sopenharmony_ci show_unix_sockets(); 3780f66f451Sopenharmony_ci } 3790f66f451Sopenharmony_ci 3800f66f451Sopenharmony_ci if ((toys.optflags & FLAG_p) && CFG_TOYBOX_FREE) 3810f66f451Sopenharmony_ci llist_traverse(TT.inodes, free); 3820f66f451Sopenharmony_ci toys.exitval = 0; 3830f66f451Sopenharmony_ci} 384