static void process_udp(char *data) { struct proc_node *ipp = udp_procs; struct ip *iph = (struct ip *) data; struct udphdr *udph; struct tuple4 addr; int hlen = iph->ip_hl << 2; int len = ntohs(iph->ip_len); int ulen; if (len - hlen < (int)sizeof(struct udphdr)) return; udph = (struct udphdr *) (data + hlen); ulen = ntohs(udph->UH_ULEN); if (len - hlen < ulen || ulen < (int)sizeof(struct udphdr)) return; if (my_udp_check ((void *) udph, ulen, iph->ip_src.s_addr, iph->ip_dst.s_addr)) return; addr.source = ntohs(udph->UH_SPORT); addr.dest = ntohs(udph->UH_DPORT); addr.saddr = iph->ip_src.s_addr; addr.daddr = iph->ip_dst.s_addr; while (ipp) { ipp->item(&addr, ((char *) udph) + sizeof(struct udphdr), ulen - sizeof(struct udphdr), data); ipp = ipp->next; } }
static void process_udp(char *data, struct timeval* ts) { struct proc_node *ipp = udp_procs; struct ip *iph = (struct ip *) data; struct udphdr *udph; struct tuple4 addr; int hlen = iph->ip_hl << 2; int len = ntohs(iph->ip_len); int ulen; if (len - hlen < (int)sizeof(struct udphdr)) return; udph = (struct udphdr *) (data + hlen); ulen = ntohs(udph->UH_ULEN); if (len - hlen < ulen || ulen < (int)sizeof(struct udphdr)) return; /* According to RFC768 a checksum of 0 is not an error (Sebastien Raveau) */ if (udph->uh_sum && my_udp_check ((void *) udph, ulen, iph->ip_src.s_addr, iph->ip_dst.s_addr)) return; addr.source = ntohs(udph->UH_SPORT); addr.dest = ntohs(udph->UH_DPORT); addr.saddr = iph->ip_src.s_addr; addr.daddr = iph->ip_dst.s_addr; while (ipp) { ipp->item(&addr, ((char *) udph) + sizeof(struct udphdr), ulen - sizeof(struct udphdr), data); ipp = ipp->next; } }
int form_syn_response(char *data, int len) { struct ethhdr *ethh; struct iphdr *iph; struct udphdr *udph; struct tcphdr *tcph; uint8_t proto_in_ip = 0; uint16_t checksum; char tmp[6]; char *payload_ptr; int payload_len; ethh = (struct ethhdr *)data; // FIXME: dest address of the server/client memcpy(tmp, ethh->h_dest, 6); memcpy(ethh->h_dest, ethh->h_source, 6); memcpy(ethh->h_source, tmp, 6); /* IP layer */ switch (ntohs(ethh->h_proto)) { case ETH_P_IP: iph = (struct iphdr *)(ethh + 1); proto_in_ip = iph->protocol; udph = (struct udphdr *)((uint32_t *)iph + iph->ihl); tcph = (struct tcphdr *)((uint32_t *)iph + iph->ihl); uint32_t tmp = iph->saddr; iph->saddr = iph->daddr; iph->daddr = tmp; /* Do checksum */ iph->check = 0; checksum = ip_fast_csum((unsigned char *)iph, iph->ihl); iph->check = ~checksum; break; default: fprint(ERROR, "protocol %04hx ", ntohs(ethh->h_proto)); goto done; } /* Transport layer */ switch (proto_in_ip) { case IPPROTO_TCP: payload_ptr = (char *)tcph + tcph->doff * 4; payload_len = len - (payload_ptr - data); /* TODO: there will be a mapping between sequence number of p-c and s-p connection, the sequence difference will be stored in the TCB, and code should be added, but not here */ tcph->ack_seq = htonl(ntohl(tcph->seq) + 1); tcph->seq = 0; uint16_t tmp_port = tcph->source; tcph->source = tcph->dest; tcph->dest = tmp_port; tcph->ack = 1; tcph->check = 0; checksum = my_tcp_check((void *)tcph, len - ((char *)tcph - data), iph->saddr, iph->daddr); tcph->check = ~checksum; break; case IPPROTO_UDP: fprint(ERROR, "a udp packet?\n"); payload_ptr = (char *)udph + 8; payload_len = len - (payload_ptr - data); udph->check = 0; checksum = my_udp_check((void *)udph, ntohs(udph->len), iph->saddr, iph->daddr); udph->check = ~checksum; break; default: fprint(ERROR, "protocol %d\n", proto_in_ip); break; } done: return 0; }