int pkt_push_udp_and_ip(lbuf_t *b, uint16_t sp, uint16_t dp, ip_addr_t *sip, ip_addr_t *dip) { uint16_t udpsum; struct udphdr *uh; if (pkt_push_udp(b, sp, dp) == NULL) { OOR_LOG(LDBG_1, "Failed to push UDP header! Discarding"); return(BAD); } lbuf_reset_udp(b); if (pkt_push_ip(b, sip, dip, IPPROTO_UDP) == NULL) { OOR_LOG(LDBG_1, "Failed to push IP header! Discarding"); return(BAD); } lbuf_reset_ip(b); uh = lbuf_udp(b); udpsum = udp_checksum(uh, ntohs(uh->len), lbuf_ip(b), ip_addr_afi(sip)); if (udpsum == -1) { OOR_LOG(LDBG_1, "Failed UDP checksum! Discarding"); return (BAD); } udpsum(uh) = udpsum; return(GOOD); }
int tun_rtr_process_input_packet(struct sock *sl) { packet_tuple_t tpl; lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN); /* Reserve space in case the received packet was IPv6. In this case the IPv6 header is * not provided */ lbuf_reserve(&pkt_buf,LBUF_STACK_OFFSET); if (tun_read_and_decap_pkt(sl->fd, &pkt_buf, &(tpl.iid)) != GOOD) { return (BAD); } OOR_LOG(LDBG_3, "Forwarding packet to OUPUT for re-encapsulation"); lbuf_point_to_l3(&pkt_buf); lbuf_reset_ip(&pkt_buf); if (pkt_parse_5_tuple(&pkt_buf, &tpl) != GOOD) { return (BAD); } tun_output(&pkt_buf, &tpl); return(GOOD); }
int vpnapi_output_recv(struct sock *sl) { lbuf_use_stack(&pkt_buf, &pkt_recv_buf, VPNAPI_RECEIVE_SIZE); lbuf_reserve(&pkt_buf, LBUF_STACK_OFFSET); if (sock_recv(sl->fd, &pkt_buf) != GOOD) { LMLOG(LWRN, "OUTPUT: Error while reading from tun!"); return (BAD); } lbuf_reset_ip(&pkt_buf); vpnapi_output(&pkt_buf); 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); }