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