您的位置:首页 > 理论基础 > 计算机网络

追踪TCP_IP实现过程

2014-11-03 23:54 169 查看
首先,我们要实现追踪,需要用到一个函数,就是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即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: