Android从源码中看netstat命令

Android的从源码中看的netstat命令

    上一篇中介绍了android通过命令netstat查看应用访问过的ip和端口。这篇通过源码来分析nestat是如何实现的。在源码中找到/external/toybox/toys/pending/netstat.c。先来看看主函数

void netstat_main(void)
{
    int tuwx = FLAG_t|FLAG_u|FLAG_w|FLAG_x;
    char *type = "w/o";

    TT.wpad = (toys.optflags&FLAG_W) ? 51 : 23;
    if (!(toys.optflags&(FLAG_r|tuwx))) toys.optflags |= tuwx;
    if (toys.optflags & FLAG_r) display_routes();
    if (!(toys.optflags&tuwx)) return;

    if (toys.optflags & FLAG_a) type = "established and";
    else if (toys.optflags & FLAG_l) type = "only";

    if (toys.optflags & FLAG_p) dirtree_read("/proc", scan_pids);

    if (toys.optflags&(FLAG_t|FLAG_u|FLAG_w)) {
        printf("Active %s (%s servers)\n", "Internet connections", type);
        printf("Proto Recv-Q Send-Q %*s %*s State      ", -TT.wpad, "Local Address",
                -TT.wpad, "Foreign Address");
        if (toys.optflags & FLAG_e) printf(" User       Inode      ");
        if (toys.optflags & FLAG_p) printf(" PID/Program Name");
        xputc('\n');

        if (toys.optflags & FLAG_t) {
            show_ip("/proc/net/tcp");
            show_ip("/proc/net/tcp6");
        }
        if (toys.optflags & FLAG_u) {
            show_ip("/proc/net/udp");
            show_ip("/proc/net/udp6");
        }
        if (toys.optflags & FLAG_w) {
            show_ip("/proc/net/raw");
            show_ip("/proc/net/raw6");
        }
    }

    if (toys.optflags & FLAG_x) {
        printf("Active %s (%s servers)\n", "UNIX domain sockets", type);

        printf("Proto RefCnt Flags\t Type\t    State\t    %s Path\n",
                (toys.optflags&FLAG_p) ? "PID/Program Name" : "I-Node");
        show_unix_sockets();
    }

    if ((toys.optflags & FLAG_p) && CFG_TOYBOX_FREE)
        llist_traverse(TT.inodes, free);
    toys.exitval = 0;
}

    从主函数中,netstat命令可以打印出3种类型的数据,分别是TCP,UDP,RAW。然后调用了show_ip函数,接下来我们看看show_ip

// Display info for tcp/udp/raw
static void show_ip(char *fname)
{
    char *ss_state = "UNKNOWN", buf[12], *s, *label = strrchr(fname, '/')+1;
    char *state_label[] = {"", "ESTABLISHED", "SYN_SENT", "SYN_RECV", "FIN_WAIT1",
        "FIN_WAIT2", "TIME_WAIT", "CLOSE", "CLOSE_WAIT",
        "LAST_ACK", "LISTEN", "CLOSING", "UNKNOWN"};
    struct passwd *pw;
    FILE *fp = fopen(fname, "r");

    if (!fp) {
        perror_msg("'%s'", fname);
        return;
    }

    if(!fgets(toybuf, sizeof(toybuf), fp)) return; //skip header.

    while (fgets(toybuf, sizeof(toybuf), fp)) {
        char lip[256], rip[256];
        union {
            struct {unsigned u; unsigned char b[4];} i4;
            struct {struct {unsigned a, b, c, d;} u; unsigned char b[16];} i6;
        } laddr, raddr;
        unsigned lport, rport, state, txq, rxq, num, uid, nitems;
        unsigned long inode;

        // Try ipv6, then try ipv4
        nitems = sscanf(toybuf,
                " %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x %*X:%*X %*X %d %*d %ld",
                &num, &laddr.i6.u.a, &laddr.i6.u.b, &laddr.i6.u.c,
  &laddr.i6.u.d, &lport, &raddr.i6.u.a, &raddr.i6.u.b,
  &raddr.i6.u.c, &raddr.i6.u.d, &rport, &state, &txq, &rxq,
  &uid, &inode);

        if (nitems!=16) {
            nitems = sscanf(toybuf,
                    " %d: %x:%x %x:%x %x %x:%x %*X:%*X %*X %d %*d %ld",
                    &num, &laddr.i4.u, &lport, &raddr.i4.u, &rport, &state, &txq,
    &rxq, &uid, &inode);

            if (nitems!=10) continue;
            nitems = AF_INET;
        } else nitems = AF_INET6;

        // Should we display this? (listening or all or TCP/UDP/RAW)
        if (!((toys.optflags & FLAG_l) && (!rport && (state & 0xA)))
                && !(toys.optflags & FLAG_a) && !(rport & (0x10 | 0x20 | 0x40)))
            continue;

        addr2str(nitems, &laddr, lport, lip, TT.wpad, label);
        addr2str(nitems, &raddr, rport, rip, TT.wpad, label);

        // Display data
        s = label;
        if (strstart(&s, "tcp")) {
            int sz = ARRAY_LEN(state_label);
            if (!state || state >= sz) state = sz-1;
            ss_state = state_label[state];
        } else if (strstart(&s, "udp")) {
            if (state == 1) ss_state = state_label[state];
            else if (state == 7) ss_state = "";
        } else if (strstart(&s, "raw")) sprintf(ss_state = buf, "%u", state);

        if (!(toys.optflags & FLAG_n) && (pw = bufgetpwuid(uid)))
            snprintf(toybuf, sizeof(toybuf), "%s", pw->pw_name);
        else snprintf(toybuf, sizeof(toybuf), "%d", uid);

        printf("%-6s%6d%7d ", label, rxq, txq);
        printf("%*.*s %*.*s ", -TT.wpad, TT.wpad, lip, -TT.wpad, TT.wpad, rip);
        printf("%-11s", ss_state);
        if ((toys.optflags & FLAG_e)) printf(" %-10s %-11ld", toybuf, inode);
        if ((toys.optflags & FLAG_p)) {
            struct num_cache *nc = get_num_cache(TT.inodes, inode);

            printf(" %s", nc ? nc->data : "-");
        }
        xputc('\n');
    }
    fclose(fp);
}

    从show_ip函数中,netstat通过读取以下系统文件来获取数据,然后通过sscanf函数,将各个项的数据读取出来。最后通过传入main函数中的参数,过滤出需要显示的数据

    /proc/net/tcp

    /proc/net/tcp6

    /proc/net/udp"

    /proc/net/udp6"

    /proc/net/raw"

    /proc/net/raw6"

        那么以上文件中都有哪些项,在终端中输入adb shell,然后输入cat /proc/net/tcp。

    从截图中,可以看到有本地地址和端口,远程地址和端口,应用UID还有其他的信息详细参考:https://blog.csdn.net/justlinux2010/article/details/21028797

        

上一篇:android通过命令netstat查看应用访问过的ip和端口

下一篇:android如何通过代码来获取每个应用访问过的ip和端口


阅读更多
个人分类: android
上一篇Android通过命令netstat查看应用访问过的IP和端口
下一篇android如何通过代码来获取每个应用访问过的ip和端口
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