+/* Translate an IP dotted-quad address to a 4-byte character string.
+ * Return NULL if the given string is not in dotted-quad format.
+ */
+
+static char *pack_ip(const char *ipaddr)
+{
+ static char ipbuf[4];
+ int tmp[4], i;
+
+ if (sscanf(ipaddr, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3])
+ != 4)
+ return NULL;
+ for (i = 0; i < 4; i++) {
+ if (tmp[i] < 0 || tmp[i] > 255)
+ return NULL;
+ ipbuf[i] = tmp[i];
+ }
+ return ipbuf;
+}
+
+#endif
+
+/*************************************************************************/
+
+/*************************************************************************/
+
+/* lhost/lport specify the local side of the connection. If they are not
+ * given (lhost==NULL, lport==0), then they are left free to vary.
+ */
+
+int conn(const char *host, int port, const char *lhost, int lport)
+{
+#if HAVE_GETHOSTBYNAME
+ struct hostent *hp;
+#else
+ char *addr;
+#endif
+ struct sockaddr_in sa, lsa;
+ int sock;
+
+ memset(&lsa, 0, sizeof(lsa));
+ if (lhost)
+ {
+#if HAVE_GETHOSTBYNAME
+ if ((hp = gethostbyname(lhost)) != NULL)
+ {
+ memcpy((char *) &lsa.sin_addr, hp->h_addr, hp->h_length);
+ lsa.sin_family = hp->h_addrtype;
+#else
+ if (addr = pack_ip(lhost))
+ {
+ memcpy((char *) &lsa.sin_addr, addr, 4);
+ lsa.sin_family = AF_INET;
+#endif
+ }
+ else
+ {
+ lhost = NULL;
+ }
+ }
+ if (lport)
+ {
+ lsa.sin_port = htons((unsigned short) lport);
+ }
+
+ memset(&sa, 0, sizeof(sa));
+#if HAVE_GETHOSTBYNAME
+ if (!(hp = gethostbyname(host)))
+ {
+ return -1;
+ }
+ memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
+ sa.sin_family = hp->h_addrtype;
+#else
+ if (!(addr = pack_ip(host)))
+ {
+ log("conn(): `%s' is not a valid IP address", host);
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy((char *) &sa.sin_addr, addr, 4);
+ sa.sin_family = AF_INET;
+#endif
+ sa.sin_port = htons((unsigned short) port);
+
+ if ((sock = socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
+ {
+ return -1;
+ }
+
+ if ((lhost || lport)
+ && bind(sock, (struct sockaddr *) &lsa, sizeof(lsa)) < 0)
+ {
+ int errno_save = errno;
+ close(sock);
+ errno = errno_save;
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
+ {
+ int errno_save = errno;
+ close(sock);
+ errno = errno_save;
+ return -1;
+ }
+
+ return sock;
+}
+
+