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