xsock_t comm_bind_udp4(const struct in_addr *my_addr, unsigned short my_port, int is_blocking, int reuse_flag) { xsock_t sock; comm_init(); sock = comm_sock_open(AF_INET, SOCK_DGRAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); /* For multicast, you need to set reuse before you bind, if you want * more than one socket to be able to bind to a particular IP (like, 0.0.0.0) */ if (reuse_flag) { if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_set_reuseport(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } } if (comm_sock_bind4(sock, my_addr, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); }
xsock_t comm_bind_tcp6(const struct in6_addr *my_addr, unsigned int my_ifindex, unsigned short my_port, int is_blocking) { #ifdef HAVE_IPV6 xsock_t sock; comm_init(); sock = comm_sock_open(AF_INET6, SOCK_STREAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_sock_bind6(sock, my_addr, my_ifindex, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); #else /* ! HAVE_IPV6 */ comm_sock_no_ipv6("comm_bind_tcp6", my_addr, my_ifindex, my_port, is_blocking); return (XORP_BAD_SOCKET); #endif /* ! HAVE_IPV6 */ }
xsock_t comm_bind_connect_tcp6(const struct in6_addr *local_addr, unsigned int my_ifindex, unsigned short local_port, const struct in6_addr *remote_addr, unsigned short remote_port, int is_blocking, int *in_progress) { #ifdef HAVE_IPV6 xsock_t sock; if (in_progress != NULL) *in_progress = 0; comm_init(); sock = comm_sock_open(AF_INET6, SOCK_STREAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_sock_bind6(sock, local_addr, my_ifindex, local_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_sock_connect6(sock, remote_addr, remote_port, is_blocking, in_progress) != XORP_OK) { /* * If this is a non-blocking socket and the connect couldn't * complete, then return the socket. */ if ((! is_blocking) && (in_progress != NULL) && (*in_progress == 1)) return (sock); comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); #else /* ! HAVE_IPV6 */ if (in_progress != NULL) *in_progress = 0; comm_sock_no_ipv6("comm_bind_connect_tcp6", local_addr, my_ifindex, local_port, remote_addr, remote_port, is_blocking, in_progress); return (XORP_BAD_SOCKET); #endif /* ! HAVE_IPV6 */ }
xsock_t comm_connect_unix(const char* path, int is_blocking) { xsock_t sock; struct sockaddr_un s_un; comm_init(); if (comm_unix_setup(&s_un, path) == -1) return (XORP_BAD_SOCKET); sock = comm_sock_open(s_un.sun_family, SOCK_STREAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (connect(sock, (struct sockaddr*) &s_un, sizeof(s_un)) == -1) { _comm_set_serrno(); if (is_blocking || comm_get_last_error() != EINPROGRESS) { XLOG_ERROR("Error connecting to unix socket. Path: %s. Error: %s", s_un.sun_path, comm_get_error_str(comm_get_last_error())); comm_sock_close(sock); return (XORP_BAD_SOCKET); } } return (sock); }
xsock_t comm_connect_udp4(const struct in_addr *remote_addr, unsigned short remote_port, int is_blocking, int *in_progress) { xsock_t sock; if (in_progress != NULL) *in_progress = 0; comm_init(); sock = comm_sock_open(AF_INET, SOCK_DGRAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (comm_sock_connect4(sock, remote_addr, remote_port, is_blocking, in_progress) != XORP_OK) { /* * If this is a non-blocking socket and the connect couldn't * complete, then return the socket. */ if ((! is_blocking) && (in_progress != NULL) && (*in_progress == 1)) return (sock); comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); }
xsock_t comm_sock_open(int domain, int type, int protocol, int is_blocking) { xsock_t sock; /* Create the kernel socket */ sock = socket(domain, type, protocol); if (sock == XORP_BAD_SOCKET) { _comm_set_serrno(); XLOG_ERROR("Error opening socket (domain = %d, type = %d, " "protocol = %d): %s", domain, type, protocol, comm_get_error_str(comm_get_last_error())); return (XORP_BAD_SOCKET); } /* Set the receiving and sending socket buffer size in the kernel */ if (comm_sock_set_rcvbuf(sock, SO_RCV_BUF_SIZE_MAX, SO_RCV_BUF_SIZE_MIN) < SO_RCV_BUF_SIZE_MIN) { _comm_set_serrno(); comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_sock_set_sndbuf(sock, SO_SND_BUF_SIZE_MAX, SO_SND_BUF_SIZE_MIN) < SO_SND_BUF_SIZE_MIN) { _comm_set_serrno(); comm_sock_close(sock); return (XORP_BAD_SOCKET); } /* Enable TCP_NODELAY */ if (type == SOCK_STREAM && (domain == AF_INET || domain == AF_INET6) && comm_set_nodelay(sock, 1) != XORP_OK) { _comm_set_serrno(); comm_sock_close(sock); return (XORP_BAD_SOCKET); } /* Set blocking mode */ if (comm_sock_set_blocking(sock, is_blocking) != XORP_OK) { _comm_set_serrno(); comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); }
int comm_close(xsock_t sock) { if (comm_sock_close(sock) != XORP_OK) return (XORP_ERROR); return (XORP_OK); }
xsock_t comm_bind_join_udp6(const struct in6_addr *mcast_addr, unsigned int my_ifindex, unsigned short my_port, int reuse_flag, int is_blocking) { #ifdef HAVE_IPV6 xsock_t sock; comm_init(); sock = comm_sock_open(AF_INET6, SOCK_DGRAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (reuse_flag) { if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_set_reuseport(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } } /* Bind the socket */ if (comm_sock_bind6(sock, NULL, 0, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } /* Join the multicast group */ if (comm_sock_join6(sock, mcast_addr, my_ifindex) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); #else /* ! HAVE_IPV6 */ comm_sock_no_ipv6("comm_bind_join_udp6", mcast_addr, my_ifindex, my_port, reuse_flag, is_blocking); return (XORP_BAD_SOCKET); #endif /* ! HAVE_IPV6 */ }
xsock_t comm_bind_tcp4(const struct in_addr *my_addr, unsigned short my_port, int is_blocking) { xsock_t sock; comm_init(); sock = comm_sock_open(AF_INET, SOCK_STREAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_sock_bind4(sock, my_addr, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); }
xsock_t comm_bind_join_udp4(const struct in_addr *mcast_addr, const struct in_addr *join_if_addr, unsigned short my_port, int reuse_flag, int is_blocking) { xsock_t sock; comm_init(); sock = comm_sock_open(AF_INET, SOCK_DGRAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); if (reuse_flag) { if (comm_set_reuseaddr(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } if (comm_set_reuseport(sock, 1) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } } /* Bind the socket */ if (comm_sock_bind4(sock, NULL, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } /* Join the multicast group */ if (comm_sock_join4(sock, mcast_addr, join_if_addr) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); } return (sock); }
int comm_sock_connect4(xsock_t sock, const struct in_addr *remote_addr, unsigned short remote_port, int is_blocking, int *in_progress) { int family; struct sockaddr_in sin_addr; if (in_progress != NULL) *in_progress = 0; family = comm_sock_get_family(sock); if (family != AF_INET) { XLOG_ERROR("Invalid family of socket %d: family = %d (expected %d)", sock, family, AF_INET); return (XORP_ERROR); } memset(&sin_addr, 0, sizeof(sin_addr)); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sin_addr.sin_len = sizeof(sin_addr); #endif sin_addr.sin_family = (u_char)family; sin_addr.sin_port = remote_port; /* XXX: in network order */ sin_addr.sin_addr.s_addr = remote_addr->s_addr; /* XXX: in network order */ if (connect(sock, (struct sockaddr *)&sin_addr, sizeof(sin_addr)) < 0) { _comm_set_serrno(); if (! is_blocking) { #ifdef HOST_OS_WINDOWS if (comm_get_last_error() == WSAEWOULDBLOCK) { #else if (comm_get_last_error() == EINPROGRESS) { #endif /* * XXX: The connection is non-blocking, and the connection * cannot be completed immediately, therefore set the * in_progress flag to 1 and return an error. */ if (in_progress != NULL) *in_progress = 1; return (XORP_ERROR); } } XLOG_ERROR("Error connecting socket (family = %d, " "remote_addr = %s, remote_port = %d): %s", family, inet_ntoa(*remote_addr), ntohs(remote_port), comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } return (XORP_OK); } int comm_sock_connect6(xsock_t sock, const struct in6_addr *remote_addr, unsigned short remote_port, int is_blocking, int *in_progress) { #ifdef HAVE_IPV6 int family; struct sockaddr_in6 sin6_addr; if (in_progress != NULL) *in_progress = 0; family = comm_sock_get_family(sock); if (family != AF_INET6) { XLOG_ERROR("Invalid family of socket %d: family = %d (expected %d)", sock, family, AF_INET6); return (XORP_ERROR); } memset(&sin6_addr, 0, sizeof(sin6_addr)); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN sin6_addr.sin6_len = sizeof(sin6_addr); #endif sin6_addr.sin6_family = (u_char)family; sin6_addr.sin6_port = remote_port; /* XXX: in network order */ sin6_addr.sin6_flowinfo = 0; /* XXX: unused (?) */ memcpy(&sin6_addr.sin6_addr, remote_addr, sizeof(sin6_addr.sin6_addr)); sin6_addr.sin6_scope_id = 0; /* XXX: unused (?) */ if (connect(sock, (struct sockaddr *)&sin6_addr, sizeof(sin6_addr)) < 0) { _comm_set_serrno(); if (! is_blocking) { #ifdef HOST_OS_WINDOWS if (comm_get_last_error() == WSAEWOULDBLOCK) { #else if (comm_get_last_error() == EINPROGRESS) { #endif /* * XXX: The connection is non-blocking, and the connection * cannot be completed immediately, therefore set the * in_progress flag to 1 and return an error. */ if (in_progress != NULL) *in_progress = 1; return (XORP_ERROR); } } XLOG_ERROR("Error connecting socket (family = %d, " "remote_addr = %s, remote_port = %d): %s", family, (remote_addr)? inet_ntop(family, remote_addr, addr_str_255, sizeof(addr_str_255)) : "ANY", ntohs(remote_port), comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } return (XORP_OK); #else /* ! HAVE_IPV6 */ if (in_progress != NULL) *in_progress = 0; comm_sock_no_ipv6("comm_sock_connect6", sock, remote_addr, remote_port, is_blocking); return (XORP_ERROR); #endif /* ! HAVE_IPV6 */ } int comm_sock_connect(xsock_t sock, const struct sockaddr *sin, int is_blocking, int *in_progress) { switch (sin->sa_family) { case AF_INET: { const struct sockaddr_in *sin4 = (const struct sockaddr_in *)((const void *)sin); return comm_sock_connect4(sock, &sin4->sin_addr, sin4->sin_port, is_blocking, in_progress); } break; #ifdef HAVE_IPV6 case AF_INET6: { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)((const void *)sin); return comm_sock_connect6(sock, &sin6->sin6_addr, sin6->sin6_port, is_blocking, in_progress); } break; #endif /* HAVE_IPV6 */ default: XLOG_FATAL("Error comm_sock_connect invalid family = %d", sin->sa_family); return (XORP_ERROR); } XLOG_UNREACHABLE(); return XORP_ERROR; } xsock_t comm_sock_accept(xsock_t sock) { xsock_t sock_accept; struct sockaddr addr; socklen_t socklen = sizeof(addr); sock_accept = accept(sock, &addr, &socklen); if (sock_accept == XORP_BAD_SOCKET) { _comm_set_serrno(); XLOG_ERROR("Error accepting socket %d: %s", sock, comm_get_error_str(comm_get_last_error())); return (XORP_BAD_SOCKET); } #ifdef HOST_OS_WINDOWS /* * Squelch Winsock event notifications on the new socket which may * have been inherited from the parent listening socket. */ (void)WSAEventSelect(sock_accept, NULL, 0); #endif /* Enable TCP_NODELAY */ if ((addr.sa_family == AF_INET || addr.sa_family == AF_INET6) && comm_set_nodelay(sock_accept, 1) != XORP_OK) { comm_sock_close(sock_accept); return (XORP_BAD_SOCKET); } return (sock_accept); }