追踪TCP_IP实现过程

首先,我们要实现追踪,需要用到一个函数,就是printk函数。(对它的初步理解就可参照C语言的printf函数)
printk()函数中会使用日志级别,这样方便我们在编程过程中自定义的进行信息的输出,更加容易的掌握系统当前的状况。而它总共分为8个级别:
#defineKERN_EMERG"<0>"/*紧急事件信息,系统崩溃之前提示,表示系统不可用*/
#defineKERN_ALERT"<1>"/*报告消息,表示必须立即采取措施*/
#defineKERN_CRIT"<2>"/*临界条件,通常设计严重的硬件或软件操作失败*/#defineKERN_ERR"<3>"/*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/#defineKERN_WARING"<4>"/*警告条件,对可能出现问题的情况出现警告*/#defineKERN_NOTICE"<5>"/*正常但又重要的条件,用于提醒。常用于与安全相关的消息
*/#defineKERN_INFO"<6>"/*提示信息,如驱动程序启动时,打印硬件信息*/
#defineKERN_DEBUG"<7>"/*调试级别的信息*/
以上是对printk函数的简要介绍,需要详细了解的可自行下去了解,网上文档资料很多。
它的用法是:printk(KERN_ALERT"Hello, socket!\n");
           printk(KERN_ALERT "Hello, bind!\n");

接下来,我们要做的就是打开各个层次对应文件,在适当的位置添加打印输出printk语句。
为了方便的话,大家可以使用命令sudo -i获得管理员权限之后就不用频繁输密码了。
应用层:相信大家对服务器——客户端模式有一定的了解,我们要做的就是在socket、bind、listen、connect、accept函数合适的位置添加printk语句,在系统内核调用该类函数时打印输出。
所要修改的文件所在路径:/usr/src/linux-3.16.6/net/sicket.c(这是我内核文件所在的路径,你们对应修改就好了)
(1)
root@xiaoxiao-Lenovo-G470:/usr/src/linux-3.16.6/net# gedit socket.c
(2)
因为在这个文件下可以修改添加语句的地方很多,在这里就不一一示范了。
先是在socket创建的位置添加(在此文件中找到一下代码):


int __sock_create(struct net *net, int family, int type, int protocol,

             struct socket **res, int kern)
{
    int err;
    struct socket *sock;
    const struct net_proto_family *pf;
       /*printk(KERN_ALERT"Hello, socket!\n");*/ (这里添加的语句)

