FreeBSD/Linux Kernel Cross Reference
sys/netns/ns_error.c
1 /* $NetBSD: ns_error.c,v 1.15 2003/08/07 16:33:45 agc Exp $ */
2
3 /*
4 * Copyright (c) 1984, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)ns_error.c 8.2 (Berkeley) 9/22/94
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: ns_error.c,v 1.15 2003/08/07 16:33:45 agc Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/time.h>
44 #include <sys/kernel.h>
45
46 #include <net/if.h>
47 #include <net/route.h>
48
49 #include <netns/ns.h>
50 #include <netns/ns_pcb.h>
51 #include <netns/ns_if.h>
52 #include <netns/ns_var.h>
53 #include <netns/idp.h>
54 #include <netns/idp_var.h>
55 #include <netns/ns_error.h>
56 #include <netns/sp.h>
57 #include <netns/spidp.h>
58 #include <netns/spp_timer.h>
59 #include <netns/spp_var.h>
60
61 #ifdef lint
62 #define NS_ERRPRINTFS 1
63 #endif
64
65 #ifdef NS_ERRPRINTFS
66 /*
67 * NS_ERR routines: error generation, receive packet processing, and
68 * routines to turnaround packets back to the originator.
69 */
70 int ns_errprintfs = 0;
71 #endif
72
73 struct ns_errstat ns_errstat;
74
75 int
76 ns_err_x(c)
77 int c;
78 {
79 u_int16_t *w, *lim, *base = ns_errstat.ns_es_codes;
80 u_int16_t x = c;
81
82 /*
83 * zero is a legit error code, handle specially
84 */
85 if (x == 0)
86 return (0);
87 lim = base + NS_ERR_MAX - 1;
88 for (w = base + 1; w < lim; w++) {
89 if (*w == 0)
90 *w = x;
91 if (*w == x)
92 break;
93 }
94 return (w - base);
95 }
96
97 /*
98 * Generate an error packet of type error
99 * in response to bad packet.
100 */
101 void
102 ns_error(om, type, param)
103 struct mbuf *om;
104 int type;
105 int param;
106 {
107 struct ns_epidp *ep;
108 struct mbuf *m;
109 struct idp *nip;
110 struct idp *oip = mtod(om, struct idp *);
111 extern int idpcksum;
112
113 /*
114 * If this packet was sent to the echo port,
115 * and nobody was there, just echo it.
116 * (Yes, this is a wart!)
117 */
118 if (type == NS_ERR_NOSOCK &&
119 oip->idp_dna.x_port == htons(2) &&
120 (type = ns_echo(om))==0)
121 return;
122
123 #ifdef NS_ERRPRINTFS
124 if (ns_errprintfs)
125 printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
126 #endif
127 /*
128 * Don't Generate error packets in response to multicasts.
129 */
130 if (oip->idp_dna.x_host.c_host[0] & 1)
131 goto freeit;
132
133 ns_errstat.ns_es_error++;
134 /*
135 * Make sure that the old IDP packet had 30 bytes of data to return;
136 * if not, don't bother. Also don't EVER error if the old
137 * packet protocol was NS_ERR.
138 */
139 if (oip->idp_len < sizeof(struct idp)) {
140 ns_errstat.ns_es_oldshort++;
141 goto freeit;
142 }
143 if (oip->idp_pt == NSPROTO_ERROR) {
144 ns_errstat.ns_es_oldns_err++;
145 goto freeit;
146 }
147
148 /*
149 * First, formulate ns_err message
150 */
151 m = m_gethdr(M_DONTWAIT, MT_HEADER);
152 if (m == NULL)
153 goto freeit;
154 m->m_len = sizeof(*ep);
155 MH_ALIGN(m, m->m_len);
156 ep = mtod(m, struct ns_epidp *);
157 if ((u_int)type > NS_ERR_TOO_BIG)
158 panic("ns_err_error");
159 ns_errstat.ns_es_outhist[ns_err_x(type)]++;
160 ep->ns_ep_errp.ns_err_num = htons((u_int16_t)type);
161 ep->ns_ep_errp.ns_err_param = htons((u_int16_t)param);
162 bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
163 nip = &ep->ns_ep_idp;
164 nip->idp_len = sizeof(*ep);
165 nip->idp_len = htons((u_int16_t)nip->idp_len);
166 nip->idp_pt = NSPROTO_ERROR;
167 nip->idp_tc = 0;
168 nip->idp_dna = oip->idp_sna;
169 nip->idp_sna = oip->idp_dna;
170 if (idpcksum) {
171 nip->idp_sum = 0;
172 nip->idp_sum = ns_cksum(m, sizeof(*ep));
173 } else
174 nip->idp_sum = 0xffff;
175 (void) ns_output(m, (struct route *)0, 0);
176
177 freeit:
178 m_freem(om);
179 }
180
181 void
182 ns_printhost(p)
183 struct ns_addr *p;
184 {
185
186 printf("<net:%x%x,host:%x%x%x,port:%x>",
187 p->x_net.s_net[0],
188 p->x_net.s_net[1],
189 p->x_host.s_host[0],
190 p->x_host.s_host[1],
191 p->x_host.s_host[2],
192 p->x_port);
193
194 }
195
196 /*
197 * Process a received NS_ERR message.
198 */
199 void
200 ns_err_input(m)
201 struct mbuf *m;
202 {
203 struct ns_errp *ep;
204 #ifdef NS_ERRPRINTFS
205 struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
206 int param;
207 #endif
208 int i;
209 int type, code;
210
211 /*
212 * Locate ns_err structure in mbuf, and check
213 * that not corrupted and of at least minimum length.
214 */
215 #ifdef NS_ERRPRINTFS
216 if (ns_errprintfs) {
217 printf("ns_err_input from ");
218 ns_printhost(&epidp->ns_ep_idp.idp_sna);
219 printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
220 }
221 #endif
222 i = sizeof (struct ns_epidp);
223 if (((m->m_flags & M_EXT) || m->m_len < i) &&
224 (m = m_pullup(m, i)) == 0) {
225 ns_errstat.ns_es_tooshort++;
226 return;
227 }
228 ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
229 type = ntohs(ep->ns_err_num);
230 #ifdef NS_ERRPRINTFS
231 param = ntohs(ep->ns_err_param);
232 #endif
233 ns_errstat.ns_es_inhist[ns_err_x(type)]++;
234
235 #ifdef NS_ERRPRINTFS
236 /*
237 * Message type specific processing.
238 */
239 if (ns_errprintfs)
240 printf("ns_err_input, type %d param %d\n", type, param);
241 #endif
242 if (type >= NS_ERR_TOO_BIG) {
243 goto badcode;
244 }
245 ns_errstat.ns_es_outhist[ns_err_x(type)]++;
246 switch (type) {
247
248 case NS_ERR_UNREACH_HOST:
249 code = PRC_UNREACH_NET;
250 goto deliver;
251
252 case NS_ERR_TOO_OLD:
253 code = PRC_TIMXCEED_INTRANS;
254 goto deliver;
255
256 case NS_ERR_TOO_BIG:
257 code = PRC_MSGSIZE;
258 goto deliver;
259
260 case NS_ERR_FULLUP:
261 code = PRC_QUENCH;
262 goto deliver;
263
264 case NS_ERR_NOSOCK:
265 code = PRC_UNREACH_PORT;
266 goto deliver;
267
268 case NS_ERR_UNSPEC_T:
269 case NS_ERR_BADSUM_T:
270 case NS_ERR_BADSUM:
271 case NS_ERR_UNSPEC:
272 code = PRC_PARAMPROB;
273 goto deliver;
274
275 deliver:
276 /*
277 * Problem with datagram; advise higher level routines.
278 */
279 #ifdef NS_ERRPRINTFS
280 if (ns_errprintfs)
281 printf("deliver to protocol %d\n",
282 ep->ns_err_idp.idp_pt);
283 #endif
284 switch(ep->ns_err_idp.idp_pt) {
285 case NSPROTO_SPP:
286 spp_ctlinput(code, NULL, ep);
287 break;
288
289 default:
290 idp_ctlinput(code, NULL, ep);
291 }
292
293 goto freeit;
294
295 default:
296 badcode:
297 ns_errstat.ns_es_badcode++;
298 goto freeit;
299
300 }
301 freeit:
302 m_freem(m);
303 }
304
305 #ifdef notdef
306 u_int32_t
307 nstime()
308 {
309 int s = splclock();
310 u_int32_t t;
311
312 t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
313 splx(s);
314 return (htonl(t));
315 }
316 #endif
317
318 int
319 ns_echo(m)
320 struct mbuf *m;
321 {
322 struct idp *idp = mtod(m, struct idp *);
323 struct echo {
324 struct idp ec_idp;
325 u_int16_t ec_op; /* Operation, 1 = request, 2 = reply */
326 } *ec = (struct echo *)idp;
327 struct ns_addr temp;
328
329 if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
330 if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
331
332 ec->ec_op = htons(2);
333
334 temp = idp->idp_dna;
335 idp->idp_dna = idp->idp_sna;
336 idp->idp_sna = temp;
337
338 if (idp->idp_sum != 0xffff) {
339 idp->idp_sum = 0;
340 idp->idp_sum = ns_cksum(m,
341 (int)(((ntohs(idp->idp_len) - 1)|1)+1));
342 }
343 (void) ns_output(m, (struct route *)0, NS_FORWARDING);
344 return(0);
345 }
Cache object: f4e9f5e6f565aa27f0c6f28a77541de9
|