📄 msgparser.c
字号:
(struct generalized_fa_fa_key_rep_ext *) *msg_pos; switch (key->subtype) { default: DEBUG(DEBUG_FLAG, "Unknown generalized FA-FA key reply " "extension subtype\n"); print_gen_key_spi("FA_FA_KEY_REP(unknown)", "FA-FA", key); return -1; } *msg_pos += GET_GEN_FA_FA_KEY_REP_EXT_LEN(key); return 0;}/* handle Normal Vendor/Organization Specific Extension */static int handle_vendor_ext(char **msg_pos, struct msg_extensions *ext){ struct vendor_ext_header *vendor_head; unsigned char *c; int vendor_id, subtype; vendor_head = (struct vendor_ext_header *) *msg_pos; /* at least Sparc doesn't seem to like non-aligned data reading * so this hack is needed to avoid a possible Bus error. * The data is in network byte order, so make sure it converted to * host byte order here. */ c = (unsigned char *) &vendor_head->vendor_id; vendor_id = (*c << 24) + (*(c+1) << 16) + (*(c+2) << 8) + *(c+3); if (vendor_id == VENDOR_ID_DYNAMICS) { c = (unsigned char *) &vendor_head->sub_type; subtype = (*c << 8) + *(c+1); switch (subtype) { case VENDOR_EXT_DYNAMICS_OPTIONS: ext->ext_dyn = (struct registration_ext_dynamics *) vendor_head; DEBUG(DEBUG_FLAG, "\tdyn_options: type %i, length %i, " "vendor_id %i, sub_type %i, version %i,\n" "\t\topts %i, seq %u\n", ext->ext_dyn->type, ext->ext_dyn->length, vendor_id, subtype, ext->ext_dyn->version, ext->ext_dyn->opts, (u32) ntohl(ext->ext_dyn->seq)); *msg_pos += vendor_head->length + 2; break; case VENDOR_EXT_DYNAMICS_FA_KEYREQ: if (get_key_ext(&ext->fa_keyreq, "fa_keyreq", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_FA_PUBKEY: if (get_key_ext(&ext->fa_pubkey, "fa_pubkey", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_MN_KEYREQ: if (get_key_ext(&ext->mn_keyreq, "mn_keyreq", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_MN_KEYREP: if (get_key_ext(&ext->mn_keyrep, "mn_keyrep", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_FA_KEYREP: if (get_key_ext(&ext->fa_keyrep, "fa_keyrep", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_FA_PUBKEYREP: if (get_key_ext(&ext->fa_pubkeyrep, "fa_pubkeyrep", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_PUBKEY_HASH: if (get_key_ext(&ext->pubkey_hash, "pubkey_hash", msg_pos) != 0) return -2; break; case VENDOR_EXT_DYNAMICS_FF_AUTH: if (ext->ff_auth) { ext->double_auth_ext |= DOUBLE_FF_AUTH; DEBUG(DEBUG_FLAG, "double FF_AUTH\n"); } ext->ff_auth = (struct vendor_msg_auth *) *msg_pos; print_msg_auth_vendor(ext->ff_auth, "ff_auth"); *msg_pos += GET_VENDOR_AUTH_EXT_LEN(ext->ff_auth); break; case VENDOR_EXT_DYNAMICS_SK_AUTH: if (ext->sk_auth) { ext->double_auth_ext |= DOUBLE_SK_AUTH; DEBUG(DEBUG_FLAG, "double SK_AUTH\n"); return -2; } ext->sk_auth = (struct vendor_msg_auth *) *msg_pos; print_msg_auth_vendor(ext->sk_auth, "sk_auth"); *msg_pos += GET_VENDOR_AUTH_EXT_LEN(ext->sk_auth); break; case VENDOR_EXT_DYNAMICS_SHA_HA_AUTH: if (ext->sha_ha_auth) { ext->double_auth_ext |= DOUBLE_SHA_HA_AUTH; DEBUG(DEBUG_FLAG, "double SHA_HA_AUTH\n"); return -2; } ext->sha_ha_auth = (struct vendor_msg_auth *) *msg_pos; print_msg_auth_vendor(ext->sha_ha_auth, "sha_ha_auth"); *msg_pos += GET_VENDOR_AUTH_EXT_LEN(ext->sha_ha_auth); break; case VENDOR_EXT_DYNAMICS_FA_NAI: if (ext->fa_nai) { DEBUG(DEBUG_FLAG, "double FA_NAI\n"); return -2; } ext->fa_nai = (struct fa_nai_ext *) *msg_pos; print_nai_ext(ext->fa_nai, "fa_nai"); *msg_pos += GET_NAI_EXT_LEN(ext->fa_nai); break; case VENDOR_EXT_DYNAMICS_PREVIOUS_FA_NAI: if (ext->prev_fa_nai) { DEBUG(DEBUG_FLAG, "double PREV_FA_NAI\n"); return -2; } ext->prev_fa_nai = (struct fa_nai_ext *) *msg_pos; print_nai_ext(ext->prev_fa_nai, "prev_fa_nai"); *msg_pos += GET_NAI_EXT_LEN(ext->prev_fa_nai); break; case VENDOR_EXT_DYNAMICS_GRE_KEY: if (ext->gre_key) { DEBUG(DEBUG_FLAG, "double GRE_KEY\n"); return -2; } ext->gre_key = (struct gre_key_ext *) *msg_pos; print_gre_key(ext->gre_key); *msg_pos += GET_GRE_KEY_EXT_LEN(ext->gre_key); break; case VENDOR_EXT_DYNAMICS_SFA_DEBUG: if (ext->sfa_debug) { DEBUG(DEBUG_FLAG, "double SFA_DEBUG\n"); return -2; } ext->sfa_debug = (struct sfa_debug_ext *) *msg_pos; print_sfa_debug(ext->sfa_debug); *msg_pos += GET_SFA_DEBUG_EXT_LEN(ext->sfa_debug); break; case VENDOR_EXT_DYNAMICS_PRIV_HA: if (ext->priv_ha) { DEBUG(DEBUG_FLAG, "double PRIV_HA\n"); return -2; } ext->priv_ha = (struct priv_ha_ext *) *msg_pos; print_priv_ha(ext->priv_ha); *msg_pos += GET_PRIV_HA_EXT_LEN(ext->priv_ha); break; case VENDOR_EXT_DYNAMICS_NONCE: if (ext->nonce) { DEBUG(DEBUG_FLAG, "double nonce\n"); return -2; } ext->nonce = (struct nonce_ext *) *msg_pos; print_nonce(ext->nonce); *msg_pos += GET_NONCE_EXT_LEN(ext->nonce); break; default: DEBUG(DEBUG_FLAG, "Unknown Dynamics " "extension subtype %i\n", subtype); *msg_pos += vendor_head->length + 2; } } else { DEBUG(DEBUG_FLAG, "Unknown vendor ID %i - " "ignoring extension\n", vendor_id); *msg_pos += vendor_head->length + 2; } return 0;}/** * parse_msg: * @msg_start: pointer to the start of the message data * @len: length of the message * @ext: pointer to a memory area that will be filled with pointers to parsed * extensions. Extensions that were not present have pointers set to NULL. * * Parses a received Mobile IP registration request or reply. Note that the * message data is not copied and @ext contains pointers to the original data, * i.e., the original data area must not be modified or freed as long as the * message extensions are used. * * Returns: * 0 success, * -1 an unindentified extension is present, * -2 the message is malformed, * -3 a request contains an unknown/unsupported vendor ID in Critical * Vendor/Organization Specific Extension (CVSE) before MN-HA auth * -4 a request contains an unknown/unsupported vendor ID in CVSE * after MN-HA auth * -5 a reply contains an unknown/unsupport vendor ID in CVSE */int parse_msg(char *msg_start, int len, struct msg_extensions *ext){ char *msg_pos = msg_start; struct msg_auth *auth; unsigned char ext_type, ext_len; int ret; assert(msg_start && ext); if (len < 1) { DEBUG(DEBUG_FLAG, "parse_msg: too short message\n"); return -2; } memset(ext, 0, sizeof(struct msg_extensions)); ext->start = msg_start; ext->len = len; switch ((unsigned char) msg_pos[0]) { case REG_REQ: ext->req = (struct reg_req *)msg_pos; print_reg_req(ext->req); msg_pos += sizeof(struct reg_req); break; case REG_REP: ext->rep = (struct reg_rep *)msg_pos; print_reg_rep(ext->rep); msg_pos += sizeof(struct reg_rep); break; case FA_REQ: ext->fa_req = (struct fa_reg_req *)msg_pos; print_fa_reg_req(ext->fa_req); msg_pos += sizeof(struct fa_reg_req); break; case FA_REP: ext->fa_rep = (struct fa_reg_rep *)msg_pos; print_fa_reg_rep(ext->fa_rep); msg_pos += sizeof(struct fa_reg_rep); break; default: DEBUG(DEBUG_FLAG, "parse_msg: unknown message type %i\n", (unsigned char) msg_pos[0]); return -2; } while (msg_pos < msg_start + len) { unsigned int extlen; switch ((unsigned char) msg_pos[0]) { case ONE_BYTE_PADDING: extlen = 1; break; case GENERALIZED_AUTH_EXT: case GENERALIZED_MN_FA_KEY_REQ_EXT: case GENERALIZED_MN_FA_KEY_REP_EXT: case GENERALIZED_MN_HA_KEY_REQ_EXT: case GENERALIZED_MN_HA_KEY_REP_EXT: case GENERALIZED_FA_HA_KEY_REP_EXT: case GENERALIZED_FA_FA_KEY_REP_EXT: if (msg_pos + 3 >= msg_start + len) { DEBUG(DEBUG_FLAG, "parse_msg: gen. auth. ext " "too short\n"); return -2; } extlen = ((unsigned char) msg_pos[2] << 8) + (unsigned char) msg_pos[3]; break; default: if (msg_pos + 1 >= msg_start + len) { DEBUG(DEBUG_FLAG, "parse_msg: ext too " "short\n"); return -2; } extlen = (unsigned char) msg_pos[1]; } if (msg_pos + extlen > msg_start + len) { char *c; DEBUG(DEBUG_FLAG, "parse_msg: message too short for " "current extension (extlen=%i, over=%i)\n", extlen, msg_pos + extlen - msg_start - len); DEBUG(DEBUG_FLAG, "dump:"); c = msg_pos; while (c < msg_start + len) { DEBUG(DEBUG_FLAG, " %02X", (unsigned char) *c++); } DEBUG(DEBUG_FLAG, "\n"); return -2; } switch ((unsigned char)msg_pos[0]) { case MH_AUTH: case MF_AUTH: case FH_AUTH: auth = (struct msg_auth *)msg_pos; if (auth->length < SPI_LEN) { DEBUG(DEBUG_FLAG, "parse_msg: AUTH too short\n"); return -2; } break; } switch ((unsigned char)msg_pos[0]) { case ONE_BYTE_PADDING: msg_pos++; break; case MH_AUTH: if (ext->mh_auth) { DEBUG(DEBUG_FLAG, "parse_msg: double MH_AUTH\n"); ext->double_auth_ext |= DOUBLE_MH_AUTH; } ext->mh_auth = (struct msg_auth *)msg_pos; print_msg_auth(ext->mh_auth, "mh_auth"); msg_pos += GET_AUTH_EXT_LEN(ext->mh_auth); break; case MF_AUTH: if (ext->mf_auth) { DEBUG(DEBUG_FLAG, "parse_msg: double MF_AUTH\n"); ext->double_auth_ext |= DOUBLE_MF_AUTH; } ext->mf_auth = (struct msg_auth *)msg_pos; print_msg_auth(ext->mf_auth, "mf_auth"); msg_pos += GET_AUTH_EXT_LEN(ext->mf_auth); break; case FH_AUTH: if (ext->fh_auth) { DEBUG(DEBUG_FLAG, "parse_msg: double FH_AUTH\n"); ext->double_auth_ext |= DOUBLE_FH_AUTH; } ext->fh_auth = (struct msg_auth *)msg_pos; print_msg_auth(ext->fh_auth, "fh_auth"); msg_pos += GET_AUTH_EXT_LEN(ext->fh_auth); break; case GENERALIZED_AUTH_EXT: ret = handle_gen_auth_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_MN_FA_KEY_REQ_EXT: ret = handle_gen_mn_fa_key_req_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_MN_FA_KEY_REP_EXT: ret = handle_gen_mn_fa_key_rep_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_MN_HA_KEY_REQ_EXT: ret = handle_gen_mn_ha_key_req_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_MN_HA_KEY_REP_EXT: ret = handle_gen_mn_ha_key_rep_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_FA_HA_KEY_REP_EXT: ret = handle_gen_fa_ha_key_rep_ext(&msg_pos, ext); if (ret != 0) return ret; break; case GENERALIZED_FA_FA_KEY_REP_EXT: ret = handle_gen_fa_fa_key_rep_ext(&msg_pos, ext); if (ret != 0) return ret; break; case MN_NAI_EXT: if (ext->mn_nai) { DEBUG(DEBUG_FLAG, "double MN_NAI_EXT\n"); print_mn_nai((struct mn_nai_ext *) msg_pos); return -2; } ext->mn_nai = (struct mn_nai_ext *) msg_pos; print_mn_nai(ext->mn_nai); msg_pos += GET_MN_NAI_EXT_LEN(ext->mn_nai); break; case MN_FA_CHALLENGE_EXT: if (ext->challenge) { DEBUG(DEBUG_FLAG, "double MN_FA_CHALLENGE_EXT\n"); print_challenge((struct challenge_ext *) msg_pos); return -2; } ext->challenge = (struct challenge_ext *) msg_pos; print_challenge(ext->challenge); msg_pos += GET_CHALLENGE_EXT_LEN(ext->challenge); break; case ENCAPS_DELIVERY_EXT: ext->encaps_del = (struct encaps_delivery_ext *) msg_pos; if (!ext->req || ext->encaps_del->length != 0) { DEBUG(DEBUG_FLAG, "parse_msg: ENCAPS_DELIVERY\n"); return -2; } DEBUG(DEBUG_FLAG, "\tencaps_delivery\n"); msg_pos += 2 + ext->encaps_del->length; break; case VENDOR_EXT_TYPE1: DEBUG(DEBUG_FLAG, "\tunknown CVSE\n"); ext->unknown_cvse = 1; if (ext->req) { if (ext->mh_auth) return -4; else return -3; } return -5; case VENDOR_EXT_TYPE2: if (handle_vendor_ext(&msg_pos, ext) != 0) return -2; break; default: ext_type = (unsigned char) msg_pos[0]; ext_len = (unsigned char) msg_pos[1]; DEBUG(DEBUG_FLAG, "Unknown extension type %i, len %i - ", (unsigned char) ext_type, ext_len); /* RFC2002, section 1.9: * unknown 0..127 ==> discard message * unknown 128..255 ==> ignore extension but process * the rest of the message */ if (ext_type < 128) { DEBUG(DEBUG_FLAG, "discarding message\n"); return -1; } else { DEBUG(DEBUG_FLAG, "ignoring extension\n"); msg_pos += ext_len + 2; break; } } } /* check that the extensions have not been too long */ if (msg_pos > msg_start + len) { DEBUG(DEBUG_FLAG, "parse_msg: too long extensions\n"); return -2; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -