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

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