1 /* $NetBSD: clnp_er.c,v 1.24 2008/01/14 04:17:35 dyoung Exp $ */
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
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
31 * @(#)clnp_er.c 8.1 (Berkeley) 6/10/93
34 /***********************************************************
35 Copyright IBM Corporation 1987
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
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>
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>
74 #include <net/route.h>
76 #include <netiso/iso.h>
77 #include <netiso/iso_var.h>
78 #include <netiso/iso_pcb.h>
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 */
89 ISO8473_V1
, /* version */
92 0, /* segment length msb */
93 0, /* segment length lsb */
95 0, /* checksum lmsb */
99 * FUNCTION: clnp_er_input
101 * PURPOSE: Process an ER pdu.
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 */
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
);
124 INCSTAT(cns_er_inhist
[clnp_er_index(reason
)]);
147 case ADDR_DESTUNREACH
:
148 cmd
= PRC_UNREACH_HOST
;
150 case ADDR_DESTUNKNOWN
:
151 cmd
= PRC_UNREACH_PROTOCOL
;
153 case SRCRT_UNSPECERR
:
155 case SRCRT_UNKNOWNADDR
:
157 cmd
= PRC_UNREACH_SRCFAIL
;
160 cmd
= PRC_TIMXCEED_INTRANS
;
163 cmd
= PRC_TIMXCEED_REASS
;
166 case DISC_UNSUPPVERS
:
167 case DISC_UNSUPPSECURE
:
168 case DISC_UNSUPPSRCRT
:
169 case DISC_UNSUPPRECRT
:
172 case REASS_INTERFERE
:
173 cmd
= PRC_TIMXCEED_REASS
;
178 * tpclnp_ctlinput1 is called directly so that we don't
179 * have to build an iso_sockaddr out of src.
182 tpclnp_ctlinput1(cmd
, src
);
188 * FUNCTION: clnp_discard
190 * PURPOSE: Discard a clnp datagram
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.
200 clnp_discard(struct mbuf
*m
, u_int reason
)
201 /* m: header of packet to discard */
202 /* reason: reason for discard */
205 if (argo_debug
[D_DISCARD
]) {
206 printf("clnp_discard: m %p, reason x%x\n", m
, reason
);
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
);
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
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
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
;
251 const struct sockaddr
*first_hop
;
252 struct iso_addr src
, dst
, *our_addr
;
254 int total_len
; /* total len of dg */
255 struct iso_ifaddr
*ia
= 0;
258 if (argo_debug
[D_DISCARD
]) {
259 printf("clnp_emit_er: m %p, hdr len %d\n",
260 m
, clnp
->cnf_hdr_len
);
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
))
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) {
282 CLNP_EXTRACT_ADDR(src
, hoff
, hend
);
283 if (hoff
== (void *) 0) {
287 * Do not send ER if we generated the packet.
293 * Trim mbuf to hold only the header. This mbuf will be the 'data' of
296 if (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)
307 /* compute our address based upon firsthop/ifp */
309 our_addr
= &ia
->ia_addr
.siso_addr
;
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
));
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
));
328 /* allocate mbuf for er pdu header: punt on no space */
330 * fixed part, two addresses and their length bytes, and a
334 M_PREPEND(m
, sizeof(struct clnp_fixed
) + 4 + 1 + 1 +
335 src
.isoa_len
+ our_addr
->isoa_len
, M_DONTWAIT
);
339 er
= mtod(m
, struct clnp_fixed
*);
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.
354 *hoff
++ = CLNPOVAL_ERREAS
; /* code */
355 *hoff
++ = 2; /* length */
356 *hoff
++ = reason
; /* discard reason */
357 *hoff
++ = 0; /* error localization = not specified */
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
));
372 INCSTAT(cns_er_outhist
[clnp_er_index(reason
)]);
373 (void) (*ifp
->if_output
) (ifp
, m
, first_hop
, rtcache_validate(&route
));
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
) {
391 return (cp
- clnp_er_codes
);
393 return (CLNP_ERRORS
+ 1);