Annotation of linux/net/tcp/icmp.c, revision 1.1.1.1

1.1       root        1: /* Internet Control Message Protocol (ICMP) icmp.c */
                      2: 
                      3: /*
                      4:     Copyright (C) 1992  Bob Harris
                      5: 
                      6:     This program is free software; you can redistribute it and/or modify
                      7:     it under the terms of the GNU General Public License as published by
                      8:     the Free Software Foundation; either version 2, or (at your option)
                      9:     any later version.
                     10: 
                     11:     This program is distributed in the hope that it will be useful,
                     12:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14:     GNU General Public License for more details.
                     15: 
                     16:     You should have received a copy of the GNU General Public License
                     17:     along with this program; if not, write to the Free Software
                     18:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
                     19: 
                     20:     The Author of tcpip package may be reached as [email protected] or
                     21:     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
                     22: 
                     23:     The author of this file may be reached at [email protected] or Sparta, Inc.
                     24:     7926 Jones Branch Dr. Suite 900, McLean Va 22102.
                     25: */
                     26: 
                     27: /* modified by Ross Biro [email protected] to do more than just
                     28:    echo responses. */
                     29: 
                     30: #include <linux/types.h>
                     31: #include <linux/sched.h>
                     32: #include <linux/kernel.h>      /* free_s */
                     33: #include <linux/fcntl.h>
                     34: #include <linux/socket.h>
                     35: #include <netinet/in.h>
                     36: #include "timer.h"
                     37: #include "ip.h"
                     38: #include "tcp.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: #include "../kern_sock.h" /* for PRINTK */
                     45: #include "icmp.h"
                     46: 
                     47: #define min(a,b) ((a)<(b)?(a):(b))
                     48: 
                     49: /* an array of errno for error messages from dest unreach. */
                     50: struct icmp_err icmp_err_convert[]=
                     51: {
                     52:    {ENETUNREACH, 1},
                     53:    {EHOSTUNREACH, 1},
                     54:    {ENOPROTOOPT, 1},
                     55:    {ECONNREFUSED, 1},
                     56:    {EOPNOTSUPP, 0},
                     57:    {EOPNOTSUPP, 0},
                     58:    {ENETUNREACH, 1},
                     59:    {EHOSTDOWN, 1},
                     60:    {ENONET, 1},
                     61:    {ENETUNREACH, 1},
                     62:    {EHOSTUNREACH, 1},
                     63:    {EOPNOTSUPP, 0},
                     64:    {EOPNOTSUPP, 0}
                     65: };
                     66: 
                     67: void
                     68: print_icmph (struct icmp_header *icmph)
                     69: {
                     70:    PRINTK ("  type = %d, code = %d, checksum = %X\n", icmph->type,
                     71:           icmph->code, icmph->checksum);
                     72:    PRINTK (" gateway = %X\n", icmph->un.gateway);
                     73: }
                     74: 
                     75: /* sends an icmp message in response to a packet. */
                     76: void
                     77: icmp_reply (struct sk_buff *skb_in,  int type, int code, struct device *dev)
                     78: {
                     79:    struct sk_buff *skb;
                     80:    struct ip_header *iph;
                     81:    int offset;
                     82:    struct icmp_header *icmph;
                     83: 
                     84:    int len;
                     85:    /* get some memory for the replay. */
                     86:    len = sizeof (*skb) + 8 /* amount of header to return. */ +
                     87:          sizeof (struct icmp_header) +
                     88:         64 /* enough for an ip header. */ +
                     89:         dev->hard_header_len;
                     90:           
                     91:    skb = malloc (len);
                     92:    if (skb == NULL) return;
                     93: 
                     94:    skb->mem_addr = skb;
                     95:    skb->mem_len = len;
                     96: 
                     97:    len -= sizeof (*skb);
                     98: 
                     99:    /* find the ip header. */
                    100:    iph = (struct ip_header *)(skb_in+1);
                    101:    iph = (struct ip_header *)((unsigned char *)iph + dev->hard_header_len);
                    102: 
                    103:    /* Build Layer 2-3 headers for message back to source */
                    104:    offset = ip_build_header( skb, iph->daddr, iph->saddr,
                    105:                            &dev, IP_ICMP, NULL, len );
                    106: 
                    107:    if (offset < 0)
                    108:      {
                    109:        skb->sk = NULL;
                    110:        free_skb (skb, FREE_READ);
                    111:        return;
                    112:      }
                    113: 
                    114:    /* Readjust length according to actual IP header size */
                    115:    skb->len = offset + sizeof (struct icmp_header) + 8;
                    116:    
                    117:    icmph = (struct icmp_header *)((unsigned char *)(skb+1) + offset);
                    118:    icmph->type = type;
                    119:    icmph->code = code;
                    120:    icmph->checksum = 0; /* we don't need to compute this. */
                    121:    icmph->un.gateway = 0; /* might as well 0 it. */
                    122:    memcpy (icmph+1, iph+1, 8);
                    123:    /* send it and free it. */
                    124:    ip_queue_xmit (NULL, dev, skb, 1);
                    125:    
                    126: }
                    127: 
                    128: /* deals with incoming icmp packets. */
                    129: 
                    130: int
                    131: icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
                    132:        unsigned long daddr, unsigned short len,
                    133:        unsigned long saddr, int redo, struct ip_protocol *protocol )
                    134: {
                    135:    int size, offset;
                    136:    struct icmp_header *icmph, *icmphr;
                    137:    struct sk_buff *skb;
                    138:    unsigned char *buff;
                    139: 
                    140: 
                    141:    /* drop broadcast packets.  */
                    142:    if ((daddr & 0xff000000) == 0 || (daddr & 0xff000000) == 0xff000000)
                    143:      {
                    144:        skb1->sk = NULL;
                    145:        free_skb (skb1, FREE_READ);
                    146:        return (0);
                    147:      }
                    148: 
                    149:    buff = skb1->h.raw;
                    150: 
                    151:    icmph = (struct icmp_header *)buff;
                    152: 
                    153:    /* Validate the packet first */
                    154:    if( icmph->checksum )
                    155:      { /* Checksums Enabled? */
                    156:        if( ip_compute_csum( (unsigned char *)icmph, len ) )
                    157:          {
                    158:             /* Failed checksum! */
                    159:             PRINTK("\nICMP ECHO failed checksum!");
                    160:             skb1->sk = NULL;
                    161:             free_skb (skb1, FREE_READ);
                    162:             return (0);
                    163:          }
                    164:      }
                    165: 
                    166:    print_icmph(icmph);
                    167: 
                    168:    /* Parse the ICMP message */
                    169:    switch( icmph->type )
                    170:      {
                    171:        case ICMP_DEST_UNREACH:
                    172:        case ICMP_SOURCE_QUENCH:
                    173:        {
                    174:           struct ip_header *iph;
                    175:           struct ip_protocol *ipprot;
                    176:           unsigned char hash;
                    177:           int err;
                    178: 
                    179:           err = icmph->type << 8 | icmph->code;
                    180: 
                    181:           /* we need to cause the socket to be closed and the error message
                    182:              to be set appropriately. */
                    183:           iph = (struct ip_header *)(icmph+1);
                    184: 
                    185:           /* get the protocol(s) */
                    186:           hash = iph->protocol & (MAX_IP_PROTOS -1 );
                    187:           for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next)
                    188:             {
                    189:                /* pass it off to everyone who wants it. */
                    190:                ipprot->err_handler (err, (unsigned char *)iph+4*iph->ihl,
                    191:                                     iph->daddr, iph->saddr, ipprot);
                    192:             }
                    193:           skb1->sk = NULL;
                    194:           free_skb (skb1, FREE_READ);
                    195:           return (0);
                    196:        }
                    197: 
                    198:        case ICMP_REDIRECT:
                    199:        {
                    200:           /* we need to put a new route in the routing table. */
                    201:           struct rtable *rt; /* we will add a new route. */
                    202:           struct ip_header *iph;
                    203: 
                    204:           iph = (struct ip_header *)(icmph+1);
                    205:           rt = malloc (sizeof (*rt));
                    206:           if (rt != NULL)
                    207:             {
                    208:                rt->net = iph->daddr;
                    209:                /* assume class C network.  Technically this is incorrect,
                    210:                   but will give it a try. */
                    211:                if ((icmph->code & 1) == 0) rt->net &= 0x00ffffff;
                    212:                rt->dev = dev;
                    213:                rt->router = icmph->un.gateway;
                    214:                add_route (rt);
                    215:             }
                    216:           skb1->sk = NULL;
                    217:           free_skb (skb1, FREE_READ);
                    218:           return (0);
                    219:        }
                    220: 
                    221:        case ICMP_ECHO: 
                    222:        
                    223:        /* Allocate an sk_buff response buffer (assume 64 byte IP header) */
                    224: 
                    225:        size = sizeof( struct sk_buff ) + dev->hard_header_len + 64 + len;
                    226:        skb = malloc( size );
                    227:        if (skb == NULL)
                    228:          {
                    229:             skb1->sk = NULL;
                    230:             free_skb (skb1, FREE_READ);
                    231:             return (0);
                    232:          }
                    233:        skb->sk = NULL;
                    234:        skb->mem_addr = skb;
                    235:        skb->mem_len = size;
                    236: 
                    237:        /* Build Layer 2-3 headers for message back to source */
                    238:        offset = ip_build_header( skb, daddr, saddr, &dev, IP_ICMP, opt, len );
                    239:        if (offset < 0)
                    240:          {
                    241:             /* Problems building header */
                    242:             PRINTK("\nCould not build IP Header for ICMP ECHO Response");
                    243:             free_s (skb->mem_addr, skb->mem_len);
                    244:             skb1->sk = NULL;
                    245:             free_skb (skb1, FREE_READ);
                    246:             return( 0 ); /* just toss the received packet */
                    247:          }
                    248: 
                    249:        /* Readjust length according to actual IP header size */
                    250:        skb->len = offset + len;
                    251: 
                    252:        /* Build ICMP_ECHO Response message */
                    253:        icmphr = (struct icmp_header *)( (char *)( skb + 1 ) + offset );
                    254:        memcpy( (char *)icmphr, (char *)icmph, len );
                    255:        icmphr->type = ICMP_ECHOREPLY;
                    256:        icmphr->code = 0;
                    257:        icmphr->checksum = 0;
                    258: 
                    259:        if( icmph->checksum )
                    260:          { /* Calculate Checksum */
                    261:             icmphr->checksum = ip_compute_csum( (void *)icmphr, len );
                    262:          }
                    263: 
                    264:        /* Ship it out - free it when done */
                    265:        ip_queue_xmit( (volatile struct sock *)NULL, dev, skb, 1 );
                    266:        
                    267:        skb1->sk = NULL;
                    268:        free_skb (skb1, FREE_READ);
                    269:        return( 0 );
                    270: 
                    271:        default:
                    272:        PRINTK("\nUnsupported ICMP type = x%x", icmph->type );
                    273:        skb1->sk = NULL;
                    274:        free_skb (skb1, FREE_READ);
                    275:        return( 0 ); /* just toss the packet */
                    276:      }
                    277: 
                    278:    /* should be unecessary, but just in case. */
                    279:    skb1->sk = NULL;
                    280:    free_skb (skb1, FREE_READ);
                    281:    return( 0 ); /* just toss the packet */
                    282: }
                    283: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.