|
|
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: */ ! 62: /* $Header: /var/src/sys/netiso/RCS/clnp_options.c,v 5.1 89/02/09 16:20:37 hagens Exp $ */ ! 63: /* $Source: /var/src/sys/netiso/RCS/clnp_options.c,v $ */ ! 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.