void NetClient::create_room() { if (!me || !server || ourself == players.end()) return; ENetPacket* pck = create_packet(2); pck->data[0] = LEMNET_ROOM_CREATE; pck->data[1] = ourself->number; enet_peer_send(server, LEMNET_CHANNEL_REPLAY, pck); }
/* * Convert the file's data into a number of packets */ void packetize(char* data, int file_length, int payload_size) { int current_byte; // Index of "data" int bytes_read; // Bytes read from "data" char* pckt_data; // Bytes meant for a packet first_seqno = 0; // Move bytes from data buffer into pckt_data and create packets current_byte = 0; bytes_read = 0; pckt_data = (char*)malloc(sizeof(pckt_data)*payload_size); //printf("Reading file...\n"); while(current_byte < file_length) { pckt_data[bytes_read] = data[current_byte]; if(bytes_read == payload_size) { //printf("Current byte: %d, Bytes read: %d\n",current_byte, bytes_read); struct packet* pckt = create_packet(pckt_data, bytes_read, DAT, current_byte - bytes_read + 1); add_packet(pckt, data_packets); free(pckt_data); pckt_data = (char*)malloc(sizeof(pckt_data)*payload_size); bytes_read = 0; } //printf("bytes_read: %d\n",bytes_read); //printf("current_byte: %d\n",current_byte); bytes_read++; current_byte++; } // End of file, packet size is less than MAX_PAYLOAD_SIZE // =>Shave off empty memory struct packet* pckt = create_packet(pckt_data, bytes_read, DAT, current_byte); add_packet(pckt, data_packets); //printf("sender: end of file\n"); // Debug: print list of data packets int i = 0; while(data_packets[i] != 0) { //if(i){printf("data packet %d seqno: %d, ackno: %d\n",i,data_packets[i]->header.seqno, data_packets[i]->header.ackno);} //if(i){printf("Data_packets[%d]:\n",i);print_contents(data_packets[i]);} i++; } }
static void request_cached_data (int sock, int hops) { int size; struct allnet_header * hp = create_packet (0, ALLNET_TYPE_DATA_REQ, hops, ALLNET_SIGTYPE_NONE, NULL, 0, NULL, 0, NULL, NULL, &size); if (! send_pipe_message_free (sock, (char *) (hp), size, ALLNET_PRIORITY_LOCAL_LOW)) printf ("unable to request cached data\n"); }
void handle_get_sports_data(uint16_t *data, uint8_t numofdata) { stlv_packet p = create_packet(); if (p == NULL) return; element_handle h = append_element(p, NULL, "A", 1); element_append_data(p, h, (uint8_t*)&data, sizeof(uint16_t) * numofdata); send_packet(p, 0, 0); }
void gg_send_command(gg_socket *s, uint8_t opcode) { pkt_t *p; p = create_packet(VERSION, PKT_MASK_RGB8, opcode, 0, 0, 0); send_packet(s, p); }
char * shmon_callback(shm_packet_t * packet) { shmon_packet_t * shmon_packet = (shmon_packet_t*)packet->dat; switch(shmon_packet->cmd) { case SHMON_CTRL_GRAB_PID: { /* Allocate shell and return its pid */ /* Read the user from shared memory */ char * user = shmon_packet->username; /* See if he is already logged in (through the hashmap) */ if(hashmap_contains(multishell_sessions, user)) { /* return the user's pid instead of the new one (if he's logged in) */ return respond_to_client((int)hashmap_get(multishell_sessions, user)); } else { /* the user is not logged in, spawn new shell */ spawn_shell(shells_forked, user); return respond_to_client(get_pid_from_hash(shells_forked++)); } break; } case SHMON_CTRL_ADD_USR: { /* Add a user to the hashmap */ /* Read the user from shared memory */ char * user = shmon_packet->username; int pid = atoi(shmon_packet->cmd_dat); hashmap_set(multishell_sessions, user, (void*)pid); break; } case SHMON_CTRL_GET_USR: { /* Get a user from the hashmap */ /* Grab process pid from user IF he exists */ /* Read the user from shared memory */ char * user = shmon_packet->username; if(hashmap_contains(multishell_sessions, user)) return respond_to_client((int)hashmap_get(multishell_sessions, user)); else return respond_to_client(-1); break; } case SHMON_CTRL_REDIR: { /* Sends packet to the destination process, causing that process to 'wake up'. */ char packet_dest[SHM_MAX_ID_SIZE]; sprintf(packet_dest, SHMON_CLIENT_LOGIN_FORMAT, atoi(shmon_packet->cmd_dat)); char shm_msg[16] = SHMON_MSG_PROC_WAKE; shm_packet_t * pack = create_packet(shmon_server, packet_dest, SHM_DEV_CLIENT, shm_msg, strlen(shm_msg)); shman_send_to_network_clear(shmon_server, pack, 0); free(pack); break; } } char * ret = malloc(SHM_MAX_PACKET_DAT_SIZE); ret[0] = 1; /* just tells it is finished really. The client won't be expecting data to return, so it's not important what number we put here */ return ret; }
void test_cls_pmr_chain(void) { odp_packet_t pkt; odph_ipv4hdr_t *ip; odph_udphdr_t *udp; odp_queue_t queue; uint32_t addr = 0; uint32_t mask; uint32_t seq; pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); ip->src_addr = odp_cpu_to_be_32(addr); ip->chksum = 0; ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt)); udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); ip->src_addr = odp_cpu_to_be_32(addr); ip->chksum = 0; ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt)); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
// send packet (docs/orcp.txt) uint32_t ORCP::send_packet(uint8_t IR, uint8_t IT, uint8_t SC, uint8_t SS, uint8_t* data, uint32_t data_size) { if(!data || data_size == 0) return 0; // create packet in buffer if(create_packet(IR, IT, SC, SS, data, data_size) == 0) return 0; return send_packet(out_buffer.data, out_buffer.size); }
void handle_get_sports_grid() { stlv_packet p = create_packet(); if (p == NULL) return; element_handle h = append_element(p, NULL, "R", 1); ui_config* config = window_readconfig(); element_append_data(p, h, (uint8_t*)&config->sports_grid_data, sizeof(config->sports_grid_data)); log_info("send_sports_grid(%d)\n", sizeof(config->sports_grid_data)); send_packet(p, 0, 0); }
struct demux_packet *new_demux_packet(size_t len) { struct demux_packet *dp = create_packet(len); dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE); if (!dp->buffer) { mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n"); abort(); } memset(dp->buffer + len, 0, 8); return dp; }
int main(int argc, const char *argv[]) { ParseArgs(argc, argv); if (cmdsOnly) { /* We make this a special case to avoid messing up other code. */ CreateBootCmds(); FinishBootCmds(); SendToDevice(&boot_cmds_packet->data[SIZE_OF_HEADER],SIZE_OF_BOOT_CMDS); exit(EXIT_SUCCESS); } if (netBoot && !toFiles) { /* Do not bother with this if we just want to write the packets to files. Means you do not have to be root to run --tofiles. */ net_init(); } else if (serBoot) { if (!SetupSerial()) { exit(0); } } CreateBootLoader(); CreateBootCmds(); FinishBootCmds(); printf("Starting boot...\n"); if (doing_flash) { printf("We're doing a flash write, this may take up to a few minutes...\n"); } if (toFiles) { udword seq = 0; struct packet_buf *p; while((p = create_packet(seq++))) { SendToDevice(p->data, p->size); } exit(EXIT_SUCCESS); } if (netBoot) { NetBoot(); } else if (serBoot) { SerBoot(); } printf("Done.\n"); return EXIT_SUCCESS; } /* main */
uint32_t ORCP::send_packet(orcp_packet* p) { if(!p) return 0; // create packet in buffer if(create_packet(p->IR, p->IT, p->SC, p->SS, p->data, p->data_size) == 0) return 0; return send_packet(out_buffer.data, out_buffer.size); }
lagopus_result_t check_packet_parse_array_expect_error(ofp_handler_proc_t handler_proc, const char *packet[], int array_len, const struct ofp_error *expected_error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; struct channel *channel = create_data_channel(); struct ofp_header xid_header; struct pbuf *pbuf; struct ofp_error error; bool error_has_occurred = false; int i; for (i = 0; i < array_len; i++) { lagopus_msg_debug(1, "packet[%d] start ... %s\n", i, packet[i]); /* create packet */ create_packet(packet[i], &pbuf); /* parse header */ if (ofp_header_decode_sneak_test(pbuf, &xid_header) != LAGOPUS_RESULT_OK) { pbuf_free(pbuf); s_destroy_static_data(); TEST_FAIL_MESSAGE("handler_test_utils.c: cannot decode header\n"); return LAGOPUS_RESULT_OFP_ERROR; } /* call func & check */ res = (handler_proc)(channel, pbuf, &xid_header, &error); lagopus_msg_debug(1, "packet[%d] done ... %s\n", i, lagopus_error_get_string(res)); if (res == LAGOPUS_RESULT_OK) { TEST_ASSERT_EQUAL_MESSAGE(0, pbuf->plen, "handler_test_utils.c: packet data len error."); } else if (res == LAGOPUS_RESULT_OFP_ERROR) { error_has_occurred = true; if (expected_error != NULL) { TEST_ASSERT_EQUAL_OFP_ERROR(expected_error, &error); } pbuf_free(pbuf); break; } /* free */ pbuf_free(pbuf); } /* free */ s_destroy_static_data(); if (error_has_occurred == true) { TEST_ASSERT_EQUAL_OFP_ERROR(expected_error, &error); } return res; }
void gg_set_duration(gg_socket *s, unsigned int duration) { pkt_t *p; p = create_packet(VERSION, PKT_MASK_RGB8, PKT_TYPE_SET_DURATION, 0, 0, 0); send_packet(s, p); free(p->data); free(p); }
void NetClient::set_room(const char target_room) { if (!me || !server || ourself == players.end()) return; ENetPacket* pck = create_packet(3); pck->data[0] = LEMNET_ROOM_CHANGE; pck->data[1] = ourself->number; pck->data[2] = target_room; enet_peer_send(server, LEMNET_CHANNEL_REPLAY, pck); // Put ourself directly into the new room, so that we cannot change // several times because of the lobby screen not updating. ourself->room = target_room; }
lagopus_result_t check_packet_parse_with_dequeue_expect_error(ofp_handler_proc_t handler_proc, const char packet[], void **get, const struct ofp_error *expected_error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; struct channel *channel = NULL; struct ofp_header xid_header; struct ofp_bridge *ofpb = NULL; struct pbuf *pbuf = NULL; struct ofp_error error; struct ofp_bridgeq *bridgeq = NULL; if (get == NULL) { return LAGOPUS_RESULT_INVALID_ARGS; } /* start ofp_handler */ if (s_start_ofp_handler() == false) { goto done; } /* get ofp_bridge */ channel = create_data_channel(); if (channel == NULL) { TEST_FAIL_MESSAGE("channel is NULL."); } res = ofp_bridgeq_mgr_bridge_lookup(channel_dpid_get(channel), &bridgeq); if (res == LAGOPUS_RESULT_OK) { ofpb = ofp_bridgeq_mgr_bridge_get(bridgeq); ofp_bridgeq_mgr_bridgeq_free(bridgeq); } else { TEST_FAIL_MESSAGE("handler_test_utils.c: " "ofp_bridgeq_mgr_bridge_get error."); } /* create packet */ create_packet(packet, &pbuf); /* parse header */ if (ofp_header_decode_sneak_test(pbuf, &xid_header) != LAGOPUS_RESULT_OK) { TEST_FAIL_MESSAGE("handler_test_utils.c: cannot decode header\n"); return LAGOPUS_RESULT_OFP_ERROR; } /* call func & check */ res = (handler_proc)(channel, pbuf, &xid_header, &error); if (res == LAGOPUS_RESULT_OK) { res = lagopus_bbq_get(&ofpb->event_dataq, get, void *, TIMEOUT); TEST_ASSERT_EQUAL_MESSAGE(LAGOPUS_RESULT_OK, res, "handler_test_utils.c: lagopus_bbq_get error."); } else if (res == LAGOPUS_RESULT_OFP_ERROR) {
int main(int argc, char *argv[]) { int sock = 0; if((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); return -1; } /* my address */ struct sockaddr_in receivesocket; memset(&receivesocket, 0, sizeof(receivesocket)); receivesocket.sin_family = AF_INET; receivesocket.sin_addr.s_addr = htonl(INADDR_ANY); receivesocket.sin_port = htons(9999); if(bind(sock, (struct sockaddr *) &receivesocket, sizeof(receivesocket)) < 0) { perror("bind"); return -1; } /* kernel address */ struct sockaddr_in sendsocket; memset(&sendsocket, 0, sizeof(sendsocket)); sendsocket.sin_family = AF_INET; sendsocket.sin_addr.s_addr = inet_addr("127.0.0.1"); sendsocket.sin_port = htons(5555); /* Send message to the server */ struct WriteCommand test; struct Command command; command.type = WriteCommandType; memcpy(command.data, &test, sizeof(struct WriteCommand)); unsigned int packet_size = 0; struct Packet *packet = create_packet(1, &packet_size); memcpy(packet->commands, &command, sizeof(struct Command)); if(sendto(sock, packet, packet_size, 0, (struct sockaddr *)&sendsocket, sizeof(sendsocket)) != packet_size) { perror("sendto"); return -1; } free(packet); return 0; }
void test_pmr_cos(void) { odp_packet_t pkt; odph_udphdr_t *udp; odp_queue_t queue; uint32_t seq; pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_PMR]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
void test_pktio_default_cos(void) { odp_packet_t pkt; odp_queue_t queue; uint32_t seq; /* create a default packet */ pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); /* Default packet should be received in default queue */ CU_ASSERT(queue == queue_list[CLS_DEFAULT]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
void gg_set_duration(gg_socket *s, unsigned int duration) { pkt_t *p; uint32_t ndur; p = create_packet(VERSION, PKT_MASK_RGB8, PKT_TYPE_SET_DURATION, 0, 0, 0); ndur = htonl(duration); p->data = (uint8_t *)malloc(sizeof(uint32_t)); memcpy(p->data, &ndur, sizeof(uint32_t)); send_packet(s, p); free(p->data); free(p); }
int send_dummy_packet(){ // Create data packet // Add checksum and packet_type bit char *payload; vlong payload_size = create_dummy_packet(&payload); int packet_size = payload_size + C_HLEN; char *packet = malloc(packet_size); create_packet(packet, ROUTER_MAC, globals.own_node, globals.other_node, DATA_PORT, payload, payload_size); int i; for (i = 0; i <= NUM_DUMMY_PACKETS; i++) send_packet_on_line(INF0, packet, packet_size); free(payload); return 0; }
void NetClient::send_chat_message(const std::string& message) { if (!me || !server) return; std::string str = gloB->user_name; str += ": "; str += message; ENetPacket* p = create_packet(NETWORK_TEXT_LENGTH + 3); p->data[0] = LEMNET_CHAT_MESSAGE; p->data[1] = ourself->number; int i = 2; while (i < NETWORK_TEXT_LENGTH + 2 && i < (int) str.length() + 2) { p->data[i] = str[i - 2]; ++i; } p->data[i] = '\0'; enet_peer_send(server, LEMNET_CHANNEL_CHAT, p); }
static int send_key_request (int sock, char * phrase, unsigned char * addr, int * nbits) { /* compute the destination address from the phrase */ unsigned char destination [ADDRESS_SIZE]; char * mapped; int mlen = map_string (phrase, &mapped); sha512_bytes (mapped, mlen, (char *) destination, 1); free (mapped); random_bytes ((char *) addr, ADDRESS_SIZE); *nbits = 8; int dsize = 1; /* nbits_fingerprint with no key */ int psize = -1; struct allnet_header * hp = create_packet (dsize, ALLNET_TYPE_KEY_REQ, 10, ALLNET_SIGTYPE_NONE, addr, *nbits, destination, *nbits, NULL, NULL, &psize); if (hp == NULL) { printf ("send_key_request: unable to create packet of size %d/%d\n", dsize, psize); return 0; } int hsize = ALLNET_SIZE(hp->transport); if (psize != hsize + dsize) { printf ("send_key_request error: psize %d != %d = %d + %d\n", psize, hsize + dsize, hsize, dsize); return 0; } char * packet = (char *) hp; struct allnet_key_request * kp = (struct allnet_key_request *) (packet + hsize); kp->nbits_fingerprint = 0; #ifdef DEBUG_PRINT printf ("sending %d-byte key request\n", psize); #endif /* DEBUG_PRINT */ if (! send_pipe_message_free (sock, packet, psize, ALLNET_PRIORITY_LOCAL)) { printf ("unable to send key request message\n"); return 0; } return 1; }
/** * If an error is encountered, display it on the server * And also send a message to the client * * Parameters: * - int err_socket => The file descriptor to the server socket * - int err_type => The error type * - char* err_message => The error message * - struct sockaddr* err_destination => The destination address (client) * - socklen_t destination_length => The length of a sockaddr structure * - int* s_state => The state of the server * */ void server_error_encountered(int err_socket, int err_type, char* err_message, struct sockaddr* err_destination, int* s_state) { // Display the error encountered perror(err_message); // Some parameters socklen_t destination_length = (socklen_t)sizeof(struct sockaddr); // Create the packet to send struct packet error_packet; create_packet(&error_packet, err_type, err_message); // Send an error packet if (sendto(err_socket, &error_packet, sizeof(struct packet), 0, err_destination, destination_length) == -1) perror("Error during the sending of the error packet."); // Then put the server free if (s_state != NULL) *s_state = S_FREE; }
void test_pktio_error_cos(void) { odp_queue_t queue; odp_packet_t pkt; /*Create an error packet */ pkt = create_packet(false); odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); /* Incorrect IpV4 version */ ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; ip->chksum = 0; enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); /* Error packet should be received in error queue */ CU_ASSERT(queue == queue_list[CLS_ERROR]); odp_packet_free(pkt); }
void NetClient::set_level(const Filename& filename) { if (!me || !server) return; Level level(filename); std::ostringstream s; s << level; // Kopiert von send_chat_message und angepasst ENetPacket* p = create_packet(s.str().length() + 3); p->data[0] = LEMNET_LEVEL_FILE; p->data[1] = ourself->number; unsigned i = 2; while (i < s.str().length() + 2) { p->data[i] = s.str()[i - 2]; ++i; } p->data[i] = '\0'; enet_peer_send(server, LEMNET_CHANNEL_MAIN, p); }
int send_packet(struct node *data_node, bool is_retransmitted) { // Create data packet // Add checksum and packet_type bit char *payload; vlong payload_size = create_data_packet(data_node->mem_ptr, data_node->size, data_node->seq_num, &payload, is_retransmitted); int packet_size = payload_size + C_HLEN; char *packet = malloc(packet_size); create_packet(packet, ROUTER_MAC, globals.own_node, globals.other_node, DATA_PORT, payload, payload_size); send_packet_on_line(INF0, packet, packet_size); free(payload); return packet_size; }
static int packetize_data(const u8 *data, size_t length) { int rc = 0; int done = 0; int packet_length; u8 *temp; u8 *end = (u8 *) data + length; pr_debug("packetize_data: data length %zd\n", length); if (!rbu_data.packetsize) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_WARNING "dell_rbu: packetsize not specified\n"); #else ; #endif return -EIO; } temp = (u8 *) data; /* packetize the hunk */ while (!done) { if ((temp + rbu_data.packetsize) < end) packet_length = rbu_data.packetsize; else { /* this is the last packet */ packet_length = end - temp; done = 1; } if ((rc = create_packet(temp, packet_length))) return rc; pr_debug("%p:%td\n", temp, (end - temp)); temp += packet_length; } rbu_data.imagesize = length; return rc; }
void test_cos_with_l2_priority(void) { odp_packet_t pkt; odph_ethhdr_t *ethhdr; odph_vlanhdr_t *vlan; odp_queue_t queue; uint32_t seq; uint8_t i; for (i = 0; i < CLS_L2_QOS_MAX; i++) { pkt = create_packet(true); seq = cls_pkt_get_seq(pkt); ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); vlan = (odph_vlanhdr_t *)(ðhdr->type); vlan->tci = odp_cpu_to_be_16(i << 13); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); } }
void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t length, const int epoll_fd, int sessions, int maxsessions) { uint8_t protocol; void *saddr; void *daddr; char source[INET6_ADDRSTRLEN + 1]; char dest[INET6_ADDRSTRLEN + 1]; char flags[10]; int flen = 0; uint8_t *payload; // Get protocol, addresses & payload uint8_t version = (*pkt) >> 4; if (version == 4) { if (length < sizeof(struct iphdr)) { log_android(ANDROID_LOG_WARN, "IP4 packet too short length %d", length); return; } struct iphdr *ip4hdr = (struct iphdr *) pkt; protocol = ip4hdr->protocol; saddr = &ip4hdr->saddr; daddr = &ip4hdr->daddr; if (ip4hdr->frag_off & IP_MF) { log_android(ANDROID_LOG_ERROR, "IP fragment offset %u", (ip4hdr->frag_off & IP_OFFMASK) * 8); return; } uint8_t ipoptlen = (uint8_t) ((ip4hdr->ihl - 5) * 4); payload = (uint8_t *) (pkt + sizeof(struct iphdr) + ipoptlen); if (ntohs(ip4hdr->tot_len) != length) { log_android(ANDROID_LOG_ERROR, "Invalid length %u header length %u", length, ntohs(ip4hdr->tot_len)); return; } if (loglevel < ANDROID_LOG_WARN) { if (!calc_checksum(0, (uint8_t *) ip4hdr, sizeof(struct iphdr))) { log_android(ANDROID_LOG_ERROR, "Invalid IP checksum"); return; } } } else if (version == 6) { if (length < sizeof(struct ip6_hdr)) { log_android(ANDROID_LOG_WARN, "IP6 packet too short length %d", length); return; } struct ip6_hdr *ip6hdr = (struct ip6_hdr *) pkt; // Skip extension headers uint16_t off = 0; protocol = ip6hdr->ip6_nxt; if (!is_upper_layer(protocol)) { log_android(ANDROID_LOG_WARN, "IP6 extension %d", protocol); off = sizeof(struct ip6_hdr); struct ip6_ext *ext = (struct ip6_ext *) (pkt + off); while (is_lower_layer(ext->ip6e_nxt) && !is_upper_layer(protocol)) { protocol = ext->ip6e_nxt; log_android(ANDROID_LOG_WARN, "IP6 extension %d", protocol); off += (8 + ext->ip6e_len); ext = (struct ip6_ext *) (pkt + off); } if (!is_upper_layer(protocol)) { off = 0; protocol = ip6hdr->ip6_nxt; log_android(ANDROID_LOG_WARN, "IP6 final extension %d", protocol); } } saddr = &ip6hdr->ip6_src; daddr = &ip6hdr->ip6_dst; payload = (uint8_t *) (pkt + sizeof(struct ip6_hdr) + off); // TODO checksum } else { log_android(ANDROID_LOG_ERROR, "Unknown version %d", version); return; } inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source)); inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest)); // Get ports & flags int syn = 0; uint16_t sport = 0; uint16_t dport = 0; if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) { if (length - (payload - pkt) < sizeof(struct icmp)) { log_android(ANDROID_LOG_WARN, "ICMP packet too short"); return; } struct icmp *icmp = (struct icmp *) payload; // http://lwn.net/Articles/443051/ sport = ntohs(icmp->icmp_id); dport = ntohs(icmp->icmp_id); } else if (protocol == IPPROTO_UDP) { if (length - (payload - pkt) < sizeof(struct udphdr)) { log_android(ANDROID_LOG_WARN, "UDP packet too short"); return; } struct udphdr *udp = (struct udphdr *) payload; sport = ntohs(udp->source); dport = ntohs(udp->dest); // TODO checksum (IPv6) } else if (protocol == IPPROTO_TCP) { if (length - (payload - pkt) < sizeof(struct tcphdr)) { log_android(ANDROID_LOG_WARN, "TCP packet too short"); return; } struct tcphdr *tcp = (struct tcphdr *) payload; sport = ntohs(tcp->source); dport = ntohs(tcp->dest); if (tcp->syn) { syn = 1; flags[flen++] = 'S'; } if (tcp->ack) flags[flen++] = 'A'; if (tcp->psh) flags[flen++] = 'P'; if (tcp->fin) flags[flen++] = 'F'; if (tcp->rst) flags[flen++] = 'R'; // TODO checksum } else if (protocol != IPPROTO_HOPOPTS && protocol != IPPROTO_IGMP && protocol != IPPROTO_ESP) report_error(args, 1, "Unknown protocol %d", protocol); flags[flen] = 0; // Limit number of sessions if (sessions >= maxsessions) { if ((protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) || (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) || (protocol == IPPROTO_TCP && syn)) { log_android(ANDROID_LOG_ERROR, "%d of max %d sessions, dropping version %d protocol %d", sessions, maxsessions, protocol, version); return; } } // Get uid jint uid = -1; if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6 || (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) || (protocol == IPPROTO_TCP && syn)) uid = get_uid_retry(version, protocol, saddr, sport); log_android(ANDROID_LOG_DEBUG, "Packet v%d %s/%u > %s/%u proto %d flags %s uid %d", version, source, sport, dest, dport, protocol, flags, uid); // Check if allowed int allowed = 0; struct allowed *redirect = NULL; if (protocol == IPPROTO_UDP && has_udp_session(args, pkt, payload)) allowed = 1; // could be a lingering/blocked session else if (protocol == IPPROTO_TCP && !syn) allowed = 1; // assume existing session else { jobject objPacket = create_packet( args, version, protocol, flags, source, sport, dest, dport, "", uid, 0); redirect = is_address_allowed(args, objPacket); allowed = (redirect != NULL); if (redirect != NULL && (*redirect->raddr == 0 || redirect->rport == 0)) redirect = NULL; } // Handle allowed traffic if (allowed) { if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) handle_icmp(args, pkt, length, payload, uid, epoll_fd); else if (protocol == IPPROTO_UDP) handle_udp(args, pkt, length, payload, uid, redirect, epoll_fd); else if (protocol == IPPROTO_TCP) handle_tcp(args, pkt, length, payload, uid, redirect, epoll_fd); } else { if (protocol == IPPROTO_UDP) block_udp(args, pkt, length, payload, uid); log_android(ANDROID_LOG_WARN, "Address v%d p%d %s/%u syn %d not allowed", version, protocol, dest, dport, syn); } }