if (stat(sun->sun_path, &st))
return (errno == ENOENT ? UNUSED : USED);
if (stat(sun->sun_path, &st))
return (errno == ENOENT ? UNUSED : USED);
+
+ /* The socket's definitely there, but is anyone actually still holding it
+ * open? The only way I know to discover this is to trundle through
+ * `/proc/net/unix'. If there's no entry, then the socket must be stale.
+ */
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(sa, 0, buf, sizeof(buf)));
if ((rc = unix_socket_status(sun, !desperatep)) == USED) return (-1);
else if (rc == STALE) unlink(sun->sun_path);
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(sa, 0, buf, sizeof(buf)));
if ((rc = unix_socket_status(sun, !desperatep)) == USED) return (-1);
else if (rc == STALE) unlink(sun->sun_path);
wildcard_address(sa->sa_family, &waddr.sa);
port_to_sockaddr(&waddr.sa, port);
snprintf(wsun.sun_path, sizeof(wsun.sun_path), "%s/%s", sockdir,
wildcard_address(sa->sa_family, &waddr.sa);
port_to_sockaddr(&waddr.sa, port);
snprintf(wsun.sun_path, sizeof(wsun.sun_path), "%s/%s", sockdir,
if ((rc = unix_socket_status(&wsun, !desperatep)) == USED) return (-1);
else if (rc == STALE) unlink(wsun.sun_path);
if ((rc = unix_socket_status(&wsun, !desperatep)) == USED) return (-1);
else if (rc == STALE) unlink(wsun.sun_path);
D( fprintf(stderr, "noip(%d): encode %s (%s)", getpid(),
present_sockaddr(sa, 0, buf, sizeof(buf)),
(f&ENCF_FRESH) ? "FRESH" : "EXISTING"); )
D( fprintf(stderr, "noip(%d): encode %s (%s)", getpid(),
present_sockaddr(sa, 0, buf, sizeof(buf)),
(f&ENCF_FRESH) ? "FRESH" : "EXISTING"); )
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(sa, 0, buf, sizeof(buf)));
rc = unix_socket_status(sun, 0);
if (rc == STALE) unlink(sun->sun_path);
if (rc == USED || (f&ENCF_FRESH)) goto found;
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(sa, 0, buf, sizeof(buf)));
rc = unix_socket_status(sun, 0);
if (rc == STALE) unlink(sun->sun_path);
if (rc == USED || (f&ENCF_FRESH)) goto found;
wildcard_address(sa->sa_family, &addr.sa);
port_to_sockaddr(&addr.sa, port);
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(&addr.sa, 0, buf, sizeof(buf)));
if (unix_socket_status(sun, 0) == STALE) unlink(sun->sun_path);
wildcard_address(sa->sa_family, &addr.sa);
port_to_sockaddr(&addr.sa, port);
snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
present_sockaddr(&addr.sa, 0, buf, sizeof(buf)));
if (unix_socket_status(sun, 0) == STALE) unlink(sun->sun_path);
for (i = 0; i < 10; i++) {
port_to_sockaddr(&addr.sa, randrange(minautoport, maxautoport));
if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
}
for (i = 0; i < 10; i++) {
port_to_sockaddr(&addr.sa, randrange(minautoport, maxautoport));
if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
}
+
+ /* Things must be getting tight. Work through all of the autoport range
+ * to see if we can find a spare one. The first time, just do it the
+ * quick way; if that doesn't work, then check harder for stale sockets.
+ */
for (desperatep = 0; desperatep < 2; desperatep++) {
for (i = minautoport; i <= maxautoport; i++) {
port_to_sockaddr(&addr.sa, i);
if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
}
}
for (desperatep = 0; desperatep < 2; desperatep++) {
for (i = minautoport; i <= maxautoport; i++) {
port_to_sockaddr(&addr.sa, i);
if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
}
}