Annotation of linux/net/tcp/icmp.c, revision 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.