|
|
1.1 root 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: *
1.1.1.3 ! root 33: * from: @(#)clnp_options.c 7.8 (Berkeley) 5/6/91
! 34: * clnp_options.c,v 1.2 1993/05/20 05:26:52 cgd Exp
1.1 root 35: */
36:
37: /***********************************************************
38: Copyright IBM Corporation 1987
39:
40: All Rights Reserved
41:
42: Permission to use, copy, modify, and distribute this software and its
43: documentation for any purpose and without fee is hereby granted,
44: provided that the above copyright notice appear in all copies and that
45: both that copyright notice and this permission notice appear in
46: supporting documentation, and that the name of IBM not be
47: used in advertising or publicity pertaining to distribution of the
48: software without specific, written prior permission.
49:
50: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
52: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56: SOFTWARE.
57:
58: ******************************************************************/
59:
60: /*
61: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
62: */
63:
64: #ifdef ISO
65:
66: #include "types.h"
67: #include "param.h"
68: #include "mbuf.h"
69: #include "domain.h"
70: #include "protosw.h"
71: #include "socket.h"
72: #include "socketvar.h"
73: #include "errno.h"
74:
75: #include "../net/if.h"
76: #include "../net/route.h"
77:
78: #include "iso.h"
79: #include "clnp.h"
80: #include "clnp_stat.h"
81: #include "argo_debug.h"
82:
83: /*
84: * FUNCTION: clnp_update_srcrt
85: *
86: * PURPOSE: Process src rt option accompanying a clnp datagram.
87: * - bump src route ptr if src routing and
88: * we appear current in src route list.
89: *
90: * RETURNS: none
91: *
92: * SIDE EFFECTS:
93: *
94: * NOTES: If source routing has been terminated, do nothing.
95: */
96: clnp_update_srcrt(options, oidx)
97: struct mbuf *options; /* ptr to options mbuf */
98: struct clnp_optidx *oidx; /* ptr to option index */
99: {
100: u_char len; /* length of current address */
101: struct iso_addr isoa; /* copy current address into here */
102:
103: if (CLNPSRCRT_TERM(oidx, options)) {
104: IFDEBUG(D_OPTIONS)
105: printf("clnp_update_srcrt: src rt terminated\n");
106: ENDDEBUG
107: return;
108: }
109:
110: len = CLNPSRCRT_CLEN(oidx, options);
111: bcopy(CLNPSRCRT_CADDR(oidx, options), (caddr_t)&isoa, len);
112: isoa.isoa_len = len;
113:
114: IFDEBUG(D_OPTIONS)
115: printf("clnp_update_srcrt: current src rt: %s\n",
116: clnp_iso_addrp(&isoa));
117: ENDDEBUG
118:
119: if (clnp_ours(&isoa)) {
120: IFDEBUG(D_OPTIONS)
121: printf("clnp_update_srcrt: updating src rt\n");
122: ENDDEBUG
123:
124: /* update pointer to next src route */
125: len++; /* count length byte too! */
126: CLNPSRCRT_OFF(oidx, options) += len;
127: }
128: }
129:
130: /*
131: * FUNCTION: clnp_dooptions
132: *
133: * PURPOSE: Process options accompanying a clnp datagram.
134: * Processing includes
135: * - log our address if recording route
136: *
137: * RETURNS: none
138: *
139: * SIDE EFFECTS:
140: *
141: * NOTES:
142: */
143: clnp_dooptions(options, oidx, ifp, isoa)
144: struct mbuf *options; /* ptr to options mbuf */
145: struct clnp_optidx *oidx; /* ptr to option index */
146: struct ifnet *ifp; /* ptr to interface pkt is leaving on */
147: struct iso_addr *isoa; /* ptr to our address for this ifp */
148: {
149: /*
150: * If record route is specified, move all
151: * existing records over, and insert the address of
152: * interface passed
153: */
154: if (oidx->cni_recrtp) {
155: char *opt; /* ptr to beginning of recrt option */
156: u_char off; /* offset from opt of first free byte */
157: char *rec_start; /* beginning of new rt recorded */
158:
159: opt = CLNP_OFFTOOPT(options, oidx->cni_recrtp);
160: off = *(opt + 1);
161: rec_start = opt + off - 1;
162:
163: IFDEBUG(D_OPTIONS)
164: printf("clnp_dooptions: record route: option x%x for %d bytes\n",
165: opt, oidx->cni_recrt_len);
166: printf("\tfree slot offset x%x\n", off);
167: printf("clnp_dooptions: recording %s\n", clnp_iso_addrp(isoa));
168: printf("clnp_dooptions: option dump:\n");
169: dump_buf(opt, oidx->cni_recrt_len);
170: ENDDEBUG
171:
172: /* proceed only if recording has not been terminated */
173: if (off != 0xff) {
174: int new_addrlen = isoa->isoa_len + 1;
175: /*
176: * if there is insufficient room to store the next address,
177: * then terminate recording. Plus 1 on isoa_len is for the
178: * length byte itself
179: */
180: if (oidx->cni_recrt_len - (off - 1) < new_addrlen) {
181: *(opt + 1) = 0xff; /* terminate recording */
182: } else {
183: IFDEBUG(D_OPTIONS)
184: printf("clnp_dooptions: new addr at x%x for %d\n",
185: rec_start, new_addrlen);
186: ENDDEBUG
187:
188: bcopy((caddr_t)isoa, rec_start, new_addrlen);
189:
190: /* update offset field */
191: *(opt + 1) += new_addrlen;
192:
193: IFDEBUG(D_OPTIONS)
194: printf("clnp_dooptions: new option dump:\n");
195: dump_buf(opt, oidx->cni_recrt_len);
196: ENDDEBUG
197: }
198: }
199: }
200: }
201:
202: /*
203: * FUNCTION: clnp_set_opts
204: *
205: * PURPOSE: Check the data mbuf passed for option sanity. If it is
206: * ok, then set the options ptr to address the data mbuf.
207: * If an options mbuf exists, free it. This implies that
208: * any old options will be lost. If data is NULL, simply
209: * free any old options.
210: *
211: * RETURNS: unix error code
212: *
213: * SIDE EFFECTS:
214: *
215: * NOTES:
216: */
217: clnp_set_opts(options, data)
218: struct mbuf **options; /* target for option information */
219: struct mbuf **data; /* source of option information */
220: {
221: int error = 0; /* error return value */
222: struct clnp_optidx dummy; /* dummy index - not used */
223:
224: /*
225: * remove any existing options
226: */
227: if (*options != NULL) {
228: m_freem(*options);
229: *options = NULL;
230: }
231:
232: if (*data != NULL) {
233: /*
234: * Insure that the options are reasonable.
235: *
236: * Also, we do not support security, priority,
237: * nor do we allow one to send an ER option
238: *
239: * The QOS parameter is checked for the DECBIT.
240: */
241: if ((clnp_opt_sanity(*data, mtod(*data, caddr_t), (*data)->m_len,
242: &dummy) != 0) ||
243: (dummy.cni_securep) ||
244: (dummy.cni_priorp) ||
245: (dummy.cni_er_reason != ER_INVALREAS)) {
246: error = EINVAL;
247: } else {
248: *options = *data;
249: *data = NULL; /* so caller won't free mbuf @ *data */
250: }
251: }
252: return error;
253: }
254:
255: /*
256: * FUNCTION: clnp_opt_sanity
257: *
258: * PURPOSE: Check the options (beginning at opts for len bytes) for
259: * sanity. In addition, fill in the option index structure
260: * in with information about each option discovered.
261: *
262: * RETURNS: success (options check out) - 0
263: * failure - an ER pdu error code describing failure
264: *
265: * SIDE EFFECTS:
266: *
267: * NOTES: Each pointer field of the option index is filled in with
268: * the offset from the beginning of the mbuf data, not the
269: * actual address.
270: */
271: clnp_opt_sanity(m, opts, len, oidx)
272: struct mbuf *m; /* mbuf options reside in */
273: caddr_t opts; /* ptr to buffer containing options */
274: int len; /* length of buffer */
275: struct clnp_optidx *oidx; /* RETURN: filled in with option idx info */
276: {
277: u_char opcode; /* code of particular option */
278: u_char oplen; /* length of a particular option */
279: caddr_t opts_end; /* ptr to end of options */
280: u_char pad = 0, secure = 0, srcrt = 0, recrt = 0, qos = 0, prior = 0;
281: /* flags for catching duplicate options */
282:
283: IFDEBUG(D_OPTIONS)
284: printf("clnp_opt_sanity: checking %d bytes of data:\n", len);
285: dump_buf(opts, len);
286: ENDDEBUG
287:
288: /* clear option index field if passed */
289: bzero((caddr_t)oidx, sizeof(struct clnp_optidx));
290:
291: /*
292: * We need to indicate whether the ER option is present. This is done
293: * by overloading the er_reason field to also indicate presense of
294: * the option along with the option value. I would like ER_INVALREAS
295: * to have value 0, but alas, 0 is a valid er reason...
296: */
297: oidx->cni_er_reason = ER_INVALREAS;
298:
299: opts_end = opts + len;
300: while (opts < opts_end) {
301: /* must have at least 2 bytes per option (opcode and len) */
302: if (opts + 2 > opts_end)
303: return(GEN_INCOMPLETE);
304:
305: opcode = *opts++;
306: oplen = *opts++;
307: IFDEBUG(D_OPTIONS)
308: printf("clnp_opt_sanity: opcode is %x and oplen %d\n",
309: opcode, oplen);
310: printf("clnp_opt_sanity: clnpoval_SRCRT is %x\n", CLNPOVAL_SRCRT);
311:
312: switch (opcode) {
313: case CLNPOVAL_PAD: {
314: printf("CLNPOVAL_PAD\n");
315: } break;
316: case CLNPOVAL_SECURE: {
317: printf("CLNPOVAL_SECURE\n");
318: } break;
319: case CLNPOVAL_SRCRT: {
320: printf("CLNPOVAL_SRCRT\n");
321: } break;
322: case CLNPOVAL_RECRT: {
323: printf("CLNPOVAL_RECRT\n");
324: } break;
325: case CLNPOVAL_QOS: {
326: printf("CLNPOVAL_QOS\n");
327: } break;
328: case CLNPOVAL_PRIOR: {
329: printf("CLNPOVAL_PRIOR\n");
330: } break;
331: case CLNPOVAL_ERREAS: {
332: printf("CLNPOVAL_ERREAS\n");
333: } break;
334: default:
335: printf("UKNOWN option %x\n", opcode);
336: }
337: ENDDEBUG
338:
339: /* don't allow crazy length values */
340: if (opts + oplen > opts_end)
341: return(GEN_INCOMPLETE);
342:
343: switch (opcode) {
344: case CLNPOVAL_PAD:
345: /*
346: * Padding: increment pointer by length of padding
347: */
348: if (pad++) /* duplicate ? */
349: return(GEN_DUPOPT);
350: opts += oplen;
351: break;
352:
353: case CLNPOVAL_SECURE: {
354: u_char format = *opts;
355:
356: if (secure++) /* duplicate ? */
357: return(GEN_DUPOPT);
358: /*
359: * Security: high 2 bits of first octet indicate format
360: * (00 in high bits is reserved).
361: * Remaining bits must be 0. Remaining octets indicate
362: * actual security
363: */
364: if (((format & 0x3f) > 0) || /* low 6 bits set ? */
365: ((format & 0xc0) == 0)) /* high 2 bits zero ? */
366: return(GEN_HDRSYNTAX);
367:
368: oidx->cni_securep = CLNP_OPTTOOFF(m, opts);
369: oidx->cni_secure_len = oplen;
370: opts += oplen;
371: } break;
372:
373: case CLNPOVAL_SRCRT: {
374: u_char type, offset; /* type of rt, offset of start */
375: caddr_t route_end; /* address of end of route option */
376:
377: IFDEBUG(D_OPTIONS)
378: printf("clnp_opt_sanity: SRC RT\n");
379: ENDDEBUG
380:
381: if (srcrt++) /* duplicate ? */
382: return(GEN_DUPOPT);
383: /*
384: * source route: There must be 2 bytes following the length
385: * field: type and offset. The type must be either
386: * partial route or complete route. The offset field must
387: * be within the option. A single exception is made, however.
388: * The offset may be 1 greater than the length. This case
389: * occurs when the last source route record is consumed.
390: * In this case, we ignore the source route option.
391: * RAH? You should be able to set offset to 'ff' like in record
392: * route!
393: * Following this is a series of address fields.
394: * Each address field is composed of a (length, address) pair.
395: * Insure that the offset and each address length is reasonable
396: */
397: route_end = opts + oplen;
398:
399: if (opts + 2 > route_end)
400: return(SRCRT_SYNTAX);
401:
402: type = *opts;
403: offset = *(opts+1);
404:
405:
406: /* type must be partial or complete */
407: if (!((type == CLNPOVAL_PARTRT) || (type == CLNPOVAL_COMPRT)))
408: return(SRCRT_SYNTAX);
409:
410: oidx->cni_srcrt_s = CLNP_OPTTOOFF(m, opts);
411: oidx->cni_srcrt_len = oplen;
412:
413: opts += offset-1; /*set opts to first addr in rt */
414:
415: /*
416: * Offset must be reasonable:
417: * less than end of options, or equal to end of options
418: */
419: if (opts >= route_end) {
420: if (opts == route_end) {
421: IFDEBUG(D_OPTIONS)
422: printf("clnp_opt_sanity: end of src route info\n");
423: ENDDEBUG
424: break;
425: } else
426: return(SRCRT_SYNTAX);
427: }
428:
429: while (opts < route_end) {
430: u_char addrlen = *opts++;
431: if (opts + addrlen > route_end)
432: return(SRCRT_SYNTAX);
433: opts += addrlen;
434: }
435: } break;
436: case CLNPOVAL_RECRT: {
437: u_char type, offset; /* type of rt, offset of start */
438: caddr_t record_end; /* address of end of record option */
439:
440: if (recrt++) /* duplicate ? */
441: return(GEN_DUPOPT);
442: /*
443: * record route: after the length field, expect a
444: * type and offset. Type must be partial or complete.
445: * Offset indicates where to start recording. Insure it
446: * is within the option. All ones for offset means
447: * recording is terminated.
448: */
449: record_end = opts + oplen;
450:
451: oidx->cni_recrtp = CLNP_OPTTOOFF(m, opts);
452: oidx->cni_recrt_len = oplen;
453:
454: if (opts + 2 > record_end)
455: return(GEN_INCOMPLETE);
456:
457: type = *opts;
458: offset = *(opts+1);
459:
460: /* type must be partial or complete */
461: if (!((type == CLNPOVAL_PARTRT) || (type == CLNPOVAL_COMPRT)))
462: return(GEN_HDRSYNTAX);
463:
464: /* offset must be reasonable */
465: if ((offset < 0xff) && (opts + offset > record_end))
466: return(GEN_HDRSYNTAX);
467: opts += oplen;
468: } break;
469: case CLNPOVAL_QOS: {
470: u_char format = *opts;
471:
472: if (qos++) /* duplicate ? */
473: return(GEN_DUPOPT);
474: /*
475: * qos: high 2 bits of first octet indicate format
476: * (00 in high bits is reserved).
477: * Remaining bits must be 0 (unless format indicates
478: * globally unique qos, in which case remaining bits indicate
479: * qos (except bit 6 which is reserved)). Otherwise,
480: * remaining octets indicate actual qos.
481: */
482: if (((format & 0xc0) == 0) || /* high 2 bits zero ? */
483: (((format & 0xc0) != CLNPOVAL_GLOBAL) &&
484: ((format & 0x3f) > 0))) /* not global,low bits used ? */
485: return(GEN_HDRSYNTAX);
486:
487: oidx->cni_qos_formatp = CLNP_OPTTOOFF(m, opts);
488: oidx->cni_qos_len = oplen;
489:
490: opts += oplen;
491: } break;
492:
493: case CLNPOVAL_PRIOR: {
494: if (prior++) /* duplicate ? */
495: return(GEN_DUPOPT);
496: /*
497: * priority: value must be one byte long
498: */
499: if (oplen != 1)
500: return(GEN_HDRSYNTAX);
501:
502: oidx->cni_priorp = CLNP_OPTTOOFF(m, opts);
503:
504: opts += oplen;
505: } break;
506:
507: case CLNPOVAL_ERREAS: {
508: /*
509: * er reason: value must be two bytes long
510: */
511: if (oplen != 2)
512: return(GEN_HDRSYNTAX);
513:
514: oidx->cni_er_reason = *opts;
515:
516: opts += oplen;
517: } break;
518:
519: default: {
520: IFDEBUG(D_OPTIONS)
521: printf("clnp_opt_sanity: UNKNOWN OPTION 0x%x\n", opcode);
522: ENDDEBUG
523: return(DISC_UNSUPPOPT);
524: }
525: }
526: }
527: IFDEBUG(D_OPTIONS)
528: printf("clnp_opt_sanity: return(0)\n", opcode);
529: ENDDEBUG
530: return(0);
531: }
532: #endif ISO
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.