⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 118.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="116.htm">上一层</a>][<a href="119.htm">下一篇</a>]
<hr><p align="left"><small>发信人: ysqcn (岁月无声), 信区: UNP <br>

标  题: 对linux中socket(AF_INET,SOCK_RAW,protocol)的讨论 <br>

 发信站: UNIX编程 (2001年07月23日17:25:19 星期一), 站内信件 <br>

  <br>

对linux中socket(AF_INET,SOCK_RAW,protocol)中protocol的讨论 <br>

  <br>

一.透过源码看问题 <br>

  <br>

在创建原始套接字的时候inet_create: <br>

  <br>

 switch (sock->type) { <br>

>>>>对原始套接字 <br>

 case SOCK_RAW: <br>

>>>>是不是有超级用户权限 <br>

  if (!capable(CAP_NET_RAW)) <br>

   goto free_and_badperm; <br>

>>>>linux下protocol不能为零 <br>

  if (!protocol) <br>

   goto free_and_noproto; <br>

  prot = &raw_prot; <br>

  sk->reuse = 1; <br>

>>>>用num记录了这个protocol,后面会用到 <br>

  sk->num = protocol; <br>



  sock->ops = &inet_dgram_ops; <br>

>>>>如果为IPPROTO_RAW,则可以自己写IP头 <br>

  if (protocol == IPPROTO_RAW) <br>

   sk->protinfo.af_inet.hdrincl = 1; <br>

  break; <br>

 default: <br>

  goto free_and_badtype; <br>

 } <br>

  <br>

 。。。。。。。。。 <br>

  <br>

>>>>原始套接字前面num被赋值为protocol <br>

 if (sk->num) { <br>

  sk->sport = htons(sk->num); <br>

  /* Add to protocol hash chains. */ <br>

>>>>实际的函数是raw_v4_hash,创建的时候就将它链接到raw_v4_htable中, <br>

>>>>注意了,hash值的计算:哈希值=sk->num & 31 <br>

>>>>如果为IPPROTO_RAW=255,就链接到raw_v4_htable[31]中了 <br>

  sk->prot->hash(sk); <br>

 } <br>

  <br>

raw的bind和connetc与udp的一样,设置一下本地地址与对方地址,raw没有端口的概念。 <br>



  <br>

数据报投递上来的时候ip_local_deliver_finish(struct sk_buff *skb): <br>

  <br>

>>>>根据IP报文中的协议字段计算hash字,会不会出现这个协议字段是IPPROTO_RAW, <br>

>>>>即255的情况,我想除了自己发包外,TCP,UDP,ICMP,IGMP应该不会出现吧:( <br>

  int hash = protocol & (MAX_INET_PROTOS - 1); <br>

>>>>根据这个hash字到相应的raw_v4_htable中去找匹配的接受套接字 <br>

  struct sock *raw_sk = raw_v4_htable[hash]; <br>

>>>>如果有原始接受套接字,则调用raw_v4_input进行处理 <br>

  if(raw_sk != NULL) <br>

   raw_sk = raw_v4_input(skb, skb->nh.iph, hash); <br>

  <br>

  <br>

下面就是raw_v4_input的简略过程了: <br>

  <br>

struct sock *raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) <br>

{ <br>

 struct sock *sk; <br>

  <br>

 read_lock(&raw_v4_lock); <br>

>>>>还是根据这个hash值到对应的raw_v4_htable中查找了 <br>

 if ((sk = raw_v4_htable[hash]) == NULL) <br>



  goto out; <br>

 sk = __raw_v4_lookup(sk, iph->protocol, <br>

        iph->saddr, iph->daddr, <br>

        skb->dev->ifindex); <br>

 while(sk != NULL) { <br>

>>>>依次根据sk组成的链表来编历协议、地址匹配的原始套接字 <br>

  struct sock *sknext = __raw_v4_lookup(sk->next, iph->protocol, <br>

            iph->saddr, iph->daddr, <br>

            skb->dev->ifindex); <br>

  。。。。。。。。 <br>

  sk = sknext; <br>

  ............... <br>

 } <br>

 ........... <br>

} <br>

  <br>

二、结论 <br>

  <br>

根据上面代码,至少可以得到如下的结论(适用于linux下): <br>

  <br>

1.protocol决不能为零,否则创建套接字将失败 <br>

  <br>

  <br>

2.所以protocol可以为下面的标准的“官方值”: <br>

  IPPROTO_ICMP = 1,  /* Internet Control Message Protocol */ <br>

  IPPROTO_IGMP = 2,  /* Internet Group Management Protocol */ <br>

  IPPROTO_IPIP = 4,  /* IPIP tunnels (older KA9Q tunnels use 94) */ <br>

  IPPROTO_TCP = 6,  /* Transmission Control Protocol */ <br>

  IPPROTO_EGP = 8,  /* Exterior Gateway Protocol  */ <br>

  IPPROTO_PUP = 12,  /* PUP protocol    */ <br>

  IPPROTO_UDP = 17,  /* User Datagram Protocol  */ <br>

  IPPROTO_IDP = 22,  /* XNS IDP protocol   */ <br>

  IPPROTO_RSVP = 46,  /* RSVP protocol   */ <br>

  IPPROTO_GRE = 47,  /* Cisco GRE tunnels (rfc 1701,1702) */ <br>

  IPPROTO_IPV6  = 41,  /* IPv6-in-IPv4 tunnelling  */ <br>

  IPPROTO_PIM    = 103,  /* Protocol Independent Multicast */ <br>

  IPPROTO_ESP = 50,            /* Encapsulation Security Payload protocol */ <br>

  <br>

  IPPROTO_AH = 51,             /* Authentication Header protocol       */ <br>

  IPPROTO_COMP   = 108,                /* Compression Header protocol */ <br>

以及 <br>

  IPPROTO_RAW  = 255,  /* Raw IP packets   */ <br>

其中对IPPROTO_RAW来说,应该与其它区别开来 <br>

IPPROTO_IP是不行的,它的值本身就为0 <br>

  <br>



3.如果protocol为上面的除IPPROT_RAW外的其它值,则IP包会传递到相应协议匹配的原 <br>

始套接字,例如如果将protocol设为IPPROTO_TCP,就可以利用原始套接字接受TCP数据 <br>

报,而不会接受到其他协议类型的数据报。 <br>

  <br>

4.最可怜的是protocol为IPPROTO_RAW的原始套接字,辛苦一场,结果标准的官方的数据 <br>

报一个也接受不到,除非发送方构造了一个协议字段255的IP报文。 <br>

  <br>

5.你可以自定义除那些标准的官方协议字段外的其它值,然后通信的双方都采用这个协 <br>

议字段,这样就可以互相收发数据了。 <br>

  <br>

6.强调一下,linux下不能用原始套接字截获所有的IP报文。 <br>

  <br>

三、测试证明 <br>

  <br>

测试程序太烂了,这里就不给出了。测试程序验证了上面1-5的结论是正确的:) <br>

  <br>

-- <br>

一万年太久,只争朝夕... <br>

※ 修改:·ysqcn 於 07月24日09:00:24 修改本文·[FROM: 202.114.2.11] <br>

※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.2.11] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="116.htm">上一层</a>][<a href="119.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -