示例#1
0
文件: packets.c 项目: muharif/oor2
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);
}