Esempio n. 1
0
/*
 * tun_add_eid_to_iface()
 *
 * Add an EID to the TUN/TAP interface
 */
int tun_add_eid_to_iface(
    lisp_addr_t         eid_address,
    char                *dev_name)
{
    struct rtattr       *rta = NULL;
    struct ifaddrmsg    *ifa = NULL;
    struct nlmsghdr     *nlh = NULL;
    char                sndbuf[4096];
    int                 retval = 0;
    int                 sockfd = 0;
    int                 ifindex = 0;

    int                 addr_size = 0;
    int                 prefix_length = 0;

    ifindex = if_nametoindex (dev_name);

    sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);

    if (sockfd < 0) {
        lispd_log_msg(LISP_LOG_ERR, "tun_add_eid_to_iface: Failed to connect to netlink socket");
        return(BAD);
    }

    if (eid_address.afi == AF_INET){
        addr_size = sizeof(struct in_addr);
        prefix_length = 32;
    }else {
        addr_size = sizeof(struct in6_addr);
        prefix_length = 128;
    }

    /*
     * Build the command
     */
    memset(sndbuf, 0, 4096);
    nlh = (struct nlmsghdr *)sndbuf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg) + sizeof(struct rtattr) + addr_size);
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
    nlh->nlmsg_type = RTM_NEWADDR;
    ifa = (struct ifaddrmsg *)(sndbuf + sizeof(struct nlmsghdr));

    ifa->ifa_prefixlen = prefix_length;
    ifa->ifa_family = eid_address.afi;
    ifa->ifa_index  = ifindex;
    ifa->ifa_scope = RT_SCOPE_UNIVERSE;
    ifa->ifa_flags = 0; // Bring it up

    rta = (struct rtattr *)(sndbuf + sizeof(struct nlmsghdr) + sizeof(struct ifaddrmsg));
    rta->rta_type = IFA_LOCAL;
    rta->rta_len = sizeof(struct rtattr) + addr_size;
    memcopy_lisp_addr((void *)((char *)rta + sizeof(struct rtattr)),&eid_address);

    retval = send(sockfd, sndbuf, nlh->nlmsg_len, 0);

    if (retval < 0) {
        lispd_log_msg(LISP_LOG_ERR, "tun_add_eid_to_iface: send() failed %s", strerror(errno));
        close(sockfd);
        return(BAD);
    }

    lispd_log_msg(LISP_LOG_DEBUG_1, "added %s EID to TUN interface.",get_char_from_lisp_addr_t(eid_address));
    close(sockfd);
    return(GOOD);
}
Esempio n. 2
0
void add_ip_header (
        char            *position,
        char            *original_packet_position,
        int             ip_payload_length,
        lisp_addr_t     *src_addr,
        lisp_addr_t     *dst_addr)
{


    struct iphdr    *iph        = NULL;
    struct iphdr    *inner_iph  = NULL;
    struct ip6_hdr  *ip6h       = NULL;
    struct ip6_hdr  *inner_ip6h = NULL;

    uint8_t tos = 0;
    uint8_t ttl = 0;


    inner_iph = (struct iphdr *) original_packet_position;

    /* We SHOULD copy ttl and tos fields from the inner packet to the encapsulated one */

    if (inner_iph->version == 4 ) {
        tos = inner_iph->tos;
        ttl = inner_iph->ttl;

    } else {
        inner_ip6h = (struct ip6_hdr *) original_packet_position;
        ttl = inner_ip6h->ip6_hops; /* ttl = Hops limit in IPv6 */

        //tos = (inner_ip6h->ip6_flow & 0x0ff00000) >> 20;  /* 4 bits version, 8 bits Traffic Class, 20 bits flow-ID */
        tos = IPV6_GET_TC(*inner_ip6h); /* tos = Traffic class field in IPv6 */
    }

    /*
     * Construct and add the outer ip header
     */

    switch (dst_addr->afi){
    case AF_INET:

        iph = (struct iphdr *) position;

        iph->version  = 4;
        //iph->ihl      = sizeof ( struct iphdr ) >>2;
        iph->ihl      = 5; /* Minimal IPv4 header */ /*XXX Beware, hardcoded. Supposing no IP options */
        iph->tos      = tos;
        iph->tot_len  = htons(ip_payload_length);
        iph->frag_off = htons(IP_DF);   /* Do not fragment flag. See 5.4.1 in LISP RFC (6830) */
        iph->ttl      = ttl;
        iph->protocol = IPPROTO_UDP;
        iph->check    = 0; //Computed by the NIC (checksum offloading)
        iph->daddr    = dst_addr->address.ip.s_addr;
        iph->saddr    = src_addr->address.ip.s_addr;
        break;

    case AF_INET6:

        ip6h = ( struct ip6_hdr *) position;
        IPV6_SET_VERSION(ip6h, 6);
        IPV6_SET_TC(ip6h,tos);
        IPV6_SET_FLOW_LABEL(ip6h,0);
        ip6h->ip6_plen = htons(ip_payload_length);
        ip6h->ip6_nxt = IPPROTO_UDP;
        ip6h->ip6_hops = ttl;
        memcopy_lisp_addr(&(ip6h->ip6_dst),dst_addr);
        memcopy_lisp_addr(&(ip6h->ip6_src),src_addr);

        break;
    default:
        break;
    }


}