/* * NAME: ip_bindery * USAGE: Establish a local passive (listening) socket at the given port. * ARGS: family - AF_INET is the only supported argument. * port - The port to establish the connection upon. May be 0, * which requests any open port. * storage - Pointer to a sockaddr structure big enough for the * specified family. Upon success, it will be filled with * the local sockaddr of the new connection. * NOTES: In most cases, the local address for 'storage' will be INADDR_ANY * which doesn't really give you any useful information. It is not * possible to authoritatively figure out the local IP address * without using ioctl(). However, we guess the best we may. * * NOTES: This function lacks IPv6 support. * This function lacks Unix Domain Socket support. */ int ip_bindery (int family, unsigned short port, SS *storage) { socklen_t len; int fd; if (inet_vhostsockaddr(family, port, NULL, storage, &len)) { syserr(-1, "ip_bindery: inet_vhostsockaddr(%d,%d) failed.", family, port); return -1; } if (!len) { syserr(-1, "ip_bindery: inet_vhostsockaddr(%d,%d) didn't " "return an address I could bind", family, port); return -1; } if ((fd = client_bind((SA *)storage, len)) < 0) { syserr(-1, "ip_bindery: client_bind(%d,%d) failed.", family, port); return -1; } return fd; }
/* * NAME: ip_bindery * USAGE: Establish a local passive (listening) socket at the given port. * ARGS: family - AF_INET is the only supported argument. * port - The port to establish the connection upon. May be 0, * which requests any open port. * storage - Pointer to a sockaddr structure big enough for the * specified family. Upon success, it will be filled with * the local sockaddr of the new connection. * NOTES: In most cases, the local address for 'storage' will be INADDR_ANY * which doesn't really give you any useful information. It is not * possible to authoritatively figure out the local IP address * without using ioctl(). However, we guess the best we may. * * NOTES: This function lacks IPv6 support. * This function lacks Unix Domain Socket support. */ int ip_bindery (int family, unsigned short port, SS *storage) { int err; socklen_t len; if ((err = inet_vhostsockaddr(family, port, storage, &len))) return err; if (!len) return -6; return client_bind((SA *)storage, len); }
/* * NAME: connectory * USAGE: Connect to a given "host" and "port" with the given "family" * ARGS: family - AF_INET is the only supported argument. * host - A hostname or "dotted quad" (or equivalent). * port - The remote port to connect to in *HOST ORDER*. * * XXX - This so violates everything I really wanted this function to be, * but I changed it to call getaddrinfo() directly instead of calling * inet_vhostsockaddr() because I wanted it to be able to take advantage * of connecting to multiple protocols and multiple ip addresses (for things * like ``us.undernet.org'') without having to do multiple calls to * getaddrinfo() which could be quite costly. */ int connectory (int family, const char *host, const char *port) { AI hints, *results, *ai; int err; int fd; SS localaddr; socklen_t locallen; memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; if ((err = Getaddrinfo(host, port, &hints, &results))) { yell("Hostname lookup for [%s:%s] failed: %s (%d)", host, port, gai_strerror(err), err); return -5; } fd = -1; for (ai = results; ai; ai = ai->ai_next) { /* First, look up the virtual host we use for this protocol. */ err = inet_vhostsockaddr(ai->ai_family, -1, &localaddr, &locallen); if (err < 0) continue; /* Now try to do the connection. */ fd = client_connect((SA *)&localaddr, locallen, ai->ai_addr, ai->ai_addrlen); if (fd < 0) { err = fd; fd = -1; continue; } else break; } Freeaddrinfo(results); if (fd < 0) return err; return fd; }