网站开发用j,上海网站seo牛巨微,室内设计软件自学,国际军事新闻最新消息头条一、 lipcap回调注册
在libpcap中#xff0c;最重要的就是打开接口#xff0c;其中关键函数为pcap_activate。这里只关注Linux平台。 只分析通用平台。
pcap_t *
pcap_create(const char *device, char *errbuf)
{
...
p pcap_create_interface(device_str, errbuf);
...
…一、 lipcap回调注册
在libpcap中最重要的就是打开接口其中关键函数为pcap_activate。这里只关注Linux平台。 只分析通用平台。
pcap_t *
pcap_create(const char *device, char *errbuf)
{
...
p pcap_create_interface(device_str, errbuf);
...
}// pcap-linux.c
pcap_t *
pcap_create_interface(const char *device, char *ebuf)
{pcap_t *handle;handle pcap_create_common(ebuf, sizeof (struct pcap_linux));if (handle NULL)return NULL;handle-activate_op pcap_activate_linux;...二、libpcap激活接口 - step1
int
pcap_activate(pcap_t *p)
{
...
status p-activate_op(p);
...
}static int
pcap_activate_linux(pcap_t *handle)
{...handle-inject_op pcap_inject_linux;handle-setfilter_op pcap_setfilter_linux;handle-setdirection_op pcap_setdirection_linux;handle-set_datalink_op pcap_set_datalink_linux;handle-getnonblock_op pcap_getnonblock_fd;handle-setnonblock_op pcap_setnonblock_fd;handle-cleanup_op pcap_cleanup_linux;handle-read_op pcap_read_linux;handle-stats_op pcap_stats_linux;...ret activate_new(handle);static int
activate_new(pcap_t *handle)
{
.../** Open a socket with protocol family packet. If the* any device was specified, we open a SOCK_DGRAM* socket for the cooked interface, otherwise we first* try a SOCK_RAW socket for the raw interface.*/sock_fd is_any_device ?socket(PF_PACKET, SOCK_DGRAM, protocol) :socket(PF_PACKET, SOCK_RAW, protocol);只考虑抓取某个特定网卡的流量因此 socket_fd socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
三、进入kernel 创建socket
int sock_create(int family, int type, int protocol, struct socket **res)
{return __sock_create(current-nsproxy-net_ns, family, type, protocol, res, 0);
}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;.../** Allocate the socket and allow the family to set things up. if* the protocol is 0, the family is instructed to select an appropriate* default.*/sock sock_alloc();...sock-type type;...pf rcu_dereference(net_families[family]);
...err pf-create(net, sock, protocol, kern);
...*res sock;return 0;
...
}首先根据family获取对应的协议族处理函数然后通过回调create函数进行实际的创建 这里create的回调为packet_create
static int packet_create(struct net *net, struct socket *sock, int protocol,int kern)
{struct sock *sk;struct packet_sock *po;__be16 proto (__force __be16)protocol; /* weird, but documented */int err;if (!capable(CAP_NET_RAW))return -EPERM;if (sock-type ! SOCK_DGRAM sock-type ! SOCK_RAW sock-type ! SOCK_PACKET)return -ESOCKTNOSUPPORT;sock-state SS_UNCONNECTED;err -ENOBUFS;sk sk_alloc(net, PF_PACKET, GFP_KERNEL, packet_proto);if (sk NULL)goto out;sock-ops packet_ops;if (sock-type SOCK_PACKET)sock-ops packet_ops_spkt;sock_init_data(sock, sk);po pkt_sk(sk);sk-sk_family PF_PACKET;po-num proto;sk-sk_destruct packet_sock_destruct;sk_refcnt_debug_inc(sk);/** Attach a protocol block*/spin_lock_init(po-bind_lock);mutex_init(po-pg_vec_lock);po-prot_hook.func packet_rcv;if (sock-type SOCK_PACKET)po-prot_hook.func packet_rcv_spkt;po-prot_hook.af_packet_priv sk;if (proto) {po-prot_hook.type proto;register_prot_hook(sk);}spin_lock_bh(net-packet.sklist_lock);sk_add_node_rcu(sk, net-packet.sklist);sock_prot_inuse_add(net, packet_proto, 1);spin_unlock_bh(net-packet.sklist_lock);return 0;
out:return err;
}这里关键是设置了po-prot_hook.func packet_rcv;, 后续处理数据就是这个入口 以及register_prot_hook将回调注册到ptype_all链表中
static void register_prot_hook(struct sock *sk)
{struct packet_sock *po pkt_sk(sk);if (!po-running) {...dev_add_pack(po-prot_hook);...po-running 1;}
}// net/core/dev.c
static inline struct list_head *ptype_head(const struct packet_type *pt)
{if (pt-type htons(ETH_P_ALL))return ptype_all;elsereturn ptype_base[ntohs(pt-type) PTYPE_HASH_MASK];
}
void dev_add_pack(struct packet_type *pt)
{struct list_head *head ptype_head(pt);spin_lock(ptype_lock);list_add_rcu(pt-list, head);spin_unlock(ptype_lock);
}