root/net/ipv4/icmp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. icmp_out_count
  2. icmp_glue_bits
  3. icmp_build_xmit
  4. icmp_send
  5. icmp_unreach
  6. icmp_redirect
  7. icmp_echo
  8. icmp_timestamp
  9. icmp_address
  10. icmp_discard
  11. icmp_rcv
  12. icmp_init

   1 /*
   2  *      NET3:   Implementation of the ICMP protocol layer. 
   3  *      
   4  *              Alan Cox, <alan@cymru.net>
   5  *
   6  *      This program is free software; you can redistribute it and/or
   7  *      modify it under the terms of the GNU General Public License
   8  *      as published by the Free Software Foundation; either version
   9  *      2 of the License, or (at your option) any later version.
  10  *
  11  *      Some of the function names and the icmp unreach table for this
  12  *      module were derived from [icmp.c 1.0.11 06/02/93] by
  13  *      Ross Biro, Fred N. van Kempen, Mark Evans, Alan Cox, Gerhard Koerting.
  14  *      Other than that this module is a complete rewrite.
  15  *
  16  *      Fixes:
  17  *              Mike Shaver     :       RFC1122 checks.
  18  *
  19  *
  20  *
  21  * RFC1122 Status: (boy, are there a lot of rules for ICMP)
  22  *  3.2.2 (Generic ICMP stuff)
  23  *   MUST discard messages of unknown type. (OK)
  24  *   MUST copy at least the first 8 bytes from the offending packet
  25  *     when sending ICMP errors. (OK)
  26  *   MUST pass received ICMP errors up to protocol level. (OK)
  27  *   SHOULD send ICMP errors with TOS == 0. (OK)
  28  *   MUST NOT send ICMP errors in reply to:
  29  *     ICMP errors (OK)
  30  *     Broadcast/multicast datagrams (OK)
  31  *     MAC broadcasts (OK)
  32  *     Non-initial fragments (OK)
  33  *     Datagram with a source address that isn't a single host. (OK)
  34  *  3.2.2.1 (Destination Unreachable)
  35  *   All the rules govern the IP layer, and are dealt with in ip.c, not here.
  36  *  3.2.2.2 (Redirect)
  37  *   Host SHOULD NOT send ICMP_REDIRECTs.  (OK)
  38  *   MUST update routing table in response to host or network redirects. 
  39  *     (host OK, network NOT YET) [Intentionally -- AC]
  40  *   SHOULD drop redirects if they're not from directly connected gateway
  41  *     (OK -- we drop it if it's not from our old gateway, which is close
  42  *      enough)
  43  * 3.2.2.3 (Source Quench)
  44  *   MUST pass incoming SOURCE_QUENCHs to transport layer (OK)
  45  *   Other requirements are dealt with at the transport layer.
  46  * 3.2.2.4 (Time Exceeded)
  47  *   MUST pass TIME_EXCEEDED to transport layer (OK)
  48  *   Other requirements dealt with at IP (generating TIME_EXCEEDED).
  49  * 3.2.2.5 (Parameter Problem)
  50  *   SHOULD generate these, but it doesn't say for what.  So we're OK. =)
  51  *   MUST pass received PARAMPROBLEM to transport layer (NOT YET)
  52  *      [Solaris 2.X seems to assert EPROTO when this occurs] -- AC
  53  * 3.2.2.6 (Echo Request/Reply)
  54  *   MUST reply to ECHO_REQUEST, and give app to do ECHO stuff (OK, OK)
  55  *   MAY discard broadcast ECHO_REQUESTs. (We don't, but that's OK.)
  56  *   MUST reply using same source address as the request was sent to.
  57  *     We're OK for unicast ECHOs, and it doesn't say anything about
  58  *     how to handle broadcast ones, since it's optional.
  59  *   MUST copy data from REQUEST to REPLY (OK)
  60  *     unless it would require illegal fragmentation (N/A)
  61  *   MUST pass REPLYs to transport/user layer (OK)
  62  *   MUST use any provided source route (reversed) for REPLY. (NOT YET)
  63  * 3.2.2.7 (Information Request/Reply)
  64  *   MUST NOT implement this. (I guess that means silently discard...?) (OK)
  65  * 3.2.2.8 (Timestamp Request/Reply)
  66  *   MAY implement (OK)
  67  *   SHOULD be in-kernel for "minimum variability" (OK)
  68  *   MAY discard broadcast REQUESTs.  (OK, but see source for inconsistency)
  69  *   MUST reply using same source address as the request was sent to. (OK)
  70  *   MUST reverse source route, as per ECHO (NOT YET)
  71  *   MUST pass REPLYs to transport/user layer (requires RAW, just like ECHO) (OK)
  72  *   MUST update clock for timestamp at least 15 times/sec (OK)
  73  *   MUST be "correct within a few minutes" (OK)
  74  * 3.2.2.9 (Address Mask Request/Reply)
  75  *   MAY implement (OK)
  76  *   MUST send a broadcast REQUEST if using this system to set netmask
  77  *     (OK... we don't use it)
  78  *   MUST discard received REPLYs if not using this system (OK)
  79  *   MUST NOT send replies unless specifically made agent for this sort
  80  *     of thing. (OK)
  81  */
  82 
  83 #include <linux/types.h>
  84 #include <linux/sched.h>
  85 #include <linux/kernel.h>
  86 #include <linux/fcntl.h>
  87 #include <linux/socket.h>
  88 #include <linux/in.h>
  89 #include <linux/inet.h>
  90 #include <linux/netdevice.h>
  91 #include <linux/string.h>
  92 #include <net/snmp.h>
  93 #include <net/ip.h>
  94 #include <net/route.h>
  95 #include <net/protocol.h>
  96 #include <net/icmp.h>
  97 #include <net/tcp.h>
  98 #include <net/snmp.h>
  99 #include <linux/skbuff.h>
 100 #include <net/sock.h>
 101 #include <linux/errno.h>
 102 #include <linux/timer.h>
 103 #include <asm/system.h>
 104 #include <asm/segment.h>
 105 #include <net/checksum.h>
 106 
 107 #define min(a,b)        ((a)<(b)?(a):(b))
 108 
 109 /*
 110  *      Statistics
 111  */
 112  
 113 struct icmp_mib icmp_statistics;
 114 
 115 /* An array of errno for error messages from dest unreach. */
 116 /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errrs'. */
 117 
 118 struct icmp_err icmp_err_convert[] = {
 119   { ENETUNREACH,        0 },    /*      ICMP_NET_UNREACH        */
 120   { EHOSTUNREACH,       0 },    /*      ICMP_HOST_UNREACH       */
 121   { ENOPROTOOPT,        1 },    /*      ICMP_PROT_UNREACH       */
 122   { ECONNREFUSED,       1 },    /*      ICMP_PORT_UNREACH       */
 123   { EOPNOTSUPP,         0 },    /*      ICMP_FRAG_NEEDED        */
 124   { EOPNOTSUPP,         0 },    /*      ICMP_SR_FAILED          */
 125   { ENETUNREACH,        1 },    /*      ICMP_NET_UNKNOWN        */
 126   { EHOSTDOWN,          1 },    /*      ICMP_HOST_UNKNOWN       */
 127   { ENONET,             1 },    /*      ICMP_HOST_ISOLATED      */
 128   { ENETUNREACH,        1 },    /*      ICMP_NET_ANO            */
 129   { EHOSTUNREACH,       1 },    /*      ICMP_HOST_ANO           */
 130   { EOPNOTSUPP,         0 },    /*      ICMP_NET_UNR_TOS        */
 131   { EOPNOTSUPP,         0 }     /*      ICMP_HOST_UNR_TOS       */
 132 };
 133 
 134 /*
 135  *      A spare long used to speed up statistics udpating
 136  */
 137  
 138 unsigned long dummy;
 139 
 140 /*
 141  *      ICMP control array. This specifies what to do with each ICMP.
 142  */
 143  
 144 struct icmp_control
 145 {
 146         unsigned long *output;          /* Address to increment on output */
 147         unsigned long *input;           /* Address to increment on input */
 148         void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len);
 149         unsigned long error;            /* This ICMP is classed as an error message */  
 150 };
 151 
 152 static struct icmp_control icmp_pointers[19];
 153 
 154 /*
 155  *      Build xmit assembly blocks
 156  */
 157 
 158 struct icmp_bxm
 159 {
 160         void *data_ptr;
 161         int data_len;
 162         struct icmphdr icmph;
 163         unsigned long csum;
 164         struct options replyopts;
 165         unsigned char  optbuf[40];
 166 };
 167 
 168 /*
 169  *      The ICMP socket. This is the most convenient way to flow control
 170  *      our ICMP output as well as maintain a clean interface throughout
 171  *      all layers. All Socketless IP sends will soon be gone.
 172  */
 173         
 174 struct socket icmp_socket;
 175 
 176 /*
 177  *      Send an ICMP frame.
 178  */
 179  
 180 
 181 /*
 182  *      Maintain the counters used in the SNMP statistics for outgoing ICMP
 183  */
 184  
 185 static void icmp_out_count(int type)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         if(type>18)
 188                 return;
 189         (*icmp_pointers[type].output)++;
 190         icmp_statistics.IcmpOutMsgs++;
 191 }
 192  
 193 /*
 194  *      Checksum each fragment, and on the first include the headers and final checksum.
 195  */
 196  
 197 static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199         struct icmp_bxm *icmp_param=(struct icmp_bxm *)p;
 200         struct icmphdr *icmph;
 201         if(offset)
 202                 icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr), 
 203                                 to, fraglen,icmp_param->csum);
 204         else
 205         {
 206 #ifdef CSUM_FOLD_WORKS
 207                 /*
 208                  *      Need this fixed to make multifragment ICMP's work again.
 209                  */
 210                 icmp_param->csum=csum_partial_copy((void *)&icmp_param->icmph, to, sizeof(struct icmphdr),
 211                         icmp_param->csum);
 212                 icmp_param->csum=csum_partial_copy(icmp_param->data_ptr, to+sizeof(struct icmphdr),
 213                                 fraglen-sizeof(struct icmphdr), icmp_param->csum);
 214                 icmph=(struct icmphdr *)to;
 215                 icmph->checksum = csum_fold(icmp_param->csum);
 216 #else
 217                 memcpy(to, &icmp_param->icmph, sizeof(struct icmphdr));
 218                 memcpy(to+sizeof(struct icmphdr), icmp_param->data_ptr, fraglen-sizeof(struct icmphdr));
 219                 icmph=(struct icmphdr *)to;
 220                 icmph->checksum=ip_compute_csum(to, fraglen);
 221 #endif
 222                                 
 223         }
 224 }
 225  
 226 /*
 227  *      Driving logic for building and sending ICMP messages.
 228  */
 229 
 230 static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 daddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         struct sock *sk=icmp_socket.data;
 233         icmp_param->icmph.checksum=0;
 234         icmp_out_count(icmp_param->icmph.type);
 235         ip_build_xmit(sk, icmp_glue_bits, icmp_param, 
 236                 icmp_param->data_len+sizeof(struct icmphdr),
 237                 daddr, saddr, &icmp_param->replyopts, 0, IPPROTO_ICMP);
 238 }
 239 
 240 
 241 /*
 242  *      Send an ICMP message in response to a situation
 243  *
 244  *      RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we don't).
 245  *                      MUST NOT change this header information.
 246  *                      MUST NOT reply to a multicast/broadcast IP address.
 247  *                      MUST NOT reply to a multicast/broadcast MAC address.
 248  *                      MUST reply to only the first fragment.
 249  */
 250 
 251 void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253         struct iphdr *iph;
 254         struct icmphdr *icmph;
 255         int atype;
 256         struct icmp_bxm icmp_param;
 257         __u32 saddr;
 258         
 259         /*
 260          *      Find the original header
 261          */
 262          
 263         iph = skb_in->ip_hdr;
 264         
 265         /*
 266          *      No replies to physical multicast/broadcast
 267          */
 268          
 269         if(skb_in->pkt_type!=PACKET_HOST)
 270                 return;
 271                 
 272         /*
 273          *      Now check at the protocol level
 274          */
 275          
 276         atype=ip_chk_addr(iph->daddr);
 277         if(atype==IS_BROADCAST||atype==IS_MULTICAST)
 278                 return;
 279                 
 280         /*
 281          *      Only reply to fragment 0. We byte re-order the constant
 282          *      mask for efficiency.
 283          */
 284          
 285         if(iph->frag_off&htons(IP_OFFSET))
 286                 return;
 287                 
 288         /* 
 289          *      If we send an ICMP error to an ICMP error a mess would result..
 290          */
 291          
 292         if(icmp_pointers[type].error)
 293         {
 294                 /*
 295                  *      We are an error, check if we are replying to an ICMP error
 296                  */
 297                  
 298                 if(iph->protocol==IPPROTO_ICMP)
 299                 {
 300                         icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
 301                         /*
 302                          *      Assume any unknown ICMP type is an error. This isn't
 303                          *      specified by the RFC, but think about it..
 304                          */
 305                         if(icmph->type>18 || icmp_pointers[icmph->type].error)
 306                                 return;
 307                 }
 308         }
 309         
 310         /*
 311          *      Tell our driver what to send
 312          */
 313          
 314         saddr=iph->daddr;
 315         if(saddr!=dev->pa_addr && ip_chk_addr(saddr)!=IS_MYADDR)
 316                 saddr=dev->pa_addr;
 317         
 318         icmp_param.icmph.type=type;
 319         icmp_param.icmph.code=code;
 320         icmp_param.icmph.un.gateway = info;
 321         icmp_param.data_ptr=iph;
 322         icmp_param.data_len=(iph->ihl<<2)+8;    /* RFC says return header + 8 bytes */
 323         
 324         /*
 325          *      Set it to build.
 326          */
 327 
 328         if (ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in) == 0)
 329           icmp_build_xmit(&icmp_param, saddr, iph->saddr);
 330 }
 331 
 332 
 333 /* 
 334  *      Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. 
 335  */
 336  
 337 static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339         struct iphdr *iph;
 340         int hash;
 341         struct inet_protocol *ipprot;
 342         unsigned char *dp;      
 343         
 344         iph = (struct iphdr *) (icmph + 1);
 345         
 346         dp= ((unsigned char *)iph)+(iph->ihl<<2);
 347         
 348         if(icmph->type==ICMP_DEST_UNREACH)
 349         {
 350                 switch(icmph->code & 15)
 351                 {
 352                         case ICMP_NET_UNREACH:
 353                                 break;
 354                         case ICMP_HOST_UNREACH:
 355                                 break;
 356                         case ICMP_PROT_UNREACH:
 357                                 printk("ICMP: %s:%d: protocol unreachable.\n",
 358                                         in_ntoa(iph->daddr), ntohs(iph->protocol));
 359                                 break;
 360                         case ICMP_PORT_UNREACH:
 361                                 break;
 362                         case ICMP_FRAG_NEEDED:
 363                                 printk("ICMP: %s: fragmentation needed and DF set.\n",
 364                                                                 in_ntoa(iph->daddr));
 365                                 break;
 366                         case ICMP_SR_FAILED:
 367                                 printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
 368                                 break;
 369                         default:
 370                                 break;
 371                 }
 372                 if(icmph->code>12)      /* Invalid type */
 373                         return;
 374         }
 375         
 376         /*
 377          *      Throw it at our lower layers
 378          *
 379          *      RFC 1122: 3.2.2 MUST extract the protocol ID from the passed header.
 380          *      RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the transport layer.
 381          *      RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to transport layer.
 382          */
 383 
 384         /*
 385          *      Get the protocol(s). 
 386          */
 387          
 388         hash = iph->protocol & (MAX_INET_PROTOS -1);
 389 
 390         /*
 391          *      This can't change while we are doing it. 
 392          *
 393          *      FIXME: Deliver to appropriate raw sockets too.
 394          */
 395          
 396         ipprot = (struct inet_protocol *) inet_protos[hash];
 397         while(ipprot != NULL) 
 398         {
 399                 struct inet_protocol *nextip;
 400 
 401                 nextip = (struct inet_protocol *) ipprot->next;
 402         
 403                 /* 
 404                  *      Pass it off to everyone who wants it. 
 405                  */
 406 
 407                 /* RFC1122: OK. Passes appropriate ICMP errors to the */
 408                 /* appropriate protocol layer (MUST), as per 3.2.2. */
 409 
 410                 if (iph->protocol == ipprot->protocol && ipprot->err_handler) 
 411                 {
 412                         ipprot->err_handler(icmph->type, icmph->code, dp,
 413                                             iph->daddr, iph->saddr, ipprot);
 414                 }
 415 
 416                 ipprot = nextip;
 417         }
 418         kfree_skb(skb, FREE_READ);
 419 }
 420 
 421 
 422 /*
 423  *      Handle ICMP_REDIRECT. 
 424  */
 425 
 426 static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 source, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 427 {
 428 #ifndef CONFIG_IP_FORWARD
 429         struct rtable *rt;
 430 #endif
 431         struct iphdr *iph;
 432         unsigned long ip;
 433 
 434         /*
 435          *      Get the copied header of the packet that caused the redirect
 436          */
 437          
 438         iph = (struct iphdr *) (icmph + 1);
 439         ip = iph->daddr;
 440 
 441 #ifdef CONFIG_IP_FORWARD
 442         /*
 443          *      We are a router. Routers should not respond to ICMP_REDIRECT messages.
 444          */
 445         printk("icmp: ICMP redirect from %s on %s ignored.\n", in_ntoa(source), dev->name);
 446 #else   
 447         switch(icmph->code & 7) 
 448         {
 449                 case ICMP_REDIR_NET:
 450                         /*
 451                          *      This causes a problem with subnetted networks. What we should do
 452                          *      is use ICMP_ADDRESS to get the subnet mask of the problem route
 453                          *      and set both. But we don't..
 454                          */
 455 #ifdef not_a_good_idea
 456                         ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
 457                                 ip, 0, icmph->un.gateway, dev,0, 0, 0);
 458 #endif
 459                         break;
 460                 case ICMP_REDIR_HOST:
 461                         /*
 462                          *      Add better route to host.
 463                          *      But first check that the redirect
 464                          *      comes from the old gateway..
 465                          *      And make sure it's an ok host address
 466                          *      (not some confused thing sending our
 467                          *      address)
 468                          */
 469                         rt = ip_rt_route(ip, NULL, NULL);
 470                         if (!rt)
 471                                 break;
 472                         if (rt->rt_gateway != source || 
 473                                 ((icmph->un.gateway^dev->pa_addr)&dev->pa_mask) ||
 474                                 ip_chk_addr(icmph->un.gateway))
 475                                 break;
 476                         printk("ICMP redirect from %s\n", in_ntoa(source));
 477                         ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
 478                                 ip, 0, icmph->un.gateway, dev,0, 0, 0, 0);
 479                         break;
 480                 case ICMP_REDIR_NETTOS:
 481                 case ICMP_REDIR_HOSTTOS:
 482                         printk("ICMP: cannot handle TOS redirects yet!\n");
 483                         break;
 484                 default:
 485                         break;
 486         }
 487 #endif          
 488         /*
 489          *      Discard the original packet
 490          */
 491          
 492         kfree_skb(skb, FREE_READ);
 493 }
 494 
 495 /*
 496  *      Handle ICMP_ECHO ("ping") requests. 
 497  *
 498  *      RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo requests.
 499  *      RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be included in the reply.
 500  *      See also WRT handling of options once they are done and working.
 501  */
 502  
 503 static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505         struct icmp_bxm icmp_param;
 506         icmp_param.icmph=*icmph;
 507         icmp_param.icmph.type=ICMP_ECHOREPLY;
 508         icmp_param.data_ptr=(icmph+1);
 509         icmp_param.data_len=len;
 510         if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
 511           icmp_build_xmit(&icmp_param, daddr, saddr);
 512         kfree_skb(skb, FREE_READ);
 513 }
 514 
 515 /*
 516  *      Handle ICMP Timestamp requests. 
 517  *      RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests.
 518  *                SHOULD be in the kernel for minimum random latency.
 519  *                MUST be accurate to a few minutes.
 520  *                MUST be updated at least at 15Hz.
 521  */
 522  
 523 static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         __u32 times[3];         /* So the new timestamp works on ALPHA's.. */
 526         struct icmp_bxm icmp_param;
 527         
 528         /*
 529          *      Too short.
 530          */
 531          
 532         if(len<12)
 533         {
 534                 icmp_statistics.IcmpInErrors++;
 535                 kfree_skb(skb, FREE_READ);
 536                 return;
 537         }
 538         
 539         /*
 540          *      Fill in the current time as ms since midnight UT: 
 541          */
 542          
 543         {
 544           struct timeval tv;
 545           do_gettimeofday(&tv);
 546           times[1] = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
 547         }
 548         times[2] = times[1];
 549         memcpy((void *)&times[0], icmph+1, 4);          /* Incoming stamp */
 550         icmp_param.icmph=*icmph;
 551         icmp_param.icmph.type=ICMP_TIMESTAMPREPLY;
 552         icmp_param.icmph.code=0;
 553         icmp_param.data_ptr=&times;
 554         icmp_param.data_len=12;
 555         if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
 556           icmp_build_xmit(&icmp_param, daddr, saddr);
 557         kfree_skb(skb,FREE_READ);
 558 }
 559 
 560 
 561 /* 
 562  *      Handle ICMP_ADDRESS_MASK requests.  (RFC950)
 563  *
 564  * RFC1122 (3.2.2.9).  A host MUST only send replies to 
 565  * ADDRESS_MASK requests if it's been configured as an address mask 
 566  * agent.  Receiving a request doesn't constitute implicit permission to 
 567  * act as one. Of course, implementing this correctly requires (SHOULD) 
 568  * a way to turn the functionality on and off.  Another one for sysctl(), 
 569  * I guess. -- MS 
 570  * Botched with a CONFIG option for now - Linus add scts sysctl please.. 
 571  */
 572  
 573 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 574 {
 575 #ifdef CONFIG_IP_ADDR_AGENT
 576         __u32 answer;
 577         struct icmp_bxm icmp_param;
 578         icmp_param.icmph.type=ICMP_ADDRESSREPLY;
 579         icmp_param.icmph.code=0;
 580         icmp_param.icmph.un.echo.id = icmph->un.echo.id;
 581         icmp_param.icmph.un.echo.sequence = icmph->un.echo.sequence;
 582         icmp_param.data_ptr=&dev->pa_mask;
 583         icmp_param.data_len=4;
 584         if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0)
 585           icmp_build_xmit(&icmp_param, daddr, saddr);
 586 #endif  
 587         kfree_skb(skb, FREE_READ);      
 588 }
 589 
 590 static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 591 {
 592         kfree_skb(skb, FREE_READ);
 593 }
 594 
 595 /* 
 596  *      Deal with incoming ICMP packets. 
 597  */
 598  
 599 int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 600          __u32 daddr, unsigned short len,
 601          __u32 saddr, int redo, struct inet_protocol *protocol)
 602 {
 603         struct icmphdr *icmph=(void *)skb->h.raw;
 604         icmp_statistics.IcmpInMsgs++;
 605         
 606         /*
 607          *      Validate the packet
 608          */
 609         
 610         if (ip_compute_csum((unsigned char *) icmph, len)) 
 611         {
 612                 /* Failed checksum! */
 613                 icmp_statistics.IcmpInErrors++;
 614                 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
 615                 kfree_skb(skb, FREE_READ);
 616                 return(0);
 617         }
 618         
 619         /*
 620          *      18 is the highest 'known' icmp type. Anything else is a mystery
 621          *
 622          *      RFC 1122: 3.2.2  Unknown ICMP messages types MUST be silently discarded.
 623          */
 624          
 625         if(icmph->type > 18)
 626         {
 627                 icmp_statistics.IcmpInErrors++;         /* Is this right - or do we ignore ? */
 628                 kfree_skb(skb,FREE_READ);
 629                 return(0);
 630         }
 631         
 632         /*
 633          *      Parse the ICMP message 
 634          */
 635 
 636         if (daddr!=dev->pa_addr && ip_chk_addr(daddr) == IS_BROADCAST)
 637         {
 638                 /*
 639                  *      RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used
 640                  *      by some network mapping tools).
 641                  *      RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently discarded if to broadcast/multicast.
 642                  */
 643                 if (icmph->type != ICMP_ECHO) 
 644                 {
 645                         icmp_statistics.IcmpInErrors++;
 646                         kfree_skb(skb, FREE_READ);
 647                         return(0);
 648                 }
 649                 daddr=dev->pa_addr;
 650         }
 651         
 652         len-=sizeof(struct icmphdr);
 653         (*icmp_pointers[icmph->type].input)++;
 654         (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len);
 655         return 0;
 656 }
 657 
 658 /*
 659  *      This table is the definition of how we handle ICMP.
 660  */
 661  
 662 static struct icmp_control icmp_pointers[19] = {
 663 /* ECHO REPLY (0) */
 664  { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0 },
 665  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 666  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 667 /* DEST UNREACH (3) */
 668  { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1 },
 669 /* SOURCE QUENCH (4) */
 670  { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1 },
 671 /* REDIRECT (5) */
 672  { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1 },
 673  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 674  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 675 /* ECHO (8) */
 676  { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0 },
 677  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 678  { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1 },
 679 /* TIME EXCEEDED (11) */
 680  { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1 },
 681 /* PARAMETER PROBLEM (12) */
 682 /* FIXME: RFC1122 3.2.2.5 - MUST pass PARAM_PROB messages to transport layer */
 683  { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_discard, 1 },
 684 /* TIMESTAMP (13) */
 685  { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0 },
 686 /* TIMESTAMP REPLY (14) */
 687  { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0 },
 688 /* INFO (15) */
 689  { &dummy, &dummy, icmp_discard, 0 },
 690 /* INFO REPLY (16) */
 691  { &dummy, &dummy, icmp_discard, 0 },
 692 /* ADDR MASK (17) */
 693  { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0 },
 694 /* ADDR MASK REPLY (18) */
 695  { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_discard, 0 }
 696 };
 697 
 698 void icmp_init(struct proto_ops *ops)
     /* [previous][next][first][last][top][bottom][index][help] */
 699 {
 700         struct sock *sk;
 701         icmp_socket.type=SOCK_RAW;
 702         icmp_socket.ops=ops;
 703         if(ops->create(&icmp_socket, IPPROTO_ICMP)<0)
 704                 panic("Failed to create the ICMP control socket.\n");
 705         sk=icmp_socket.data;
 706         sk->allocation=GFP_ATOMIC;
 707         sk->num = 256;                  /* Don't receive any data */
 708 }
 709 

/* [previous][next][first][last][top][bottom][index][help] */