/**@brief this generates a Fins frame which is sent to the arp module so that the * (1) a host receives an ARP reply, OR (2) sends an ARP request to a network * @param fins_frame is the pointer to the received fins frame * @param task indicates whether the arp message is a request or a reply to or from network */ void fins_from_net(struct finsFrame *fins_frame, int task) { uint32_t IP_addrs_read; uint64_t MAC_addrs; struct ARP_message *msg1 = (struct ARP_message*)malloc(sizeof(struct ARP_message)); struct ARP_message *msg2 = (struct ARP_message*)malloc(sizeof(struct ARP_message)); struct arp_hdr *arp_net = (struct arp_hdr*) malloc(sizeof(struct arp_hdr)); PRINT_DEBUG("\nFins data frame which carries a request or reply ARP from a network\n"); IP_addrs_read = read_IP_addrs(); MAC_addrs = search_MAC_addrs(IP_addrs_read, ptr_neighbor_list); if (task==1){ mimic_net_request(IP_addrs_read, MAC_addrs, msg1); arp_msg_to_hdr(msg1, arp_net); host_to_net(arp_net); arp_to_fins(arp_net, fins_frame); } else if (task==2){ gen_requestARP(IP_addrs_read, msg1); mimic_net_reply(msg1, msg2); arp_msg_to_hdr(msg2, arp_net); host_to_net(arp_net); arp_to_fins(arp_net, fins_frame); } fins_frame->destinationID.id = ARPID; free(msg1); free(msg2); }
/************************************************************************* * change packet's format from SOS message to MAC * *************************************************************************/ void sosmsg_to_mac(Message *msg, VMAC_PPDU *ppdu) { ppdu->len = msg->len + PRE_PAYLOAD_LEN + POST_PAYLOAD_LEN; ppdu->mpdu.daddr = host_to_net(msg->daddr); ppdu->mpdu.saddr = host_to_net(msg->saddr); ppdu->mpdu.did = msg->did; ppdu->mpdu.sid = msg->sid; ppdu->mpdu.type = msg->type; ppdu->mpdu.data = msg->data; }
/* Send the packets to tell our friends what our DHT public key is. * * if onion_dht_both is 0, use only the onion to send the packet. * if it is 1, use only the dht. * if it is something else, use both. * * return the number of packets sent on success * return -1 on failure. */ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) { if (friend_num >= onion_c->num_friends) return -1; uint8_t data[FAKEID_DATA_MAX_LENGTH]; data[0] = FAKEID_DATA_ID; uint64_t no_replay = unix_time(); host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); memcpy(data + 1, &no_replay, sizeof(no_replay)); memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); Node_format nodes[MAX_SENT_NODES]; uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES); uint32_t i; for (i = 0; i < num_nodes; ++i) to_net_family(&nodes[i].ip_port.ip); memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes); int num1 = -1, num2 = -1; if (onion_dht_both != 1) num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); if (onion_dht_both != 0) num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); if (num1 == -1) return num2; if (num2 == -1) return num1; return num1 + num2; }
/**@brief This function sends out a fins frame that passes an arp request out to the network * @param sought_IP_addrs is the IP address whose associated MAC address is sought * @param fins_arp_out points to the fins frame which will be sent from the module * */ void arp_out_request(uint32_t sought_IP_addrs, struct finsFrame *fins_arp_out){ gen_requestARP(sought_IP_addrs, &arp_msg); arp_msg_to_hdr(&arp_msg, packet); host_to_net(packet); print_arp_hdr(packet); arp_to_fins(packet, fins_arp_out); /**arp request to be sent to network*/ }
/**@brief This function sends out a fins frame with a reply arp in response to a request * from the network * @param fins_arp_out points to the fins frame which will be sent from the module * */ void arp_out_reply(struct finsFrame *fins_arp_out){ struct ARP_message arp_msg_reply; gen_replyARP(&arp_msg, &arp_msg_reply); arp_msg_to_hdr(&arp_msg_reply, packet); host_to_net(packet); print_arp_hdr(packet); arp_to_fins(packet, fins_arp_out); /**arp reply to be sent to network */ }
static int save_blocklist(char *path) { if (arg_opts.ignore_data_file) return 0; if (path == NULL) return -1; int len = sizeof(BlockedFriend) * Blocked_Contacts.num_blocked; char *data = malloc(len); if (data == NULL) exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY); int i; int count = 0; for (i = 0; i < Blocked_Contacts.max_index; ++i) { if (count > Blocked_Contacts.num_blocked) return -1; if (Blocked_Contacts.list[i].active) { BlockedFriend tmp; memset(&tmp, 0, sizeof(BlockedFriend)); tmp.namelength = htons(Blocked_Contacts.list[i].namelength); memcpy(tmp.name, Blocked_Contacts.list[i].name, Blocked_Contacts.list[i].namelength + 1); memcpy(tmp.pub_key, Blocked_Contacts.list[i].pub_key, TOX_CLIENT_ID_SIZE); uint8_t lastonline[sizeof(uint64_t)]; memcpy(lastonline, &Blocked_Contacts.list[i].last_on, sizeof(uint64_t)); host_to_net(lastonline, sizeof(uint64_t)); memcpy(&tmp.last_on, lastonline, sizeof(uint64_t)); memcpy(data + count * sizeof(BlockedFriend), &tmp, sizeof(BlockedFriend)); ++count; } } FILE *fp = fopen(path, "wb"); if (fp == NULL) { free(data); return -1; } int ret = 0; if (fwrite(data, len, 1, fp) != 1) ret = -1; fclose(fp); free(data); return ret; }
/**@brief this function receives an arp message from outside and processes it * @param fins_received is the pointer to the fins frame which has been received by the ARP module */ void arp_in(struct finsFrame *fins_received){ struct ARP_message *arp_msg_ptr; fins_arp_in = fins_received; /**request or reply received from the network and as transmitted by the ethernet stub*/ if (fins_arp_in->dataOrCtrl == DATA && (fins_arp_in->destinationID.id == (unsigned char) ARPID)) { fins_to_arp(fins_arp_in, packet); //extract arp hdr from the fins frame host_to_net(packet); //convert it into the right format (e.g. htons issue etc.) arp_msg_ptr = &arp_msg; arp_hdr_to_msg(packet, arp_msg_ptr); //convert the hdr into an internal ARP message (e.g. use uint64_t instead of unsigned char) print_msgARP(arp_msg_ptr); if (check_valid_arp(arp_msg_ptr)==1){ update_cache(arp_msg_ptr); if ((arp_msg_ptr->target_IP_addrs==interface_IP_addrs) && (arp_msg_ptr->operation==ARPREQUESTOP)) arp_out(REPLYDATA);//generate reply else if ((arp_msg_ptr->target_IP_addrs==interface_IP_addrs) && (arp_msg_ptr->operation==ARPREPLYOP)) { target_IP_addrs = arp_msg.sender_IP_addrs; arp_out(REPLYCONTROL);//generate fins control carrying neighbor's MAC address } } } else if ((fins_arp_in->dataOrCtrl == CONTROL) && (fins_arp_in->ctrlFrame.opcode == WRITEREQUEST) && (fins_arp_in->destinationID.id == (unsigned char) ARPID)) {/**as a request received from the ethernet stub-- IP address is provided in this fins control frame*/ memcpy(fins_IP_address, fins_arp_in->ctrlFrame.paramterValue, PROTOCOLADDRSLEN); target_IP_addrs = gen_IP_addrs(fins_IP_address[0],fins_IP_address[1],fins_IP_address[2],fins_IP_address[3]); /**request initiated by the ethernet stub*/ if (search_list(ptr_cacheHeader, target_IP_addrs)==0)//i.e. not found arp_out(REQUESTDATA); //generate arp request for MAC address and send out to the network else arp_out(REPLYCONTROL);//generate fins control carrying MAC address foe ethernet } print_cache(); }
/* Send the packets to tell our friends what our DHT public key is. * * if onion_dht_both is 0, use only the onion to send the packet. * if it is 1, use only the dht. * if it is something else, use both. * * return the number of packets sent on success * return -1 on failure. */ static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) { if (friend_num >= onion_c->num_friends) return -1; uint8_t data[FAKEID_DATA_MAX_LENGTH]; data[0] = FAKEID_DATA_ID; uint64_t no_replay = unix_time(); host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); memcpy(data + 1, &no_replay, sizeof(no_replay)); memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); Node_format nodes[MAX_SENT_NODES]; uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2)); uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays); num_nodes += num_relays; int nodes_len = 0; if (num_nodes != 0) { nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, num_nodes); if (nodes_len <= 0) return -1; } int num1 = -1, num2 = -1; if (onion_dht_both != 1) num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); if (onion_dht_both != 0) num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); if (num1 == -1) return num2; if (num2 == -1) return num1; return num1 + num2; }