Add some details on exactly how to comply with the GPL
[oweals/busybox.git] / libbb / xconnect.c
index 9e771495d671f9147f4b5de2496e986dae885477..29b984720fc437cb9a9d33c9b03b9e04085445df 100644 (file)
@@ -6,75 +6,66 @@
  *
  */
 
-#include "inet_common.h"
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <errno.h>
 #include <netdb.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include "libbb.h"
 
-int xconnect(const char *host, const char *port)
+/* Return network byte ordered 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 short bb_lookup_port(const char *port, unsigned short default_port)
 {
-#if CONFIG_FEATURE_IPV6
-       struct addrinfo hints;
-       struct addrinfo *res;
-       struct addrinfo *addr_info;
-       int error;
-       int s;
+       unsigned short port_nr = htons(default_port);
+       if (port) {
+               char *endptr;
+               int old_errno;
+               long port_long;
 
-       memset(&hints, 0, sizeof(hints));
-       /* set-up hints structure */
-       hints.ai_family = PF_UNSPEC;
-       hints.ai_socktype = SOCK_STREAM;
-       error = getaddrinfo(host, port, &hints, &res);
-       if (error||!res)
-               perror_msg_and_die(gai_strerror(error));
-       addr_info=res;
-       while (res) {
-               s=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-               if (s<0)
-               {
-                       error=s;
-                       res=res->ai_next;
-                       continue;
+               /* Since this is a lib function, we're not allowed to reset errno to 0.
+                * Doing so could break an app that is deferring checking of errno. */
+               old_errno = errno;
+               errno = 0;
+               port_long = strtol(port, &endptr, 10);
+               if (errno != 0 || *endptr!='\0' || endptr==port || port_long < 0 || port_long > 65535) {
+                       struct servent *tserv = getservbyname(port, "tcp");
+                       if (tserv) {
+                               port_nr = tserv->s_port;
+                       }
+               } else {
+                       port_nr = htons(port_long);
                }
-               /* try to connect() to res->ai_addr */
-               error = connect(s, res->ai_addr, res->ai_addrlen);
-               if (error >= 0)
-                       break;
-               close(s);
-               res=res->ai_next;
-       }
-       freeaddrinfo(addr_info);
-       if (error < 0)
-       {
-               perror_msg_and_die("Unable to connect to remote host (%s)", host);
+               errno = old_errno;
        }
-       return s;
-#else
-       struct sockaddr_in s_addr;
-       int s = socket(AF_INET, SOCK_STREAM, 0);
-       struct servent *tserv;
-       int port_nr=atoi(port);
-       struct hostent * he;
-
-       if (port_nr==0 && (tserv = getservbyname(port, "tcp")) != NULL)
-               port_nr = tserv->s_port;
+       return port_nr;
+}
 
-       memset(&s_addr, 0, sizeof(struct sockaddr_in));
-       s_addr.sin_family = AF_INET;
-       s_addr.sin_port = htons(port_nr);
+void bb_lookup_host(struct sockaddr_in *s_in, const char *host)
+{
+       struct hostent *he;
 
+       memset(s_in, 0, sizeof(struct sockaddr_in));
+       s_in->sin_family = AF_INET;
        he = xgethostbyname(host);
-       memcpy(&s_addr.sin_addr, he->h_addr, sizeof s_addr.sin_addr);
+       memcpy(&(s_in->sin_addr), he->h_addr_list[0], he->h_length);
+}
 
-       if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0)
+int xconnect(struct sockaddr_in *s_addr)
+{
+       int s = socket(AF_INET, SOCK_STREAM, 0);
+       if (connect(s, (struct sockaddr_in *)s_addr, sizeof(struct sockaddr_in)) < 0)
        {
-               perror_msg_and_die("Unable to connect to remote host (%s)", host);
+               bb_perror_msg_and_die("Unable to connect to remote host (%s)", 
+                               inet_ntoa(s_addr->sin_addr));
        }
        return s;
-#endif
 }