X-Git-Url: https://git.distorted.org.uk/~mdw/preload-hacks/blobdiff_plain/c0ae47b31fbdf9729f6ea531d674b93252b1b775..refs/tags/1.2.2:/noip.c?ds=sidebyside diff --git a/noip.c b/noip.c index fea6f74..aca7b75 100644 --- a/noip.c +++ b/noip.c @@ -63,6 +63,7 @@ #define UNUSED 0u /* No sign of anyone using it */ #define STALE 1u /* Socket exists, but is abandoned */ #define USED 16u /* Socket is in active use */ +#define LISTEN 2u /* Socket has an active listener */ enum { DENY, ALLOW }; /* ACL verdicts */ @@ -680,6 +681,7 @@ static int unix_socket_status(struct sockaddr_un *sun, int quickp) FILE *fp = 0; size_t len, n; int rc; + unsigned long f; char buf[256]; /* If we can't find the socket node, then it's definitely not in use. If @@ -710,6 +712,8 @@ static int unix_socket_status(struct sockaddr_un *sun, int quickp) if (n >= len + 2 && buf[n - len - 2] == ' ' && buf[n - 1] == '\n' && memcmp(buf + n - len - 1, sun->sun_path, len) == 0) { rc |= USED; + if (sscanf(buf, "%*s %*x %*x %lx", &f) < 0 || (f&0x00010000)) + rc |= LISTEN; } } if (ferror(fp)) @@ -796,6 +800,7 @@ static int encode_unused_inet_addr(struct sockaddr *sa, * Returns zero on success; -1 on failure. */ #define ENCF_FRESH 1u +#define ENCF_REUSEADDR 2u static int encode_inet_addr(struct sockaddr_un *sun, const struct sockaddr *sa, unsigned f) @@ -821,6 +826,7 @@ static int encode_inet_addr(struct sockaddr_un *sun, * want an existing socket, then we're done. */ rc = encode_single_inet_addr(sa, sun, 0); + if ((f&ENCF_REUSEADDR) && !(rc&LISTEN)) unlink(sun->sun_path); if ((rc&USED) || (f&ENCF_FRESH)) goto found; /* We're looking for a socket which already exists. This is @@ -1719,6 +1725,9 @@ int bind(int sk, const struct sockaddr *sa, socklen_t len) { struct sockaddr_un sun; int rc; + unsigned f; + int reusep; + socklen_t n; Dpid; D({ char buf[ADDRBUFSZ]; @@ -1734,7 +1743,11 @@ int bind(int sk, const struct sockaddr *sa, socklen_t len) if (fixup_real_ip_socket(sk, sa->sa_family, 0)) return (-1); } else { - encode_inet_addr(&sun, sa, ENCF_FRESH); + f = ENCF_FRESH; + n = sizeof(reusep); + if (!getsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reusep, &n) && reusep) + f |= ENCF_REUSEADDR; + encode_inet_addr(&sun, sa, f); sa = SA(&sun); len = SUN_LEN(&sun); } @@ -1952,7 +1965,7 @@ int getpeername(int sk, struct sockaddr *sa, socklen_t *len) D( fprintf(stderr, "noip(%d): ... GETPEERNAME", pid); ) } D( dump_addrresult(rc, sa, *len); ) - return (0); + return (rc); } int getsockopt(int sk, int lev, int opt, void *p, socklen_t *len)