📄 fa_hash.c
字号:
ntohs(upper_fa_addr.sin_port)); res = own_sendto(up_interface->udp_sock, upper_fa_addr.sin_addr, upper_fa_addr.sin_port, buf, pos - buf); dynamics_check_sendto(res, pos - buf, "fa_register"); own_req_pending = 1;}static int validate_fa_reg(char *msg, struct msg_extensions *ext, struct sockaddr_in *cli_addr){ struct fa_spi_entry *fa_spi; if (ext->ff_auth == NULL) { LOG2(LOG_ALERT, "FA reg. - no ff_auth ext - FA=%s\n", inet_ntoa(cli_addr->sin_addr)); return -1; } if (ext->fa_nai == NULL) { LOG2(LOG_ALERT, "FA reg. - no fa_nai ext - FA=%s\n", inet_ntoa(cli_addr->sin_addr)); return -2; } fa_spi = get_fa_spi(0, cli_addr->sin_addr, SPI_AGENT_FA); if (fa_spi == NULL) { LOG2(LOG_ALERT, "FA reg. - no shared secret - FA=%s\n", inet_ntoa(cli_addr->sin_addr)); return -3; } if (!auth_check_vendor(AUTH_ALG_MD5, fa_spi->shared_secret, fa_spi->shared_secret_len, (unsigned char *) msg, ext->ff_auth)) { LOG2(LOG_ALERT, "FA reg. - authentication failed - FA=%s\n", inet_ntoa(cli_addr->sin_addr)); return -4; } return 0;}static void send_fa_reg_reply(__u8 code, struct msg_extensions *ext, struct sockaddr_in *cli_addr, struct interface_entry *iface, __u8 *next_nonce){ char buf[MAXMSG], *pos; struct fa_reg_rep *rep; struct fa_spi_entry *fa_spi; int res; rep = (struct fa_reg_rep *) buf; memset(rep, 0, sizeof(struct fa_reg_rep)); rep->type = FA_REP; rep->code = code; memcpy(&rep->down_nonce, &ext->fa_req->down_nonce, FA_REG_NONCE_LEN); if (next_nonce != NULL) memcpy(&rep->up_nonce, next_nonce, FA_REG_NONCE_LEN); pos = (char *) (rep + 1); if (ext->fa_nai != NULL) { memcpy(pos, ext->fa_nai, GET_NAI_EXT_LEN(ext->fa_nai)); pos += GET_NAI_EXT_LEN(ext->fa_nai); } fa_spi = get_fa_spi(0, cli_addr->sin_addr, SPI_AGENT_FA); if (fa_spi != NULL) { pos += auth_add_vendor( AUTH_ALG_MD5, fa_spi->shared_secret, fa_spi->shared_secret_len, (unsigned char *) buf, (struct vendor_msg_auth *) pos, VENDOR_EXT_DYNAMICS_FF_AUTH, htonl(fa_spi->spi)); } DEBUG(DEBUG_FLAG, "Sending FA reg. reply code %i to %s:%i\n", code, inet_ntoa(cli_addr->sin_addr), ntohs(cli_addr->sin_port)); res = own_sendto(iface->udp_sock, cli_addr->sin_addr, cli_addr->sin_port, buf, pos - buf); dynamics_check_sendto(res, pos - buf, "send_fa_reg_reply");}static void forward_fa_reg_request(struct lower_fa_data *data, __u8 opts, struct msg_extensions *ext, __u8 *up_nonce){ char buf[MAXMSG], *pos; struct fa_reg_req *req; struct fa_spi_entry *fa_spi; int res; req = (struct fa_reg_req *) buf; memset(req, 0, sizeof(struct fa_reg_req)); req->type = FA_REQ; req->opts = opts; req->lifetime = ext->fa_req->lifetime; get_new_nonce(data->wait_nonce_rep); memcpy(&req->down_nonce, data->wait_nonce_rep, FA_REG_NONCE_LEN); if (up_nonce != NULL) memcpy(&req->up_nonce, up_nonce, FA_REG_NONCE_LEN); pos = (char *) (req + 1); if (ext->fa_nai != NULL) { memcpy(pos, ext->fa_nai, GET_NAI_EXT_LEN(ext->fa_nai)); pos += GET_NAI_EXT_LEN(ext->fa_nai); } fa_spi = get_fa_spi(0, upper_fa_addr.sin_addr, SPI_AGENT_FA); if (fa_spi != NULL) { pos += auth_add_vendor( AUTH_ALG_MD5, fa_spi->shared_secret, fa_spi->shared_secret_len, (unsigned char *) buf, (struct vendor_msg_auth *) pos, VENDOR_EXT_DYNAMICS_FF_AUTH, htonl(fa_spi->spi)); } DEBUG(DEBUG_FLAG, "Forwarding FA reg. request to %s:%i\n", inet_ntoa(upper_fa_addr.sin_addr), ntohs(upper_fa_addr.sin_port)); res = own_sendto(up_interface->udp_sock, upper_fa_addr.sin_addr, upper_fa_addr.sin_port, buf, pos - buf); dynamics_check_sendto(res, pos - buf, "forward_fa_reg_request");}int handle_fa_req(char *msg, int n, struct msg_extensions *ext, struct sockaddr_in *cli_addr, struct interface_entry *iface){ int res, sync_nonce = 0; struct lower_fa_data key, *data; DEBUG(DEBUG_FLAG, "Handling FA request\n"); res = validate_fa_reg(msg, ext, cli_addr); if (res == -1 || res == -2) { send_fa_reg_reply(FA_REP_INVALID_REQ, ext, cli_addr, iface, NULL); return -1; } else if (res == -3 || res == -4) { send_fa_reg_reply(FA_REP_AUTH_FAILED, ext, cli_addr, iface, NULL); return -1; } else if (res < 0) return -1; key.nai_len = GET_NAI_LEN(ext->fa_nai); if (key.nai_len > MAX_NAI_LEN) key.nai_len = MAX_NAI_LEN; memcpy(key.nai, MSG_NAI_DATA(ext->fa_nai), key.nai_len); data = (struct lower_fa_data *) hashtable_fetch(fa_hash, lower_fa_hashfunc, &key, lower_fa_cmpfunc); if (data == NULL) { DEBUG(DEBUG_FLAG, "\tno entry for this NAI found - adding " "and synchronizing nonces\n"); data = (struct lower_fa_data *) malloc(sizeof(struct lower_fa_data)); if (data == NULL) { LOG2(LOG_ALERT, "handle_fa_req - not enough memory\n"); return -1; } memset(data, 0, sizeof(struct lower_fa_data)); list_init_node(&data->node); data->nai_len = GET_NAI_LEN(ext->fa_nai); if (data->nai_len > MAX_NAI_LEN) data->nai_len = MAX_NAI_LEN; memcpy(data->nai, MSG_NAI_DATA(ext->fa_nai), data->nai_len); data->req_iface = iface; memcpy(&data->req_from, cli_addr, sizeof(data->req_from)); memcpy(&data->use_nonce_down, &ext->fa_req->down_nonce, FA_REG_NONCE_LEN); data->req_lifetime = ntohs(ext->fa_req->lifetime); time(&data->expire); data->expire += data->req_lifetime; DEBUG(DEBUG_FLAG, "\texpire entry: %s", ctime(&data->expire)); res = hashtable_add(fa_hash, lower_fa_hashfunc, (void *) data, &data->node); if (res == 0) { DEBUG(DEBUG_FLAG, "\thashtable_add failed\n"); free(data); return -1; } sync_nonce = 1; } else if (ext->fa_req->opts && FA_REQ_NONCE_SYNC) sync_nonce = 1; if (sync_nonce) { DEBUG(DEBUG_FLAG, "\tsynchronizing nonces\n"); if (config->highest_FA) { get_new_nonce(data->wait_nonce_req); send_fa_reg_reply(FA_REP_NONCE_FAILED, ext, cli_addr, iface, data->wait_nonce_req); } else forward_fa_reg_request(data, ext->fa_req->opts | FA_REQ_NONCE_SYNC, ext, NULL); return 0; } /* check nonce */ if (memcmp(data->wait_nonce_req, ext->fa_req->up_nonce, FA_REG_NONCE_LEN) != 0) { DEBUG(DEBUG_FLAG, "\tnonce did not match\n"); get_new_nonce(data->wait_nonce_req); send_fa_reg_reply(FA_REP_NONCE_FAILED, ext, cli_addr, iface, data->wait_nonce_req); return -1; } time(&data->req_time); if (config->highest_FA) { data->iface = iface; data->from = *cli_addr; data->reply_time = data->req_time; data->req_lifetime = data->lifetime = ntohs(ext->fa_req->lifetime); data->expire = data->reply_time + data->lifetime; data->confirmed = 1; get_new_nonce(data->wait_nonce_req); send_fa_reg_reply(FA_REP_OK, ext, cli_addr, iface, data->wait_nonce_req); update_next_hop(cli_addr->sin_addr, data->expire); } else { data->req_from = *cli_addr; data->req_iface = iface; data->req_lifetime = ntohs(ext->fa_req->lifetime); memcpy(&data->use_nonce_down, &ext->fa_req->down_nonce, FA_REG_NONCE_LEN); forward_fa_reg_request(data, ext->fa_req->opts, ext, data->use_nonce_up); } return 0;}static void forward_fa_reg_reply(struct lower_fa_data *data, struct msg_extensions *ext){ char buf[MAXMSG], *pos; struct fa_reg_rep *rep; struct fa_spi_entry *fa_spi; int res; rep = (struct fa_reg_rep *) buf; memset(rep, 0, sizeof(struct fa_reg_rep)); rep->type = FA_REP; rep->code = ext->fa_rep->code; get_new_nonce(data->wait_nonce_req); memcpy(&rep->down_nonce, data->use_nonce_down, FA_REG_NONCE_LEN); memcpy(&rep->up_nonce, data->wait_nonce_req, FA_REG_NONCE_LEN); pos = (char *) (rep + 1); if (ext->fa_nai != NULL) { memcpy(pos, ext->fa_nai, GET_NAI_EXT_LEN(ext->fa_nai)); pos += GET_NAI_EXT_LEN(ext->fa_nai); } fa_spi = get_fa_spi(0, data->req_from.sin_addr, SPI_AGENT_FA); if (fa_spi != NULL) { pos += auth_add_vendor( AUTH_ALG_MD5, fa_spi->shared_secret, fa_spi->shared_secret_len, (unsigned char *) buf, (struct vendor_msg_auth *) pos, VENDOR_EXT_DYNAMICS_FF_AUTH, htonl(fa_spi->spi)); } DEBUG(DEBUG_FLAG, "Forwarding FA reg. reply to %s:%i\n", inet_ntoa(data->req_from.sin_addr), ntohs(data->req_from.sin_port)); res = own_sendto(data->req_iface->udp_sock, data->req_from.sin_addr, data->req_from.sin_port, buf, pos - buf); dynamics_check_sendto(res, pos - buf, "forward_fa_reg_reply");}int handle_fa_rep(char *msg, int n, struct msg_extensions *ext, struct sockaddr_in *cli_addr, struct interface_entry *iface){ struct lower_fa_data key, *data; DEBUG(DEBUG_FLAG, "Handling FA reply\n"); if (validate_fa_reg(msg, ext, cli_addr) < 0) return -1; /* check for a reply to own registration */ if (!config->highest_FA && fa_nai != NULL && GET_NAI_LEN(fa_nai) == GET_NAI_LEN(ext->fa_nai) && memcmp(MSG_NAI_DATA(fa_nai), MSG_NAI_DATA(ext->fa_nai), GET_NAI_LEN(fa_nai)) == 0) { DEBUG(DEBUG_FLAG, "\treply to own request\n"); if (!own_req_pending) { DEBUG(DEBUG_FLAG, "\tno pending request - reply " "dropped\n"); return -1; } if (memcmp(&next_wait_nonce, &ext->fa_rep->down_nonce, FA_REG_NONCE_LEN) != 0) { DEBUG(DEBUG_FLAG, "\tnonce mismatch - reply " "dropped\n"); return -1; } own_req_pending = 0; if (ext->fa_rep->code == FA_REP_OK) { DEBUG(DEBUG_FLAG, "\tregistration succeeded\n"); time(&last_reg_ok); fa_reg_next_try = last_reg_ok + config->fa_reg_lifetime - (get_rand32() % 60); DEBUG(DEBUG_FLAG, "\tnext registration: %s", ctime(&fa_reg_next_try)); next_wait_time = 1; denial_replies = 0; } else { DEBUG(DEBUG_FLAG, "\tregistration failed - code=%i\n", ext->fa_rep->code); if (ext->fa_rep->code == FA_REP_NONCE_FAILED && denial_replies == 0) { DEBUG(DEBUG_FLAG, "\tfirst nonce synch => " "retry immediately\n"); next_wait_time = 1; time(&fa_reg_next_try); } denial_replies++; } memcpy(&next_send_nonce, &ext->fa_rep->up_nonce, FA_REG_NONCE_LEN); return 0; } key.nai_len = GET_NAI_LEN(ext->fa_nai); if (key.nai_len > MAX_NAI_LEN) key.nai_len = MAX_NAI_LEN; memcpy(key.nai, MSG_NAI_DATA(ext->fa_nai), key.nai_len); data = (struct lower_fa_data *) hashtable_fetch(fa_hash, lower_fa_hashfunc, &key, lower_fa_cmpfunc); if (data == NULL) { DEBUG(DEBUG_FLAG, "\tno entry found - reply dropped\n"); return -1; } if (data->req_iface == NULL) { DEBUG(DEBUG_FLAG, "\tno pending request - reply dropped\n"); return -1; } if (memcmp(data->wait_nonce_rep, &ext->fa_rep->down_nonce, FA_REG_NONCE_LEN) != 0) { DEBUG(DEBUG_FLAG, "\tnonce mismatch - reply dropped\n"); return -1; } forward_fa_reg_reply(data, ext); if (ext->fa_rep->code == FA_REP_OK) { DEBUG(DEBUG_FLAG, "\tregistration succeeded - updating " "data\n"); data->confirmed = 1; time(&data->reply_time); data->lifetime = data->req_lifetime; data->expire = data->reply_time + data->lifetime; data->iface = data->req_iface; data->from = data->req_from; data->req_iface = NULL; update_next_hop(data->from.sin_addr, data->expire); } else DEBUG(DEBUG_FLAG, "\tregistration failed\n"); memcpy(data->use_nonce_up, &ext->fa_rep->up_nonce, FA_REG_NONCE_LEN); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -