Example #1
0
int
vpnapi_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn)
{
    int ret;
    int sock;
    ip_addr_t *src_addr, *dst_addr;
    vpnapi_ctr_dplane_data_t * data;

    data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data;


    if (lisp_addr_lafi(&udp_conn->ra) != LM_AFI_IP) {
        OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: Destination address %s of UDP connection is not a IP. "
                "Discarding!", lisp_addr_to_char(&udp_conn->ra));
        return(BAD);
    }

    src_addr = lisp_addr_ip(&udp_conn->la);
    dst_addr = lisp_addr_ip(&udp_conn->ra);

    if (!lisp_addr_is_no_addr(&udp_conn->la) &&  (ip_addr_afi(src_addr) != ip_addr_afi(dst_addr))) {
        OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: src %s and dst %s of UDP connection have "
                "different IP AFI. Discarding!", ip_addr_to_char(src_addr),
                ip_addr_to_char(dst_addr));
        return(BAD);
    }

    switch (ip_addr_afi(dst_addr)){
    case AF_INET:
        if (udp_conn->lp == LISP_CONTROL_PORT){
            sock = data->ipv4_ctrl_socket;
        }else{
            sock = data->ipv4_data_socket;
        }
        break;
    case AF_INET6:
        sock = data->ipv6_ctrl_socket;
        break;
    default:
        return (BAD);
    }

    ret = send_datagram_packet (sock, lbuf_data(buff), lbuf_size(buff), &udp_conn->ra, udp_conn->rp);

    if (ret != GOOD) {
        OOR_LOG(LDBG_1, "Failed to send contrl message from RLOC: %s -> %s",
                lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra));
        return(BAD);
    } else {
        OOR_LOG(LDBG_1, "Sent control message IP: %s -> %s UDP: %d -> %d",
                lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra),
                udp_conn->lp, udp_conn->rp);
        return(GOOD);
    }
}
int
sock_recv(int sfd, lbuf_t *b)
{
    int nread;
    nread = read(sfd, lbuf_data(b), lbuf_tailroom(b));
    if (nread == 0) {
        LMLOG(LWRN, "sock_recv: recvmsg error: %s", strerror(errno));
        return (BAD);
    }

    lbuf_set_size(b, lbuf_size(b) + nread);
    return(GOOD);
}
Example #3
0
static int
vpnapi_output_unicast(lbuf_t *b, packet_tuple_t *tuple)
{
    fwd_info_t *fi;
    fwd_entry_t *fe;

    fi = ttable_lookup(&ttable, tuple);
    if (!fi) {
        fi = ctrl_get_forwarding_info(tuple);
        if (!fi){
            return (BAD);
        }
        fe = fi->fwd_info;
        if (fe && fe->srloc && fe->drloc)  {
            switch (lisp_addr_ip_afi(fe->srloc)){
            case AF_INET:
                fe->out_sock = &(((vpnapi_data_t *)dplane_vpnapi.datap_data)->ipv4_data_socket);
                break;
            case AF_INET6:
                fe->out_sock = &(((vpnapi_data_t *)dplane_vpnapi.datap_data)->ipv6_data_socket);
                break;
            default:
                LMLOG(LDBG_3,"OUTPUT: No output socket for afi %d", lisp_addr_ip_afi(fe->srloc));
                return(BAD);
            }
        }

        ttable_insert(&ttable, pkt_tuple_clone(tuple), fi);
    }else{
        fe = fi->fwd_info;
    }

    /* Packets with no/negative map cache entry AND no PETR
     * OR packets with missing src or dst RLOCs
     * forward them natively */
    if (!fe || !fe->srloc || !fe->drloc) {
        LMLOG(LDBG_3,"OUTPUT: Packet with non lisp destination. No PeTRs compatibles to be used. Discarding packet");
        return(BAD);
    }

    LMLOG(LDBG_3,"OUTPUT: Sending encapsulated packet: RLOC %s -> %s\n",
            lisp_addr_to_char(fe->srloc),
            lisp_addr_to_char(fe->drloc));

    /* push lisp data hdr */
    lisp_data_push_hdr(b);

    return(send_datagram_packet (*(fe->out_sock), lbuf_data(b), lbuf_size(b),
            fe->drloc, LISP_DATA_PORT));
}
Example #4
0
int
tun_process_input_packet(sock_t *sl)
{
    uint32_t iid;
    lbuf_use_stack(&pkt_buf, &pkt_recv_buf, MAX_IP_PKT_LEN);

    if (tun_read_and_decap_pkt(sl->fd, &pkt_buf, &iid) != GOOD) {
        return (BAD);
    }

    /* XXX Destination packet should be checked it belongs to this xTR */
    if ((write(tun_receive_fd, lbuf_l3(&pkt_buf), lbuf_size(&pkt_buf))) < 0) {
        OOR_LOG(LDBG_2, "lisp_input: write error: %s\n ", strerror(errno));
    }

    return (GOOD);
}
Example #5
0
struct ip6_hdr *
pkt_push_ipv6(lbuf_t *b, struct in6_addr *src, struct in6_addr *dst, int proto)
{
    struct ip6_hdr *ip6h;
    int len;

    len = lbuf_size(b);
    ip6h = lbuf_push_uninit(b, sizeof(struct ip6_hdr));

    ip6h->ip6_hops = 255;
    ip6h->ip6_vfc = (IP6VERSION << 4);
    ip6h->ip6_nxt = proto;
    ip6h->ip6_plen = htons(len);
    memcpy(ip6h->ip6_src.s6_addr, src->s6_addr, sizeof(struct in6_addr));
    memcpy(ip6h->ip6_dst.s6_addr, dst->s6_addr, sizeof(struct in6_addr));
    return(ip6h);
}
Example #6
0
/*  Process a LISP protocol message sitting on
 *  socket s with address family afi */
