diff --git a/src/proxymain.c b/src/proxymain.c index ae67926..03c65ed 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -7,6 +7,31 @@ */ #include "proxy.h" + +#ifdef WITH_UN +/* A service bound to a Unix socket path notes its file, as a service of a + newer configuration may bind the same path before this one closes: the + file is then the other's, which closing must not remove. */ +static void unbound(struct srvparam *srv){ + struct stat st; + + if(*SAFAMILY(&srv->intsa) == AF_UNIX && *SAADDR(&srv->intsa) && + !stat((char *)SAADDR(&srv->intsa), &st)){ + srv->undev = (uint64_t)st.st_dev; + srv->unino = (uint64_t)st.st_ino; + } +} + +static void ununlink(struct srvparam *srv){ + struct stat st; + + if(*SAFAMILY(&srv->intsa) == AF_UNIX && *SAADDR(&srv->intsa) && + !stat((char *)SAADDR(&srv->intsa), &st) && + (uint64_t)st.st_dev == srv->undev && (uint64_t)st.st_ino == srv->unino) + unlink((char *)SAADDR(&srv->intsa)); +} +#endif + #ifdef __linux__ #include #endif @@ -84,7 +109,7 @@ void * threadfunc (void *p) { continue; } #endif - if(socksendto(param, param->remsock, (struct sockaddr*)¶m->sinsr, (unsigned char *)"C", 1, CONNBACK_TO*1000) != 1){ + if(socksend(param, param->remsock, (unsigned char *)"C", 1, CONNBACK_TO) != 1){ dolog(param, (unsigned char *)"Connect back sending command failed"); param->srv->so._closesocket(param->sostate, param->remsock); param->remsock = INVALID_SOCKET; @@ -687,7 +712,12 @@ int MODULEMAINFUNC (int argc, char** argv){ else { #endif #ifndef NOPORTMAP - if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((uint16_t)atoi(argv[i])))==0 || (srv.targetport = htons((uint16_t)atoi(argv[i+2])))==0) { + /* the port of a Unix socket target is ignored, 0 as the manual has it */ + if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((uint16_t)atoi(argv[i])))==0 || ((srv.targetport = htons((uint16_t)atoi(argv[i+2])))==0 +#ifdef WITH_UN + && strncmp(argv[i+1], "unix:", 5) +#endif + )) { #ifndef STDMAIN haveerror = 1; #endif @@ -870,6 +900,9 @@ int MODULEMAINFUNC (int argc, char** argv){ return -3; } } +#ifdef WITH_UN + unbound(&srv); +#endif if(!isudp){ if(srv.so._listen (srv.so.state, sock, srv.backlog?srv.backlog : 1+(srv.maxchild>>3))==-1) { sprintf((char *)buf, "listen(): %s", strerror(errno)); @@ -1020,7 +1053,7 @@ int MODULEMAINFUNC (int argc, char** argv){ continue; } - if(sockrecvfrom(NULL, new_sock,(struct sockaddr*)&defparam.sincr,buf,1,60*1000) != 1 || *buf!='C') { + if(sockrecvfrom(NULL, new_sock, NULL, buf, 1, 60*1000) != 1 || *buf!='C') { so._closesocket(so.state, new_sock); new_sock = INVALID_SOCKET; usleep(SLEEPTIME); @@ -1320,7 +1353,7 @@ void srvfree(struct srvparam * srv){ if(srv->srvsock != INVALID_SOCKET) { so._closesocket(srv->so.state, srv->srvsock); #ifdef WITH_UN - if(*SAFAMILY(&srv->intsa) == AF_UNIX && *SAADDR(&srv->intsa))unlink((char *)SAADDR(&srv->intsa)); + ununlink(srv); #endif } srv->srvsock = INVALID_SOCKET; diff --git a/src/sockgetchar.c b/src/sockgetchar.c index 56b3b19..18cef3f 100644 --- a/src/sockgetchar.c +++ b/src/sockgetchar.c @@ -64,8 +64,9 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin, res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to); if (res<1) return 0; sasize = sizeof(PROXYSOCKADDRTYPE); + /* sin NULL for a stream socket: nothing to learn the address into */ do { - res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize); + res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, sin? &sasize : NULL):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, sin? &sasize : NULL); } while (res < 0 && (errno == EAGAIN || errno == EINTR)); return res; } diff --git a/src/sockmap.c b/src/sockmap.c index 4fce489..d2c0d0a 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -92,7 +92,6 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){ int sleeptime = 0; FILTER_ACTION action; int res = 0; - SASIZETYPE sasize; int needaction = 0; int graceclinum=0, gracesrvnum=0, graceclitraf=0, gracesrvtraf=0; time_t gracetime = 0; @@ -246,8 +245,7 @@ log("send to server from buf"); param->clioffset = param->cliinbuf = 0; if(fromclient) TOCLIENTBUF = 1; } - sasize = SASIZE(¶m->sinsr); - res = param->srv->so._sendto(param->sostate, param->remsock, (char *)param->clibuf + param->clioffset, (int)MIN(inclientbuf, fromclient), 0, (struct sockaddr*)¶m->sinsr, sasize); + res = param->srv->so._sendto(param->sostate, param->remsock, (char *)param->clibuf + param->clioffset, (int)MIN(inclientbuf, fromclient), 0, NULL, 0); if(res <= 0) { TOSERVER = 0; if(errno && errno != EAGAIN && errno != EINTR){ @@ -293,8 +291,7 @@ log("send to client from buf"); if(fromserver) TOSERVERBUF = 1; continue; } - sasize = SASIZE(¶m->sincr); - res = param->srv->so._sendto(param->sostate, param->clisock, (char *)param->srvbuf + param->srvoffset, (int)MIN(inserverbuf,fromserver), 0, (struct sockaddr*)¶m->sincr, sasize); + res = param->srv->so._sendto(param->sostate, param->clisock, (char *)param->srvbuf + param->srvoffset, (int)MIN(inserverbuf,fromserver), 0, NULL, 0); if(res <= 0) { TOCLIENT = 0; if(errno && errno != EAGAIN && errno != EINTR){ @@ -485,8 +482,7 @@ log("done read from server to pipe\n"); #ifdef WITHLOG log("read from client to buf"); #endif - sasize = sizeof(param->sincr); - res = param->srv->so._recvfrom(param->sostate, param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)param->clibufsize - param->cliinbuf, fromclient-inclientbuf), 0, (struct sockaddr *)¶m->sincr, &sasize); + res = param->srv->so._recvfrom(param->sostate, param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)param->clibufsize - param->cliinbuf, fromclient-inclientbuf), 0, NULL, NULL); if(res <= 0) { FROMCLIENT = 0; if(res == 0) { @@ -518,8 +514,7 @@ log("done read from client to buf"); #ifdef WITHLOG log("read from server to buf"); #endif - sasize = sizeof(param->sinsr); - res = param->srv->so._recvfrom(param->sostate, param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)param->srvbufsize - param->srvinbuf, fromserver-inserverbuf), 0, (struct sockaddr *)¶m->sinsr, &sasize); + res = param->srv->so._recvfrom(param->sostate, param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)param->srvbufsize - param->srvinbuf, fromserver-inserverbuf), 0, NULL, NULL); if(res <= 0) { FROMSERVER = 0; if(res == 0) { diff --git a/src/socks.c b/src/socks.c index 96ab08c..cde98ec 100644 --- a/src/socks.c +++ b/src/socks.c @@ -227,7 +227,7 @@ fprintf(stderr, "%hu bound to communicate with server\n", *SAPORT(¶m->sinsl) fflush(stderr); #endif } - sasize = SASIZE(¶m->sinsl); + sasize = sizeof(param->sinsl); param->srv->so._getsockname(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsl, &sasize); } if(command == 3) { @@ -246,7 +246,7 @@ fflush(stderr); sin = param->sincl; *SAPORT(&sin) = 0; if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);} - sasize = SASIZE(&sin); + sasize = sizeof(sin); param->srv->so._getsockname(param->sostate, param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "%hu binded to communicate with client\n", diff --git a/src/structures.h b/src/structures.h index 21cea79..e119643 100644 --- a/src/structures.h +++ b/src/structures.h @@ -105,6 +105,7 @@ int #ifdef WITH_UN #include +#include #endif #define ALLOW 0 @@ -152,7 +153,9 @@ int #define UN_SAADDR(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (unsigned char *)((struct sockaddr_un *)sa)->sun_path : #define UN_SAADDRLEN(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (int)sizeof(((struct sockaddr_un *)sa)->sun_path) : #define UN_SASOCK(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? PF_UNIX : -#define UN_SASIZE(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? sizeof(struct sockaddr_un) : +/* an abstract name (Linux) is its bytes after the leading 0, no more: + padded with zeros it would be another name */ +#define UN_SASIZE(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (((struct sockaddr_un *)sa)->sun_path[0] || !((struct sockaddr_un *)sa)->sun_path[1]? sizeof(struct sockaddr_un) : offsetof(struct sockaddr_un, sun_path) + 1 + strlen(((struct sockaddr_un *)sa)->sun_path + 1)) : #define UN_SAISNULL(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (((struct sockaddr_un *)sa)->sun_path[0] == 0 && ((struct sockaddr_un *)sa)->sun_path[1] == 0) : #else #define UN_SAPORT(sa) @@ -527,6 +530,8 @@ struct srvparam { AUTHFUNC authfunc; PROXYFUNC pf; SOCKET srvsock, cbsock; + /* the file of a Unix socket bound to a path, to remove only it */ + uint64_t undev, unino; int childcount; int maxchild; int backlog; diff --git a/src/udpsockmap.c b/src/udpsockmap.c index 63c9b73..d9d3811 100644 --- a/src/udpsockmap.c +++ b/src/udpsockmap.c @@ -136,7 +136,7 @@ int udpbind(struct clientparam *param) return 12; } } - sasize = SASIZE(¶m->sinsl); + sasize = sizeof(param->sinsl); param->srv->so._getsockname(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsl, &sasize); return 0;