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