linux-old/net/ipv4/protocol.c
<<
>>
Prefs
   1/*
   2 * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3 *              operating system.  INET is implemented using the  BSD Socket
   4 *              interface as the means of communication with the user level.
   5 *
   6 *              INET protocol dispatch tables.
   7 *
   8 * Version:     $Id: protocol.c,v 1.9 1997/10/29 20:27:34 kuznet Exp $
   9 *
  10 * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12 *
  13 * Fixes:
  14 *              Alan Cox        : Ahah! udp icmp errors don't work because
  15 *                                udp_err is never called!
  16 *              Alan Cox        : Added new fields for init and ready for
  17 *                                proper fragmentation (_NO_ 4K limits!)
  18 *              Richard Colella : Hang on hash collision
  19 *
  20 *              This program is free software; you can redistribute it and/or
  21 *              modify it under the terms of the GNU General Public License
  22 *              as published by the Free Software Foundation; either version
  23 *              2 of the License, or (at your option) any later version.
  24 */
  25
  26#include <asm/uaccess.h>
  27#include <asm/system.h>
  28#include <linux/types.h>
  29#include <linux/kernel.h>
  30#include <linux/sched.h>
  31#include <linux/string.h>
  32#include <linux/config.h>
  33#include <linux/socket.h>
  34#include <linux/in.h>
  35#include <linux/inet.h>
  36#include <linux/netdevice.h>
  37#include <linux/timer.h>
  38#include <net/ip.h>
  39#include <net/protocol.h>
  40#include <net/tcp.h>
  41#include <linux/skbuff.h>
  42#include <net/sock.h>
  43#include <net/icmp.h>
  44#include <net/udp.h>
  45#include <net/ipip.h>
  46#include <linux/igmp.h>
  47
  48#define IPPROTO_PREVIOUS NULL
  49
  50#ifdef CONFIG_IP_MULTICAST
  51
  52static struct inet_protocol igmp_protocol = 
  53{
  54        igmp_rcv,               /* IGMP handler         */
  55        NULL,                   /* IGMP error control   */
  56        IPPROTO_PREVIOUS,       /* next                 */
  57        IPPROTO_IGMP,           /* protocol ID          */
  58        0,                      /* copy                 */
  59        NULL,                   /* data                 */
  60        "IGMP"                  /* name                 */
  61};
  62
  63#undef  IPPROTO_PREVIOUS
  64#define IPPROTO_PREVIOUS &igmp_protocol
  65
  66#endif
  67
  68static struct inet_protocol tcp_protocol = 
  69{
  70        tcp_v4_rcv,             /* TCP handler          */
  71        tcp_v4_err,             /* TCP error control    */  
  72        IPPROTO_PREVIOUS,
  73        IPPROTO_TCP,            /* protocol ID          */
  74        0,                      /* copy                 */
  75        NULL,                   /* data                 */
  76        "TCP"                   /* name                 */
  77};
  78
  79#undef  IPPROTO_PREVIOUS
  80#define IPPROTO_PREVIOUS &tcp_protocol
  81
  82static struct inet_protocol udp_protocol = 
  83{
  84        udp_rcv,                /* UDP handler          */
  85        udp_err,                /* UDP error control    */
  86        IPPROTO_PREVIOUS,       /* next                 */
  87        IPPROTO_UDP,            /* protocol ID          */
  88        0,                      /* copy                 */
  89        NULL,                   /* data                 */
  90        "UDP"                   /* name                 */
  91};
  92
  93#undef  IPPROTO_PREVIOUS
  94#define IPPROTO_PREVIOUS &udp_protocol
  95
  96
  97static struct inet_protocol icmp_protocol = 
  98{
  99        icmp_rcv,               /* ICMP handler         */
 100        NULL,                   /* ICMP error control   */
 101        IPPROTO_PREVIOUS,       /* next                 */
 102        IPPROTO_ICMP,           /* protocol ID          */
 103        0,                      /* copy                 */
 104        NULL,                   /* data                 */
 105        "ICMP"                  /* name                 */
 106};
 107
 108#undef  IPPROTO_PREVIOUS
 109#define IPPROTO_PREVIOUS &icmp_protocol
 110
 111
 112struct inet_protocol *inet_protocol_base = IPPROTO_PREVIOUS;
 113
 114struct inet_protocol *inet_protos[MAX_INET_PROTOS] = 
 115{
 116        NULL
 117};
 118
 119
 120/*
 121 *      Find a protocol in the protocol tables given its
 122 *      IP type.
 123 */
 124
 125struct inet_protocol *inet_get_protocol(unsigned char prot)
 126{
 127        unsigned char hash;
 128        struct inet_protocol *p;
 129
 130        hash = prot & (MAX_INET_PROTOS - 1);
 131        for (p = inet_protos[hash] ; p != NULL; p=p->next) 
 132        {
 133                if (p->protocol == prot) 
 134                        return((struct inet_protocol *) p);
 135        }
 136        return(NULL);
 137}
 138
 139/*
 140 *      Add a protocol handler to the hash tables
 141 */
 142
 143void inet_add_protocol(struct inet_protocol *prot)
 144{
 145        unsigned char hash;
 146        struct inet_protocol *p2;
 147
 148        hash = prot->protocol & (MAX_INET_PROTOS - 1);
 149        prot ->next = inet_protos[hash];
 150        inet_protos[hash] = prot;
 151        prot->copy = 0;
 152
 153        /*
 154         *      Set the copy bit if we need to. 
 155         */
 156         
 157        p2 = (struct inet_protocol *) prot->next;
 158        while(p2 != NULL) 
 159        {
 160                if (p2->protocol == prot->protocol) 
 161                {
 162                        prot->copy = 1;
 163                        break;
 164                }
 165                p2 = (struct inet_protocol *) p2->next;
 166        }
 167}
 168
 169/*
 170 *      Remove a protocol from the hash tables.
 171 */
 172 
 173int inet_del_protocol(struct inet_protocol *prot)
 174{
 175        struct inet_protocol *p;
 176        struct inet_protocol *lp = NULL;
 177        unsigned char hash;
 178
 179        hash = prot->protocol & (MAX_INET_PROTOS - 1);
 180        if (prot == inet_protos[hash]) 
 181        {
 182                inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
 183                return(0);
 184        }
 185
 186        p = (struct inet_protocol *) inet_protos[hash];
 187        while(p != NULL) 
 188        {
 189                /*
 190                 * We have to worry if the protocol being deleted is
 191                 * the last one on the list, then we may need to reset
 192                 * someone's copied bit.
 193                 */
 194                if (p->next != NULL && p->next == prot) 
 195                {
 196                        /*
 197                         * if we are the last one with this protocol and
 198                         * there is a previous one, reset its copy bit.
 199                         */
 200                        if (p->copy == 0 && lp != NULL) 
 201                                lp->copy = 0;
 202                        p->next = prot->next;
 203                        return(0);
 204                }
 205                if (p->next != NULL && p->next->protocol == prot->protocol) 
 206                        lp = p;
 207
 208                p = (struct inet_protocol *) p->next;
 209        }
 210        return(-1);
 211}
 212
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.