/* Process encapsulated map request header: lisp header and the interal IP and * UDP header */ int lisp_msg_ecm_decap(lbuf_t *pkt, uint16_t *src_port) { uint16_t ipsum = 0; uint16_t udpsum = 0; int udp_len = 0; struct udphdr *udph; struct ip *iph; /* this is the new start of the packet */ lisp_msg_pull_ecm_hdr(pkt); /* Set and extract inner layer 3 packet */ lbuf_reset_l3(pkt); iph = pkt_pull_ip(pkt); /* Set and extract inner layer 4 packet */ lbuf_reset_l4(pkt); udph = pkt_pull_udp(pkt); /* Set the beginning of the LISP msg*/ lbuf_reset_lisp(pkt); /* This should overwrite the external port (dst_port in map-reply = * inner src_port in encap map-request) */ *src_port = ntohs(udph->source); #ifdef BSD udp_len = ntohs(udph->uh_ulen); #else udp_len = ntohs(udph->len); #endif /* Verify the checksums. */ if (iph->ip_v == IPVERSION) { ipsum = ip_checksum((uint16_t *) iph, sizeof(struct ip)); if (ipsum != 0) { OOR_LOG(LDBG_2, "IP checksum failed."); } } /* Verify UDP checksum only if different from 0. * This means we ACCEPT UDP checksum 0! */ if (udph->check != 0) { udpsum = udp_checksum(udph, udp_len, iph, ip_version_to_sock_afi(iph->ip_v)); if (udpsum != 0) { OOR_LOG(LDBG_2, "UDP checksum failed."); return (BAD); } } OOR_LOG(LDBG_2, "%s, inner IP: %s -> %s, inner UDP: %d -> %d", lisp_msg_hdr_to_char(pkt), ip_to_char(&iph->ip_src, ip_version_to_sock_afi(iph->ip_v)), ip_to_char(&iph->ip_dst, ip_version_to_sock_afi(iph->ip_v)), ntohs(udph->source), ntohs(udph->dest)); return (GOOD); }
int tun_read_and_decap_pkt(int sock, lbuf_t *b, uint32_t *iid) { uint8_t ttl = 0, tos = 0; int afi; struct udphdr *udph; lisp_data_hdr_t *lisph; vxlan_gpe_hdr_t *vxlanh; int port; if (sock_data_recv(sock, b, &afi, &ttl, &tos) != GOOD) { return(BAD); } if (afi == AF_INET){ /* With input RAW UDP sockets in IPv4, we get the whole external * IPv4 packet */ lbuf_reset_ip(b); pkt_pull_ip(b); lbuf_reset_udp(b); }else{ /* With input RAW UDP sockets in IPv6, we get the whole external * UDP packet */ lbuf_reset_udp(b); } udph = pkt_pull_udp(b); /* FILTER UDP: with input RAW UDP sockets, we receive all UDP packets, * we only want LISP data ones */ switch (ntohs(udph->dest)){ case LISP_DATA_PORT: lisph = lisp_data_pull_hdr(b); if (LDHDR_LSB_BIT(lisph)){ *iid = lisp_data_hdr_get_iid(lisph); }else{ *iid = 0; } port = LISP_DATA_PORT; break; case VXLAN_GPE_DATA_PORT: vxlanh = vxlan_gpe_data_pull_hdr(b); if (VXLAN_HDR_VNI_BIT(vxlanh)){ *iid = vxlan_gpe_hdr_get_vni(vxlanh); } port = VXLAN_GPE_DATA_PORT; break; default: return (ERR_NOT_ENCAP); } /* RESET L3: prepare for output */ lbuf_reset_l3(b); /* UPDATE IP TOS and TTL. Checksum is also updated for IPv4 * NOTE: we always assume an IP payload*/ ip_hdr_set_ttl_and_tos(lbuf_data(b), ttl, tos); OOR_LOG(LDBG_3, "INPUT (%d): %s",port, ip_src_and_dst_to_char(lbuf_l3(b), "Inner IP: %s -> %s")); return(GOOD); }