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