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