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 *
33 * @(#)clnp_er.c 7.7 (Berkeley) 5/6/91
34 */
35
36/***********************************************************
37 Copyright IBM Corporation 1987
38
39 All Rights Reserved
40
41Permission to use, copy, modify, and distribute this software and its
42documentation for any purpose and without fee is hereby granted,
43provided that the above copyright notice appear in all copies and that
44both that copyright notice and this permission notice appear in
45supporting documentation, and that the name of IBM not be
46used in advertising or publicity pertaining to distribution of the
47software without specific, written prior permission.
48
49IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
50ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
51IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
52ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
53WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
54ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55SOFTWARE.
56
57******************************************************************/
58
59/*
60 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 */
62/* $Header: /var/src/sys/netiso/RCS/clnp_er.c,v 5.1 89/02/09 16:20:18 hagens Exp $ */
63/* $Source: /var/src/sys/netiso/RCS/clnp_er.c,v $ */
64
65#include "param.h"
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 */
105clnp_er_input(m, src, reason)
106struct mbuf *m; /* ptr to packet itself */
107struct iso_addr *src; /* ptr to src of er */
108u_char reason; /* reason code of er */
109{
110 int cmd = -1;
111 extern u_char clnp_protox[];
112
113 IFDEBUG(D_CTLINPUT)
114 printf("clnp_er_input: m x%x, src %s, reason x%x\n", m,
115 clnp_iso_addrp(src), reason);
116 ENDDEBUG
117
118 INCSTAT(cns_er_inhist[clnp_er_index(reason)]);
119 switch (reason) {
120 case GEN_NOREAS:
121 case GEN_PROTOERR:
122 break;
123 case GEN_BADCSUM:
124 cmd = PRC_PARAMPROB;
125 break;
126 case GEN_CONGEST:
127 cmd = PRC_QUENCH;
128 break;
129 case GEN_HDRSYNTAX:
130 cmd = PRC_PARAMPROB;
131 break;
132 case GEN_SEGNEEDED:
133 cmd = PRC_MSGSIZE;
134 break;
135 case GEN_INCOMPLETE:
136 cmd = PRC_PARAMPROB;
137 break;
138 case GEN_DUPOPT:
139 cmd = PRC_PARAMPROB;
140 break;
141 case ADDR_DESTUNREACH:
142 cmd = PRC_UNREACH_HOST;
143 break;
144 case ADDR_DESTUNKNOWN:
145 cmd = PRC_UNREACH_PROTOCOL;
146 break;
147 case SRCRT_UNSPECERR:
148 case SRCRT_SYNTAX:
149 case SRCRT_UNKNOWNADDR:
150 case SRCRT_BADPATH:
151 cmd = PRC_UNREACH_SRCFAIL;
152 break;
153 case TTL_EXPTRANSIT:
154 cmd = PRC_TIMXCEED_INTRANS;
155 break;
156 case TTL_EXPREASS:
157 cmd = PRC_TIMXCEED_REASS;
158 break;
159 case DISC_UNSUPPOPT:
160 case DISC_UNSUPPVERS:
161 case DISC_UNSUPPSECURE:
162 case DISC_UNSUPPSRCRT:
163 case DISC_UNSUPPRECRT:
164 cmd = PRC_PARAMPROB;
165 break;
166 case REASS_INTERFERE:
167 cmd = PRC_TIMXCEED_REASS;
168 break;
169 }
170
171 /*
172 * tpclnp_ctlinput1 is called directly so that we don't
173 * have to build an iso_sockaddr out of src.
174 */
175 if (cmd >= 0)
176 tpclnp_ctlinput1(cmd, src);
177
178 m_freem(m);
179}
180
181/*
182 * FUNCTION: clnp_discard
183 *
184 * PURPOSE: Discard a clnp datagram
185 *
186 * RETURNS: nothing
187 *
188 * SIDE EFFECTS: Will emit an ER pdu if possible
189 *
190 * NOTES: This code assumes that we have previously tried to pull
191 * up the header of the datagram into one mbuf.
192 */
193clnp_discard(m, reason)
194struct mbuf *m; /* header of packet to discard */
195char reason; /* reason for discard */
196{
197 IFDEBUG(D_DISCARD)
198 printf("clnp_discard: m x%x, reason x%x\n", m, reason);
199 ENDDEBUG
200
201 if (m != NULL) {
202 if (m->m_len >= sizeof(struct clnp_fixed)) {
203 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
204
205 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
206 (clnp->cnf_type & CNF_ERR_OK)) {
207 clnp_emit_er(m, reason);
208 return;
209 }
210 }
211 m_freem(m);
212 }
213}
214
215/*
216 * FUNCTION: clnp_emit_er
217 *
218 * PURPOSE: Send an ER pdu.
219 * The src of the of the ER pdu is the host that is sending
220 * the ER (ie. us), *not* the original destination of the
221 * packet.
222 *
223 * RETURNS: nothing
224 *
225 * SIDE EFFECTS:
226 *
227 * NOTES: Takes responsibility for freeing mbuf passed
228 * This function may be called with a packet that
229 * was created by us; in this case, do not send
230 * an ER.
231 */
232clnp_emit_er(m, reason)
233struct mbuf *m; /* header of packet to discard */
234char reason; /* reason for discard */
235{
236 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
237 register struct clnp_fixed *er;
238 struct route_iso route;
239 struct ifnet *ifp;
240 struct sockaddr *first_hop;
241 struct iso_addr src, dst, *our_addr;
242 caddr_t hoff, hend;
243 int total_len; /* total len of dg */
244 struct mbuf *m0; /* contains er pdu hdr */
245 struct iso_ifaddr *ia = 0;
246
247 IFDEBUG(D_DISCARD)
248 printf("clnp_emit_er: m x%x, hdr len %d\n", m, clnp->cnf_hdr_len);
249 ENDDEBUG
250
251 bzero((caddr_t)&route, sizeof(route));
252
253 /*
254 * If header length is incorrect, or entire header is not contained
255 * in this mbuf, we punt
256 */
257 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) ||
258 (clnp->cnf_hdr_len > CLNP_HDR_MAX) ||
259 (clnp->cnf_hdr_len > m->m_len))
260 goto bad;
261
262 /* extract src, dest address */
263 hend = (caddr_t)clnp + clnp->cnf_hdr_len;
264 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
265 CLNP_EXTRACT_ADDR(dst, hoff, hend);
266 if (hoff == (caddr_t)0) {
267 goto bad;
268 }
269 CLNP_EXTRACT_ADDR(src, hoff, hend);
270 if (hoff == (caddr_t)0) {
271 goto bad;
272 }
273
274 /*
275 * Do not send ER if we generated the packet.
276 */
277 if (clnp_ours(&src))
278 goto bad;
279
280 /*
281 * Trim mbuf to hold only the header.
282 * This mbuf will be the 'data' of the er pdu
283 */
284 if (m->m_next != NULL) {
285 m_freem(m->m_next);
286 m->m_next = NULL;
287 }
288
289 if (m->m_len > clnp->cnf_hdr_len)
290 m_adj(m, (int)-(m->m_len - (int)clnp->cnf_hdr_len));
291
292 /* route er pdu: note we send pkt to src of original packet */
293 if (clnp_route(&src, &route, /* flags */0, &first_hop, &ia) != 0)
294 goto bad;
295
296 /* compute our address based upon firsthop/ifp */
297 if (ia)
298 our_addr = &ia->ia_addr.siso_addr;
299 else
300 goto bad;
301 ifp = ia->ia_ifp;
302
303 IFDEBUG(D_DISCARD)
304 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src));
305 printf(" from %s\n", clnp_iso_addrp(our_addr));
306 ENDDEBUG
307
308 IFDEBUG(D_DISCARD)
309 printf("clnp_emit_er: packet routed to %s\n",
310 clnp_iso_addrp(&((struct sockaddr_iso *)first_hop)->siso_addr));
311 ENDDEBUG
312
313 /* allocate mbuf for er pdu header: punt on no space */
314 MGET(m0, M_DONTWAIT, MT_HEADER);
315 if (m0 == 0)
316 goto bad;
317
318 m0->m_next = m;
319 er = mtod(m0, struct clnp_fixed *);
320 *er = er_template;
321
322 /* setup src/dst on er pdu */
323 /* NOTE REVERSAL OF SRC/DST */
324 hoff = (caddr_t)er + sizeof(struct clnp_fixed);
325 CLNP_INSERT_ADDR(hoff, src);
326 CLNP_INSERT_ADDR(hoff, *our_addr);
327
328 /*
329 * TODO: if complete src rt was specified, then reverse path, and
330 * copy into er as option.
331 */
332
333 /* add er option */
334 *hoff++ = CLNPOVAL_ERREAS; /* code */
335 *hoff++ = 2; /* length */
336 *hoff++ = reason; /* discard reason */
337 *hoff++ = 0; /* error localization = not specified */
338
339 /* set length */
340 er->cnf_hdr_len = m0->m_len = (u_char)(hoff - (caddr_t)er);
341 total_len = m0->m_len + m->m_len;
342 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len);
343
344 /* compute checksum (on header only) */
345 iso_gen_csum(m0, CLNP_CKSUM_OFF, (int)er->cnf_hdr_len);
346
347 /* trim packet if too large for interface */
348 if (total_len > ifp->if_mtu)
349 m_adj(m0, -(total_len - ifp->if_mtu));
350
351 /* send packet */
352 INCSTAT(cns_er_outhist[clnp_er_index(reason)]);
353 (void) (*ifp->if_output)(ifp, m0, first_hop, route.ro_rt);
354 goto done;
355
356bad:
357 m_freem(m);
358
359done:
360 /* free route if it is a temp */
361 if (route.ro_rt != NULL)
362 RTFREE(route.ro_rt);
363}
364
365clnp_er_index(p)
366u_char p;
367{
368 register u_char *cp = clnp_er_codes + CLNP_ERRORS;
369 while (cp > clnp_er_codes) {
370 cp--;
371 if (*cp == p)
372 return (cp - clnp_er_codes);
373 }
374 return (CLNP_ERRORS + 1);
375}