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