/* * Bind a socket to a specific address and port if specified * Afi is used when the src address is not specified */ int bind_socket(int sock, int afi, lisp_addr_t *src_addr, int src_port) { int result = TRUE; struct sockaddr *sock_addr; int sock_addr_len; struct sockaddr_in sock_addr_v4; struct sockaddr_in6 sock_addr_v6; switch(afi){ case AF_INET: memset ( ( char * ) &sock_addr_v4, 0, sizeof ( sock_addr_v4 ) ); sock_addr_v4.sin_family = AF_INET; if (src_port != 0){ sock_addr_v4.sin_port = htons(src_port); } if (src_addr != NULL){ sock_addr_v4.sin_addr.s_addr = ip_addr_get_v4(lisp_addr_ip(src_addr))->s_addr; }else{ sock_addr_v4.sin_addr.s_addr = INADDR_ANY; } sock_addr = ( struct sockaddr * ) &sock_addr_v4; sock_addr_len = sizeof ( struct sockaddr_in ); break; case AF_INET6: memset ( ( char * ) &sock_addr_v6, 0, sizeof ( sock_addr_v6 ) ); sock_addr_v6.sin6_family = AF_INET6; if (src_port != 0){ sock_addr_v6.sin6_port = htons(src_port); } if (src_addr != NULL){ memcpy(&(sock_addr_v6.sin6_addr),ip_addr_get_v6(lisp_addr_ip(src_addr)),sizeof(struct in6_addr)); }else{ sock_addr_v6.sin6_addr = in6addr_any; } sock_addr = ( struct sockaddr * ) &sock_addr_v6; sock_addr_len = sizeof ( struct sockaddr_in6 ); break; default: return (BAD); } if (bind(sock,sock_addr,sock_addr_len) != 0){ OOR_LOG(LDBG_1, "bind_socket: %s", strerror(errno)); result = BAD; }else{ OOR_LOG(LDBG_1, "bind_socket: Binded socket %d to source address %s and port %d with afi %d", sock, lisp_addr_to_char(src_addr),src_port, afi); } return (result); }
int vpnapi_control_dp_send_msg(oor_ctrl_t *ctrl, lbuf_t *buff, uconn_t *udp_conn) { int ret; int sock; ip_addr_t *src_addr, *dst_addr; vpnapi_ctr_dplane_data_t * data; data = (vpnapi_ctr_dplane_data_t *)ctrl->control_data_plane->control_dp_data; if (lisp_addr_lafi(&udp_conn->ra) != LM_AFI_IP) { OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: Destination address %s of UDP connection is not a IP. " "Discarding!", lisp_addr_to_char(&udp_conn->ra)); return(BAD); } src_addr = lisp_addr_ip(&udp_conn->la); dst_addr = lisp_addr_ip(&udp_conn->ra); if (!lisp_addr_is_no_addr(&udp_conn->la) && (ip_addr_afi(src_addr) != ip_addr_afi(dst_addr))) { OOR_LOG(LDBG_2, "vpnapi_control_dp_send_msg: src %s and dst %s of UDP connection have " "different IP AFI. Discarding!", ip_addr_to_char(src_addr), ip_addr_to_char(dst_addr)); return(BAD); } switch (ip_addr_afi(dst_addr)){ case AF_INET: if (udp_conn->lp == LISP_CONTROL_PORT){ sock = data->ipv4_ctrl_socket; }else{ sock = data->ipv4_data_socket; } break; case AF_INET6: sock = data->ipv6_ctrl_socket; break; default: return (BAD); } ret = send_datagram_packet (sock, lbuf_data(buff), lbuf_size(buff), &udp_conn->ra, udp_conn->rp); if (ret != GOOD) { OOR_LOG(LDBG_1, "Failed to send contrl message from RLOC: %s -> %s", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra)); return(BAD); } else { OOR_LOG(LDBG_1, "Sent control message IP: %s -> %s UDP: %d -> %d", lisp_addr_to_char(&udp_conn->la), lisp_addr_to_char(&udp_conn->ra), udp_conn->lp, udp_conn->rp); 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); }
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); }
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); }