}
}
-/* Return network byte ordered port number for a service.
+/* Return port number for a service.
* If "port" is a number use it as the port.
* If "port" is a name it is looked up in /etc/services, if it isnt found return
* default_port */
unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
{
- unsigned port_nr = htons(default_port);
+ unsigned port_nr = default_port;
if (port) {
int old_errno;
if (errno || port_nr > 65535) {
struct servent *tserv = getservbyname(port, protocol);
if (tserv)
- port_nr = tserv->s_port;
- } else {
- port_nr = htons(port_nr);
+ port_nr = ntohs(tserv->s_port);
}
errno = old_errno;
}
- return port_nr;
+ return (uint16_t)port_nr;
}
/* "New" networking API */
-void set_port(len_and_sockaddr *lsa, unsigned port)
+int get_nport(len_and_sockaddr *lsa)
+{
+#if ENABLE_FEATURE_IPV6
+ if (lsa->sa.sa_family == AF_INET6) {
+ return lsa->sin6.sin6_port;
+ }
+#endif
+ if (lsa->sa.sa_family == AF_INET) {
+ return lsa->sin.sin_port;
+ }
+ return -1;
+ /* What? UNIX socket? IPX?? :) */
+}
+
+void set_nport(len_and_sockaddr *lsa, unsigned port)
{
#if ENABLE_FEATURE_IPV6
if (lsa->sa.sa_family == AF_INET6) {
r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
r->len = result->ai_addrlen;
memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
- set_port(r, port);
+ set_nport(r, htons(port));
freeaddrinfo(result);
return r;
}
return str2sockaddr(host, port, NI_NUMERICHOST);
}
-static int xsocket_stream(len_and_sockaddr *lsa)
+int xsocket_stream(len_and_sockaddr **lsap)
{
+ len_and_sockaddr *lsa;
int fd;
+ int len = sizeof(struct sockaddr_in);
+ int family = AF_INET;
+
#if ENABLE_FEATURE_IPV6
fd = socket(AF_INET6, SOCK_STREAM, 0);
- lsa->sa.sa_family = AF_INET6;
- lsa->len = sizeof(struct sockaddr_in6);
- if (fd >= 0)
- return fd;
+ if (fd >= 0) {
+ len = sizeof(struct sockaddr_in6);
+ family = AF_INET6;
+ } else
#endif
- fd = xsocket(AF_INET, SOCK_STREAM, 0);
- lsa->sa.sa_family = AF_INET;
- lsa->len = sizeof(struct sockaddr_in);
+ {
+ fd = xsocket(AF_INET, SOCK_STREAM, 0);
+ }
+ lsa = xzalloc(offsetof(len_and_sockaddr, sa) + len);
+ lsa->len = len;
+ lsa->sa.sa_family = family;
+ *lsap = lsa;
return fd;
}
/* user specified bind addr dictates family */
fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
} else {
- lsa = xzalloc(offsetof(len_and_sockaddr, sa) +
- USE_FEATURE_IPV6(sizeof(struct sockaddr_in6))
- SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in))
- );
- fd = xsocket_stream(lsa);
+ fd = xsocket_stream(&lsa);
}
setsockopt_reuseaddr(fd);
xbind(fd, &lsa->sa, lsa->len);
flags | NI_NUMERICSERV /* do not resolve port# */
);
if (rc) return NULL;
+// We probably need to use [%s]:%s for IPv6...
return xasprintf("%s:%s", host, serv);
}