]> git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/clnp_er.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / netiso / clnp_er.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*-
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 *
54 * @(#)clnp_er.c 8.1 (Berkeley) 6/10/93
55 */
56
57 /***********************************************************
58 Copyright IBM Corporation 1987
59
60 All Rights Reserved
61
62 Permission to use, copy, modify, and distribute this software and its
63 documentation for any purpose and without fee is hereby granted,
64 provided that the above copyright notice appear in all copies and that
65 both that copyright notice and this permission notice appear in
66 supporting documentation, and that the name of IBM not be
67 used in advertising or publicity pertaining to distribution of the
68 software without specific, written prior permission.
69
70 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76 SOFTWARE.
77
78 ******************************************************************/
79
80 /*
81 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
82 */
83
84 #include <sys/param.h>
85 #include <sys/mbuf.h>
86 #include <sys/domain.h>
87 #include <sys/protosw.h>
88 #include <sys/socket.h>
89 #include <sys/socketvar.h>
90 #include <sys/errno.h>
91
92 #include <net/if.h>
93 #include <net/route.h>
94
95 #include <netiso/iso.h>
96 #include <netiso/iso_var.h>
97 #include <netiso/iso_pcb.h>
98 #define CLNP_ER_CODES
99 #include <netiso/clnp.h>
100 #include <netiso/clnp_stat.h>
101 #include <netiso/argo_debug.h>
102
103 static struct clnp_fixed er_template = {
104 ISO8473_CLNP, /* network identifier */
105 0, /* length */
106 ISO8473_V1, /* version */
107 CLNP_TTL, /* ttl */
108 CLNP_ER, /* type */
109 0, /* segment length */
110 0 /* checksum */
111 };
112
113 /*
114 * FUNCTION: clnp_er_input
115 *
116 * PURPOSE: Process an ER pdu.
117 *
118 * RETURNS:
119 *
120 * SIDE EFFECTS:
121 *
122 * NOTES:
123 */
124 clnp_er_input(m, src, reason)
125 struct mbuf *m; /* ptr to packet itself */
126 struct iso_addr *src; /* ptr to src of er */
127 u_char reason; /* reason code of er */
128 {
129 int cmd = -1;
130 extern u_char clnp_protox[];
131
132 IFDEBUG(D_CTLINPUT)
133 printf("clnp_er_input: m x%x, src %s, reason x%x\n", m,
134 clnp_iso_addrp(src), reason);
135 ENDDEBUG
136
137 INCSTAT(cns_er_inhist[clnp_er_index(reason)]);
138 switch (reason) {
139 case GEN_NOREAS:
140 case GEN_PROTOERR:
141 break;
142 case GEN_BADCSUM:
143 cmd = PRC_PARAMPROB;
144 break;
145 case GEN_CONGEST:
146 cmd = PRC_QUENCH;
147 break;
148 case GEN_HDRSYNTAX:
149 cmd = PRC_PARAMPROB;
150 break;
151 case GEN_SEGNEEDED:
152 cmd = PRC_MSGSIZE;
153 break;
154 case GEN_INCOMPLETE:
155 cmd = PRC_PARAMPROB;
156 break;
157 case GEN_DUPOPT:
158 cmd = PRC_PARAMPROB;
159 break;
160 case ADDR_DESTUNREACH:
161 cmd = PRC_UNREACH_HOST;
162 break;
163 case ADDR_DESTUNKNOWN:
164 cmd = PRC_UNREACH_PROTOCOL;
165 break;
166 case SRCRT_UNSPECERR:
167 case SRCRT_SYNTAX:
168 case SRCRT_UNKNOWNADDR:
169 case SRCRT_BADPATH:
170 cmd = PRC_UNREACH_SRCFAIL;
171 break;
172 case TTL_EXPTRANSIT:
173 cmd = PRC_TIMXCEED_INTRANS;
174 break;
175 case TTL_EXPREASS:
176 cmd = PRC_TIMXCEED_REASS;
177 break;
178 case DISC_UNSUPPOPT:
179 case DISC_UNSUPPVERS:
180 case DISC_UNSUPPSECURE:
181 case DISC_UNSUPPSRCRT:
182 case DISC_UNSUPPRECRT:
183 cmd = PRC_PARAMPROB;
184 break;
185 case REASS_INTERFERE:
186 cmd = PRC_TIMXCEED_REASS;
187 break;
188 }
189
190 /*
191 * tpclnp_ctlinput1 is called directly so that we don't
192 * have to build an iso_sockaddr out of src.
193 */
194 if (cmd >= 0)
195 tpclnp_ctlinput1(cmd, src);
196
197 m_freem(m);
198 }
199
200 /*
201 * FUNCTION: clnp_discard
202 *
203 * PURPOSE: Discard a clnp datagram
204 *
205 * RETURNS: nothing
206 *
207 * SIDE EFFECTS: Will emit an ER pdu if possible
208 *
209 * NOTES: This code assumes that we have previously tried to pull
210 * up the header of the datagram into one mbuf.
211 */
212 clnp_discard(m, reason)
213 struct mbuf *m; /* header of packet to discard */
214 char reason; /* reason for discard */
215 {
216 IFDEBUG(D_DISCARD)
217 printf("clnp_discard: m x%x, reason x%x\n", m, reason);
218 ENDDEBUG
219
220 if (m != NULL) {
221 if (m->m_len >= sizeof(struct clnp_fixed)) {
222 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
223
224 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
225 (clnp->cnf_type & CNF_ERR_OK)) {
226 clnp_emit_er(m, reason);
227 return;
228 }
229 }
230 m_freem(m);
231 }
232 }
233
234 /*
235 * FUNCTION: clnp_emit_er
236 *
237 * PURPOSE: Send an ER pdu.
238 * The src of the of the ER pdu is the host that is sending
239 * the ER (ie. us), *not* the original destination of the
240 * packet.
241 *
242 * RETURNS: nothing
243 *
244 * SIDE EFFECTS:
245 *
246 * NOTES: Takes responsibility for freeing mbuf passed
247 * This function may be called with a packet that
248 * was created by us; in this case, do not send
249 * an ER.
250 */
251 clnp_emit_er(m, reason)
252 struct mbuf *m; /* header of packet to discard */
253 char reason; /* reason for discard */
254 {
255 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
256 register struct clnp_fixed *er;
257 struct route_iso route;
258 struct ifnet *ifp;
259 struct sockaddr *first_hop;
260 struct iso_addr src, dst, *our_addr;
261 caddr_t hoff, hend;
262 int total_len; /* total len of dg */
263 struct mbuf *m0; /* contains er pdu hdr */
264 struct iso_ifaddr *ia = 0;
265
266 IFDEBUG(D_DISCARD)
267 printf("clnp_emit_er: m x%x, hdr len %d\n", m, clnp->cnf_hdr_len);
268 ENDDEBUG
269
270 bzero((caddr_t)&route, sizeof(route));
271
272 /*
273 * If header length is incorrect, or entire header is not contained
274 * in this mbuf, we punt
275 */
276 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) ||
277 (clnp->cnf_hdr_len > CLNP_HDR_MAX) ||
278 (clnp->cnf_hdr_len > m->m_len))
279 goto bad;
280
281 /* extract src, dest address */
282 hend = (caddr_t)clnp + clnp->cnf_hdr_len;
283 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
284 CLNP_EXTRACT_ADDR(dst, hoff, hend);
285 if (hoff == (caddr_t)0) {
286 goto bad;
287 }
288 CLNP_EXTRACT_ADDR(src, hoff, hend);
289 if (hoff == (caddr_t)0) {
290 goto bad;
291 }
292
293 /*
294 * Do not send ER if we generated the packet.
295 */
296 if (clnp_ours(&src))
297 goto bad;
298
299 /*
300 * Trim mbuf to hold only the header.
301 * This mbuf will be the 'data' of the er pdu
302 */
303 if (m->m_next != NULL) {
304 m_freem(m->m_next);
305 m->m_next = NULL;
306 }
307
308 if (m->m_len > clnp->cnf_hdr_len)
309 m_adj(m, (int)-(m->m_len - (int)clnp->cnf_hdr_len));
310
311 /* route er pdu: note we send pkt to src of original packet */
312 if (clnp_route(&src, &route, /* flags */0, &first_hop, &ia) != 0)
313 goto bad;
314
315 /* compute our address based upon firsthop/ifp */
316 if (ia)
317 our_addr = &ia->ia_addr.siso_addr;
318 else
319 goto bad;
320 ifp = ia->ia_ifp;
321
322 IFDEBUG(D_DISCARD)
323 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src));
324 printf(" from %s\n", clnp_iso_addrp(our_addr));
325 ENDDEBUG
326
327 IFDEBUG(D_DISCARD)
328 printf("clnp_emit_er: packet routed to %s\n",
329 clnp_iso_addrp(&((struct sockaddr_iso *)first_hop)->siso_addr));
330 ENDDEBUG
331
332 /* allocate mbuf for er pdu header: punt on no space */
333 MGET(m0, M_DONTWAIT, MT_HEADER);
334 if (m0 == 0)
335 goto bad;
336
337 m0->m_next = m;
338 er = mtod(m0, struct clnp_fixed *);
339 *er = er_template;
340
341 /* setup src/dst on er pdu */
342 /* NOTE REVERSAL OF SRC/DST */
343 hoff = (caddr_t)er + sizeof(struct clnp_fixed);
344 CLNP_INSERT_ADDR(hoff, src);
345 CLNP_INSERT_ADDR(hoff, *our_addr);
346
347 /*
348 * TODO: if complete src rt was specified, then reverse path, and
349 * copy into er as option.
350 */
351
352 /* add er option */
353 *hoff++ = CLNPOVAL_ERREAS; /* code */
354 *hoff++ = 2; /* length */
355 *hoff++ = reason; /* discard reason */
356 *hoff++ = 0; /* error localization = not specified */
357
358 /* set length */
359 er->cnf_hdr_len = m0->m_len = (u_char)(hoff - (caddr_t)er);
360 total_len = m0->m_len + m->m_len;
361 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len);
362
363 /* compute checksum (on header only) */
364 iso_gen_csum(m0, CLNP_CKSUM_OFF, (int)er->cnf_hdr_len);
365
366 /* trim packet if too large for interface */
367 if (total_len > ifp->if_mtu)
368 m_adj(m0, -(total_len - ifp->if_mtu));
369
370 /* send packet */
371 INCSTAT(cns_er_outhist[clnp_er_index(reason)]);
372 (void) (*ifp->if_output)(ifp, m0, first_hop, route.ro_rt);
373 goto done;
374
375 bad:
376 m_freem(m);
377
378 done:
379 /* free route if it is a temp */
380 if (route.ro_rt != NULL)
381 RTFREE(route.ro_rt);
382 }
383
384 clnp_er_index(p)
385 u_char p;
386 {
387 register 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);
392 }
393 return (CLNP_ERRORS + 1);
394 }