lisp_addr_t * pref_get_network_address(lisp_addr_t *address) { lisp_addr_t *network_address = NULL; if (!lisp_addr_is_ip_pref(address)){ OOR_LOG(LDBG_2, "get_network_address: Address %s is not a prefix ", lisp_addr_to_char(address)); return (NULL); } switch (lisp_addr_ip_afi(address)){ case AF_INET: network_address = pref_get_network_address_v4(address); break; case AF_INET6: network_address = pref_get_network_address_v6(address); break; default: OOR_LOG(LDBG_2, "get_network_address: Afi not supported (%d). It should never " "reach this point", lisp_addr_ip_afi(address)); break; } return (network_address); }
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)); }
static locator_t * get_locator_with_afi(mapping_t *m, int afi) { glist_t *loct_list = NULL; glist_entry_t *it_list = NULL; glist_entry_t *it_loct = NULL; locator_t *loct = NULL; lisp_addr_t *addr = NULL; int lafi = 0; int afi_type = 0; glist_for_each_entry(it_list,mapping_locators_lists(m)){ loct_list = (glist_t *)glist_entry_data(it_list); locator_list_lafi_type(loct_list,&lafi,&afi_type); if (lafi == LM_AFI_NO_ADDR || (lafi == LM_AFI_IP && afi_type != afi)){ continue; } glist_for_each_entry(it_loct,loct_list){ loct = (locator_t *)glist_entry_data(it_loct); if (locator_state(loct) == DOWN){ continue; } addr = locator_addr(loct); addr = lisp_addr_get_ip_addr(addr); if (lisp_addr_ip_afi (addr) == afi){ return (loct); } }
/* * Get lafi and type of a list */ void locator_list_lafi_type ( glist_t *loct_list, int *lafi, int *type) { locator_t *loct = NULL; lisp_addr_t *addr = NULL; *lafi = 0; *type = 0; if (loct_list == NULL || glist_size(loct_list) == 0){ return; } loct = (locator_t *)glist_first_data(loct_list); addr = locator_addr(loct); *lafi = lisp_addr_lafi(addr); switch(*lafi){ case LM_AFI_NO_ADDR: *type = 0; return; case LM_AFI_IP: *type = lisp_addr_ip_afi(addr); return; case LM_AFI_IPPREF: LMLOG(LDBG_2, "locator_list_lafi_type: locator list should not contain prefixes"); return; case LM_AFI_LCAF: *type = lisp_addr_lcaf_type(addr); return; } }
int vpnapi_control_dp_updated_addr(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *old_addr,lisp_addr_t *new_addr) { int addr_afi; vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; addr_afi = lisp_addr_ip_afi(new_addr); /* Check if the detected change of address id the same. */ if (lisp_addr_cmp(old_addr, new_addr) == 0) { OOR_LOG(LDBG_2, "vpnapi_control_dp_updated_addr: The change of address detected " "for interface %s doesn't affect", iface->iface_name); return (GOOD); }; switch (addr_afi){ case AF_INET: vpnapi_control_dp_reset_socket(data, data->ipv4_ctrl_socket, AF_INET); break; case AF_INET6: vpnapi_control_dp_reset_socket(data, data->ipv6_ctrl_socket, AF_INET6); break; default: return (BAD); } return (GOOD); }
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 (lisp_addr_ip_afi(src_addr)) { 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 = ip_addr_get_v4(lisp_addr_ip(src_addr))->s_addr; iph->ip_dst.s_addr = ip_addr_get_v4(lisp_addr_ip(dst_addr))->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,ip_addr_get_v6(lisp_addr_ip(src_addr)), sizeof(struct in6_addr)); memcpy(ip6h->ip6_dst.s6_addr,ip_addr_get_v6(lisp_addr_ip(dst_addr)), sizeof(struct in6_addr)); udph = (struct udphdr *) CO(ip6h, sizeof(struct ip6_hdr)); break; default: OOR_LOG(LDBG_2, "build_ip_header: Uknown AFI of the source address: %d", lisp_addr_ip_afi(src_addr)); return (NULL); } return (udph); }
/* * If prefix b is contained in prefix a, then return TRUE. Otherwise return FALSE. * If both prefixs are the same it also returns TRUE */ int pref_is_prefix_b_part_of_a (lisp_addr_t *a_prefix,lisp_addr_t *b_prefix) { lisp_addr_t * a_network_addr; lisp_addr_t * b_network_addr_prefix_a; int a_pref_len; int b_pref_len; int res; if (!lisp_addr_is_ip_pref(a_prefix) || !lisp_addr_is_ip_pref(b_prefix)){ return FALSE; } if (lisp_addr_ip_afi(a_prefix) != lisp_addr_ip_afi(b_prefix)){ return FALSE; } a_pref_len = lisp_addr_get_plen(a_prefix); b_pref_len = lisp_addr_get_plen(b_prefix); if (a_pref_len > b_pref_len){ return FALSE; } a_network_addr = pref_get_network_address(a_prefix); lisp_addr_set_plen(b_prefix, a_pref_len); b_network_addr_prefix_a = pref_get_network_address(b_prefix); lisp_addr_set_plen(b_prefix, b_pref_len); if (lisp_addr_cmp (a_network_addr, b_network_addr_prefix_a) == 0){ res = TRUE; }else{ res = FALSE; } lisp_addr_del(a_network_addr); lisp_addr_del(b_network_addr_prefix_a); return (res); }
int vpnapi_control_dp_updated_route(oor_ctrl_t *ctrl, int command, iface_t *iface, lisp_addr_t *src_pref, lisp_addr_t *dst_pref, lisp_addr_t *gateway) { if (lisp_addr_ip_afi(gateway) != LM_AFI_NO_ADDR && lisp_addr_ip_afi(dst_pref) == LM_AFI_NO_ADDR) { /* Check if the addres is a global address*/ if (ip_addr_is_link_local(lisp_addr_ip(gateway)) == TRUE) { OOR_LOG(LDBG_3,"vpnapi_updated_route: the extractet address " "from the netlink messages is a local link address: %s " "discarded", lisp_addr_to_char(gateway)); return (GOOD); } vpnapi_control_dp_process_new_gateway(ctrl,iface,gateway); } return (GOOD); }
int send_datagram_packet (int sock, const void *packet, int packet_length, lisp_addr_t *addr_dest, int port_dest) { struct sockaddr_in sock_addr_v4; struct sockaddr_in6 sock_addr_v6; struct sockaddr *sock_addr = NULL; int sock_addr_len = 0; switch (lisp_addr_ip_afi(addr_dest)){ case AF_INET: memset(&sock_addr_v4,0,sizeof(sock_addr_v4)); /* be sure */ sock_addr_v4.sin_port = htons(port_dest); sock_addr_v4.sin_family = AF_INET; sock_addr_v4.sin_addr.s_addr = ip_addr_get_v4(lisp_addr_ip(addr_dest))->s_addr; sock_addr = (struct sockaddr *) &sock_addr_v4; sock_addr_len = sizeof(sock_addr_v4); break; case AF_INET6: memset(&sock_addr_v6,0,sizeof(sock_addr_v6)); /* be sure */ sock_addr_v6.sin6_family = AF_INET6; sock_addr_v6.sin6_port = htons(port_dest); memcpy(&sock_addr_v6.sin6_addr, ip_addr_get_v6(lisp_addr_ip(addr_dest)),sizeof(struct in6_addr)); sock_addr = (struct sockaddr *) &sock_addr_v6; sock_addr_len = sizeof(sock_addr_v6); break; default: OOR_LOG(LDBG_2, "send_datagram_packet: Unknown afi %d",lisp_addr_ip_afi(addr_dest)); return (BAD); } if (sendto(sock, packet, packet_length, 0, sock_addr, sock_addr_len) < 0){ OOR_LOG(LDBG_2, "send_datagram_packet: send failed %s.",strerror ( errno )); return (BAD); } return (GOOD); }
/* Calculate the hash of the 5 tuples of a packet */ uint32_t pkt_tuple_hash(packet_tuple_t *tuple) { int hash = 0; int len = 0; int port = tuple->src_port; uint32_t *tuples = NULL; port = port + ((int)tuple->dst_port << 16); switch (lisp_addr_ip_afi(&tuple->src_addr)){ case AF_INET: /* 1 integer src_addr * + 1 integer dst_adr * + 1 integer (ports) * + 1 integer protocol * + 1 iid*/ len = 5; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], &tuple->src_addr); lisp_addr_copy_to(&tuples[1], &tuple->dst_addr); tuples[2] = port; tuples[3] = tuple->protocol; tuples[4] = tuple->iid; break; case AF_INET6: /* 4 integer src_addr * + 4 integer dst_adr * + 1 integer (ports) * + 1 integer protocol * + 1 iid */ len = 11; tuples = xmalloc(len * sizeof(uint32_t)); lisp_addr_copy_to(&tuples[0], &tuple->src_addr); lisp_addr_copy_to(&tuples[4], &tuple->dst_addr); tuples[8] = port; tuples[9] = tuple->protocol; tuples[10] = tuple->iid; break; } /* XXX: why 2013 used as initial value? */ hash = hashword(tuples, len, 2013); free(tuples); return (hash); }
void vpnapi_control_dp_process_new_gateway(oor_ctrl_t *ctrl, iface_t *iface, lisp_addr_t *gateway) { int afi; vpnapi_ctr_dplane_data_t * data; afi = lisp_addr_ip_afi(gateway); data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; /* Recreate sockets */ switch(afi){ case AF_INET: vpnapi_control_dp_reset_socket(data, data->ipv4_ctrl_socket,AF_INET); break; case AF_INET6: vpnapi_control_dp_reset_socket(data, data->ipv6_ctrl_socket,AF_INET6); break; default: return; } }
uint8_t * build_ip_udp_pcket(uint8_t *orig_pkt, int orig_pkt_len,lisp_addr_t *addr_from, lisp_addr_t *addr_dest, int port_from,int port_dest, int *encap_pkt_len) { uint8_t *encap_pkt; void *iph_ptr; struct udphdr *udph_ptr; int ip_hdr_len; int udp_hdr_len; int udp_hdr_and_payload_len; uint16_t udpsum; if (lisp_addr_ip_afi(addr_from) != lisp_addr_ip_afi(addr_dest)) { OOR_LOG(LDBG_2, "add_ip_udp_header: Different AFI addresses %d (%s) and %d (%s)", lisp_addr_ip_afi(addr_from), lisp_addr_to_char(addr_from), lisp_addr_ip_afi(addr_dest), lisp_addr_to_char(addr_dest)); return (NULL); } if ((lisp_addr_ip_afi(addr_from) != AF_INET) && (lisp_addr_ip_afi(addr_from) != AF_INET6)) { OOR_LOG(LDBG_2, "add_ip_udp_header: Unknown AFI %d", lisp_addr_ip_afi(addr_from)); return (NULL); } /* Headers lengths */ ip_hdr_len = ip_sock_afi_to_hdr_len(lisp_addr_ip_afi(addr_from)); udp_hdr_len = sizeof(struct udphdr); udp_hdr_and_payload_len = udp_hdr_len + orig_pkt_len; /* Assign memory for the original packet plus the new headers */ *encap_pkt_len = ip_hdr_len + udp_hdr_len + orig_pkt_len; if ((encap_pkt = (uint8_t *) malloc(*encap_pkt_len)) == NULL) { OOR_LOG(LDBG_2, "add_ip_udp_header: Couldn't allocate memory for the packet to be generated %s", strerror(errno)); return (NULL); } /* Make sure it's clean */ memset(encap_pkt, 0, *encap_pkt_len); /* IP header */ iph_ptr = encap_pkt; if ((udph_ptr = build_ip_header(iph_ptr, addr_from, addr_dest, udp_hdr_and_payload_len)) == NULL) { OOR_LOG(LDBG_2, "add_ip_udp_header: Couldn't build the inner ip header"); free(encap_pkt); return (NULL); } /* UDP header */ #ifdef BSD udph_ptr->uh_sport = htons(port_from); udph_ptr->uh_dport = htons(port_dest); udph_ptr->uh_ulen = htons(udp_payload_len); udph_ptr->uh_sum = 0; #else udph_ptr->source = htons(port_from); udph_ptr->dest = htons(port_dest); udph_ptr->len = htons(udp_hdr_and_payload_len); udph_ptr->check = 0; #endif /* Copy original packet after the headers */ memcpy(CO(udph_ptr, udp_hdr_len), orig_pkt, orig_pkt_len); /* * Now compute the headers checksums */ if ((udpsum = udp_checksum(udph_ptr, udp_hdr_and_payload_len, iph_ptr, lisp_addr_ip_afi(addr_from))) == -1) { free(encap_pkt); return (NULL); } udpsum(udph_ptr) = udpsum; return (encap_pkt); }