📄 clnp_options.c
字号:
* the offset from the beginning of the mbuf data, not the * actual address. */clnp_opt_sanity(m, opts, len, oidx)struct mbuf *m; /* mbuf options reside in */caddr_t opts; /* ptr to buffer containing options */int len; /* length of buffer */struct clnp_optidx *oidx; /* RETURN: filled in with option idx info */{ u_char opcode; /* code of particular option */ u_char oplen; /* length of a particular option */ caddr_t opts_end; /* ptr to end of options */ u_char pad = 0, secure = 0, srcrt = 0, recrt = 0, qos = 0, prior = 0; /* flags for catching duplicate options */ IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: checking %d bytes of data:\n", len); dump_buf(opts, len); ENDDEBUG /* clear option index field if passed */ bzero((caddr_t)oidx, sizeof(struct clnp_optidx)); /* * We need to indicate whether the ER option is present. This is done * by overloading the er_reason field to also indicate presense of * the option along with the option value. I would like ER_INVALREAS * to have value 0, but alas, 0 is a valid er reason... */ oidx->cni_er_reason = ER_INVALREAS; opts_end = opts + len; while (opts < opts_end) { /* must have at least 2 bytes per option (opcode and len) */ if (opts + 2 > opts_end) return(GEN_INCOMPLETE); opcode = *opts++; oplen = *opts++; IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: opcode is %x and oplen %d\n", opcode, oplen); printf("clnp_opt_sanity: clnpoval_SRCRT is %x\n", CLNPOVAL_SRCRT); switch (opcode) { case CLNPOVAL_PAD: { printf("CLNPOVAL_PAD\n"); } break; case CLNPOVAL_SECURE: { printf("CLNPOVAL_SECURE\n"); } break; case CLNPOVAL_SRCRT: { printf("CLNPOVAL_SRCRT\n"); } break; case CLNPOVAL_RECRT: { printf("CLNPOVAL_RECRT\n"); } break; case CLNPOVAL_QOS: { printf("CLNPOVAL_QOS\n"); } break; case CLNPOVAL_PRIOR: { printf("CLNPOVAL_PRIOR\n"); } break; case CLNPOVAL_ERREAS: { printf("CLNPOVAL_ERREAS\n"); } break; default: printf("UKNOWN option %x\n", opcode); } ENDDEBUG /* don't allow crazy length values */ if (opts + oplen > opts_end) return(GEN_INCOMPLETE); switch (opcode) { case CLNPOVAL_PAD: /* * Padding: increment pointer by length of padding */ if (pad++) /* duplicate ? */ return(GEN_DUPOPT); opts += oplen; break; case CLNPOVAL_SECURE: { u_char format = *opts; if (secure++) /* duplicate ? */ return(GEN_DUPOPT); /* * Security: high 2 bits of first octet indicate format * (00 in high bits is reserved). * Remaining bits must be 0. Remaining octets indicate * actual security */ if (((format & 0x3f) > 0) || /* low 6 bits set ? */ ((format & 0xc0) == 0)) /* high 2 bits zero ? */ return(GEN_HDRSYNTAX); oidx->cni_securep = CLNP_OPTTOOFF(m, opts); oidx->cni_secure_len = oplen; opts += oplen; } break; case CLNPOVAL_SRCRT: { u_char type, offset; /* type of rt, offset of start */ caddr_t route_end; /* address of end of route option */ IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: SRC RT\n"); ENDDEBUG if (srcrt++) /* duplicate ? */ return(GEN_DUPOPT); /* * source route: There must be 2 bytes following the length * field: type and offset. The type must be either * partial route or complete route. The offset field must * be within the option. A single exception is made, however. * The offset may be 1 greater than the length. This case * occurs when the last source route record is consumed. * In this case, we ignore the source route option. * RAH? You should be able to set offset to 'ff' like in record * route! * Following this is a series of address fields. * Each address field is composed of a (length, address) pair. * Insure that the offset and each address length is reasonable */ route_end = opts + oplen; if (opts + 2 > route_end) return(SRCRT_SYNTAX); type = *opts; offset = *(opts+1); /* type must be partial or complete */ if (!((type == CLNPOVAL_PARTRT) || (type == CLNPOVAL_COMPRT))) return(SRCRT_SYNTAX); oidx->cni_srcrt_s = CLNP_OPTTOOFF(m, opts); oidx->cni_srcrt_len = oplen; opts += offset-1; /*set opts to first addr in rt */ /* * Offset must be reasonable: * less than end of options, or equal to end of options */ if (opts >= route_end) { if (opts == route_end) { IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: end of src route info\n"); ENDDEBUG break; } else return(SRCRT_SYNTAX); } while (opts < route_end) { u_char addrlen = *opts++; if (opts + addrlen > route_end) return(SRCRT_SYNTAX); opts += addrlen; } } break; case CLNPOVAL_RECRT: { u_char type, offset; /* type of rt, offset of start */ caddr_t record_end; /* address of end of record option */ if (recrt++) /* duplicate ? */ return(GEN_DUPOPT); /* * record route: after the length field, expect a * type and offset. Type must be partial or complete. * Offset indicates where to start recording. Insure it * is within the option. All ones for offset means * recording is terminated. */ record_end = opts + oplen; oidx->cni_recrtp = CLNP_OPTTOOFF(m, opts); oidx->cni_recrt_len = oplen; if (opts + 2 > record_end) return(GEN_INCOMPLETE); type = *opts; offset = *(opts+1); /* type must be partial or complete */ if (!((type == CLNPOVAL_PARTRT) || (type == CLNPOVAL_COMPRT))) return(GEN_HDRSYNTAX); /* offset must be reasonable */ if ((offset < 0xff) && (opts + offset > record_end)) return(GEN_HDRSYNTAX); opts += oplen; } break; case CLNPOVAL_QOS: { u_char format = *opts; if (qos++) /* duplicate ? */ return(GEN_DUPOPT); /* * qos: high 2 bits of first octet indicate format * (00 in high bits is reserved). * Remaining bits must be 0 (unless format indicates * globally unique qos, in which case remaining bits indicate * qos (except bit 6 which is reserved)). Otherwise, * remaining octets indicate actual qos. */ if (((format & 0xc0) == 0) || /* high 2 bits zero ? */ (((format & 0xc0) != CLNPOVAL_GLOBAL) && ((format & 0x3f) > 0))) /* not global,low bits used ? */ return(GEN_HDRSYNTAX); oidx->cni_qos_formatp = CLNP_OPTTOOFF(m, opts); oidx->cni_qos_len = oplen; opts += oplen; } break; case CLNPOVAL_PRIOR: { if (prior++) /* duplicate ? */ return(GEN_DUPOPT); /* * priority: value must be one byte long */ if (oplen != 1) return(GEN_HDRSYNTAX); oidx->cni_priorp = CLNP_OPTTOOFF(m, opts); opts += oplen; } break; case CLNPOVAL_ERREAS: { /* * er reason: value must be two bytes long */ if (oplen != 2) return(GEN_HDRSYNTAX); oidx->cni_er_reason = *opts; opts += oplen; } break; default: { IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: UNKNOWN OPTION 0x%x\n", opcode); ENDDEBUG return(DISC_UNSUPPOPT); } } } IFDEBUG(D_OPTIONS) printf("clnp_opt_sanity: return(0)\n", opcode); ENDDEBUG return(0);}#endif /* ISO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -