Ejemplo n.º 1
0
int
ip_hdr_set_ttl_and_tos(struct iphdr *iph, int ttl, int tos)
{
    struct ip6_hdr *ip6h;

    if (iph->version == 4) {
        /*XXX It seems that there is a bug in uClibc that causes ttl=0 in
         * OpenWRT. This is a quick workaround */
        if (ttl != 0) {
            iph->ttl = ttl;
        }

        iph->tos = tos;

        /* We need to recompute the checksum since we have changed the TTL
         * and TOS header fields.
         *
         * New checksum must be computed with the checksum header field
         * with 0s */
        iph->check = 0;
        iph->check = ip_checksum((uint16_t*) iph, sizeof(struct iphdr));

    } else if (iph->version == 6) {
        ip6h = (struct ip6_hdr *) iph;

        /*XXX It seems that there is a bug in uClibc that causes ttl=0 in
         * OpenWRT. This is a quick workaround */
        if (ttl != 0) {
            /* ttl = Hops limit in IPv6 */
            ip6h->ip6_hops = ttl;
        }

        /* tos = Traffic class field in IPv6 */
        IPV6_SET_TC(ip6h, tos);
    } else {
        return(BAD);
    }

    return(GOOD);
}
Ejemplo 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;
    }


}
Ejemplo n.º 3
0
void process_input_packet(int fd,
                          int afi,
                          int tun_receive_fd)
{
    uint8_t             *packet = NULL;
    int                 length = 0;
    uint8_t             ttl = 0;
    uint8_t             tos = 0;

    struct lisphdr      *lisp_hdr = NULL;
    struct iphdr        *iph = NULL;
    struct ip6_hdr      *ip6h = NULL;
    struct udphdr       *udph = NULL;


    if ((packet = (uint8_t *) malloc(MAX_IP_PACKET))==NULL){
        lispd_log_msg(LISP_LOG_ERR,"process_input_packet: Couldn't allocate space for packet: %s", strerror(errno));
        return;
    }

    memset(packet,0,MAX_IP_PACKET);
    
    if (get_data_packet (fd,
                         afi,
                         packet,
                         &length,
                         &ttl,
                         &tos) == BAD){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_input_packet: get_data_packet error: %s", strerror(errno));
        free(packet);
        return;
    }

    if(afi == AF_INET){
        /* With input RAW UDP sockets in IPv4, we get the whole external IPv4 packet */
        udph = (struct udphdr *) CO(packet,sizeof(struct iphdr));
    }else{
        /* With input RAW UDP sockets in IPv6, we get the whole external UDP packet */
        udph = (struct udphdr *) packet;
    }
    
    /* With input RAW UDP sockets, we receive all UDP packets, we only want lisp data ones */
    if(ntohs(udph->dest) != LISP_DATA_PORT){
        free(packet);
        //lispd_log_msg(LISP_LOG_DEBUG_3,"INPUT (No LISP data): UDP dest: %d ",ntohs(udph->dest));
        return;
    }

    lisp_hdr = (struct lisphdr *) CO(udph,sizeof(struct udphdr));

    length = length - sizeof(struct udphdr) - sizeof(struct lisphdr);
    
    iph = (struct iphdr *) CO(lisp_hdr,sizeof(struct lisphdr));

    lispd_log_msg(LISP_LOG_DEBUG_3,"INPUT (4341): Inner src: %s | Inner dst: %s ",
                  get_char_from_lisp_addr_t(extract_src_addr_from_packet((char *)iph)),
                  get_char_from_lisp_addr_t(extract_dst_addr_from_packet((char *)iph)));
    
    if (iph->version == 4) {
        
        if(ttl!=0){ /*XXX It seems that there is a bug in uClibc that causes ttl=0 in OpenWRT. This is a quick workaround */
            iph->ttl = ttl;
        }
        iph->tos = tos;

        /* We need to recompute the checksum since we have changed the TTL and TOS header fields */
        iph->check = 0; /* New checksum must be computed with the checksum header field with 0s */
        iph->check = ip_checksum((uint16_t*) iph, sizeof(struct iphdr));
        
    }else{
        ip6h = ( struct ip6_hdr *) iph;

        if(ttl!=0){ /*XXX It seems that there is a bug in uClibc that causes ttl=0 in OpenWRT. This is a quick workaround */
            ip6h->ip6_hops = ttl; /* ttl = Hops limit in IPv6 */
        }
        
        IPV6_SET_TC(ip6h,tos); /* tos = Traffic class field in IPv6 */
    }

    if ((write(tun_receive_fd, iph, length)) < 0){
        lispd_log_msg(LISP_LOG_DEBUG_2,"lisp_input: write error: %s\n ", strerror(errno));
    }
    
    free(packet);
}