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