應用程序使用RAW socket從內核中抓取指定協議的數據包流程分析;

應用程序使用RAW socket從內核中抓取指定協議的數據包流程分析;

應用程序:

int init_sockets()

{

    struct ifreq ifr;

    struct sockaddr_ll addr;

    struct sockaddr_in addr2;

 

    drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));//802.1x協議(0x888e)

    if (drv->sock < 0) {

        perror("socket[PF_PACKET,SOCK_RAW]");

        return -1;

    }

 

    os_memset(&ifr, 0, sizeof(ifr));

    os_strlcpy(ifr.ifr_name, “eth0”, sizeof(ifr.ifr_name));//指定接口eth0

    if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {//獲取eth0接口的index

        perror("ioctl(SIOCGIFINDEX)");

        return -1;

    }

 

    os_memset(&addr, 0, sizeof(addr));

    addr.sll_family = AF_PACKET;

    addr.sll_ifindex = ifr.ifr_ifindex;

    

    if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {//綁定sock

        perror("bind");

        return -1;

}

...

    return 0;

}

 

void read(int sock...)

{

    int len;

    unsigned char buf[3000];

len = recv(sock, buf, sizeof(buf), 0);

...

}

int send(int sock, char *buf, int bufsize)

{

return send(sock, buf, bufsize, 0);

...

}

 

 

內核協議:(net/packet/af_packet.c)

函數

說明

static int packet_create(struct net *net, struct socket *sock, int protocol)

Create a packet of type SOCK_PACKET.

static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)

Bind the sock to the protocol

static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)

Attach a packet hook

void dev_add_pack(struct packet_type *pt)

Add a protocol handler to the networking stack

static int packet_ioctl(struct socket *sock, unsigned int cmd,

                                          unsigned long arg)

ioctl

static int packet_notifier(struct notifier_block *this, unsigned long msg, void *data)

setup a packet notifier

static int packet_getsockopt(struct socket *sock, int level, int optname,

                                               char __user *optval, int __user *optlen)

getsocket()

static int

packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)

setsocket()

static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)

join in multicast group

static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)

leave multicast group

static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,

                                            struct msghdr *msg, size_t len, int flags)

Pull a packet from our receive queue and hand it to the user. If necessary we block.

static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,

                            struct msghdr *msg, size_t len)

send msg to

static int packet_release(struct socket *sock)

Close a PACKET socket. This is fairly simple. We immediately go to 'closed' state and remove our protocol entry in the device list.

 

用戶空間

內核空間

說明

socket()

packet_create()

創建特定類型socket

ioctl()

packet_ioctl()

 

bind()

packet_bind()

綁定socket

recv()

packet_recvmsg()

 

send()

packet_sendmsg()

 

setsocket()

packet_setsockopt()

 

getsocket()

packet_getsockopt()

 

注意:如果沒有註冊對802.1x協議包的監聽操作,則802.1x協議包在netif_receive_skb()函數中將在最後被丟棄。

         if (pt_prev) {

//監聽並處理802.1x協議包

                   ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);

         } else {

//如果沒有監聽操作,802.1x協議包將在這裏丟棄

                   kfree_skb(skb);

                   /* Jamal, now you will not able to escape explaining

                    * me how you were going to use this. :-)

                    */

                   ret = NET_RX_DROP;

         }

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章