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

📄 icmp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 2 页
字号:
  1 /*
  2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
  3  *              operating system.  INET is implemented using the  BSD Socket
  4  *              interface as the means of communication with the user level.
  5  *
  6  *              Internet Control Message Protocol (ICMP)
  7  *
  8  * Version:     @(#)icmp.c      1.0.11  06/02/93
  9  *
 10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
 11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 12  *              Mark Evans, <evansmp@uhura.aston.ac.uk>
 13  *
 14  * Fixes:       
 15  *              Alan Cox        :       Generic queue usage.
 16  *              Gerhard Koerting:       ICMP addressing corrected
 17  *              Alan Cox        :       Use tos/ttl settings
 18  *
 19  *
 20  *              This program is free software; you can redistribute it and/or
 21  *              modify it under the terms of the GNU General Public License
 22  *              as published by the Free Software Foundation; either version
 23  *              2 of the License, or (at your option) any later version.
 24  */
 25 #include <linux/types.h>
 26 #include <linux/sched.h>
 27 #include <linux/kernel.h>
 28 #include <linux/fcntl.h>
 29 #include <linux/socket.h>
 30 #include <linux/in.h>
 31 #include "inet.h"
 32 #include "dev.h"
 33 #include "ip.h"
 34 #include "route.h"
 35 #include "protocol.h"
 36 #include "icmp.h"
 37 #include "tcp.h"
 38 #include "skbuff.h"
 39 #include "sock.h"
 40 #include <linux/errno.h>
 41 #include <linux/timer.h>
 42 #include <asm/system.h>
 43 #include <asm/segment.h>
 44 
 45 
 46 #define min(a,b)        ((a)<(b)?(a):(b))
 47 
 48 
 49 /* An array of errno for error messages from dest unreach. */
 50 struct icmp_err icmp_err_convert[] = {
 51   { ENETUNREACH,        1 },    /*      ICMP_NET_UNREACH        */
 52   { EHOSTUNREACH,       1 },    /*      ICMP_HOST_UNREACH       */
 53   { ENOPROTOOPT,        1 },    /*      ICMP_PROT_UNREACH       */
 54   { ECONNREFUSED,       1 },    /*      ICMP_PORT_UNREACH       */
 55   { EOPNOTSUPP,         0 },    /*      ICMP_FRAG_NEEDED        */
 56   { EOPNOTSUPP,         0 },    /*      ICMP_SR_FAILED          */
 57   { ENETUNREACH,        1 },    /*      ICMP_NET_UNKNOWN        */
 58   { EHOSTDOWN,          1 },    /*      ICMP_HOST_UNKNOWN       */
 59   { ENONET,             1 },    /*      ICMP_HOST_ISOLATED      */
 60   { ENETUNREACH,        1 },    /*      ICMP_NET_ANO            */
 61   { EHOSTUNREACH,       1 },    /*      ICMP_HOST_ANO           */
 62   { EOPNOTSUPP,         0 },    /*      ICMP_NET_UNR_TOS        */
 63   { EOPNOTSUPP,         0 }     /*      ICMP_HOST_UNR_TOS       */
 64 };
 65 
 66 
 67 /* Display the contents of an ICMP header. */
 68 static void
 69 print_icmp(struct icmphdr *icmph)
 70 {
 71   if (inet_debug != DBG_ICMP) return;
 72 
 73   printk("ICMP: type = %d, code = %d, checksum = %X\n",
 74                         icmph->type, icmph->code, icmph->checksum);
 75   printk("      gateway = %s\n", in_ntoa(icmph->un.gateway));
 76 }
 77 
 78 
 79 /* Send an ICMP message. */
 80 void
 81 icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
 82 {
 83   struct sk_buff *skb;
 84   struct iphdr *iph;
 85   int offset;
 86   struct icmphdr *icmph;
 87   int len;
 88 
 89   DPRINTF((DBG_ICMP, "icmp_send(skb_in = %X, type = %d, code = %d, dev=%X)\n",
 90                                                 skb_in, type, code, dev));
 91 
 92   /* Get some memory for the reply. */
 93   len = sizeof(struct sk_buff) + dev->hard_header_len +
 94         sizeof(struct iphdr) + sizeof(struct icmphdr) +
 95         sizeof(struct iphdr) + 8;       /* amount of header to return */
 96            
 97   skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
 98   if (skb == NULL) 
 99         return;
100 
101   skb->sk = NULL;
102   skb->mem_addr = skb;
103   skb->mem_len = len;
104   len -= sizeof(struct sk_buff);
105 
106   /* Find the IP header. */
107   iph = (struct iphdr *) (skb_in->data + dev->hard_header_len);
108 
109   /* Build Layer 2-3 headers for message back to source. */
110   offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
111                            &dev, IPPROTO_ICMP, NULL, len, skb_in->ip_hdr->tos,255);
112   if (offset < 0) {
113         skb->sk = NULL;
114         kfree_skb(skb, FREE_READ);
115         return;
116   }
117 
118   /* Re-adjust length according to actual IP header size. */
119   skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
120   icmph = (struct icmphdr *) (skb->data + offset);
121   icmph->type = type;
122   icmph->code = code;
123   icmph->checksum = 0;
124   icmph->un.gateway = 0;
125   memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
126 
127   icmph->checksum = ip_compute_csum((unsigned char *)icmph,
128                          sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
129 
130   DPRINTF((DBG_ICMP, ">>\n"));
131   print_icmp(icmph);
132 
133   /* Send it and free it. */
134   ip_queue_xmit(NULL, dev, skb, 1);
135 }
136 
137 
138 /* Handle ICMP_UNREACH and ICMP_QUENCH. */
139 static void
140 icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
141 {
142   struct inet_protocol *ipprot;
143   struct iphdr *iph;
144   unsigned char hash;
145   int err;
146 
147   err = (icmph->type << 8) | icmph->code;
148   iph = (struct iphdr *) (icmph + 1);
149   switch(icmph->code & 7) {
150         case ICMP_NET_UNREACH:
151                 DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
152                                                         in_ntoa(iph->daddr)));
153                 break;
154         case ICMP_HOST_UNREACH:
155                 DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n",
156                                                 in_ntoa(iph->daddr)));
157                 break;
158         case ICMP_PROT_UNREACH:
159                 printk("ICMP: %s:%d: protocol unreachable.\n",
160                         in_ntoa(iph->daddr), ntohs(iph->protocol));
161                 break;
162         case ICMP_PORT_UNREACH:
163                 DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n",
164                         in_ntoa(iph->daddr), -1 /* FIXME: ntohs(iph->port) */));
165                 break;
166         case ICMP_FRAG_NEEDED:
167                 printk("ICMP: %s: fragmentation needed and DF set.\n",
168                                                         in_ntoa(iph->daddr));
169                 break;
170         case ICMP_SR_FAILED:
171                 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
172                 break;
173         default:
174                 DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n",
175                                 (icmph->code & 7), in_ntoa(iph->daddr)));
176                 break;
177   }
178 
179   /* Get the protocol(s). */
180   hash = iph->protocol & (MAX_INET_PROTOS -1);
181 
182   /* This can change while we are doing it. */
183   ipprot = (struct inet_protocol *) inet_protos[hash];
184   while(ipprot != NULL) {
185         struct inet_protocol *nextip;
186 
187         nextip = (struct inet_protocol *) ipprot->next;
188 
189         /* Pass it off to everyone who wants it. */
190         if (iph->protocol == ipprot->protocol && ipprot->err_handler) {
191                 ipprot->err_handler(err, (unsigned char *)(icmph + 1),
192                                     iph->daddr, iph->saddr, ipprot);
193         }
194 
195         ipprot = nextip;
196   }
197   skb->sk = NULL;
198   kfree_skb(skb, FREE_READ);
199 }
200 
201 
202 /* Handle ICMP_REDIRECT. */
203 static void
204 icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
205 {
206   struct iphdr *iph;
207   unsigned long ip;
208 
209   iph = (struct iphdr *) (icmph + 1);
210   ip = iph->daddr;
211   switch(icmph->code & 7) {
212         case ICMP_REDIR_NET:
213 #ifdef not_a_good_idea
214                 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
215                         ip, 0, icmph->un.gateway, dev);
216                 break;
217 #endif
218         case ICMP_REDIR_HOST:
219                 rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
220                         ip, 0, icmph->un.gateway, dev);
221                 break;
222         case ICMP_REDIR_NETTOS:
223         case ICMP_REDIR_HOSTTOS:

⌨️ 快捷键说明

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