荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: ykwch.bbs@bbs.cqupt.edu.cn (心蓝--雨下), 信区: Linux
标  题: packet_rcv
发信站: 幽幽黄桷兰 (Sat Apr  5 15:29:38 2003)
转信站: SZU!news.tiaozhan.com!news.zixia.net!news.happynet.org!CQUPT

packet_rcv
    我们已经知道了,如果使用socket(AF_SOCKET, ..)产生一个PACKET SOCKET的话,de
v_add_pack加入的函数是packet_rcv,下面是这个在net/packet/af_packet.c里面的函数
:
static int packet_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt)
{
struct sock *sk;
struct sockaddr_ll *sll = (struct sockaddr_ll*)skb->cb;
sk = (struct sock *) pt->data;
//我们在packet_create中令data = sk了,remember?
if (skb->pkt_type == PACKET_LOOPBACK) {
kfree_skb(skb);
return 0;
}
skb->dev = dev;
sll->sll_family = AF_PACKET;
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_pkttype = skb->pkt_type;
sll->sll_ifindex = dev->ifindex;
sll->sll_halen = 0;
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
if (dev->hard_header)
if (sk->type != SOCK_DGRAM)
skb_push(skb, skb->data - skb->mac.raw);
else if (skb->pkt_type == PACKET_OUTGOING)
skb_pull(skb, skb->nh.raw - skb->data);
if (sock_queue_rcv_skb(sk,skb)<0)
{
kfree_skb(skb);
return 0;
}
return(0);
}
    pkt_type属性是什么地方确定的?
    这里还有几个函数要说明:
skb_pull在include/linux/skbuff.h中间:
extern __inline__ char *__skb_pull(struct sk_buff *skb,
unsigned int len)
{
skb->len-=len;
return skb->data+=len;
}
extern __inline__ unsigned char * skb_pull(struct sk_buff *skb,
unsigned int len)
{
if (len > skb->len)
return NULL;
return __skb_pull(skb,len);
}
    不过是把头部的数据空出来,相应调整数据头部data的地址和长度.
    同样skb_push在include/linux/skbuff.h中间:
extern __inline__ unsigned char *__skb_push(struct sk_buff *skb,
unsigned int len)
{
skb->data-=len;
skb->len+=len;
return skb->data;
}
extern __inline__ unsigned char *skb_push(struct sk_buff *skb,
unsigned int len)
{
skb->data-=len;
skb->len+=len;
if(skb->data head)
{
__label__ here;
skb_under_panic(skb, len, &&here);
here: ;
}
return skb->data;
}
    这个调整使数据长度加长,和skb_pull相反,不过skb_push显然更加安全一点.
    在上面的程序中间,如果设备有一个明确的link_level_header,就考虑要不要调整数
据长度和地址,如果sk->type不是SOCK_DGRAM的话,说明程序对整个数据包包括ll地址都
感兴趣.这样需要加长数据段使得数据包含ll头部.不然如果数据是向外走的,则需要把数
据裁减到只包含从网络层数据包头开始的地方.所以是从nh.raw剪掉data,这就是差值.(
nh=network header)
    经过了这些处理以后,现在的skb已经是可以提交的了,这样就调用sock_queue_rcv_
skb函数将这个skb加入到相应socket的接收缓冲区中去.

--
蒹葭苍苍白露为霜所谓伊人在水一方溯洄从之道阻且长
溯游从之宛在水中央
蒹葭萋萋白露未晞所谓伊人在水之湄溯洄从之道阻且跻
溯游从之宛在水中坻
蒹葭采采白露未已所谓伊人在水之涘溯洄从之道阻且右
溯游从之宛在水中沚
※ 来源:·幽幽黄桷兰 bbs.cqupt.edu.cn·[FROM: BlueCrystal]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店