zoukankan      html  css  js  c++  java
  • Systemtap examples, Network

    http://blog.163.com/digoal@126/blog/static/16387704020131014104256627/
     
    例子来自tcpdumplike.stp脚本, 当tcp.receive事件触发后, 取出类似tcpdump输出的源ip, 目的ip, 源端口, 目的端口, 以及6个tcp包的控制比特位信息.
    tcp.receive alias实际上包含2个内核函数, 分别代表ipv4和ipv6. 
    kernel.function("tcp_v4_rcv")
    kernel.function("tcp_v6_rcv")!, module("ipv6").function("tcp_v6_rcv")
    // !表示有限匹配kernel.function("tcp_v6_rcv"), 匹配后下面的module就不触发了.
     
    脚本内容以及注解
    [root@db-172-16-3-150 network]# cd /usr/share/systemtap/testsuite/systemtap.examples/network
    [root@db-172-16-3-150 network]# cat tcpdumplike.stp
    #!/usr/bin/stap
     
    // A TCP dump like example
     
    probe begin, timer.s(1) {
      printf("----------------------------------------------------------------- ")
      printf("       Source IP         Dest IP  SPort  DPort  U  A  P  R  S  F ")
      printf("----------------------------------------------------------------- ")
    }
    // stap脚本开始, 并且以后每秒输出一次头信息. 方便阅读.
     
    probe tcp.receive {
      printf(" %15s %15s  %5d  %5d  %d  %d  %d  %d  %d  %d ",
             saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin)
    }
    // 跟踪tcp.receive事件, 事件出发时, 输出
    // saddr 源IP
    // daddr 目的IP
    // sport 源端口
    // dport 目的端口
    // urg, ack, psh, rst syn, fin 6个tcp包的控制比特位信息
     
    执行输出举例
    [root@db-172-16-3-150 network]# stap ./tcpdumplike.stp 
    -----------------------------------------------------------------
           Source IP         Dest IP  SPort  DPort  U  A  P  R  S  F 
    -----------------------------------------------------------------
         172.16.8.31    172.16.3.150  51167     22  0  1  0  0  0  0
         172.16.8.31    172.16.3.150  54223     22  0  1  1  0  0  0
         172.16.8.31    172.16.3.150  54223     22  0  1  1  0  0  0
         172.16.8.31    172.16.3.150  54223     22  0  1  0  0  0  0
         172.16.8.31    172.16.3.150  51167     22  0  1  1  0  0  0
         172.16.3.40    172.16.3.150  51927   9000  0  0  0  0  1  0
    最后一行的A=0, S=1, 表示这个包是从172.16.3.40发过来的建立三次握手的第一个包.
    U=1的话, 表示重要的包, 接收到后不要放到缓冲区, 直接处理.
     
    本文用到的tcp.receive probe alias原型.
    /usr/share/systemtap/tapset/tcp.stp
    /**
     * probe tcp.receive - Called when a TCP packet is received
     * @name: Name of the probe point
     * @iphdr: IP header address
     * @protocol: Packet protocol from driver
     * @family: IP address family
     * @saddr: A string representing the source IP address
     * @daddr: A string representing the destination IP address
     * @sport: TCP source port
     * @dport: TCP destination port
     * @urg: TCP URG flag
     * @ack: TCP ACK flag
     * @psh: TCP PSH flag
     * @rst: TCP RST flag
     * @syn: TCP SYN flag
     * @fin: TCP FIN flag
     */
    probe tcp.receive = tcp.ipv4.receive, tcp.ipv6.receive
    {
    }
    // tcp.receive包含ipv4和ipv6的alias.
     
    probe tcp.ipv4.receive = kernel.function("tcp_v4_rcv")
    {
            name = "tcp.ipv4.receive"
            iphdr = __get_skb_iphdr($skb)
            # If we're here, by definition we're doing AF_INET, not AF_INET6.
            family = %{ /* pure */ AF_INET %}
            saddr = format_ipaddr(__ip_skb_saddr(iphdr), %{ /* pure */ AF_INET %})
            daddr = format_ipaddr(__ip_skb_daddr(iphdr), %{ /* pure */ AF_INET %})
            protocol = __ip_skb_proto(iphdr)
     
            tcphdr = __get_skb_tcphdr($skb)
            dport = __tcp_skb_dport(tcphdr)
            sport = __tcp_skb_sport(tcphdr)
            urg = __tcp_skb_urg(tcphdr)
            ack = __tcp_skb_ack(tcphdr)
            psh = __tcp_skb_psh(tcphdr)
            rst = __tcp_skb_rst(tcphdr)
            syn = __tcp_skb_syn(tcphdr)
            fin = __tcp_skb_fin(tcphdr)
    }
     
    probe tcp.ipv6.receive = kernel.function("tcp_v6_rcv")!,
            module("ipv6").function("tcp_v6_rcv")
    {
            name = "tcp.ipv6.receive"
            iphdr = __get_skb_iphdr(@defined($skb) ? $skb : kernel_pointer($pskb))
            # If we're here, by definition we're doing AF_INET6, not AF_INET.
            family = %{ /* pure */ AF_INET6 %}
            saddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->saddr,
                                  %{ /* pure */ AF_INET6 %})
            daddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->daddr,
                                  %{ /* pure */ AF_INET6 %})
            # If we're here, by definition we're doing IPPROTO_TCP.  There
            # isn't a protocol field in 'struct ipv6hdr'.  There is one in
            # 'struct sk_buff', but that protocol field is an Ethernet
            # Procol ID (ETH_P_*), not an IP protocol ID (IPPROTO_*).
            protocol = %{ /* pure */ IPPROTO_TCP %}
     
            tcphdr = __get_skb_tcphdr(@defined($skb) ? $skb : kernel_pointer($pskb))
            dport = __tcp_skb_dport(tcphdr)
            sport = __tcp_skb_sport(tcphdr)
            urg = __tcp_skb_urg(tcphdr)
            ack = __tcp_skb_ack(tcphdr)
            psh = __tcp_skb_psh(tcphdr)
            rst = __tcp_skb_rst(tcphdr)
            syn = __tcp_skb_syn(tcphdr)
            fin = __tcp_skb_fin(tcphdr)
    }
    // 一些tcp常用的函数
    //
    //Definitions of the TCP protocol sk_state field listed below.
    //
    //     TCP_ESTABLISHED = 1,   Normal data transfer
    //     TCP_SYN_SENT   = 2,   App. has started to open a connection
    //     TCP_SYN_RECV   = 3,   A connection request has arrived; wait for ACK
    //     TCP_FIN_WAIT1  = 4,   App. has said it is finished
    //     TCP_FIN_WAIT2  = 5,   The other side has agreed to close
    //     TCP_TIME_WAIT  = 6,   Wait for all packets to die off
    //     TCP_CLOSE      = 7,   No connection is active or pending 
    //     TCP_CLOSE_WAIT = 8,   The other side has initiated a release
    //     TCP_LAST_ACK   = 9,   Last ACK, wait for all packets to die off
    //     TCP_LISTEN     = 10,  Waiting for incoming call
    //     TCP_CLOSING    = 11,  Both sides have tried to close simultaneously
    //     TCP_MAX_STATES = 12   Max states number
    // 
    function tcp_ts_get_info_state:long(sock:long)
    %{ /* pure */
            struct sock *sk = (struct sock *)(long) STAP_ARG_sock;
            STAP_RETVALUE = (int64_t) kread(&(sk->sk_state));
            CATCH_DEREF_FAULT();
    %}
     
    /* return the TCP destination port for a given sock */
    function __tcp_sock_dport:long (sock:long)
    {
        return (@defined(@cast(sock, "inet_sock")->inet_dport)
                ? @cast(sock, "inet_sock")->inet_dport # kernel >= 2.6.33
                : (@defined(@cast(sock, "inet_sock")->dport)
                   ? @cast(sock, "inet_sock", "kernel")->dport # kernel >= 2.6.11
                   : @cast(sock, "inet_sock", "kernel<net/ip.h>")->inet->dport))
    }
    // 内嵌了C代码, 为了取出sock的值.
     
    TCP 包头信息

    TCP Header Format

                                        
        0                   1                   2                   3   
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |          Source Port          |       Destination Port        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                        Sequence Number                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Acknowledgment Number                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |  Data |           |U|A|P|R|S|F|                               |
       | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
       |       |           |G|K|H|T|N|N|                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |         Urgent Pointer        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Options                    |    Padding    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             data                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    
                                TCP Header Format
    
              Note that one tick mark represents one bit position.
    
                                   Figure 3.
    控制比特信息 : 

    Control Bits: 6 bits (from left to right):

        URG:  Urgent Pointer field significant
        ACK:  Acknowledgment field significant
        PSH:  Push Function
        RST:  Reset the connection
        SYN:  Synchronize sequence numbers
        FIN:  No more data from sender
     
    [参考]
    1. /usr/share/systemtap/testsuite/systemtap.examples
    3. systemtap-testsuite
    5. /usr/share/systemtap/testsuite/systemtap.examples/index.txt
    6. /usr/share/systemtap/testsuite/systemtap.examples/keyword-index.txt
    7. /usr/share/systemtap/tapset
  • 相关阅读:
    跟layout_weight说88,轻松搞定百分比布局
    跟闪退、程序崩溃说88
    程序的需求层次
    开博
    第十章 数组与集合 发牌程序 实例代码
    C#面向对象基础01
    winform form
    html
    C#语言基础02
    C#语言基础01
  • 原文地址:https://www.cnblogs.com/zengkefu/p/6372276.html
Copyright © 2011-2022 走看看