diff options
Diffstat (limited to 'pfinet/linux-inet/protocol.c')
-rw-r--r-- | pfinet/linux-inet/protocol.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/pfinet/linux-inet/protocol.c b/pfinet/linux-inet/protocol.c new file mode 100644 index 00000000..a47d27cd --- /dev/null +++ b/pfinet/linux-inet/protocol.c @@ -0,0 +1,177 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * INET protocol dispatch tables. + * + * Version: @(#)protocol.c 1.0.5 05/25/93 + * + * Authors: Ross Biro, <bir7@leland.Stanford.Edu> + * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> + * + * Fixes: + * Alan Cox : Ahah! udp icmp errors don't work because + * udp_err is never called! + * Alan Cox : Added new fields for init and ready for + * proper fragmentation (_NO_ 4K limits!) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <asm/segment.h> +#include <asm/system.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/socket.h> +#include <linux/in.h> +#include <linux/inet.h> +#include <linux/netdevice.h> +#include <linux/timer.h> +#include "ip.h" +#include "protocol.h" +#include "tcp.h" +#include <linux/skbuff.h> +#include "sock.h" +#include "icmp.h" +#include "udp.h" +#include <linux/igmp.h> + + +static struct inet_protocol tcp_protocol = { + tcp_rcv, /* TCP handler */ + NULL, /* No fragment handler (and won't be for a long time) */ + tcp_err, /* TCP error control */ + NULL, /* next */ + IPPROTO_TCP, /* protocol ID */ + 0, /* copy */ + NULL, /* data */ + "TCP" /* name */ +}; + + +static struct inet_protocol udp_protocol = { + udp_rcv, /* UDP handler */ + NULL, /* Will be UDP fraglist handler */ + udp_err, /* UDP error control */ + &tcp_protocol, /* next */ + IPPROTO_UDP, /* protocol ID */ + 0, /* copy */ + NULL, /* data */ + "UDP" /* name */ +}; + + +static struct inet_protocol icmp_protocol = { + icmp_rcv, /* ICMP handler */ + NULL, /* ICMP never fragments anyway */ + NULL, /* ICMP error control */ + &udp_protocol, /* next */ + IPPROTO_ICMP, /* protocol ID */ + 0, /* copy */ + NULL, /* data */ + "ICMP" /* name */ +}; + +#ifndef CONFIG_IP_MULTICAST +struct inet_protocol *inet_protocol_base = &icmp_protocol; +#else +static struct inet_protocol igmp_protocol = { + igmp_rcv, /* IGMP handler */ + NULL, /* IGMP never fragments anyway */ + NULL, /* IGMP error control */ + &icmp_protocol, /* next */ + IPPROTO_IGMP, /* protocol ID */ + 0, /* copy */ + NULL, /* data */ + "IGMP" /* name */ +}; + +struct inet_protocol *inet_protocol_base = &igmp_protocol; +#endif + +struct inet_protocol *inet_protos[MAX_INET_PROTOS] = { + NULL +}; + + +struct inet_protocol * +inet_get_protocol(unsigned char prot) +{ + unsigned char hash; + struct inet_protocol *p; + + hash = prot & (MAX_INET_PROTOS - 1); + for (p = inet_protos[hash] ; p != NULL; p=p->next) { + if (p->protocol == prot) return((struct inet_protocol *) p); + } + return(NULL); +} + + +void +inet_add_protocol(struct inet_protocol *prot) +{ + unsigned char hash; + struct inet_protocol *p2; + + hash = prot->protocol & (MAX_INET_PROTOS - 1); + prot ->next = inet_protos[hash]; + inet_protos[hash] = prot; + prot->copy = 0; + + /* Set the copy bit if we need to. */ + p2 = (struct inet_protocol *) prot->next; + while(p2 != NULL) { + if (p2->protocol == prot->protocol) { + prot->copy = 1; + break; + } + p2 = (struct inet_protocol *) prot->next; + } +} + + +int +inet_del_protocol(struct inet_protocol *prot) +{ + struct inet_protocol *p; + struct inet_protocol *lp = NULL; + unsigned char hash; + + hash = prot->protocol & (MAX_INET_PROTOS - 1); + if (prot == inet_protos[hash]) { + inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next; + return(0); + } + + p = (struct inet_protocol *) inet_protos[hash]; + while(p != NULL) { + /* + * We have to worry if the protocol being deleted is + * the last one on the list, then we may need to reset + * someone's copied bit. + */ + if (p->next != NULL && p->next == prot) { + /* + * if we are the last one with this protocol and + * there is a previous one, reset its copy bit. + */ + if (p->copy == 0 && lp != NULL) lp->copy = 0; + p->next = prot->next; + return(0); + } + + if (p->next != NULL && p->next->protocol == prot->protocol) { + lp = p; + } + + p = (struct inet_protocol *) p->next; + } + return(-1); +} |