X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/preload-hacks/blobdiff_plain/97162e5b05244df7dee91813544cd2e1566d881c..54ef96bf3ee587718974b094f64fbff1301cc997:/noip.c diff --git a/noip.c b/noip.c index 45ed9a5..345f325 100644 --- a/noip.c +++ b/noip.c @@ -57,6 +57,11 @@ #include #include +#ifndef SUN_LEN +# define SUN_LEN (sun) \ + (strlen((sun)->sun_path) + offsetof(struct sockaddr_un, sun_path)) +#endif + /*----- Data structures ---------------------------------------------------*/ /* Unix socket status values. */ @@ -800,6 +805,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) @@ -825,6 +831,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 @@ -1120,7 +1127,11 @@ static int do_implicit_bind(int sk, const struct sockaddr *sa, unsigned f) sockaddr_in_range_p(sa, &i->minaddr, &i->maxaddr)) { D( fprintf(stderr, "noip(%d): match!\n", pid); ) addr.sa.sa_family = sa->sa_family; - ipaddr_to_sockaddr(&addr.sa, &i->bindaddr); + switch (i->how) { + case EXPLICIT: ipaddr_to_sockaddr(&addr.sa, &i->bindaddr); break; + case SAME: copy_sockaddr(&addr.sa, sa); break; + } + port_to_sockaddr(&addr.sa, 0); goto found; } } @@ -1723,6 +1734,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]; @@ -1738,7 +1752,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); } @@ -1956,7 +1974,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)