int pkt_parse_5_tuple(lbuf_t *b, packet_tuple_t *tuple) { struct iphdr *iph = NULL; struct ip6_hdr *ip6h = NULL; struct udphdr *udp = NULL; struct tcphdr *tcp = NULL; lbuf_t packet = *b; iph = lbuf_ip(&packet); lisp_addr_set_lafi(&tuple->src_addr, LM_AFI_IP); lisp_addr_set_lafi(&tuple->dst_addr, LM_AFI_IP); switch (iph->version) { case 4: lisp_addr_ip_init(&tuple->src_addr, &iph->saddr, AF_INET); lisp_addr_ip_init(&tuple->dst_addr, &iph->daddr, AF_INET); tuple->protocol = iph->protocol; lbuf_pull(&packet, iph->ihl * 4); break; case 6: ip6h = (struct ip6_hdr *)iph; lisp_addr_ip_init(&tuple->src_addr, &ip6h->ip6_src, AF_INET6); lisp_addr_ip_init(&tuple->dst_addr, &ip6h->ip6_dst, AF_INET6); /* XXX: assuming no extra headers */ tuple->protocol = ip6h->ip6_nxt; lbuf_pull(&packet, sizeof(struct ip6_hdr)); break; default: OOR_LOG(LDBG_2, "pkt_parse_5_tuple: Not an IP packet!"); return (BAD); } OOR_LOG(LDBG_2, "pkt_parse_5_tuple: %", tuple->protocol); if (tuple->protocol == IPPROTO_UDP) { udp = lbuf_data(&packet); tuple->src_port = ntohs(udp->source); tuple->dst_port = ntohs(udp->dest); } else if (tuple->protocol == IPPROTO_TCP) { tcp = lbuf_data(&packet); tuple->src_port = ntohs(tcp->source); tuple->dst_port = ntohs(tcp->dest); } else { /* If protocol is not TCP or UDP, ports of the tuple set to 0 */ tuple->src_port = 0; tuple->dst_port = 0; } return (GOOD); }
/* Get a packet from the socket. It also returns the destination addres and * source port of the packet */ int sock_ctrl_recv(int sock, struct lbuf *buf, uconn_t *uc) { union control_data { struct cmsghdr cmsg; u_char data4[CMSG_SPACE(sizeof(struct in_pktinfo))]; u_char data6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; }; union sockunion su; struct msghdr msg; struct iovec iov[1]; union control_data cmsg; struct cmsghdr *cmsgptr = NULL; int nbytes = 0; iov[0].iov_base = lbuf_data(buf); iov[0].iov_len = lbuf_tailroom(buf); memset(&msg, 0, sizeof msg); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = &cmsg; msg.msg_controllen = sizeof cmsg; msg.msg_name = &su; msg.msg_namelen = sizeof(union sockunion); nbytes = recvmsg(sock, &msg, 0); if (nbytes == -1) { LMLOG(LWRN, "sock_recv_ctrl: recvmsg error: %s", strerror(errno)); return (BAD); } lbuf_set_size(buf, lbuf_size(buf) + nbytes); /* read local address, remote port and remote address */ if (su.s4.sin_family == AF_INET) { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) { lisp_addr_ip_init(&uc->la, &(((struct in_pktinfo *) (CMSG_DATA(cmsgptr)))->ipi_addr), AF_INET); break; } } lisp_addr_ip_init(&uc->ra, &su.s4.sin_addr, AF_INET); uc->rp = ntohs(su.s4.sin_port); } else { for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO) { lisp_addr_ip_init(&uc->la, &(((struct in6_pktinfo *) (CMSG_DATA(cmsgptr)))->ipi6_addr), AF_INET6); break; } } lisp_addr_ip_init(&uc->ra, &su.s6.sin6_addr, AF_INET6); uc->rp = ntohs(su.s6.sin6_port); } return (GOOD); }