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