aboutsummaryrefslogtreecommitdiff
path: root/pfinet/linux-inet/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'pfinet/linux-inet/protocol.c')
-rw-r--r--pfinet/linux-inet/protocol.c177
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);
+}