This commit was generated by cvs2svn to track changes on a CVS vendor
[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 33 * from: @(#)clnp_er.c 7.7 (Berkeley) 5/6/91
fde1aeb2 34 * $Id: clnp_er.c,v 1.3 1993/11/25 01:35:40 wollman Exp $
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"
fde1aeb2 65#include "systm.h"
15637ed4
RG
66#include "mbuf.h"
67#include "domain.h"
68#include "protosw.h"
69#include "socket.h"
70#include "socketvar.h"
71#include "errno.h"
72
73#include "../net/if.h"
74#include "../net/route.h"
75
76#include "iso.h"
77#include "iso_var.h"
78#include "iso_pcb.h"
79#define CLNP_ER_CODES
80#include "clnp.h"
81#include "clnp_stat.h"
82#include "argo_debug.h"
83
84static struct clnp_fixed er_template = {
85 ISO8473_CLNP, /* network identifier */
86 0, /* length */
87 ISO8473_V1, /* version */
88 CLNP_TTL, /* ttl */
89 CLNP_ER, /* type */
90 0, /* segment length */
91 0 /* checksum */
92};
93
94/*
95 * FUNCTION: clnp_er_input
96 *
97 * PURPOSE: Process an ER pdu.
98 *
99 * RETURNS:
100 *
101 * SIDE EFFECTS:
102 *
103 * NOTES:
104 */
4c45483e 105void
15637ed4 106clnp_er_input(m, src, reason)
4c45483e
GW
107 struct mbuf *m; /* ptr to packet itself */
108 struct iso_addr *src; /* ptr to src of er */
109 u_char reason; /* reason code of er */
15637ed4
RG
110{
111 int cmd = -1;
112 extern u_char clnp_protox[];
113
114 IFDEBUG(D_CTLINPUT)
115 printf("clnp_er_input: m x%x, src %s, reason x%x\n", m,
116 clnp_iso_addrp(src), reason);
117 ENDDEBUG
118
119 INCSTAT(cns_er_inhist[clnp_er_index(reason)]);
120 switch (reason) {
121 case GEN_NOREAS:
122 case GEN_PROTOERR:
123 break;
124 case GEN_BADCSUM:
125 cmd = PRC_PARAMPROB;
126 break;
127 case GEN_CONGEST:
128 cmd = PRC_QUENCH;
129 break;
130 case GEN_HDRSYNTAX:
131 cmd = PRC_PARAMPROB;
132 break;
133 case GEN_SEGNEEDED:
134 cmd = PRC_MSGSIZE;
135 break;
136 case GEN_INCOMPLETE:
137 cmd = PRC_PARAMPROB;
138 break;
139 case GEN_DUPOPT:
140 cmd = PRC_PARAMPROB;
141 break;
142 case ADDR_DESTUNREACH:
143 cmd = PRC_UNREACH_HOST;
144 break;
145 case ADDR_DESTUNKNOWN:
146 cmd = PRC_UNREACH_PROTOCOL;
147 break;
148 case SRCRT_UNSPECERR:
149 case SRCRT_SYNTAX:
150 case SRCRT_UNKNOWNADDR:
151 case SRCRT_BADPATH:
152 cmd = PRC_UNREACH_SRCFAIL;
153 break;
154 case TTL_EXPTRANSIT:
155 cmd = PRC_TIMXCEED_INTRANS;
156 break;
157 case TTL_EXPREASS:
158 cmd = PRC_TIMXCEED_REASS;
159 break;
160 case DISC_UNSUPPOPT:
161 case DISC_UNSUPPVERS:
162 case DISC_UNSUPPSECURE:
163 case DISC_UNSUPPSRCRT:
164 case DISC_UNSUPPRECRT:
165 cmd = PRC_PARAMPROB;
166 break;
167 case REASS_INTERFERE:
168 cmd = PRC_TIMXCEED_REASS;
169 break;
170 }
171
172 /*
173 * tpclnp_ctlinput1 is called directly so that we don't
174 * have to build an iso_sockaddr out of src.
175 */
176 if (cmd >= 0)
177 tpclnp_ctlinput1(cmd, src);
178
179 m_freem(m);
180}
181
182/*
183 * FUNCTION: clnp_discard
184 *
185 * PURPOSE: Discard a clnp datagram
186 *
187 * RETURNS: nothing
188 *
189 * SIDE EFFECTS: Will emit an ER pdu if possible
190 *
191 * NOTES: This code assumes that we have previously tried to pull
192 * up the header of the datagram into one mbuf.
193 */
4c45483e 194void
15637ed4 195clnp_discard(m, reason)
4c45483e
GW
196 struct mbuf *m; /* header of packet to discard */
197 char reason; /* reason for discard */
15637ed4
RG
198{
199 IFDEBUG(D_DISCARD)
200 printf("clnp_discard: m x%x, reason x%x\n", m, reason);
201 ENDDEBUG
202
203 if (m != NULL) {
204 if (m->m_len >= sizeof(struct clnp_fixed)) {
205 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
206
207 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
208 (clnp->cnf_type & CNF_ERR_OK)) {
209 clnp_emit_er(m, reason);
210 return;
211 }
212 }
213 m_freem(m);
214 }
215}
216
217/*
218 * FUNCTION: clnp_emit_er
219 *
220 * PURPOSE: Send an ER pdu.
221 * The src of the of the ER pdu is the host that is sending
222 * the ER (ie. us), *not* the original destination of the
223 * packet.
224 *
225 * RETURNS: nothing
226 *
227 * SIDE EFFECTS:
228 *
229 * NOTES: Takes responsibility for freeing mbuf passed
230 * This function may be called with a packet that
231 * was created by us; in this case, do not send
232 * an ER.
233 */
4c45483e 234void
15637ed4 235clnp_emit_er(m, reason)
4c45483e
GW
236 struct mbuf *m; /* header of packet to discard */
237 char reason; /* reason for discard */
15637ed4
RG
238{
239 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
240 register struct clnp_fixed *er;
241 struct route_iso route;
242 struct ifnet *ifp;
243 struct sockaddr *first_hop;
244 struct iso_addr src, dst, *our_addr;
245 caddr_t hoff, hend;
246 int total_len; /* total len of dg */
247 struct mbuf *m0; /* contains er pdu hdr */
248 struct iso_ifaddr *ia = 0;
249
250 IFDEBUG(D_DISCARD)
251 printf("clnp_emit_er: m x%x, hdr len %d\n", m, clnp->cnf_hdr_len);
252 ENDDEBUG
253
254 bzero((caddr_t)&route, sizeof(route));
255
256 /*
257 * If header length is incorrect, or entire header is not contained
258 * in this mbuf, we punt
259 */
260 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) ||
261 (clnp->cnf_hdr_len > CLNP_HDR_MAX) ||
262 (clnp->cnf_hdr_len > m->m_len))
263 goto bad;
264
265 /* extract src, dest address */
266 hend = (caddr_t)clnp + clnp->cnf_hdr_len;
267 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
268 CLNP_EXTRACT_ADDR(dst, hoff, hend);
269 if (hoff == (caddr_t)0) {
270 goto bad;
271 }
272 CLNP_EXTRACT_ADDR(src, hoff, hend);
273 if (hoff == (caddr_t)0) {
274 goto bad;
275 }
276
277 /*
278 * Do not send ER if we generated the packet.
279 */
280 if (clnp_ours(&src))
281 goto bad;
282
283 /*
284 * Trim mbuf to hold only the header.
285 * This mbuf will be the 'data' of the er pdu
286 */
287 if (m->m_next != NULL) {
288 m_freem(m->m_next);
289 m->m_next = NULL;
290 }
291
292 if (m->m_len > clnp->cnf_hdr_len)
293 m_adj(m, (int)-(m->m_len - (int)clnp->cnf_hdr_len));
294
295 /* route er pdu: note we send pkt to src of original packet */
296 if (clnp_route(&src, &route, /* flags */0, &first_hop, &ia) != 0)
297 goto bad;
298
299 /* compute our address based upon firsthop/ifp */
300 if (ia)
301 our_addr = &ia->ia_addr.siso_addr;
302 else
303 goto bad;
304 ifp = ia->ia_ifp;
305
306 IFDEBUG(D_DISCARD)
307 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src));
308 printf(" from %s\n", clnp_iso_addrp(our_addr));
309 ENDDEBUG
310
311 IFDEBUG(D_DISCARD)
312 printf("clnp_emit_er: packet routed to %s\n",
313 clnp_iso_addrp(&((struct sockaddr_iso *)first_hop)->siso_addr));
314 ENDDEBUG
315
316 /* allocate mbuf for er pdu header: punt on no space */
317 MGET(m0, M_DONTWAIT, MT_HEADER);
318 if (m0 == 0)
319 goto bad;
320
321 m0->m_next = m;
322 er = mtod(m0, struct clnp_fixed *);
323 *er = er_template;
324
325 /* setup src/dst on er pdu */
326 /* NOTE REVERSAL OF SRC/DST */
327 hoff = (caddr_t)er + sizeof(struct clnp_fixed);
328 CLNP_INSERT_ADDR(hoff, src);
329 CLNP_INSERT_ADDR(hoff, *our_addr);
330
331 /*
332 * TODO: if complete src rt was specified, then reverse path, and
333 * copy into er as option.
334 */
335
336 /* add er option */
337 *hoff++ = CLNPOVAL_ERREAS; /* code */
338 *hoff++ = 2; /* length */
339 *hoff++ = reason; /* discard reason */
340 *hoff++ = 0; /* error localization = not specified */
341
342 /* set length */
343 er->cnf_hdr_len = m0->m_len = (u_char)(hoff - (caddr_t)er);
344 total_len = m0->m_len + m->m_len;
345 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len);
346
347 /* compute checksum (on header only) */
348 iso_gen_csum(m0, CLNP_CKSUM_OFF, (int)er->cnf_hdr_len);
349
350 /* trim packet if too large for interface */
351 if (total_len > ifp->if_mtu)
352 m_adj(m0, -(total_len - ifp->if_mtu));
353
354 /* send packet */
355 INCSTAT(cns_er_outhist[clnp_er_index(reason)]);
356 (void) (*ifp->if_output)(ifp, m0, first_hop, route.ro_rt);
357 goto done;
358
359bad:
360 m_freem(m);
361
362done:
363 /* free route if it is a temp */
364 if (route.ro_rt != NULL)
365 RTFREE(route.ro_rt);
366}
367
4c45483e 368int
15637ed4 369clnp_er_index(p)
4c45483e 370 u_char p;
15637ed4
RG
371{
372 register u_char *cp = clnp_er_codes + CLNP_ERRORS;
373 while (cp > clnp_er_codes) {
374 cp--;
375 if (*cp == p)
376 return (cp - clnp_er_codes);
377 }
378 return (CLNP_ERRORS + 1);
379}