    /*
     *      Check protocol is in range
     */
    if (family < 0 || family >= NPROTO)
        return -EAFNOSUPPORT;
    if (type < 0 || type >= SOCK_MAX)
        return -EINVAL;


然后就是bind函数下添加printk语句:
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{
    struct socket *sock;
    struct sockaddr_storage address;
    int err, fput_needed;
        /*printk(KERN_ALERT "Hello, bind!\n"); */(同样,这里是添加的语句)


你们看到的在语句两边加了/*  */,这个是注释。如果注释掉,就不会显示出来。其他函数自行添加。


传输层:tcp传输控制协议完成传输层所制定的功能,我们所要追踪修改的文件就是有关tcp的函数。
所要修改的文件路径:/usr/src/linux-3.16.6/net/ipv4
(1)
root@xiaoxiao-Lenovo-G470:/usr/src/linux-3.16.6/net/ipv4# gedit tcp_input.c
(2)在tcp_input.c中要修改的是一下几处:


int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,

              const struct tcphdr *th, unsigned int len)
{
    struct tcp_sock *tp = tcp_sk(sk);
    struct inet_connection_sock *icsk = inet_csk(sk);
    struct request_sock *req;
    int queued = 0;
    bool acceptable;
    u32 synack_stamp;
        printk(KERN_EMERG"hello,tcp_rcv_state_process!\n"); (这是添加的语句,此处是tcp接受数据包的函数,当调用此函数时会输出该语句)

    tp->rx_opt.saw_tstamp = 0;

    switch (sk->sk_state) {
    case TCP_CLOSE:
        {
        printk(KERN_EMERG"Hello, tcp_close!\n");(case 代表的是一个事件状态,这里是tcp关闭;在此处添加语句时,要注意语法,复合语句的使用,C语言学过的哈)
        goto discard;
        }
         

    case TCP_LISTEN:
        printk(KERN_EMERG"Hello, tcp_listen!\n"); (tcp监听事件发生)

        if (th->ack)
        {
         printk(KERN_EMERG"Hello, ack symbol!\n");(这里的ack是确认字符(应答信号),表示发来的数据已确认接受无误,发送方收到ack信号后就会发送下一个数据)
            return 1;
        }

        if (th->rst)
        {
            goto discard;
        printk(KERN_EMERG"Hello, rst symbol!\n");(rst代表重置链接、复位连接,作用是一个报文段发往基准的连接出现错误时,tcp会发出一个复位报文段。)

        }

        if (th->syn) {
        printk(KERN_EMERG"Hello, syn symbol!\n");(syn是tcp/ip建立连接时使用的握手信号,这里表示发出握手信号。)
            if (th->fin)
                goto discard;
            if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
                return 1;



网络层:ip互联网协议,它可以旧爱那个应用程序的信息(比如电子邮件或网页传输的内容)转换为网络可以传输的数据包。
所要修改的文件路径:/usr/src/linux_3.16.6/net/ipv4
(1)
root@xiaoxiao-Lenovo-G470:/usr/src/linux-3.16.6/net/ipv4# gedit ip_input.c
(2)

static int ip_rcv_finish(struct sk_buff *skb)

{
    const struct iphdr *iph = ip_hdr(skb);
    struct rtable *rt;
        printk(KERN_ALERT"Hello, ip_rcv_finish!\n");(调用此函数,表明这里已经进入网络层)
    if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
        const struct net_protocol *ipprot;
        int protocol = iph->protocol;



数据链路层:在这里我们所追踪的是我们的网卡驱动调用的函数,首先我们要做的就是找我们系统中网卡驱动程序文件。
(1)查看网卡驱动:lspci |grep net
xiaoxiao@xiaoxiao-Lenovo-G470:~$ lspci |grep net
07:00.0 Ethernet controller: Qualcomm Atheros AR8152 v2.0 Fast Ethernet (rev c1)       这是我找到的我所用的驱动型号

(2)查找我的驱动文件,如上所示,我的驱动在这(Atheros)里面,到时候就去这个路径下面找。


root@xiaoxiao-Lenovo-G470:/usr/src/linux-3.16.6/drivers/net/ethernet/atheros/atl1c# ls

atl1c_ethtool.c  atl1c_hw.h    atl1c_main.c~  atl1c.o
atl1c_ethtool.o  atl1c_hw.o    atl1c_main.o   built-in.o
atl1c.h          atl1c.ko      atl1c.mod.c    Makefile
atl1c_hw.c       atl1c_main.c  atl1c.mod.o    modules.order


如上所示,我的驱动文件就是atl1c_main.c(这是我的有线网卡驱动)

(3)gedit atl1c_main.c
root@xiaoxiao-Lenovo-G470:/usr/src/linux-3.16.6/drivers/net/ethernet/atheros/atl1c# gedit atl1c_main.c
(4)进入atl1c_main.c中添加语句,当进入到数据链路层时便会打印输出我们所加的语句。


static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,

                      struct net_device *netdev)
{
    struct atl1c_adapter *adapter = netdev_priv(netdev);
    unsigned long flags;
    u16 tpd_req = 1;
    struct atl1c_tpd_desc *tpd;
    enum atl1c_trans_queue type = atl1c_trans_normal;
        printk(KERN_ALERT"Hello, atl1c_xmit_frame!\n");(这里是我们添加的语句,表示进入数据链路层)
    if (test_bit(__AT_DOWN, &adapter->flags)) {
        dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
    }




以上修改做完之后,记得保存,修改的时候要细心一点,不要修改错了。
接下来要做的就是编译内核以及安装。(下面的命令都是进入内核目录下,跟之前编译内核步骤差不多)
1、make
2、make modules
3、make modules_install
4、make install  
成功之后重启电脑,你就会看见你添加的语句。
注:切换到纯命令行界面下:alt+ctrl+f1或者f2都可以,进入图形界面是alt+ctrl+f7即可。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值