|
|
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.