int
vpnapi_control_dp_recv_msg(sock_t *sl)
{
    uconn_t uc;
    lbuf_t *b;
    oor_ctrl_t *ctrl;
    oor_ctrl_dev_t *dev;

    ctrl = sl->arg;
    /* Only one device supported for now */
    dev = glist_first_data(ctrl->devices);

    uc.lp = LISP_CONTROL_PORT;

    b = lisp_msg_create_buf();

    if (sock_ctrl_recv(sl->fd, b, &uc) != GOOD) {
        OOR_LOG(LDBG_1, "Couldn't retrieve socket information"
                "for control message! Discarding packet!");
        lbuf_del(b);
        return (BAD);
    }
    if (lbuf_size(b) < 4){
        OOR_LOG(LDBG_3, "Received a non LISP message in the "
                "control port! Discarding packet!");
        return (BAD);
    }

    lbuf_reset_lisp(b);
    OOR_LOG(LDBG_1, "Received %s, IP: %s -> %s, UDP: %d -> %d",
            lisp_msg_hdr_to_char(b), lisp_addr_to_char(&uc.ra),
            lisp_addr_to_char(&uc.la), uc.rp, uc.lp);

    /* direct call of ctrl device
     * TODO: check type to decide where to send msg*/
    ctrl_dev_recv(dev, b, &uc);

    lbuf_del(b);

    return (GOOD);
}
Example #7
0
void *
pkt_push_udp(lbuf_t *b, uint16_t sp, uint16_t dp)
{
    struct udphdr *uh;
    int udp_len;

    udp_len = sizeof(struct udphdr) + lbuf_size(b);
    uh = lbuf_push_uninit(b, sizeof(struct udphdr));

#ifdef BSD
    uh->uh_sport = htons(port_from);
    uh->uh_dport = htons(port_dest);
    uh->uh_ulen = htons(udp_payload_len);
    uh->uh_sum = 0;
#else
    uh->source = htons(sp);
    uh->dest = htons(dp);
    uh->len = htons(udp_len);
    uh->check = 0; /* to be filled in after IP is pushed */
#endif
    return(uh);
}
Example #8
0
struct ip *
pkt_push_ipv4(lbuf_t *b, struct in_addr *src, struct in_addr *dst, int proto)
{
    struct ip *iph;
    iph = lbuf_push_uninit(b, sizeof(struct ip));

    /* XXX: assume no other headers */
    iph->ip_hl = 5;
    iph->ip_v = IPVERSION;
    iph->ip_tos = 0;
    iph->ip_len = htons(lbuf_size(b));
    iph->ip_id = htons(get_IP_ID());
    /* Do not fragment flag. See 5.4.1 in LISP RFC (6830)
     * TODO: decide if we allow fragments in case of control */
    iph->ip_off = htons(IP_DF);
    iph->ip_ttl = 255;
    iph->ip_p = proto;
    iph->ip_src.s_addr = src->s_addr;
    iph->ip_dst.s_addr = dst->s_addr;
    /* FIXME: ip checksum could be offloaded to NIC*/
    /* iph->ip_sum = 0; */
    iph->ip_sum = ip_checksum((uint16_t *) iph, sizeof(struct ip));
    return(iph);
}
int
sock_data_recv(int sock, lbuf_t *b, int *afi, uint8_t *ttl, uint8_t *tos)
{
    /* Space for TTL and TOS data */
    union control_data {
        struct cmsghdr cmsg;
        u_char data[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(int))];
    };

    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(b);
    iov[0].iov_len = lbuf_tailroom(b);

    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, "read_packet: recvmsg error: %s", strerror(errno));
        return (BAD);
    }

    lbuf_set_size(b, lbuf_size(b) + nbytes);

    if (su.s4.sin_family == AF_INET) {
        for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr =
                CMSG_NXTHDR(&msg, cmsgptr)) {

            if (cmsgptr->cmsg_level == IPPROTO_IP
                    && cmsgptr->cmsg_type == IP_TTL) {
                *ttl = *((uint8_t *) CMSG_DATA(cmsgptr));
            }

            if (cmsgptr->cmsg_level == IPPROTO_IP
                    && cmsgptr->cmsg_type == IP_TOS) {
                *tos = *((uint8_t *) CMSG_DATA(cmsgptr));
            }
        }
        *afi = AF_INET;
    } else {
        for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr =
                CMSG_NXTHDR(&msg, cmsgptr)) {

            if (cmsgptr->cmsg_level == IPPROTO_IPV6
                    && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
                *ttl = *((uint8_t *) CMSG_DATA(cmsgptr));
            }

            if (cmsgptr->cmsg_level == IPPROTO_IPV6
                    && cmsgptr->cmsg_type == IPV6_TCLASS) {
                *tos = *((uint8_t *) CMSG_DATA(cmsgptr));
            }
        }
        *afi = AF_INET6;
    }

    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);
}