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: @(#)protocol.c 1.0.5 05/25/93
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 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 */
24 #include <asm/segment.h>
25 #include <asm/system.h>
26 #include <linux/types.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/string.h>
30 #include <linux/socket.h>
31 #include <linux/in.h>
32 #include <linux/inet.h>
33 #include <linux/netdevice.h>
34 #include "ip.h"
35 #include "protocol.h"
36 #include "tcp.h"
37 #include <linux/skbuff.h>
38 #include "sock.h"
39 #include "icmp.h"
40 #include "udp.h"
41
42
43 static struct inet_protocol tcp_protocol = {
44 tcp_rcv, /* TCP handler */
45 NULL, /* No fragment handler (and won't be for a long time) */
46 tcp_err, /* TCP error control */
47 NULL, /* next */
48 IPPROTO_TCP, /* protocol ID */
49 0, /* copy */
50 NULL, /* data */
51 "TCP" /* name */
52 };
53
54
55 static struct inet_protocol udp_protocol = {
56 udp_rcv, /* UDP handler */
57 NULL, /* Will be UDP fraglist handler */
58 udp_err, /* UDP error control */
59 &tcp_protocol, /* next */
60 IPPROTO_UDP, /* protocol ID */
61 0, /* copy */
62 NULL, /* data */
63 "UDP" /* name */
64 };
65
66
67 static struct inet_protocol icmp_protocol = {
68 icmp_rcv, /* ICMP handler */
69 NULL, /* ICMP never fragments anyway */
70 NULL, /* ICMP error control */
71 &udp_protocol, /* next */
72 IPPROTO_ICMP, /* protocol ID */
73 0, /* copy */
74 NULL, /* data */
75 "ICMP" /* name */
76 };
77
78
79 struct inet_protocol *inet_protocol_base = &icmp_protocol;
80 struct inet_protocol *inet_protos[MAX_INET_PROTOS] = {
81 NULL
82 };
83
84
85 struct inet_protocol *
86 inet_get_protocol(unsigned char prot)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
87 {
88 unsigned char hash;
89 struct inet_protocol *p;
90
91 hash = prot & (MAX_INET_PROTOS - 1);
92 for (p = inet_protos[hash] ; p != NULL; p=p->next) {
93 if (p->protocol == prot) return((struct inet_protocol *) p);
94 }
95 return(NULL);
96 }
97
98
99 void
100 inet_add_protocol(struct inet_protocol *prot)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
101 {
102 unsigned char hash;
103 struct inet_protocol *p2;
104
105 hash = prot->protocol & (MAX_INET_PROTOS - 1);
106 prot ->next = inet_protos[hash];
107 inet_protos[hash] = prot;
108 prot->copy = 0;
109
110 /* Set the copy bit if we need to. */
111 p2 = (struct inet_protocol *) prot->next;
112 while(p2 != NULL) {
113 if (p2->protocol == prot->protocol) {
114 prot->copy = 1;
115 break;
116 }
117 p2 = (struct inet_protocol *) prot->next;
118 }
119 }
120
121
122 int
123 inet_del_protocol(struct inet_protocol *prot)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
124 {
125 struct inet_protocol *p;
126 struct inet_protocol *lp = NULL;
127 unsigned char hash;
128
129 hash = prot->protocol & (MAX_INET_PROTOS - 1);
130 if (prot == inet_protos[hash]) {
131 inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
132 return(0);
133 }
134
135 p = (struct inet_protocol *) inet_protos[hash];
136 while(p != NULL) {
137 /*
138 * We have to worry if the protocol being deleted is
139 * the last one on the list, then we may need to reset
140 * someone's copied bit.
141 */
142 if (p->next != NULL && p->next == prot) {
143 /*
144 * if we are the last one with this protocol and
145 * there is a previous one, reset its copy bit.
146 */
147 if (p->copy == 0 && lp != NULL) lp->copy = 0;
148 p->next = prot->next;
149 return(0);
150 }
151
152 if (p->next != NULL && p->next->protocol == prot->protocol) {
153 lp = p;
154 }
155
156 p = (struct inet_protocol *) p->next;
157 }
158 return(-1);
159 }