xsock_t comm_bind_tcp(const struct sockaddr *sock, int is_blocking) { switch (sock->sa_family) { case AF_INET: { const struct sockaddr_in *sin = (const struct sockaddr_in *)((const void *)sock); return comm_bind_tcp4(&sin->sin_addr, sin->sin_port, is_blocking); } break; #ifdef HAVE_IPV6 case AF_INET6: { const struct sockaddr_in6 *sin = (const struct sockaddr_in6 *)((const void *)sock); return comm_bind_tcp6(&sin->sin6_addr, sin->sin6_scope_id, sin->sin6_port, is_blocking); } break; #endif /* HAVE_IPV6 */ default: XLOG_FATAL("Error comm_bind_tcp invalid family = %d", sock->sa_family); break; } XLOG_UNREACHABLE(); return (XORP_BAD_SOCKET); }
int comm_sock_bind(xsock_t sock, const struct sockaddr *sin) { switch (sin->sa_family) { case AF_INET: { const struct sockaddr_in *sin4 = (const struct sockaddr_in *)((const void *)sin); return comm_sock_bind4(sock, &sin4->sin_addr, sin4->sin_port); } break; #ifdef HAVE_IPV6 case AF_INET6: { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)((const void *)sin); return comm_sock_bind6(sock, &sin6->sin6_addr, sin6->sin6_scope_id, sin6->sin6_port); } break; #endif /* HAVE_IPV6 */ default: XLOG_FATAL("Error comm_sock_bind invalid family = %d", sin->sa_family); return (XORP_ERROR); } XLOG_UNREACHABLE(); return XORP_ERROR; }
int comm_set_multicast_ttl(xsock_t sock, int val) { int family = comm_sock_get_family(sock); switch (family) { case AF_INET: { /* XXX: Most platforms now use int for this option; * legacy BSD specified u_char. */ u_char ip_multicast_ttl = val; if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, XORP_SOCKOPT_CAST(&ip_multicast_ttl), sizeof(ip_multicast_ttl)) < 0) { _comm_set_serrno(); XLOG_ERROR("setsockopt IP_MULTICAST_TTL %u: %s", ip_multicast_ttl, comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } break; } #ifdef HAVE_IPV6 case AF_INET6: { int ip_multicast_ttl = val; if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, XORP_SOCKOPT_CAST(&ip_multicast_ttl), sizeof(ip_multicast_ttl)) < 0) { _comm_set_serrno(); XLOG_ERROR("setsockopt IPV6_MULTICAST_HOPS %u: %s", ip_multicast_ttl, comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } break; } #endif /* HAVE_IPV6 */ default: XLOG_FATAL("Error %s setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS " "on socket %d: invalid family = %d", (val)? "set": "reset", sock, family); return (XORP_ERROR); } return (XORP_OK); }
int comm_set_loopback(xsock_t sock, int val) { int family = comm_sock_get_family(sock); switch (family) { case AF_INET: { u_char loop = val; if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, XORP_SOCKOPT_CAST(&loop), sizeof(loop)) < 0) { _comm_set_serrno(); XLOG_ERROR("setsockopt IP_MULTICAST_LOOP %u: %s", loop, comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } break; } #ifdef HAVE_IPV6 case AF_INET6: { unsigned int loop6 = val; if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, XORP_SOCKOPT_CAST(&loop6), sizeof(loop6)) < 0) { _comm_set_serrno(); XLOG_ERROR("setsockopt IPV6_MULTICAST_LOOP %u: %s", loop6, comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } break; } #endif /* HAVE_IPV6 */ default: XLOG_FATAL("Error %s setsockopt IP_MULTICAST_LOOP/IPV6_MULTICAST_LOOP " "on socket %d: invalid family = %d", (val)? "set": "reset", sock, family); return (XORP_ERROR); } return (XORP_OK); }
int comm_set_tos(xsock_t sock, int val) { #ifdef IP_TOS /* * Most implementations use 'int' to represent the value of * the IP_TOS option. */ int family, ip_tos; family = comm_sock_get_family(sock); if (family != AF_INET) { XLOG_FATAL("Error %s setsockopt IP_TOS on socket %d: " "invalid family = %d", (val)? "set": "reset", sock, family); return (XORP_ERROR); } /* * Note that it is not guaranteed that the TOS will be successfully * set or indeed propagated where the host platform is running * its own traffic classifier; the use of comm_set_tos() is * intended for link-scoped traffic. */ ip_tos = val; if (setsockopt(sock, IPPROTO_IP, IP_TOS, XORP_SOCKOPT_CAST(&ip_tos), sizeof(ip_tos)) < 0) { _comm_set_serrno(); XLOG_ERROR("setsockopt IP_TOS 0x%x: %s", ip_tos, comm_get_error_str(comm_get_last_error())); return (XORP_ERROR); } return (XORP_OK); #else UNUSED(sock); UNUSED(val); XLOG_WARNING("IP_TOS Undefined!"); return (XORP_ERROR); #endif /* ! IP_TOS */ }
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); }