net/socket.c
点击(此处)折叠或打开
- SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
- {
- ......
- retval = sock_create(family, type, protocol, &sock);
- ......
- }
点击(此处)折叠或打开
- 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)
- {
- ......
- pf = rcu_dereference(net_families[family]);
- ......
- err = pf->create(net, sock, protocol, kern);
- ......
- }
点击(此处)折叠或打开
- static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
- int sock_register(const struct net_proto_family *ops)
- {
- ......
- if (rcu_dereference_protected(net_families[ops->family],
- lockdep_is_held(&net_family_lock)))
- err = -EEXIST;
- else {
- rcu_assign_pointer(net_families[ops->family], ops);
- err = 0;
- }
- ......
- }
net/packet/af_packet.c
点击(此处)折叠或打开
- static const struct net_proto_family packet_family_ops = {
- .family = PF_PACKET,
- .create = packet_create,
- .owner = THIS_MODULE,
- };
- static int __init packet_init(void)
- {
- ......
- sock_register(&packet_family_ops);
- ......
- }
- module_init(packet_init);
点击(此处)折叠或打开
- 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 */
- ......
- sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto);
- ......
- sock->ops = &packet_ops;
- ......
- po = pkt_sk(sk);
sk->sk_family = PF_PACKET; - po->num = proto;
- ......
- po->prot_hook.func = packet_rcv;
- ......
- po->prot_hook.af_packet_priv = sk;
- if (proto) {
- po->prot_hook.type = proto;
- register_prot_hook(sk);
- }
- ......
- }
AF_PACKET套接字的功能来源于prot_hook,其本身是struct packet_type类型:
1:type成员设定为了socket()传递的参数(这里是ETH_P_ALL)
2:过滤得到的包的处理函数保存于func成员,这里被设定为 packet_rcv()
3:dev成员用于对net_device的过滤,可以在bind()中指定
点击(此处)折叠或打开
- static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- {
- ......
- if (sll->sll_ifindex) {
- err = -ENODEV;
- dev = dev_get_by_index(sock_net(sk), sll->sll_ifindex);
- if (dev == NULL)
- goto out;
- }
- err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num);
- ......
- }
点击(此处)折叠或打开
- static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)
- {
- struct packet_sock *po = pkt_sk(sk);
- ......
- po->prot_hook.dev = dev;
- po->ifindex = dev ? dev->ifindex : 0;
- ......
- if (!dev || (dev->flags & IFF_UP)) {
- register_prot_hook(sk);
- ......
- }
可见在bind()中若指定了绑定的net_device同样会触发prot_hook的注册动作。
点击(此处)折叠或打开
- static void register_prot_hook(struct sock *sk)
- {
- struct packet_sock *po = pkt_sk(sk);
- if (!po->running) {
- if (po->fanout)
- __fanout_link(sk, po);
- else
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
- }
- }
点击(此处)折叠或打开
- 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);
- }
点击(此处)折叠或打开
- static struct list_head ptype_all __read_mostly; /* Taps */
- static inline struct list_head *ptype_head(const struct packet_type *pt)
- {
- if (pt->type == htons(ETH_P_ALL))
- return &ptype_all;
- else
- return &ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
- }
历尽千辛万苦,终于知道AF_PACKET套接字把自己的prot_hook挂到了ptype_all链表上或ptype_base链表上。至于prot_hook怎么发挥作用进行监听,请听下回分解!