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.12 2000/10/03 07:29:00 anton 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 <linux/brlock.h>
39 #include <net/ip.h>
40 #include <net/protocol.h>
41 #include <net/tcp.h>
42 #include <linux/skbuff.h>
43 #include <net/sock.h>
44 #include <net/icmp.h>
45 #include <net/udp.h>
46 #include <net/ipip.h>
47 #include <linux/igmp.h>
48
49 #define IPPROTO_PREVIOUS NULL
50
51 #ifdef CONFIG_IP_MULTICAST
52
53 static struct inet_protocol igmp_protocol =
54 {
55 igmp_rcv, /* IGMP handler */
56 NULL, /* IGMP error control */
57 IPPROTO_PREVIOUS, /* next */
58 IPPROTO_IGMP, /* protocol ID */
59 0, /* copy */
60 NULL, /* data */
61 "IGMP" /* name */
62 };
63
64 #undef IPPROTO_PREVIOUS
65 #define IPPROTO_PREVIOUS &igmp_protocol
66
67 #endif
68
69 static struct inet_protocol tcp_protocol =
70 {
71 tcp_v4_rcv, /* TCP handler */
72 tcp_v4_err, /* TCP error control */
73 IPPROTO_PREVIOUS,
74 IPPROTO_TCP, /* protocol ID */
75 0, /* copy */
76 NULL, /* data */
77 "TCP" /* name */
78 };
79
80 #undef IPPROTO_PREVIOUS
81 #define IPPROTO_PREVIOUS &tcp_protocol
82
83 static struct inet_protocol udp_protocol =
84 {
85 udp_rcv, /* UDP handler */
86 udp_err, /* UDP error control */
87 IPPROTO_PREVIOUS, /* next */
88 IPPROTO_UDP, /* protocol ID */
89 0, /* copy */
90 NULL, /* data */
91 "UDP" /* name */
92 };
93
94 #undef IPPROTO_PREVIOUS
95 #define IPPROTO_PREVIOUS &udp_protocol
96
97
98 static struct inet_protocol icmp_protocol =
99 {
100 icmp_rcv, /* ICMP handler */
101 NULL, /* ICMP error control */
102 IPPROTO_PREVIOUS, /* next */
103 IPPROTO_ICMP, /* protocol ID */
104 0, /* copy */
105 NULL, /* data */
106 "ICMP" /* name */
107 };
108
109 #undef IPPROTO_PREVIOUS
110 #define IPPROTO_PREVIOUS &icmp_protocol
111
112
113 struct inet_protocol *inet_protocol_base = IPPROTO_PREVIOUS;
114
115 struct inet_protocol *inet_protos[MAX_INET_PROTOS];
116
117 /*
118 * Add a protocol handler to the hash tables
119 */
120
121 void inet_add_protocol(struct inet_protocol *prot)
122 {
123 unsigned char hash;
124 struct inet_protocol *p2;
125
126 hash = prot->protocol & (MAX_INET_PROTOS - 1);
127 br_write_lock_bh(BR_NETPROTO_LOCK);
128 prot ->next = inet_protos[hash];
129 inet_protos[hash] = prot;
130 prot->copy = 0;
131
132 /*
133 * Set the copy bit if we need to.
134 */
135
136 p2 = (struct inet_protocol *) prot->next;
137 while(p2 != NULL)
138 {
139 if (p2->protocol == prot->protocol)
140 {
141 prot->copy = 1;
142 break;
143 }
144 p2 = (struct inet_protocol *) p2->next;
145 }
146 br_write_unlock_bh(BR_NETPROTO_LOCK);
147 }
148
149 /*
150 * Remove a protocol from the hash tables.
151 */
152
153 int inet_del_protocol(struct inet_protocol *prot)
154 {
155 struct inet_protocol *p;
156 struct inet_protocol *lp = NULL;
157 unsigned char hash;
158
159 hash = prot->protocol & (MAX_INET_PROTOS - 1);
160 br_write_lock_bh(BR_NETPROTO_LOCK);
161 if (prot == inet_protos[hash])
162 {
163 inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
164 br_write_unlock_bh(BR_NETPROTO_LOCK);
165 return(0);
166 }
167
168 p = (struct inet_protocol *) inet_protos[hash];
169 while(p != NULL)
170 {
171 /*
172 * We have to worry if the protocol being deleted is
173 * the last one on the list, then we may need to reset
174 * someone's copied bit.
175 */
176 if (p->next != NULL && p->next == prot)
177 {
178 /*
179 * if we are the last one with this protocol and
180 * there is a previous one, reset its copy bit.
181 */
182 if (p->copy == 0 && lp != NULL)
183 lp->copy = 0;
184 p->next = prot->next;
185 br_write_unlock_bh(BR_NETPROTO_LOCK);
186 return(0);
187 }
188 if (p->next != NULL && p->next->protocol == prot->protocol)
189 lp = p;
190
191 p = (struct inet_protocol *) p->next;
192 }
193 br_write_unlock_bh(BR_NETPROTO_LOCK);
194 return(-1);
195 }
196
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.