void ipv4_error(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); switch (ff->ctrlFrame.param_id) { case IPV4_ERROR_GET_ADDR: PRINT_DEBUG("param_id=IPV4_ERROR_GET_ADDR (%d)", ff->ctrlFrame.param_id); //should we separate icmp & error messages? what about disabling ICMP, what errors should it stop? //if yes, eth->ip->icmp or ip->proto //if no, eth->icmp->proto //if partial, eth->ip->icmp->proto (allows for similar to iptables) //Sending to ICMP mimic kernel func, if remove icmp stops error //if doing routing tables, factor in and process ff->ctrlFrame.sender_id = module->index; ff->ctrlFrame.param_id = IPV4_ERROR_GET_ADDR; //reroute to icmp, though could go directly int sent = module_send_flow(module, ff, IPV4_FLOW_ICMP); if (sent == 0) { freeFinsFrame(ff); } break; default: PRINT_DEBUG("param_id=default (%d)", ff->ctrlFrame.param_id); PRINT_WARN("todo"); freeFinsFrame(ff); break; } }
void switch_process_ff(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p", module, ff); if (ff->metaData == NULL) { PRINT_ERROR("Error fcf.metadata==NULL"); exit(-1); } PRINT_WARN("TODO: switch process received frames: ff=%p, meta=%p", ff, ff->metaData); print_finsFrame(ff); if (ff->dataOrCtrl == FF_CONTROL) { switch_fcf(module, ff); PRINT_DEBUG(""); } else if (ff->dataOrCtrl == FF_DATA) { if (ff->dataFrame.directionFlag == DIR_UP) { //switch_in_fdf(module, ff); PRINT_WARN("todo"); freeFinsFrame(ff); } else if (ff->dataFrame.directionFlag == DIR_DOWN) { //switch_out_fdf(ff); PRINT_WARN("todo"); freeFinsFrame(ff); } else { PRINT_ERROR("todo error"); exit(-1); } } else { PRINT_ERROR("todo error: dataOrCtrl=%u", ff->dataOrCtrl); exit(-1); } }
void module_set_param_flows(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct fins_module_table *mt = (struct fins_module_table *) module->data; if (module->flows_max < ff->ctrlFrame.data_len) { PRINT_WARN("todo error"); freeFinsFrame(ff); return; } mt->flows_num = ff->ctrlFrame.data_len; struct fins_module_flow *flows = (struct fins_module_flow *) ff->ctrlFrame.data; int i; for (i = 0; i < mt->flows_num; i++) { mt->flows[i].link_id = flows[i].link_id; mt->flows[i].link = (struct link_record *) list_find1(mt->link_list, link_id_test, &mt->flows[i].link_id); } #ifdef DEBUG uint8_t buf[1000]; uint8_t *pt = buf; int ret; for (i = 0; i < mt->flows_num; i++) { //ret = sprintf((char *) pt, "%u, ", mt->flows[i].link_id); ret = sprintf((char *) pt, "%u (%p), ", mt->flows[i].link_id, mt->flows[i].link); pt += ret; } *pt = '\0'; PRINT_DEBUG("flows: max=%u, num=%u, ['%s']", module->flows_max, mt->flows_num, buf); #endif //freeFF frees flows freeFinsFrame(ff); }
void module_set_param_links(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct fins_module_table *mt = (struct fins_module_table *) module->data; if (ff->ctrlFrame.data_len != sizeof(struct linked_list)) { PRINT_WARN("todo error"); freeFinsFrame(ff); return; } if (mt->link_list != NULL) { list_free(mt->link_list, free); } mt->link_list = (struct linked_list *) ff->ctrlFrame.data; int i; for (i = 0; i < mt->flows_num; i++) { mt->flows[i].link = (struct link_record *) list_find1(mt->link_list, link_id_test, &mt->flows[i].link_id); } #ifdef DEBUG list_for_each(mt->link_list, link_print); #endif ff->ctrlFrame.data = NULL; freeFinsFrame(ff); }
void switch_fcf(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); //TODO fill out switch (ff->ctrlFrame.opcode) { case CTRL_ALERT: PRINT_DEBUG("opcode=CTRL_ALERT (%d)", CTRL_ALERT); PRINT_WARN("todo"); module_reply_fcf(module, ff, FCF_FALSE, 0); break; case CTRL_ALERT_REPLY: PRINT_DEBUG("opcode=CTRL_ALERT_REPLY (%d)", CTRL_ALERT_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_READ_PARAM: PRINT_DEBUG("opcode=CTRL_READ_PARAM (%d)", CTRL_READ_PARAM); PRINT_WARN("todo"); module_reply_fcf(module, ff, FCF_FALSE, 0); break; case CTRL_READ_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_READ_PARAM_REPLY (%d)", CTRL_READ_PARAM_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_SET_PARAM: PRINT_DEBUG("opcode=CTRL_SET_PARAM (%d)", CTRL_SET_PARAM); switch_set_param(module, ff); break; case CTRL_SET_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_SET_PARAM_REPLY (%d)", CTRL_SET_PARAM_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_EXEC: PRINT_DEBUG("opcode=CTRL_EXEC (%d)", CTRL_EXEC); PRINT_WARN("todo"); module_reply_fcf(module, ff, FCF_FALSE, 0); break; case CTRL_EXEC_REPLY: PRINT_DEBUG("opcode=CTRL_EXEC_REPLY (%d)", CTRL_EXEC_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_ERROR: PRINT_DEBUG("opcode=CTRL_ERROR (%d)", CTRL_ERROR); PRINT_WARN("todo"); freeFinsFrame(ff); break; default: PRINT_ERROR("opcode=default (%d)", ff->ctrlFrame.opcode); exit(-1); break; } }
void rtm_fcf(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); //TODO when recv FCF, pull params from meta to figure out connection, send through socket switch (ff->ctrlFrame.opcode) { case CTRL_ALERT: PRINT_DEBUG("opcode=CTRL_ALERT (%d)", CTRL_ALERT); PRINT_ERROR("todo"); module_reply_fcf(module, ff, 0, 0); break; case CTRL_ALERT_REPLY: PRINT_DEBUG("opcode=CTRL_ALERT_REPLY (%d)", CTRL_ALERT_REPLY); PRINT_ERROR("todo"); freeFinsFrame(ff); break; case CTRL_READ_PARAM: PRINT_DEBUG("opcode=CTRL_READ_PARAM (%d)", CTRL_READ_PARAM); PRINT_ERROR("todo"); module_reply_fcf(module, ff, 0, 0); break; case CTRL_READ_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_READ_PARAM_REPLY (%d)", CTRL_READ_PARAM_REPLY); rtm_read_param_reply(module, ff); break; case CTRL_SET_PARAM: PRINT_DEBUG("opcode=CTRL_SET_PARAM (%d)", CTRL_SET_PARAM); rtm_set_param(module, ff); break; case CTRL_SET_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_SET_PARAM_REPLY (%d)", CTRL_SET_PARAM_REPLY); rtm_set_param_reply(module, ff); break; case CTRL_EXEC: PRINT_DEBUG("opcode=CTRL_EXEC (%d)", CTRL_EXEC); PRINT_ERROR("todo"); module_reply_fcf(module, ff, 0, 0); break; case CTRL_EXEC_REPLY: PRINT_DEBUG("opcode=CTRL_EXEC_REPLY (%d)", CTRL_EXEC_REPLY); rtm_exec_reply(module, ff); break; case CTRL_ERROR: PRINT_DEBUG("opcode=CTRL_ERROR (%d)", CTRL_ERROR); PRINT_ERROR("todo"); freeFinsFrame(ff); break; default: PRINT_DEBUG("opcode=default (%d)", ff->ctrlFrame.opcode); PRINT_ERROR("todo"); exit(-1); break; } }
void rtm_get_ff(struct fins_module *module) { struct rtm_data *md = (struct rtm_data *) module->data; struct finsFrame *ff; do { secure_sem_wait(module->event_sem); secure_sem_wait(module->input_sem); ff = read_queue(module->input_queue); sem_post(module->input_sem); } while (module->state == FMS_RUNNING && ff == NULL && !md->interrupt_flag); //TODO change logic here, combine with switch_to_rtm? if (module->state != FMS_RUNNING) { if (ff != NULL) { freeFinsFrame(ff); } return; } if (ff != NULL) { if (ff->metaData == NULL) { PRINT_ERROR("Error fcf.metadata==NULL"); exit(-1); } if (ff->dataOrCtrl == FF_CONTROL) { rtm_fcf(module, ff); PRINT_DEBUG(""); } else if (ff->dataOrCtrl == FF_DATA) { if (ff->dataFrame.directionFlag == DIR_UP) { //rtm_in_fdf(module, ff); PRINT_WARN("todo error"); freeFinsFrame(ff); } else if (ff->dataFrame.directionFlag == DIR_DOWN) { //rtm_out_fdf(module, ff); PRINT_WARN("todo error"); freeFinsFrame(ff); } else { PRINT_ERROR("todo error"); exit(-1); } } else { PRINT_ERROR("todo error"); exit(-1); } } else if (md->interrupt_flag) { md->interrupt_flag = 0; rtm_interrupt(module); //TODO unused, implement or remove } else { PRINT_ERROR("todo error: dataOrCtrl=%u", ff->dataOrCtrl); exit(-1); } }
void ipv4_fcf(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); //TODO make sure is meant for IP, filter out FCF sent through flows w/multi dest //TODO fill out switch (ff->ctrlFrame.opcode) { case CTRL_ALERT: PRINT_DEBUG("opcode=CTRL_ALERT (%d)", CTRL_ALERT); PRINT_WARN("todo"); module_reply_fcf(module, ff, FCF_FALSE, 0); break; case CTRL_ALERT_REPLY: PRINT_DEBUG("opcode=CTRL_ALERT_REPLY (%d)", CTRL_ALERT_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_READ_PARAM: PRINT_DEBUG("opcode=CTRL_READ_PARAM (%d)", CTRL_READ_PARAM); ipv4_read_param(module, ff); break; case CTRL_READ_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_READ_PARAM_REPLY (%d)", CTRL_READ_PARAM_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_SET_PARAM: PRINT_DEBUG("opcode=CTRL_SET_PARAM (%d)", CTRL_SET_PARAM); ipv4_set_param(module, ff); break; case CTRL_SET_PARAM_REPLY: PRINT_DEBUG("opcode=CTRL_SET_PARAM_REPLY (%d)", CTRL_SET_PARAM_REPLY); PRINT_WARN("todo"); freeFinsFrame(ff); break; case CTRL_EXEC: PRINT_DEBUG("opcode=CTRL_EXEC (%d)", CTRL_EXEC); ipv4_exec(module, ff); break; case CTRL_EXEC_REPLY: PRINT_DEBUG("opcode=CTRL_EXEC_REPLY (%d)", CTRL_EXEC_REPLY); ipv4_exec_reply(module, ff); break; case CTRL_ERROR: PRINT_DEBUG("opcode=CTRL_ERROR (%d)", CTRL_ERROR); ipv4_error(module, ff); break; default: PRINT_ERROR("opcode=default (%d)", ff->ctrlFrame.opcode); exit(-1); break; } }
void ipv4_exec_reply_get_addr(struct finsFrame *ff, uint64_t src_mac, uint64_t dst_mac) { PRINT_DEBUG("Entered: ff=%p, src_mac=%llx, dst_mac=%llx", ff, src_mac, dst_mac); struct ip4_store *store = store_list_find(ff->ctrlFrame.serial_num); if (store) { store_list_remove(store); metadata *params = store->ff->metaData; uint32_t ether_type = IP4_ETH_TYPE; metadata_writeToElement(params, "send_dst_mac", &dst_mac, META_TYPE_INT64); metadata_writeToElement(params, "send_src_mac", &src_mac, META_TYPE_INT64); metadata_writeToElement(params, "send_ether_type", ðer_type, META_TYPE_INT32); PRINT_DEBUG("recv frame: dst=0x%12.12llx, src=0x%12.12llx, type=0x%x", dst_mac, src_mac, ether_type); //print_finsFrame(fins_frame); ipv4_to_switch(store->ff); store->ff = NULL; store_free(store); freeFinsFrame(ff); } else { PRINT_ERROR("todo error"); //TODO error sending back FDF as FCF? saved pdu for that } }
void rtm_set_param_reply(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct rtm_data *md = (struct rtm_data *) module->data; secure_sem_wait(&md->shared_sem); struct rtm_command *cmd = (struct rtm_command *) list_find1(md->cmd_list, rtm_cmd_serial_test, &ff->ctrlFrame.serial_num); if (cmd != NULL) { list_remove(md->cmd_list, cmd); struct rtm_console *console = (struct rtm_console *) list_find1(md->console_list, rtm_console_id_test, &cmd->console_id); if (console != NULL) { //TODO extract answer if (ff->ctrlFrame.ret_val) { //send '' ? rtm_send_text(console->fd, "successful"); } else { //send error rtm_send_text(console->fd, "unsuccessful"); } } else { PRINT_ERROR("todo error"); } sem_post(&md->shared_sem); free(cmd); } else { sem_post(&md->shared_sem); PRINT_ERROR("todo error"); //TODO error, drop freeFinsFrame(ff); } }
void rtm_set_param_reply(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct rtm_data *md = (struct rtm_data *) module->data; secure_sem_wait(&md->shared_sem); struct rtm_command *cmd = (struct rtm_command *) list_find1(md->cmd_list, rtm_cmd_serial_test, &ff->ctrlFrame.serial_num); if (cmd != NULL) { list_remove(md->cmd_list, cmd); struct rtm_console *console = (struct rtm_console *) list_find1(md->console_list, rtm_console_id_test, &cmd->console_id); if (console != NULL) { if (ff->ctrlFrame.ret_val == FCF_TRUE) { rtm_send_text(console->fd, "successful"); } else { //send error uint32_t ret_msg; secure_metadata_readFromElement(ff->metaData, "ret_msg", &ret_msg); char temp[100]; sprintf(temp, "unsuccessful, returned error=%u", ret_msg); rtm_send_text(console->fd, temp); } } else { PRINT_WARN("todo error"); } sem_post(&md->shared_sem); free(cmd); } else { sem_post(&md->shared_sem); PRINT_WARN("todo error"); //TODO error, drop freeFinsFrame(ff); } }
void udp_sent_free(struct udp_sent *sent) { PRINT_DEBUG("Entered: sent=%p", sent); if (sent->ff != NULL) { freeFinsFrame(sent->ff); } free(sent); }
void udp_exec_clear_sent(struct fins_module *module, struct finsFrame *ff, uint32_t host_ip, uint16_t host_port, uint32_t rem_ip, uint16_t rem_port) { PRINT_DEBUG("Entered: module=%p, ff=%p, host=%u:%u, rem=%u:%u", module, ff, host_ip, host_port, rem_ip, rem_port); struct udp_data *md = (struct udp_data *) module->data; if (!list_is_empty(md->sent_packet_list)) { struct linked_list *old_list = list_remove_all2(md->sent_packet_list, udp_sent_host_test, &host_ip, &host_port); list_free(old_list, udp_sent_free); } freeFinsFrame(ff); }
void module_set_param_dual(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct fins_module_table *mt = (struct fins_module_table *) module->data; if (ff->ctrlFrame.data_len != sizeof(struct fins_module_table)) { PRINT_WARN("todo error"); freeFinsFrame(ff); return; } struct fins_module_table *table = (struct fins_module_table *) ff->ctrlFrame.data; if (module->flows_max < table->flows_num || table->link_list == NULL) { PRINT_WARN("todo error"); freeFinsFrame(ff); return; } mt->link_list = table->link_list; mt->flows_num = table->flows_num; if (mt->flows_num != 0) { memcpy(mt->flows, table->flows, mt->flows_num * sizeof(struct fins_module_flow)); } #ifdef DEBUG uint8_t buf[1000]; uint8_t *pt = buf; int ret; int i; for (i = 0; i < mt->flows_num; i++) { //ret = sprintf((char *) pt, "%u, ", mt->flows[i].link_id); ret = sprintf((char *) pt, "%u (%p), ", mt->flows[i].link_id, mt->flows[i].link); pt += ret; } *pt = '\0'; PRINT_DEBUG("flows: max=%u, num=%u, ['%s']", module->flows_max, mt->flows_num, buf); list_for_each(mt->link_list, link_print); #endif //freeFF frees table freeFinsFrame(ff); }
void store_free(struct ip4_store *store) { PRINT_DEBUG("Entered: store=%p", store); if (store->pdu) { PRINT_DEBUG("Freeing pdu=%p", store->pdu); free(store->pdu); } if (store->ff) freeFinsFrame(store->ff); free(store); }
void ipv4_get_ff(struct fins_module *module) { struct finsFrame *ff; do { secure_sem_wait(module->event_sem); secure_sem_wait(module->input_sem); ff = read_queue(module->input_queue); sem_post(module->input_sem); } while (module->state == FMS_RUNNING && ff == NULL); //TODO change logic here, combine with switch_to_ipv4? if (module->state != FMS_RUNNING) { if (ff != NULL) { freeFinsFrame(ff); } return; } if (ff->metaData == NULL) { PRINT_ERROR("Error fcf.metadata==NULL"); exit(-1); } if (ff->dataOrCtrl == FF_CONTROL) { ipv4_fcf(module, ff); PRINT_DEBUG(""); } else if (ff->dataOrCtrl == FF_DATA) { if (ff->dataFrame.directionFlag == DIR_UP) { ipv4_in_fdf(module, ff); PRINT_DEBUG(""); } else if (ff->dataFrame.directionFlag == DIR_DOWN) { ipv4_out_fdf(module, ff); PRINT_DEBUG(""); } else { PRINT_ERROR("Error: Wrong value of fdf.directionFlag"); exit(-1); } } else { PRINT_ERROR("Error: Wrong ff->dataOrCtrl value"); exit(-1); } }
void rtm_alert(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct rtm_data *md = (struct rtm_data *) module->data; //Get from fcf: module index, opcode==CTRL_ALERT, param_id secure_sem_wait(&md->shared_sem); //search for consoles with type==listener/dual, & registered for module index / param_id struct linked_list *listening_list = list_find_all2(md->console_list, rtm_console_listening_test, &ff->ctrlFrame.sender_id, &ff->ctrlFrame.param_id); //for each console push the traffic struct rtm_console *console; while (!list_is_empty(listening_list)) { console = (struct rtm_console *) list_remove_front(listening_list); rtm_send_fd(console->fd, ff->ctrlFrame.data_len, ff->ctrlFrame.data); } sem_post(&md->shared_sem); free(listening_list); freeFinsFrame(ff); }
void rtm_read_param_reply(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct rtm_data *md = (struct rtm_data *) module->data; secure_sem_wait(&md->shared_sem); struct rtm_command *cmd = (struct rtm_command *) list_find1(md->cmd_list, rtm_cmd_serial_test, &ff->ctrlFrame.serial_num); if (cmd != NULL) { list_remove(md->cmd_list, cmd); struct rtm_console *console = (struct rtm_console *) list_find1(md->console_list, rtm_console_id_test, &cmd->console_id); if (console != NULL) { //TODO extract answer if (ff->ctrlFrame.ret_val == FCF_TRUE) { char temp[100]; int32_t val_int32; int64_t val_int64; float val_float; char *val_str; switch (cmd->param_type) { case META_TYPE_INT32: secure_metadata_readFromElement(ff->metaData, "value", &val_int32); sprintf(temp, "'%s'=%d", cmd->param_str, val_int32); break; case META_TYPE_INT64: secure_metadata_readFromElement(ff->metaData, "value", &val_int64); sprintf(temp, "'%s'=%lld", cmd->param_str, val_int64); break; case META_TYPE_FLOAT: secure_metadata_readFromElement(ff->metaData, "value", &val_float); sprintf(temp, "'%s'=%f", cmd->param_str, val_float); break; case META_TYPE_STRING: secure_metadata_readFromElement(ff->metaData, "value", &val_str); sprintf(temp, "'%s'='%s'", cmd->param_str, val_str); break; default: PRINT_ERROR("todo error"); exit(-1); } rtm_send_text(console->fd, temp); } else { //send error uint32_t ret_msg; secure_metadata_readFromElement(ff->metaData, "ret_msg", &ret_msg); char temp[100]; sprintf(temp, "unsuccessful, returned error=%u", ret_msg); rtm_send_text(console->fd, temp); } } else { PRINT_WARN("todo error"); } sem_post(&md->shared_sem); free(cmd); } else { sem_post(&md->shared_sem); PRINT_WARN("todo error"); //TODO error, drop freeFinsFrame(ff); } }
void udp_error(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct udp_data *md = (struct udp_data *) module->data; //uint32_t src_ip; //uint32_t src_port; //uint32_t dst_ip; //uint32_t dst_port; //uint32_t udp_len; //uint32_t checksum; switch (ff->ctrlFrame.param_id) { case UDP_ERROR_TTL: PRINT_DEBUG("param_id=UDP_ERROR_TTL (%d)", ff->ctrlFrame.param_id); /* struct udp_packet *udp_hdr = (struct udp_packet *) ff->ctrlFrame.data; struct udp_header hdr; hdr.u_src = ntohs(udp_hdr->u_src); hdr.u_dst = ntohs(udp_hdr->u_dst); hdr.u_len = ntohs(udp_hdr->u_len); hdr.u_cksum = ntohs(udp_hdr->u_cksum); */ //if recv_dst_ip==send_src_ip, recv_dst_port==send_src_port, recv_udp_len==, recv_checksum==, \\should be unique! if (list_is_empty(md->sent_packet_list)) { PRINT_WARN("todo error"); //TODO drop freeFinsFrame(ff); } else { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { //TODO make func!! struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { metadata_copy(sent->ff->metaData, ff->metaData); ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_TTL; //TODO error msg code //ERROR_UDP_TTL? ff->ctrlFrame.data_len = sent->ff->dataFrame.pduLength; ff->ctrlFrame.data = sent->ff->dataFrame.pdu; sent->ff->dataFrame.pdu = NULL; if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } list_remove(md->sent_packet_list, sent); udp_sent_free(sent); PRINT_DEBUG("Freeing: pdu=%p", pdu); free(pdu); } else { PRINT_WARN("todo error"); freeFinsFrame(ff); //TODO drop? } } else { PRINT_WARN("todo"); freeFinsFrame(ff); } } break; case UDP_ERROR_DEST_UNREACH: PRINT_DEBUG("param_id=UDP_ERROR_DEST_UNREACH (%d)", ff->ctrlFrame.param_id); if (list_is_empty(md->sent_packet_list)) { PRINT_WARN("todo error"); //TODO drop freeFinsFrame(ff); } else { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { metadata_copy(sent->ff->metaData, ff->metaData); ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_DEST_UNREACH; //TODO error msg code //ERROR_UDP_TTL? ff->ctrlFrame.data_len = sent->ff->dataFrame.pduLength; ff->ctrlFrame.data = sent->ff->dataFrame.pdu; sent->ff->dataFrame.pdu = NULL; if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } list_remove(md->sent_packet_list, sent); udp_sent_free(sent); PRINT_DEBUG("Freeing: pdu=%p", pdu); free(pdu); } else { PRINT_WARN("todo error"); //TODO drop? freeFinsFrame(ff); } } else { PRINT_WARN("todo"); freeFinsFrame(ff); } } break; case UDP_ERROR_GET_ADDR: PRINT_DEBUG("param_id=UDP_ERROR_GET_ADDR (%d)", ff->ctrlFrame.param_id); if (!list_is_empty(md->sent_packet_list)) { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { //TODO make func!! struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { list_remove(md->sent_packet_list, sent); udp_sent_free(sent); } } } ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_GET_ADDR; //TODO error msg code //ERROR_UDP_TTL? if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } break; default: PRINT_ERROR("Error unknown param_id=%d", ff->ctrlFrame.param_id); PRINT_WARN("todo error"); freeFinsFrame(ff); break; } }
int TerminateFinsQueue(finsQueue Q) { PRINT_DEBUG("Entered: Q=%p, name='%s'", Q, Q->name); int counter = 0; int empty = 0; int size = Q->Size; int i; //ElementType X = (ElementType)malloc (sizeof(ElementType)); int min; int max; PRINT_DEBUG("Front=%d, Rear=%d, Cap=%d", Q->Front, Q->Rear, Q->Capacity); if (Q->Front <= Q->Rear) { min = Q->Front; max = Q->Rear; for (i = min; i <= max; i++) { if (Q->Array[i]) { /* if (Q->Array[i]->dataOrCtrl == FF_DATA) { if (Q->Array[i]->dataFrame.pdu) { free(Q->Array[i]->dataFrame.pdu); } } */ if (freeFinsFrame(Q->Array[i]) == 0) { //PRINT_DEBUG("333"); //PRINT_DEBUG("Element number %d was already NULL before deleting",i); empty++; } else { counter++; } } } } else { max = Q->Front; min = Q->Rear; for (i = max; i < Q->Capacity; i++) { if (Q->Array[i]) { /* if (Q->Array[i]->dataOrCtrl == FF_DATA) { if (Q->Array[i]->dataFrame.pdu) { free(Q->Array[i]->dataFrame.pdu); } } */ if (freeFinsFrame(Q->Array[i]) == 0) { //PRINT_DEBUG("333"); //PRINT_DEBUG("Element number %d was already NULL before deleting",i); empty++; } else { counter++; } } } for (i = 0; i <= min; i++) { if (Q->Array[i]) { /* if (Q->Array[i]->dataOrCtrl == FF_DATA) { if (Q->Array[i]->dataFrame.pdu) { free(Q->Array[i]->dataFrame.pdu); } } */ if (freeFinsFrame(Q->Array[i]) == 0) { //PRINT_DEBUG("333"); //PRINT_DEBUG("Element number %d was already NULL before deleting",i); empty++; } else { counter++; } } } } //while (checkEmpty(Q)) PRINT_DEBUG("Empty cleared=%d/%d", empty, Q->Capacity); Q->Size = 0; if (counter == size) return (1); else return (0); }
void *switch_loop(void *local) { PRINT_DEBUG("Entered"); int i; struct finsFrame *ff; int counter = 0; while (switch_running) { /** the receiving Queues are only the even numbers * 0,2,4,6,8,10,12,14. This is why we increase the counter by 2 */ for (i = 0; i < MAX_modules; i = i + 2) { sem_wait(IO_queues_sem[i]); ff = read_queue(modules_IO_queues[i]); sem_post(IO_queues_sem[i]); if (ff != NULL) { counter++; //PRINT_DEBUG("Counter %d", counter); switch (ff->destinationID.id) { case ARP_ID: PRINT_DEBUG("Counter=%d, from='%s' to ARP Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_ARP_Qsem); write_queue(ff, Switch_to_ARP_Queue); sem_post(&Switch_to_ARP_Qsem); break; case RTM_ID: PRINT_DEBUG("Counter=%d, from='%s' to RTM Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_RTM_Qsem); write_queue(ff, Switch_to_RTM_Queue); sem_post(&Switch_to_RTM_Qsem); break; case DAEMON_ID: PRINT_DEBUG("Counter=%d, from='%s' to Daemon Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_Daemon_Qsem); write_queue(ff, Switch_to_Daemon_Queue); sem_post(&Switch_to_Daemon_Qsem); break; case UDP_ID: PRINT_DEBUG("Counter=%d, from='%s' to UDP Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_UDP_Qsem); write_queue(ff, Switch_to_UDP_Queue); sem_post(&Switch_to_UDP_Qsem); break; case TCP_ID: PRINT_DEBUG("Counter=%d, from='%s' to TCP Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_TCP_Qsem); write_queue(ff, Switch_to_TCP_Queue); sem_post(&Switch_to_TCP_Qsem); break; case IPV4_ID: PRINT_DEBUG("Counter=%d, from='%s' to IPv4 Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_IPv4_Qsem); write_queue(ff, Switch_to_IPv4_Queue); sem_post(&Switch_to_IPv4_Qsem); break; case INTERFACE_ID: PRINT_DEBUG("Counter=%d, from='%s' to Interface Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_Interface_Qsem); write_queue(ff, Switch_to_Interface_Queue); sem_post(&Switch_to_Interface_Qsem); break; case ICMP_ID: PRINT_DEBUG("Counter=%d, from='%s' to ICMP Queue +1, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); sem_wait(&Switch_to_ICMP_Qsem); write_queue(ff, Switch_to_ICMP_Queue); sem_post(&Switch_to_ICMP_Qsem); break; default: PRINT_DEBUG("Counter=%d, from='%s' to Unknown Dest, ff=%p, meta=%p", counter, modules_IO_queues[i]->name, ff, ff->metaData); freeFinsFrame(ff); break; } // end of Switch statement } // end of if (ff != NULL ) else { //PRINT_DEBUG("No frame read from Queue # %d", i); } } //end of for For loop (Round Robin reading from Modules) } // end of while loop PRINT_DEBUG("Exited"); pthread_exit(NULL); } // end of switch_init Function
void *switch_loop(void *local) { struct fins_module *module = (struct fins_module *) local; PRINT_DEBUG("Entered: module=%p, index=%u, id=%u, name='%s'", module, module->index, module->id, module->name); struct switch_data *md = (struct switch_data *) module->data; uint32_t i; int ret; //int32_t val; struct finsFrame *ff; //uint8_t index; int counter = 0; while (module->state == FMS_RUNNING) { secure_sem_wait(module->event_sem); //TODO uncomment, for testing //secure_sem_wait(module->input_sem); secure_sem_wait(&md->overall->sem); for (i = 0; i < MAX_MODULES; i++) { if (md->overall->modules[i] != NULL) { //helgrind says is race condition, though there will always be FF when post to event_sem if (!IsEmpty(md->overall->modules[i]->output_queue)) { //added as optimization /* //can possibly cause switch to be "behind" ret = sem_getvalue(md->overall->modules[i]->output_sem, &val); if (ret) { PRINT_ERROR("sem get value prob: src module_index=%u, ret=%d", i, ret); exit(-1); } //*/ //if (val != 0) { while ((ret = sem_wait(md->overall->modules[i]->output_sem)) && errno == EINTR) ; if (ret != 0) { PRINT_ERROR("sem wait prob: src module_index=%u, ret=%d", i, ret); exit(-1); } ff = read_queue(md->overall->modules[i]->output_queue); sem_post(md->overall->modules[i]->output_sem); //if (ff != NULL) { //shouldn't occur counter++; //index = ff->destinationID; if (ff->destinationID < 0 || ff->destinationID > MAX_MODULES) { PRINT_ERROR("dropping ff: illegal destination: src module_index=%u, dst module_index=%u, ff=%p, meta=%p", i, ff->destinationID, ff, ff->metaData); //TODO if FCF set ret_val=0 & return? or free or just exit(-1)? freeFinsFrame(ff); } else { //if (i != id) //TODO add this? if (md->overall->modules[ff->destinationID] != NULL) { PRINT_DEBUG("Counter=%d, from='%s', to='%s', ff=%p, meta=%p", counter, md->overall->modules[i]->name, md->overall->modules[ff->destinationID]->name, ff, ff->metaData); //TODO decide if should drop all traffic to switch input queues, or use that as linking table requests if (ff->destinationID == module->index) { switch_process_ff(module, ff); } else { while ((ret = sem_wait(md->overall->modules[ff->destinationID]->input_sem)) && errno == EINTR) ; if (ret != 0) { PRINT_ERROR("sem wait prob: dst index=%u, ff=%p, meta=%p, ret=%d", ff->destinationID, ff, ff->metaData, ret); exit(-1); } if (write_queue(ff, md->overall->modules[ff->destinationID]->input_queue)) { sem_post(md->overall->modules[ff->destinationID]->event_sem); sem_post(md->overall->modules[ff->destinationID]->input_sem); } else { sem_post(md->overall->modules[ff->destinationID]->input_sem); PRINT_ERROR("Write queue error: dst index=%u, ff=%p, meta=%p", ff->destinationID, ff, ff->metaData); freeFinsFrame(ff); } } } else { PRINT_ERROR("dropping ff: destination not registered: src index=%u, dst index=%u, ff=%p, meta=%p", i, ff->destinationID, ff, ff->metaData); print_finsFrame(ff); //TODO if FCF set ret_val=0 & return? or free or just exit(-1)? freeFinsFrame(ff); } //} //} } } } } //sem_post(module->input_sem); sem_post(&md->overall->sem); } PRINT_DEBUG("Exited: module=%p, index=%u, id=%u, name='%s'", module, module->index, module->id, module->name); return NULL; }
void IP4_receive_fdf(void) { struct finsFrame* pff = NULL; uint32_t protocol; do { sem_wait(&Switch_to_IPv4_Qsem); pff = read_queue(Switch_to_IPv4_Queue); sem_post(&Switch_to_IPv4_Qsem); } while (ipv4_running && pff == NULL); if (!ipv4_running) { return; } if (pff->dataOrCtrl == CONTROL) { PRINT_DEBUG("Received frame: D/C: %d, DestID=%d, ff=%p, meta=%p", pff->dataOrCtrl, pff->destinationID.id, pff, pff->metaData); ipv4_fcf(pff); } else if (pff->dataOrCtrl == DATA) { PRINT_DEBUG("Received frame: D/C: %d, DestID=%d, ff=%p, meta=%p", pff->dataOrCtrl, pff->destinationID.id, pff, pff->metaData); PRINT_DEBUG("PDU Length: %d", pff->dataFrame.pduLength); PRINT_DEBUG("Data direction: %d", pff->dataFrame.directionFlag); PRINT_DEBUG("pdu=%p", pff->dataFrame.pdu); if (pff->dataFrame.directionFlag == UP) { PRINT_DEBUG("IP4_in"); IP4_in(pff, (struct ip4_packet*) pff->dataFrame.pdu, pff->dataFrame.pduLength); } else if (pff->dataFrame.directionFlag == DOWN) { PRINT_DEBUG("IP4_out"); metadata *params = pff->metaData; if (params == NULL) { PRINT_ERROR("todo error"); freeFinsFrame(pff); return; } int ret = 0; ret += metadata_readFromElement(params, "send_protocol", &protocol) == META_FALSE; if (ret) { PRINT_ERROR("metadata read error: ret=%d", ret); } PRINT_DEBUG("%lu", my_ip_addr); PRINT_DEBUG("Transport protocol going out passed to IPv4: protocol=%u", protocol); switch (protocol) { case IP4_PT_ICMP: IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_ICMP); break; case IP4_PT_TCP: IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_TCP); break; case IP4_PT_UDP: IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_UDP); break; default: PRINT_ERROR("invalid protocol: protocol=%u", protocol); /** * TODO investigate why the freeFinsFrame below create segmentation fault */ freeFinsFrame(pff); break; } } else { PRINT_ERROR("Error: Wrong value of fdf.directionFlag"); freeFinsFrame(pff); } } else { PRINT_ERROR("Error: Wrong pff->dataOrCtrl value"); freeFinsFrame(pff); } }
/** * @brief Function processing all the incoming packets * * Responsible for parsing, checking reassembling and passing packets out. */ void ipv4_in_fdf(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct ipv4_data *md = (struct ipv4_data *) module->data; struct ip4_packet* ppacket = (struct ip4_packet*) ff->dataFrame.pdu; int len = ff->dataFrame.pduLength; md->stats.receivedtotal++; /* Parse the header. Some of the items only needed to be inserted into FDF meta data*/ struct ip4_header header; header.source = ntohl(ppacket->ip_src); header.destination = ntohl(ppacket->ip_dst); header.version = IP4_VER(ppacket); header.header_length = IP4_HLEN(ppacket); header.differentiated_service = ppacket->ip_dif; header.packet_length = ntohs(ppacket->ip_len); header.id = ntohs(ppacket->ip_id); header.flags = (uint8_t) (IP4_FLG(ntohs(ppacket->ip_fragoff))); header.fragmentation_offset = ntohs(ppacket->ip_fragoff) & IP4_FRAGOFF; header.ttl = ppacket->ip_ttl; header.protocol = ppacket->ip_proto; PRINT_DEBUG("protocol number is %d", header.protocol); header.checksum = ntohs(ppacket->ip_cksum); PRINT_DEBUG(""); /** Check packet version */ if (header.version != IP4_VERSION) { md->stats.badver++; md->stats.droppedtotal++; PRINT_ERROR("Packet ID %d has a wrong IP version (%d)", header.id, header.version); //free ppacket return; } PRINT_DEBUG(""); /* Check minimum header length */ if (header.header_length < IP4_MIN_HLEN) { PRINT_ERROR("Packet header length (%d) in packet ID %d is smaller than the defined minimum (20).", header.header_length, header.id); md->stats.badhlen++; md->stats.droppedtotal++; //free ppacket freeFinsFrame(ff); return; } //int hlen = header.header_length; //IP4_HLEN(ppacket); //PRINT_DEBUG("hdr_len=%u, hlen=%u", header.header_length, IP4_HLEN(ppacket)); /* Check the integrity of the header. Drop the packet if corrupted header.*/ if (ipv4_checksum(ppacket, header.header_length) != 0) { //TODO check this checksum, don't think it does uneven? PRINT_ERROR("Checksum check failed on packet ID %d, non zero result: %d", header.id, ipv4_checksum(ppacket, header.header_length)); md->stats.badsum++; md->stats.droppedtotal++; //free ppacket freeFinsFrame(ff); return; } PRINT_DEBUG(""); /* Check the length of the packet. If physical shorter than the declared in the header * drop the packet */ if (header.packet_length != len) { md->stats.badlen++; PRINT_DEBUG("The declared length is not equal to the actual length. pkt_len=%u len=%u", header.packet_length, len); if (header.packet_length > len) { PRINT_DEBUG("The header length is even longer than the len"); md->stats.droppedtotal++; //free ppacket freeFinsFrame(ff); return; } } PRINT_DEBUG(""); if (header.ttl == 0) { PRINT_WARN("todo"); //TODO discard packet & send TTL icmp to sender freeFinsFrame(ff); return; } PRINT_DEBUG("src=%u, dst=%u (hostf)", header.source, header.destination); /* Check the destination address, if not our, forward*/ if (header.destination != IPV4_ADDR_ANY_IP && header.destination != IPV4_ADDR_EVERY_IP) { //TODO check this struct addr_record *addr = (struct addr_record *) list_find1(md->addr_list, addr_ipv4_test, &header.destination); if (addr == NULL) { addr = (struct addr_record *) list_find1(md->addr_list, addr_bdcv4_test, &header.destination); if (addr == NULL) { if (ipv4_forward(module, ff, ppacket, header.destination, len)) { //TODO disabled atm md->stats.forwarded++; PRINT_DEBUG(""); } else { md->stats.droppedtotal++; PRINT_DEBUG(""); freeFinsFrame(ff); } return; } } } PRINT_DEBUG(""); /* Check fragmentation errors */ if ((header.flags & (IP4_DF | IP4_MF)) == (IP4_DF | IP4_MF)) { md->stats.fragerror++; md->stats.droppedtotal++; PRINT_ERROR("Packet ID %d has both DF and MF flags set", header.id); //free ppacket freeFinsFrame(ff); return; } /* If not fragmented, pass out. If fragmented, call reassembly algorithm. * If reassembly of an entire packet completed by this frame, pass out. * Otherwise return. */ PRINT_DEBUG(""); if (((header.flags & IP4_MF) | header.fragmentation_offset) == 0) { md->stats.delivered++; PRINT_DEBUG(""); ipv4_send_fdf_in(module, ff, &header, ppacket); } else { PRINT_WARN("todo"); //TODO fix this!! convert to module based PRINT_DEBUG("Packet ID %d is fragmented", header.id); struct ip4_packet* ppacket_reassembled = NULL; //IP4_reass(&header, ppacket); //free ppacket if (ppacket_reassembled != NULL) { md->stats.delivered++; md->stats.reassembled++; ipv4_send_fdf_in(module, ff, &header, ppacket_reassembled); } else { } } }
void udp_in_fdf(struct fins_module *module, struct finsFrame* ff) { struct udp_data *md = (struct udp_data *) module->data; PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); /* point to the necessary data in the FDF */ PRINT_DEBUG("%d", (int)ff); struct udp_header* packet = (struct udp_header*) ff->dataFrame.pdu; uint32_t protocol; secure_metadata_readFromElement(ff->metaData, "recv_protocol", &protocol); uint32_t family; secure_metadata_readFromElement(ff->metaData, "recv_family", &family); uint32_t src_ip; secure_metadata_readFromElement(ff->metaData, "recv_src_ipv4", &src_ip); uint32_t dst_ip; secure_metadata_readFromElement(ff->metaData, "recv_dst_ipv4", &dst_ip); if (protocol != UDP_PT_UDP) { md->stats.wrongProtocol++; md->stats.totalBadDatagrams++; PRINT_WARN("wrong protocol: expected=%u, proto=%u", UDP_PT_UDP, protocol); freeFinsFrame(ff); return; } /* begins checking the UDP packets integrity */ /** TODO Fix the length check below , I will highlighted for now */ uint32_t hlen = ntohs(packet->u_len); if (ff->dataFrame.pduLength != hlen) { md->stats.mismatchingLengths++; md->stats.totalBadDatagrams++; PRINT_DEBUG("UDP_in"); freeFinsFrame(ff); return; } /* the packet is does have an "Ignore checksum" value and fails the checksum, it is thrown away */ uint16_t checksum = UDP_checksum((struct udp_packet*) packet, htonl(src_ip), htonl(dst_ip)); uint32_t src_port = ntohs(packet->u_src); uint32_t dst_port = ntohs(packet->u_dst); PRINT_DEBUG("proto=%u, src=%u:%u, dst=%u:%u", protocol, src_ip, (uint16_t)src_port, dst_ip, (uint16_t)dst_port); PRINT_DEBUG("UDP_checksum=%u, checksum=%u", checksum, ntohs(packet->u_cksum)); if (packet->u_cksum != IGNORE_CHEKSUM) { if (checksum != 0) { md->stats.badChecksum++; md->stats.totalBadDatagrams++; PRINT_ERROR("bad checksum=0x%x, calc=0x%x", packet->u_cksum, checksum); freeFinsFrame(ff); return; } } else { md->stats.noChecksum++; PRINT_DEBUG("ignore checksum=%d", md->stats.noChecksum); } secure_metadata_writeToElement(ff->metaData, "recv_src_port", &src_port, META_TYPE_INT32); secure_metadata_writeToElement(ff->metaData, "recv_dst_port", &dst_port, META_TYPE_INT32); PRINT_DEBUG("PDU Length including UDP header %d", ff->dataFrame.pduLength); PRINT_DEBUG("PDU Length %d", (int)(ff->dataFrame.pduLength - U_HEADER_LEN)); int leng = ff->dataFrame.pduLength; ff->dataFrame.pduLength = leng - U_HEADER_LEN; uint8_t *old = ff->dataFrame.pdu; uint8_t *pdu = (uint8_t *) secure_malloc(ff->dataFrame.pduLength); memcpy(pdu, old + U_HEADER_LEN, ff->dataFrame.pduLength); ff->dataFrame.pdu = pdu; //######################### #ifdef DEBUG uint8_t *temp = (uint8_t *) secure_malloc(ff->dataFrame.pduLength + 1); memcpy(temp, ff->dataFrame.pdu, ff->dataFrame.pduLength); temp[ff->dataFrame.pduLength] = '\0'; PRINT_DEBUG("pduLen=%d, pdu='%s'", ff->dataFrame.pduLength, temp); free(temp); #endif //######################### md->stats.totalRecieved++; PRINT_DEBUG("UDP total recv'd=%d, ff=%p, meta=%p", md->stats.totalRecieved, ff, ff->metaData); if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_ERROR("send to switch error, ff=%p", ff); freeFinsFrame(ff); } PRINT_DEBUG("Freeing: pdu=%p", old); free(old); }
void ipv4_exec_reply(struct finsFrame *ff) { PRINT_DEBUG("Entered: ff=%p, meta=%p", ff, ff->metaData); int ret = 0; metadata *params = ff->metaData; if (params) { switch (ff->ctrlFrame.param_id) { case EXEC_ARP_GET_ADDR: PRINT_DEBUG("param_id=EXEC_ARP_GET_ADDR (%d)", ff->ctrlFrame.param_id); if (ff->ctrlFrame.ret_val) { uint64_t src_mac, dst_mac; ret += metadata_readFromElement(params, "src_mac", &src_mac) == META_FALSE; ret += metadata_readFromElement(params, "dst_mac", &dst_mac) == META_FALSE; if (ret) { PRINT_ERROR("ret=%d", ret); //TODO send nack } else { //ipv4_exec_reply_get_addr(ff, src_mac, dst_mac); struct ip4_store *store = store_list_find(ff->ctrlFrame.serial_num); if (store) { PRINT_DEBUG("store=%p, ff=%p, serial_num=%u", store, store->ff, store->serial_num); store_list_remove(store); uint32_t ether_type = IP4_ETH_TYPE; metadata_writeToElement(store->ff->metaData, "send_ether_type", ðer_type, META_TYPE_INT32); metadata_writeToElement(store->ff->metaData, "send_dst_mac", &dst_mac, META_TYPE_INT64); metadata_writeToElement(store->ff->metaData, "send_src_mac", &src_mac, META_TYPE_INT64); PRINT_DEBUG("recv frame: dst=0x%12.12llx, src=0x%12.12llx, type=0x%x", dst_mac, src_mac, ether_type); //print_finsFrame(fins_frame); ipv4_to_switch(store->ff); store->ff = NULL; store_free(store); freeFinsFrame(ff); } else { PRINT_ERROR("todo error"); } } } else { //TODO error sending back FDF as FCF? saved pdu for that PRINT_ERROR("todo error"); } break; default: PRINT_ERROR("Error unknown param_id=%d", ff->ctrlFrame.param_id); //TODO implement? freeFinsFrame(ff); break; } } else { //TODO send nack PRINT_ERROR("Error fcf.metadata==NULL"); freeFinsFrame(ff); } }
void ipv4_exec_reply(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); PRINT_WARN("todo"); freeFinsFrame(ff); }
void udp_out_fdf(struct fins_module *module, struct finsFrame* ff) { struct udp_data *md = (struct udp_data *) module->data; //struct udp_metadata_parsed parsed_meta; //struct udp_packet packet_host; struct udp_packet *packet_netw; uint16_t packet_length; /* read the FDF and make sure everything is correct*/ PRINT_DEBUG("UDP_out, ff=%p, meta=%p", ff, ff->metaData); //print_finsFrame(ff); packet_length = ff->dataFrame.pduLength + U_HEADER_LEN; if (packet_length > IP_MAXLEN) { PRINT_ERROR("todo error, data too long max 65536, len=%d", packet_length); } uint8_t *udp_dataunit = (uint8_t *) secure_malloc(packet_length); packet_netw = (struct udp_packet *) udp_dataunit; uint8_t *pdu = ff->dataFrame.pdu; /** constructs the UDP packet from the FDF and the meta data */ //######################### #ifdef DEBUG if (1) { uint8_t *temp = (uint8_t *) secure_malloc(ff->dataFrame.pduLength + 1); memcpy(temp, pdu, ff->dataFrame.pduLength); temp[ff->dataFrame.pduLength] = '\0'; PRINT_DEBUG("pduLen=%d, pdu='%s'", ff->dataFrame.pduLength, temp); free(temp); } #endif //######################### uint32_t dst_port; uint32_t src_port; uint32_t dst_ip; uint32_t src_ip; uint32_t family; secure_metadata_readFromElement(ff->metaData, "send_family", &family); secure_metadata_readFromElement(ff->metaData, "send_src_ipv4", &src_ip); secure_metadata_readFromElement(ff->metaData, "send_src_port", &src_port); secure_metadata_readFromElement(ff->metaData, "send_dst_ipv4", &dst_ip); secure_metadata_readFromElement(ff->metaData, "send_dst_port", &dst_port); uint32_t protocol = UDP_PROTOCOL; secure_metadata_writeToElement(ff->metaData, "send_protocol", &protocol, META_TYPE_INT32); /** fixing the values because of the conflict between uint16 type and * the 32 bit META_INT_TYPE */ //packet_host.u_src = srcbuf16; //packet_host.u_dst = dstbuf16; //packet_host.u_len = packet_length; //packet_host.u_cksum = 0; packet_netw->u_src = htons((uint16_t) src_port); packet_netw->u_dst = htons((uint16_t) dst_port); packet_netw->u_len = htons(packet_length); packet_netw->u_cksum = 0; memcpy(packet_netw->u_data, pdu, ff->dataFrame.pduLength); PRINT_DEBUG("src=%u:%u, dst=%u:%u, pkt_len=%u", src_ip, (uint16_t)src_port, dst_ip, (uint16_t)dst_port, packet_length); uint16_t checksum = UDP_checksum(packet_netw, htonl(src_ip), htonl(dst_ip)); packet_netw->u_cksum = htons(checksum); //packet_netw->u_cksum = 0; PRINT_DEBUG("checksum (h):0x%x", checksum); //PRINT_DEBUG("%u,%u", src_ip, dst_ip); PRINT_DEBUG("pkt_netw: %d,%d,%d,0x%x", packet_netw->u_src, packet_netw->u_dst, packet_netw->u_len, packet_netw->u_cksum); //ff->dataFrame.pdu = udp_dataunit; /* creates a new FDF to be sent out */ PRINT_DEBUG("%p", udp_dataunit); ff->dataFrame.pduLength = packet_length; ff->dataFrame.pdu = udp_dataunit; md->stats.totalSent++; struct finsFrame *ff_clone = cloneFinsFrame(ff); //TODO add switch & move between ipv4/ipv6 if (!module_send_flow(module, ff, UDP_FLOW_IPV4)) { PRINT_ERROR("send to switch error, ff=%p", ff); freeFinsFrame(ff); } struct udp_sent *sent = udp_sent_create(ff_clone, src_ip, src_port, dst_ip, dst_port); if (list_has_space(md->sent_packet_list)) { list_append(md->sent_packet_list, sent); PRINT_DEBUG("sent_packet_list=%p, len=%u, max=%u", md->sent_packet_list, md->sent_packet_list->len, md->sent_packet_list->max); gettimeofday(&sent->stamp, 0); } else { //PRINT_DEBUG("Clearing sent_packet_list"); //udp_sent_list_gc(udp_sent_packet_list, UDP_MSL_TO_DEFAULT); //if (!udp_sent_list_has_space(udp_sent_packet_list)) { PRINT_DEBUG("Dropping head of sent_packet_list"); struct udp_sent *old = (struct udp_sent *) list_remove_front(md->sent_packet_list); udp_sent_free(old); //} list_append(md->sent_packet_list, sent); PRINT_DEBUG("sent_packet_list=%p, len=%u, max=%u", md->sent_packet_list, md->sent_packet_list->len, md->sent_packet_list->max); gettimeofday(&sent->stamp, 0); } PRINT_DEBUG("Freeing: pdu=%p", pdu); free(pdu); }