struct udphdr *build_ip_header( uint8_t *cur_ptr, lisp_addr_t *src_addr, lisp_addr_t *dst_addr, int ip_len) { struct ip *iph; struct ip6_hdr *ip6h; struct udphdr *udph; switch (src_addr->afi) { case AF_INET: ip_len = ip_len + sizeof(struct ip); iph = (struct ip *) cur_ptr; iph->ip_hl = 5; iph->ip_v = IPVERSION; iph->ip_tos = 0; iph->ip_len = htons(ip_len); iph->ip_id = htons(get_IP_ID()); iph->ip_off = 0; /* XXX Control packets can be fragmented */ iph->ip_ttl = 255; iph->ip_p = IPPROTO_UDP; iph->ip_src.s_addr = src_addr->address.ip.s_addr; iph->ip_dst.s_addr = dst_addr->address.ip.s_addr; iph->ip_sum = 0; iph->ip_sum = ip_checksum((uint16_t *)cur_ptr, sizeof(struct ip)); udph = (struct udphdr *) CO(iph,sizeof(struct ip)); break; case AF_INET6: ip6h = (struct ip6_hdr *) cur_ptr; ip6h->ip6_hops = 255; ip6h->ip6_vfc = (IP6VERSION << 4); ip6h->ip6_nxt = IPPROTO_UDP; ip6h->ip6_plen = htons(ip_len); memcpy(ip6h->ip6_src.s6_addr, src_addr->address.ipv6.s6_addr, sizeof(struct in6_addr)); memcpy(ip6h->ip6_dst.s6_addr, dst_addr->address.ipv6.s6_addr, sizeof(struct in6_addr)); udph = (struct udphdr *) CO(ip6h,sizeof(struct ip6_hdr)); break; default: lispd_log_msg(LISP_LOG_DEBUG_2,"build_ip_header: Uknown AFI of the source address: %d",src_addr->afi); return(NULL); } return(udph); }
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); }