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