struct packet *udp6Reply(struct packet *m0) { ethdr *eh; ip6hdr *ip; udphdr *ui; struct packet *m; m = new_pkt(m0->len); if (m == NULL) return NULL; copy_pkt(m, m0); eh = (ethdr *)(m->data); ip = (ip6hdr *)(eh + 1); ui = (udphdr *)(ip + 1); swap_ehead(m->data); swap_ip6head(m); ip->ip6_hlim = TTL; ui->sport ^= ui->dport; ui->dport ^= ui->sport; ui->sport ^= ui->dport; ui->cksum = 0; ui->cksum = cksum6(ip, IPPROTO_UDP, ntohs(ui->len)); return m; }
/** * @brief Feed a list packets into an eBPF program. * @details This is a mock function emulating the behavior of a running * eBPF program. It takes a list of input packets and iteratively parses them * using the given imported ebpf_filter function. The output defines whether * or not the packet is "dropped." If the packet is not dropped, its content is * copied and appended to an output packet list. * * @param pkt_list A list of input packets running through the filter. * @return The list of packets "surviving" the filter function */ pcap_list_t *feed_packets(packet_filter ebpf_filter, pcap_list_t *pkt_list, int debug) { pcap_list_t *output_pkts = allocate_pkt_list(); uint32_t list_len = get_pkt_list_length(pkt_list); for (uint32_t i = 0; i < list_len; i++) { /* Parse each packet in the list and check the result */ struct sk_buff skb; pcap_pkt *input_pkt = get_packet(pkt_list, i); skb.data = (void *) input_pkt->data; skb.len = input_pkt->pcap_hdr.len; int result = ebpf_filter(&skb); if (result != 0) { /* We copy the entire content to emulate an outgoing packet */ pcap_pkt *out_pkt = copy_pkt(input_pkt); output_pkts = append_packet(output_pkts, out_pkt); } if (debug) printf("Result of the eBPF parsing is: %d\n", result); } return output_pkts; }
void test_case(uint16_t payload_sz, uint8_t *ip_opt, int ip_opt_size, custom_opt_t *opt, uint16_t expected_opt_len) { pkt_t *pkt; error_t err; ip_t *new_ip; ip_t *ip; uint16_t new_hdr_len; int res; uint16_t old_csum; uint16_t old_len; uint16_t old_hdr_len; uint16_t new_len; pkt_t *copy; uint8_t *pay1, *pay2; LOG("Test case : creating packet, appending IP option\n"); pkt = create_pkt(payload_sz, ip_opt, ip_opt_size); ip = (ip_t *)pkt->msg; old_hdr_len = ip->ip_hl * 4; old_csum = ip->ip_sum; old_len = ntohs(ip->ip_len); copy = copy_pkt(pkt); res = ip_add_custom_option(pkt, opt, &err); if (res) { LOG_ERR("Test Case failed with %d\n", res); free(pkt); return; } LOG("Test case : checking new header len\n"); new_ip = (ip_t *)pkt->msg; new_hdr_len = new_ip->ip_hl * 4; LOG("New hdr len : %d\n", new_hdr_len); if (new_hdr_len <= MIN_IP_SIZE) { LOG_ERR("Test Case failed, expecting bigger header size"); LOG_ERR("Recieved header size %d\n", new_hdr_len); free(pkt); return; } LOG("Test case : testing new packet len\n"); new_len = payload_sz + MIN_IP_SIZE + expected_opt_len; if (ntohs(new_ip->ip_len) != new_len) { LOG_ERR("Test case failed, incorrect packet len\n"); LOG_ERR("Expected %d, Recvd %d\n", new_len, ntohs(new_ip->ip_len)); free(pkt); return; } LOG("Test case : checking ip checksum\n"); if (old_csum == new_ip->ip_sum) { LOG_ERR("Test case failed, expecting a different checksum\n"); free(pkt); return; } LOG("Test case : comparing payload\n"); pay1 = (uint8_t *)copy->msg + MIN_IP_SIZE + ip_opt_size; pay2 = (uint8_t *)new_ip + new_hdr_len; if (compare_payload(pay1, pay2, payload_sz)) { LOG_ERR("Test case failed, payloads didn't match\n"); free(pkt); return; } LOG("Test case : remove option\n"); res = ip_remove_custom_option(pkt, opt, &err); if (res) { LOG_ERR("Test case failed, remove option failed with %d\n", res); free(pkt); return; } LOG("Test case : comparing packet len after removing options\n"); new_ip = (ip_t *)pkt->msg; new_hdr_len = new_ip->ip_hl * 4; if (ntohs(new_ip->ip_len) != copy->len) { LOG_ERR("Test case failed, recvd len (%d), expected (%d)\n", pkt->len, copy->len); free(pkt); return; } LOG("Test case : comparing packet contents after removing options\n"); pay1 = (uint8_t *)copy->msg + MIN_IP_SIZE + ip_opt_size; pay2 = (uint8_t *)new_ip + new_hdr_len; if (memcmp(pay1, pay2, payload_sz)) { LOG_ERR("Test case failed, contents didn't match\n"); free(pkt); return; } free(pkt); }