AF_PACKET套接字解密 --- 01
2013-03-13 18:24
260 查看
AF_PACKET套接字解密 --- 01 2012-05-23
22:08:23
分类: LINUX
使用socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)创建的套接字到底为何于众不同,今日追踪了一下。使用Linux 3.2.5版内核
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;
}
}
net/core/dev.c
点击(此处)折叠或打开
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怎么发挥作用进行监听,请听下回分解!
22:08:23
分类: LINUX
使用socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)创建的套接字到底为何于众不同,今日追踪了一下。使用Linux 3.2.5版内核
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;
}
}
net/core/dev.c
点击(此处)折叠或打开
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怎么发挥作用进行监听,请听下回分解!
相关文章推荐
- AF_PACKET套接字解密 http://write.blog.csdn.net/postedit
- AF_PACKET套接字解密 一
- AF_PACKET套接字解密
- AF_PACKET套接字解密 二
- AF_PACKET套接字解密 --- 02
- AF_INET与套接字
- 封包加密解密-01
- 【网络编程学习笔记01】Socket套接字编程(TCP/IP)
- PEInfo编程思路讲解01 - 工具篇01|解密系列
- OD使用教程 - 调试篇01|解密系列
- 链路层套接字PF_PACKET简介
- PEInfo编程思路讲解01 - 工具篇01|解密系列
- OD使用教程 - 调试篇01|解密系列
- java加密解密--密钥库,密钥格式-01
- snort 中的afpacket
- 使用AF_PACKET抓无线数据包
- python核心编程学习笔记-2016-08-21-01-客户端/服务器架构、套接字
- 最新整理手机解密大全01