int ip_hdr_ttl_and_tos(struct iphdr *iph, int *ttl, int *tos) { struct ip6_hdr *ip6h; switch (iph->version) { case 4: *tos = iph->tos; *ttl = iph->ttl; return(GOOD); case 6: ip6h = (struct ip6_hdr *) iph; *ttl = ip6h->ip6_hops; *tos = IPV6_GET_TC(*ip6h); return(GOOD); default: return(BAD); } }
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; } }