FreeBSD/Linux Kernel Cross Reference
sys/netiso/clnp_er.c
1 /* $NetBSD: clnp_er.c,v 1.16 2005/02/26 22:39:49 perry Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 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 * @(#)clnp_er.c 8.1 (Berkeley) 6/10/93
32 */
33
34 /***********************************************************
35 Copyright IBM Corporation 1987
36
37 All Rights Reserved
38
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
46
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 SOFTWARE.
54
55 ******************************************************************/
56
57 /*
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
59 */
60
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: clnp_er.c,v 1.16 2005/02/26 22:39:49 perry Exp $");
63
64 #include <sys/param.h>
65 #include <sys/mbuf.h>
66 #include <sys/domain.h>
67 #include <sys/protosw.h>
68 #include <sys/socket.h>
69 #include <sys/socketvar.h>
70 #include <sys/errno.h>
71 #include <sys/systm.h>
72
73 #include <net/if.h>
74 #include <net/route.h>
75
76 #include <netiso/iso.h>
77 #include <netiso/iso_var.h>
78 #include <netiso/iso_pcb.h>
79 #define CLNP_ER_CODES
80 #include <netiso/clnp.h>
81 #include <netiso/clnp_stat.h>
82 #include <netiso/argo_debug.h>
83 #include <netiso/tp_param.h>
84 #include <netiso/tp_var.h>
85
86 static const struct clnp_fixed er_template = {
87 ISO8473_CLNP, /* network identifier */
88 0, /* length */
89 ISO8473_V1, /* version */
90 CLNP_TTL, /* ttl */
91 CLNP_ER, /* type */
92 0, /* segment length */
93 0 /* checksum */
94 };
95
96 /*
97 * FUNCTION: clnp_er_input
98 *
99 * PURPOSE: Process an ER pdu.
100 *
101 * RETURNS:
102 *
103 * SIDE EFFECTS:
104 *
105 * NOTES:
106 */
107 void
108 clnp_er_input(
109 struct mbuf *m, /* ptr to packet itself */
110 struct iso_addr *src, /* ptr to src of er */
111 u_int reason) /* reason code of er */
112 {
113 int cmd = -1;
114
115 #ifdef ARGO_DEBUG
116 if (argo_debug[D_CTLINPUT]) {
117 printf("clnp_er_input: m %p, src %s, reason x%x\n",
118 m, clnp_iso_addrp(src), reason);
119 }
120 #endif
121
122 INCSTAT(cns_er_inhist[clnp_er_index(reason)]);
123 switch (reason) {
124 case GEN_NOREAS:
125 case GEN_PROTOERR:
126 break;
127 case GEN_BADCSUM:
128 cmd = PRC_PARAMPROB;
129 break;
130 case GEN_CONGEST:
131 cmd = PRC_QUENCH;
132 break;
133 case GEN_HDRSYNTAX:
134 cmd = PRC_PARAMPROB;
135 break;
136 case GEN_SEGNEEDED:
137 cmd = PRC_MSGSIZE;
138 break;
139 case GEN_INCOMPLETE:
140 cmd = PRC_PARAMPROB;
141 break;
142 case GEN_DUPOPT:
143 cmd = PRC_PARAMPROB;
144 break;
145 case ADDR_DESTUNREACH:
146 cmd = PRC_UNREACH_HOST;
147 break;
148 case ADDR_DESTUNKNOWN:
149 cmd = PRC_UNREACH_PROTOCOL;
150 break;
151 case SRCRT_UNSPECERR:
152 case SRCRT_SYNTAX:
153 case SRCRT_UNKNOWNADDR:
154 case SRCRT_BADPATH:
155 cmd = PRC_UNREACH_SRCFAIL;
156 break;
157 case TTL_EXPTRANSIT:
158 cmd = PRC_TIMXCEED_INTRANS;
159 break;
160 case TTL_EXPREASS:
161 cmd = PRC_TIMXCEED_REASS;
162 break;
163 case DISC_UNSUPPOPT:
164 case DISC_UNSUPPVERS:
165 case DISC_UNSUPPSECURE:
166 case DISC_UNSUPPSRCRT:
167 case DISC_UNSUPPRECRT:
168 cmd = PRC_PARAMPROB;
169 break;
170 case REASS_INTERFERE:
171 cmd = PRC_TIMXCEED_REASS;
172 break;
173 }
174
175 /*
176 * tpclnp_ctlinput1 is called directly so that we don't
177 * have to build an iso_sockaddr out of src.
178 */
179 if (cmd >= 0)
180 tpclnp_ctlinput1(cmd, src);
181
182 m_freem(m);
183 }
184
185 /*
186 * FUNCTION: clnp_discard
187 *
188 * PURPOSE: Discard a clnp datagram
189 *
190 * RETURNS: nothing
191 *
192 * SIDE EFFECTS: Will emit an ER pdu if possible
193 *
194 * NOTES: This code assumes that we have previously tried to pull
195 * up the header of the datagram into one mbuf.
196 */
197 void
198 clnp_discard(m, reason)
199 struct mbuf *m; /* header of packet to discard */
200 u_int reason; /* reason for discard */
201 {
202 #ifdef ARGO_DEBUG
203 if (argo_debug[D_DISCARD]) {
204 printf("clnp_discard: m %p, reason x%x\n", m, reason);
205 }
206 #endif
207
208 if (m != NULL) {
209 if (m->m_len >= sizeof(struct clnp_fixed)) {
210 struct clnp_fixed *clnp =
211 mtod(m, struct clnp_fixed *);
212
213 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
214 (clnp->cnf_type & CNF_ERR_OK)) {
215 clnp_emit_er(m, reason);
216 return;
217 }
218 }
219 m_freem(m);
220 }
221 }
222
223 /*
224 * FUNCTION: clnp_emit_er
225 *
226 * PURPOSE: Send an ER pdu.
227 * The src of the of the ER pdu is the host that is sending
228 * the ER (ie. us), *not* the original destination of the
229 * packet.
230 *
231 * RETURNS: nothing
232 *
233 * SIDE EFFECTS:
234 *
235 * NOTES: Takes responsibility for freeing mbuf passed
236 * This function may be called with a packet that
237 * was created by us; in this case, do not send
238 * an ER.
239 */
240 void
241 clnp_emit_er(m, reason)
242 struct mbuf *m; /* header of packet to discard */
243 u_int reason; /* reason for discard */
244 {
245 struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
246 struct clnp_fixed *er;
247 struct route_iso route;
248 struct ifnet *ifp;
249 struct sockaddr *first_hop;
250 struct iso_addr src, dst, *our_addr;
251 caddr_t hoff, hend;
252 int total_len; /* total len of dg */
253 struct iso_ifaddr *ia = 0;
254
255 #ifdef ARGO_DEBUG
256 if (argo_debug[D_DISCARD]) {
257 printf("clnp_emit_er: m %p, hdr len %d\n",
258 m, clnp->cnf_hdr_len);
259 }
260 #endif
261
262 bzero((caddr_t) & route, sizeof(route));
263
264 /*
265 * If header length is incorrect, or entire header is not contained
266 * in this mbuf, we punt
267 */
268 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) ||
269 (clnp->cnf_hdr_len > CLNP_HDR_MAX) ||
270 (clnp->cnf_hdr_len > m->m_len))
271 goto bad;
272
273 /* extract src, dest address */
274 hend = (caddr_t) clnp + clnp->cnf_hdr_len;
275 hoff = (caddr_t) clnp + sizeof(struct clnp_fixed);
276 CLNP_EXTRACT_ADDR(dst, hoff, hend);
277 if (hoff == (caddr_t) 0) {
278 goto bad;
279 }
280 CLNP_EXTRACT_ADDR(src, hoff, hend);
281 if (hoff == (caddr_t) 0) {
282 goto bad;
283 }
284 /*
285 * Do not send ER if we generated the packet.
286 */
287 if (clnp_ours(&src))
288 goto bad;
289
290 /*
291 * Trim mbuf to hold only the header. This mbuf will be the 'data' of
292 * the er pdu
293 */
294 if (m->m_next != NULL) {
295 m_freem(m->m_next);
296 m->m_next = NULL;
297 }
298 if (m->m_len > clnp->cnf_hdr_len)
299 m_adj(m, (int) -(m->m_len - (int) clnp->cnf_hdr_len));
300
301 /* route er pdu: note we send pkt to src of original packet */
302 if (clnp_route(&src, &route, /* flags */ 0, &first_hop, &ia) != 0)
303 goto bad;
304
305 /* compute our address based upon firsthop/ifp */
306 if (ia)
307 our_addr = &ia->ia_addr.siso_addr;
308 else
309 goto bad;
310 ifp = ia->ia_ifp;
311
312 #ifdef ARGO_DEBUG
313 if (argo_debug[D_DISCARD]) {
314 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src));
315 printf(" from %s\n", clnp_iso_addrp(our_addr));
316 }
317 #endif
318
319 #ifdef ARGO_DEBUG
320 if (argo_debug[D_DISCARD]) {
321 printf("clnp_emit_er: packet routed to %s\n",
322 clnp_iso_addrp(&satosiso(first_hop)->siso_addr));
323 }
324 #endif
325
326 /* allocate mbuf for er pdu header: punt on no space */
327 /*
328 * fixed part, two addresses and their length bytes, and a
329 * 4-byte option
330 */
331
332 M_PREPEND(m, sizeof(struct clnp_fixed) + 4 + 1 + 1 +
333 src.isoa_len + our_addr->isoa_len, M_DONTWAIT);
334 if (m == 0)
335 goto bad;
336
337 er = mtod(m, struct clnp_fixed *);
338 *er = er_template;
339
340 /* setup src/dst on er pdu */
341 /* NOTE REVERSAL OF SRC/DST */
342 hoff = (caddr_t) er + sizeof(struct clnp_fixed);
343 CLNP_INSERT_ADDR(hoff, src);
344 CLNP_INSERT_ADDR(hoff, *our_addr);
345
346 /*
347 * TODO: if complete src rt was specified, then reverse path, and
348 * copy into er as option.
349 */
350
351 /* add er option */
352 *hoff++ = CLNPOVAL_ERREAS; /* code */
353 *hoff++ = 2; /* length */
354 *hoff++ = reason; /* discard reason */
355 *hoff++ = 0; /* error localization = not specified */
356
357 /* set length */
358 er->cnf_hdr_len = (u_char) (hoff - (caddr_t) er);
359 total_len = m->m_pkthdr.len;
360 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len);
361
362 /* compute checksum (on header only) */
363 iso_gen_csum(m, CLNP_CKSUM_OFF, (int) er->cnf_hdr_len);
364
365 /* trim packet if too large for interface */
366 if (total_len > ifp->if_mtu)
367 m_adj(m, -(total_len - ifp->if_mtu));
368
369 /* send packet */
370 INCSTAT(cns_er_outhist[clnp_er_index(reason)]);
371 (void) (*ifp->if_output) (ifp, m, first_hop, route.ro_rt);
372 goto done;
373
374 bad:
375 m_freem(m);
376
377 done:
378 /* free route if it is a temp */
379 if (route.ro_rt != NULL)
380 RTFREE(route.ro_rt);
381 }
382
383 int
384 clnp_er_index(u_int p)
385 {
386 u_char *cp = clnp_er_codes + CLNP_ERRORS;
387 while (cp > clnp_er_codes) {
388 cp--;
389 if (*cp == p)
390 return (cp - clnp_er_codes);
391 }
392 return (CLNP_ERRORS + 1);
393 }
Cache object: 00be230f00f3b220d2985c993628920e
|