No empty .Rs/.Re
[netbsd-mini2440.git] / sys / netiso / clnp_er.c
blobbae6c273c5b6c8d1cc1ecb5549f734bbb46ae1c9
1 /* $NetBSD: clnp_er.c,v 1.24 2008/01/14 04:17:35 dyoung Exp $ */
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
31 * @(#)clnp_er.c 8.1 (Berkeley) 6/10/93
34 /***********************************************************
35 Copyright IBM Corporation 1987
37 All Rights Reserved
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.
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.
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: clnp_er.c,v 1.24 2008/01/14 04:17:35 dyoung Exp $");
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>
73 #include <net/if.h>
74 #include <net/route.h>
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>
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 msb */
93 0, /* segment length lsb */
94 0, /* checksum msb */
95 0, /* checksum lmsb */
99 * FUNCTION: clnp_er_input
101 * PURPOSE: Process an ER pdu.
103 * RETURNS:
105 * SIDE EFFECTS:
107 * NOTES:
109 void
110 clnp_er_input(
111 struct mbuf *m, /* ptr to packet itself */
112 struct iso_addr *src, /* ptr to src of er */
113 u_int reason) /* reason code of er */
115 int cmd = -1;
117 #ifdef ARGO_DEBUG
118 if (argo_debug[D_CTLINPUT]) {
119 printf("clnp_er_input: m %p, src %s, reason x%x\n",
120 m, clnp_iso_addrp(src), reason);
122 #endif
124 INCSTAT(cns_er_inhist[clnp_er_index(reason)]);
125 switch (reason) {
126 case GEN_NOREAS:
127 case GEN_PROTOERR:
128 break;
129 case GEN_BADCSUM:
130 cmd = PRC_PARAMPROB;
131 break;
132 case GEN_CONGEST:
133 cmd = PRC_QUENCH;
134 break;
135 case GEN_HDRSYNTAX:
136 cmd = PRC_PARAMPROB;
137 break;
138 case GEN_SEGNEEDED:
139 cmd = PRC_MSGSIZE;
140 break;
141 case GEN_INCOMPLETE:
142 cmd = PRC_PARAMPROB;
143 break;
144 case GEN_DUPOPT:
145 cmd = PRC_PARAMPROB;
146 break;
147 case ADDR_DESTUNREACH:
148 cmd = PRC_UNREACH_HOST;
149 break;
150 case ADDR_DESTUNKNOWN:
151 cmd = PRC_UNREACH_PROTOCOL;
152 break;
153 case SRCRT_UNSPECERR:
154 case SRCRT_SYNTAX:
155 case SRCRT_UNKNOWNADDR:
156 case SRCRT_BADPATH:
157 cmd = PRC_UNREACH_SRCFAIL;
158 break;
159 case TTL_EXPTRANSIT:
160 cmd = PRC_TIMXCEED_INTRANS;
161 break;
162 case TTL_EXPREASS:
163 cmd = PRC_TIMXCEED_REASS;
164 break;
165 case DISC_UNSUPPOPT:
166 case DISC_UNSUPPVERS:
167 case DISC_UNSUPPSECURE:
168 case DISC_UNSUPPSRCRT:
169 case DISC_UNSUPPRECRT:
170 cmd = PRC_PARAMPROB;
171 break;
172 case REASS_INTERFERE:
173 cmd = PRC_TIMXCEED_REASS;
174 break;
178 * tpclnp_ctlinput1 is called directly so that we don't
179 * have to build an iso_sockaddr out of src.
181 if (cmd >= 0)
182 tpclnp_ctlinput1(cmd, src);
184 m_freem(m);
188 * FUNCTION: clnp_discard
190 * PURPOSE: Discard a clnp datagram
192 * RETURNS: nothing
194 * SIDE EFFECTS: Will emit an ER pdu if possible
196 * NOTES: This code assumes that we have previously tried to pull
197 * up the header of the datagram into one mbuf.
199 void
200 clnp_discard(struct mbuf *m, u_int reason)
201 /* m: header of packet to discard */
202 /* reason: reason for discard */
204 #ifdef ARGO_DEBUG
205 if (argo_debug[D_DISCARD]) {
206 printf("clnp_discard: m %p, reason x%x\n", m, reason);
208 #endif
210 if (m != NULL) {
211 if (m->m_len >= sizeof(struct clnp_fixed)) {
212 struct clnp_fixed *clnp =
213 mtod(m, struct clnp_fixed *);
215 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
216 (clnp->cnf_type & CNF_ERR_OK)) {
217 clnp_emit_er(m, reason);
218 return;
221 m_freem(m);
226 * FUNCTION: clnp_emit_er
228 * PURPOSE: Send an ER pdu.
229 * The src of the of the ER pdu is the host that is sending
230 * the ER (ie. us), *not* the original destination of the
231 * packet.
233 * RETURNS: nothing
235 * SIDE EFFECTS:
237 * NOTES: Takes responsibility for freeing mbuf passed
238 * This function may be called with a packet that
239 * was created by us; in this case, do not send
240 * an ER.
242 void
243 clnp_emit_er(struct mbuf *m, u_int reason)
244 /* m: header of packet to discard */
245 /* reason: reason for discard */
247 struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
248 struct clnp_fixed *er;
249 struct route route;
250 struct ifnet *ifp;
251 const struct sockaddr *first_hop;
252 struct iso_addr src, dst, *our_addr;
253 char *hoff, *hend;
254 int total_len; /* total len of dg */
255 struct iso_ifaddr *ia = 0;
257 #ifdef ARGO_DEBUG
258 if (argo_debug[D_DISCARD]) {
259 printf("clnp_emit_er: m %p, hdr len %d\n",
260 m, clnp->cnf_hdr_len);
262 #endif
264 memset(&route, 0, sizeof(route));
267 * If header length is incorrect, or entire header is not contained
268 * in this mbuf, we punt
270 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) ||
271 (clnp->cnf_hdr_len > CLNP_HDR_MAX) ||
272 (clnp->cnf_hdr_len > m->m_len))
273 goto bad;
275 /* extract src, dest address */
276 hend = (char *)clnp + clnp->cnf_hdr_len;
277 hoff = (char *)clnp + sizeof(struct clnp_fixed);
278 CLNP_EXTRACT_ADDR(dst, hoff, hend);
279 if (hoff == (void *) 0) {
280 goto bad;
282 CLNP_EXTRACT_ADDR(src, hoff, hend);
283 if (hoff == (void *) 0) {
284 goto bad;
287 * Do not send ER if we generated the packet.
289 if (clnp_ours(&src))
290 goto bad;
293 * Trim mbuf to hold only the header. This mbuf will be the 'data' of
294 * the er pdu
296 if (m->m_next != NULL) {
297 m_freem(m->m_next);
298 m->m_next = NULL;
300 if (m->m_len > clnp->cnf_hdr_len)
301 m_adj(m, (int) -(m->m_len - (int) clnp->cnf_hdr_len));
303 /* route er pdu: note we send pkt to src of original packet */
304 if (clnp_route(&src, &route, /* flags */ 0, &first_hop, &ia) != 0)
305 goto bad;
307 /* compute our address based upon firsthop/ifp */
308 if (ia)
309 our_addr = &ia->ia_addr.siso_addr;
310 else
311 goto bad;
312 ifp = ia->ia_ifp;
314 #ifdef ARGO_DEBUG
315 if (argo_debug[D_DISCARD]) {
316 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src));
317 printf(" from %s\n", clnp_iso_addrp(our_addr));
319 #endif
321 #ifdef ARGO_DEBUG
322 if (argo_debug[D_DISCARD]) {
323 printf("clnp_emit_er: packet routed to %s\n",
324 clnp_iso_addrp(&satocsiso(first_hop)->siso_addr));
326 #endif
328 /* allocate mbuf for er pdu header: punt on no space */
330 * fixed part, two addresses and their length bytes, and a
331 * 4-byte option
334 M_PREPEND(m, sizeof(struct clnp_fixed) + 4 + 1 + 1 +
335 src.isoa_len + our_addr->isoa_len, M_DONTWAIT);
336 if (m == 0)
337 goto bad;
339 er = mtod(m, struct clnp_fixed *);
340 *er = er_template;
342 /* setup src/dst on er pdu */
343 /* NOTE REVERSAL OF SRC/DST */
344 hoff = (char *)er + sizeof(struct clnp_fixed);
345 CLNP_INSERT_ADDR(hoff, src);
346 CLNP_INSERT_ADDR(hoff, *our_addr);
349 * TODO: if complete src rt was specified, then reverse path, and
350 * copy into er as option.
353 /* add er option */
354 *hoff++ = CLNPOVAL_ERREAS; /* code */
355 *hoff++ = 2; /* length */
356 *hoff++ = reason; /* discard reason */
357 *hoff++ = 0; /* error localization = not specified */
359 /* set length */
360 er->cnf_hdr_len = (u_char) (hoff - (char *)er);
361 total_len = m->m_pkthdr.len;
362 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len);
364 /* compute checksum (on header only) */
365 iso_gen_csum(m, CLNP_CKSUM_OFF, (int) er->cnf_hdr_len);
367 /* trim packet if too large for interface */
368 if (total_len > ifp->if_mtu)
369 m_adj(m, -(total_len - ifp->if_mtu));
371 /* send packet */
372 INCSTAT(cns_er_outhist[clnp_er_index(reason)]);
373 (void) (*ifp->if_output) (ifp, m, first_hop, rtcache_validate(&route));
374 goto done;
376 bad:
377 m_freem(m);
379 done:
380 /* free route if it is a temp */
381 rtcache_free(&route);
385 clnp_er_index(u_int p)
387 u_char *cp = clnp_er_codes + CLNP_ERRORS;
388 while (cp > clnp_er_codes) {
389 cp--;
390 if (*cp == p)
391 return (cp - clnp_er_codes);
393 return (CLNP_ERRORS + 1);