you're not interested in one or the other information, pass NULL as
the pointer. */
-void
+static void
sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
{
switch (sa->sa_family)
}
\f
static int
-resolve_bind_address (const char *host, struct sockaddr *sa, int flags)
+resolve_bind_address (struct sockaddr *sa)
{
struct address_list *al;
- /* #### Shouldn't we do this only once? opt.bind_address won't
- change during a Wget run! */
+ /* Make sure this is called only once. opt.bind_address doesn't
+ change during a Wget run. */
+ static int called, should_bind;
+ static ip_address ip;
+ if (called)
+ {
+ if (should_bind)
+ sockaddr_set_data (sa, &ip, 0);
+ return should_bind;
+ }
+ called = 1;
- al = lookup_host (host, flags | LH_SILENT | LH_PASSIVE);
- if (al == NULL)
+ al = lookup_host_passive (opt.bind_address);
+ if (!al)
{
- /* #### We should print the error message here. */
+ /* #### We should be able to print the error message here. */
logprintf (LOG_NOTQUIET,
_("%s: unable to resolve bind address `%s'; disabling bind.\n"),
exec_name, opt.bind_address);
+ should_bind = 0;
return 0;
}
/* Pick the first address in the list and use it as bind address.
- Perhaps we should try multiple addresses, but I don't think
- that's necessary in practice. */
- sockaddr_set_data (sa, address_list_address_at (al, 0), 0);
+ Perhaps we should try multiple addresses in succession, but I
+ don't think that's necessary in practice. */
+ ip = *address_list_address_at (al, 0);
address_list_release (al);
+
+ sockaddr_set_data (sa, &ip, 0);
+ should_bind = 1;
return 1;
}
\f
address. */
struct sockaddr_storage bind_ss;
struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
- if (resolve_bind_address (opt.bind_address, bind_sa, 0))
+ if (resolve_bind_address (bind_sa))
{
if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
goto err;
return ACCEPTOK;
}
-/* Return the local IP address associated with the connection on FD. */
+/* Get the IP address associated with the connection on FD and store
+ it to IP. Return 1 on success, 0 otherwise.
+
+ If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
+ (client) side of the socket. Else if ENDPOINT is ENDPOINT_PEER, it
+ returns the address of the remote (peer's) side of the socket. */
int
-conaddr (int fd, ip_address *ip)
+socket_ip_address (int sock, ip_address *ip, int endpoint)
{
struct sockaddr_storage storage;
struct sockaddr *sockaddr = (struct sockaddr *)&storage;
socklen_t addrlen = sizeof (storage);
+ int ret;
- if (getsockname (fd, sockaddr, &addrlen) < 0)
+ if (endpoint == ENDPOINT_LOCAL)
+ ret = getsockname (sock, sockaddr, &addrlen);
+ else if (endpoint == ENDPOINT_PEER)
+ ret = getpeername (sock, sockaddr, &addrlen);
+ else
+ abort ();
+ if (ret < 0)
return 0;
switch (sockaddr->sa_family)
register_extended (int fd, xreader_t reader, xwriter_t writer,
xpoller_t poller, xcloser_t closer, void *ctx)
{
- struct extended_info *info = xnew (struct extended_info);
+ struct extended_info *info;
+
+ /* The file descriptor must be non-negative to be registered.
+ Negative values are ignored by xclose(), and -1 cannot be used as
+ hash key. */
+ assert (fd >= 0);
+
+ info = xnew (struct extended_info);
info->reader = reader;
info->writer = writer;
info->poller = poller;