mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-30 14:45:49 +08:00
Compare commits
No commits in common. "371d8396b4a24361f0cb0797df3df7e78824b5af" and "a07665c01f4b307ebcc7b16b0178ca75cdf534cc" have entirely different histories.
371d8396b4
...
a07665c01f
30
CHANGELOG
30
CHANGELOG
@ -1,14 +1,18 @@
|
|||||||
3proxy-0.9.9.1 Released October, 10 2026
|
3proxy-0.9.9 Released August, 20 2026
|
||||||
|
|
||||||
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
! Fix: DNS replies are validated now: a reply from an address other than the nameserver the query was sent to, and a reply with a question section not matching the query, are dropped; both were accepted before
|
||||||
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
! Fix: socket leak with SOCKSv5 UDP ASSOCIATE through a parent proxy, sockets were accumulated in CLOSE_WAIT state until descriptors ran out
|
||||||
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
! Fix: file descriptor leak in HTTP proxy on the ftp:// request path
|
||||||
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
! Fix: crash with illegal instruction on some platforms (e.g. some musl based Linux builds), caused by a memcpy on overlapping buffers
|
||||||
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
! Fix: extip and ha (HAProxy PROXY protocol) parents are applied to SOCKSv5 UDP ASSOCIATE now
|
||||||
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
! Fix: only socks5 and socks5+ parents are tried for UDP ASSOCIATE, other parent types can not be used for UDP
|
||||||
! Fix: pcre_extend did nothing, the rules it appended were never consulted
|
! Fix: udppm through a SOCKSv5 parent did not work
|
||||||
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
! Fix: -Ne and -Ni options were never applied, the option letter was not parsed; -Ne is not applied to the UDP ASSOCIATE reply anymore, -Ni is applied to it
|
||||||
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
! Fix: -4 / -6 handling for UDP in socks; a single UDP association can use both IPv4 and IPv6 destinations now
|
||||||
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
! Fix: a datagram with a null destination address is dropped now
|
||||||
! Fix: dnspr did not work on Windows, the socket it answers from could not be bound
|
! Fix: DNS over TCP: a reply which did not fit a single read was never processed
|
||||||
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
! Documentation: "How to apply ACLs to UDP traffic" added to HOWTO; authentication cache, ACL and UDP notes added to "Optimizing 3proxy for High Load" and to security recommendations
|
||||||
|
+ SOCKSv5 UDP: the destination of every datagram is authorized, so ACLs limiting the destination address, host name or port apply to UDP traffic now; the parent proxy and the external address are selected for the destination of the datagram and not for the UDP ASSOCIATE request
|
||||||
|
+ socks: -U option to control what happens when the destination changes within an UDP association: log it, authorize it, both (default) or neither
|
||||||
|
+ -C option (for TCP services) to terminate the session as soon as any of the sides closes the connection; by default the session is kept until both sides close it (TCP half-close)
|
||||||
|
+ timeouts: LINGER value added (11th, default 5), used to deliver buffered data after one of the sides has closed its sending side and as SO_LINGER value on outgoing connections
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
3proxy-0.9.9.1 Вышел 10 Октября 2026
|
3proxy-0.9.9 Вышел 20 Августа 2026
|
||||||
|
|
||||||
! Исправление: падение (segmentation fault) при перезагрузке конфигурации (SIGUSR1) на нагруженном сервере: закрывающаяся сессия могла обращаться к службе после того, как перезагрузка её освободила; гонка существовала с 0.9.7, а добавленная в 0.9.9 задержка закрытия (linger) в 5 секунд сделала её гораздо вероятнее (#1278)
|
! Исправление: ответы DNS теперь проверяются: ответ с адреса, отличного от адреса сервера имён, которому был отправлен запрос, а также ответ с секцией вопроса, не совпадающей с запросом, отбрасываются; ранее оба принимались
|
||||||
! Исправление: -Di и -De (привязка к интерфейсу) не применялись к сокетам SOCKSv5 UDP ASSOCIATE и BIND, к соединению данных FTP прокси и к обратному соединению (connect back) (#1277)
|
! Исправление: утечка сокетов при SOCKSv5 UDP ASSOCIATE через вышестоящий прокси, сокеты накапливались в состоянии CLOSE_WAIT до исчерпания дескрипторов
|
||||||
! Исправление: SOCKSv5 UDP ASSOCIATE по IPv6: адрес отправителя датаграммы обрезался, и ответ отправлялся не на тот адрес (#1279)
|
! Исправление: утечка файловых дескрипторов в HTTP-прокси на пути обработки запроса ftp://
|
||||||
! Исправление: SOCKSv5 UDP ASSOCIATE: правило доступа с именами хостов срабатывало для любой датаграммы, отправленной на адрес, а не на имя; теперь адрес используется как имя хоста, так же как для запросов TCP
|
! Исправление: аварийное завершение с недопустимой инструкцией на некоторых платформах (например, в некоторых сборках Linux на основе musl) из-за memcpy на перекрывающихся буферах
|
||||||
! Исправление: буфера могло не хватить для заголовков, добавляемых HTTP прокси, после того как pcre_rewrite увеличил запрос
|
! Исправление: родители типа extip и ha (HAProxy PROXY protocol) теперь применяются к SOCKSv5 UDP ASSOCIATE
|
||||||
! Исправление: переполнение буфера в куче в pcre_rewrite: ссылка $N на группу, не участвовавшую в совпадении, выводилась своими цифрами, которые не учитывались при выделении памяти под результат
|
! Исправление: для UDP ASSOCIATE используются только родители socks5 и socks5+, остальные типы для UDP неприменимы
|
||||||
! Исправление: pcre_extend ничего не делал, добавленные им правила никогда не проверялись
|
! Исправление: udppm через вышестоящий прокси SOCKSv5 не работал
|
||||||
! Исправление: сертификаты, создаваемые для TLS MitM (openssl), не содержали идентификаторов ключа субъекта и издателя и отвергались строгой проверкой, в том числе клиентами macOS, OpenSSL с x509_strict и Python 3.13
|
! Исправление: опции -Ne и -Ni никогда не применялись, буква опции не разбиралась; -Ne больше не применяется к ответу на UDP ASSOCIATE, -Ni применяется к нему
|
||||||
! Исправление: обращение по нулевому указателю в ftppr при PASS без USER и в smtpp при имени пользователя без хоста
|
! Исправление: обработка -4 / -6 для UDP в socks; одна UDP-ассоциация теперь может использовать адреса назначения и IPv4, и IPv6
|
||||||
! Исправление: с wolfSSL на glibc не запускалась ни одна служба: стека потока по умолчанию не хватало для thread-local памяти wolfSSL, pthread_create() завершался ошибкой, о которой не сообщалось
|
! Исправление: датаграмма с нулевым адресом назначения теперь отбрасывается
|
||||||
! Исправление: dnspr не работал в Windows, сокет, с которого он отвечает, не удавалось привязать
|
! Исправление: DNS поверх TCP: ответ, не помещавшийся в одно чтение, никогда не обрабатывался
|
||||||
- Двоичные файлы для Windows больше не подписываются самоподписанным сертификатом Authenticode: доверия он не давал и вызывал ложные срабатывания антивирусов
|
! Документация: в HOWTO добавлен раздел "Как применять ACL к UDP-трафику"; в "Optimizing 3proxy for High Load" и в рекомендации по безопасности добавлены заметки о кэше аутентификации, ACL и UDP
|
||||||
|
+ SOCKSv5 UDP: адрес назначения каждой датаграммы авторизуется, поэтому ACL, ограничивающие адрес назначения, имя хоста или порт, теперь применяются к UDP-трафику; вышестоящий прокси и внешний адрес выбираются для адреса назначения датаграммы, а не для запроса UDP ASSOCIATE
|
||||||
|
+ socks: опция -U для управления тем, что происходит при смене адреса назначения в рамках UDP-ассоциации: журналировать, авторизовать, и то и другое (по умолчанию) или ничего
|
||||||
|
+ Опция -C (для TCP-сервисов) завершает сессию, как только любая из сторон закрывает соединение; по умолчанию сессия сохраняется, пока соединение не закроют обе стороны (полузакрытие TCP)
|
||||||
|
+ timeouts: добавлено значение LINGER (11-е, по умолчанию 5), используется для доставки буферизованных данных после того, как одна из сторон закрыла свою передающую сторону, а также как значение SO_LINGER для исходящих соединений
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,9 +1,3 @@
|
|||||||
3proxy (0.9.9.1-1) buster; urgency=medium
|
|
||||||
|
|
||||||
*3proxy 0.9.9.1 initial build
|
|
||||||
|
|
||||||
-- z3APA3A <3apa3a@3proxy.org> Sat, 10 Oct 2026 16:57:17 +0000
|
|
||||||
|
|
||||||
3proxy (0.9.9.0-1) buster; urgency=medium
|
3proxy (0.9.9.0-1) buster; urgency=medium
|
||||||
|
|
||||||
*3proxy 0.9.9.0 initial build
|
*3proxy 0.9.9.0 initial build
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
|
||||||
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
|
||||||
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
|
||||||
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
|
||||||
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
|
||||||
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
|
||||||
! Fix: pcre_extend did nothing, the rules it appended were never consulted
|
|
||||||
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
|
||||||
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
|
||||||
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
|
||||||
! Fix: dnspr did not work on Windows, the socket it answers from could not be bound
|
|
||||||
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
Name: 3proxy
|
Name: 3proxy
|
||||||
Version: 0.9.9.1
|
Version: 0.9.9.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: 3proxy tiny proxy server
|
Summary: 3proxy tiny proxy server
|
||||||
License: GPL/LGPL/Apache/BSD
|
License: GPL/LGPL/Apache/BSD
|
||||||
|
|||||||
63
src/common.c
63
src/common.c
@ -677,49 +677,6 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -Di / -De: ties a socket to the interface asked for, for TCP and UDP alike.
|
|
||||||
Where the option is set per protocol, family is the one of the address the
|
|
||||||
socket will be bound to. */
|
|
||||||
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family){
|
|
||||||
if(!device) return 0;
|
|
||||||
#if defined SO_BINDTODEVICE
|
|
||||||
if(sf->_setsockopt(state, sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1))
|
|
||||||
return 1;
|
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(device);
|
|
||||||
if(!idx || (family == AF_INET && sf->_setsockopt(state, sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
|
||||||
return 1;
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if(family == AF_INET6 && sf->_setsockopt(state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the external side, a socket to be bound to sinsl */
|
|
||||||
int extbindtodevice(struct clientparam *param, SOCKET sock){
|
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->obindtodevice, *SAFAMILY(¶m->sinsl));
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the internal side, a socket to be bound to sincl */
|
|
||||||
int intbindtodevice(struct clientparam *param, SOCKET sock){
|
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->ibindtodevice, *SAFAMILY(¶m->sincl));
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int doconnect(struct clientparam * param){
|
int doconnect(struct clientparam * param){
|
||||||
SASIZETYPE size;
|
SASIZETYPE size;
|
||||||
|
|
||||||
@ -767,7 +724,25 @@ int doconnect(struct clientparam * param){
|
|||||||
setopts(param->remsock, param->srv->srvsockopts);
|
setopts(param->remsock, param->srv->srvsockopts);
|
||||||
|
|
||||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||||
if(extbindtodevice(param, param->remsock)) return 12;
|
#if defined SO_BINDTODEVICE
|
||||||
|
if(param->srv->obindtodevice) {
|
||||||
|
if(param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
if(param->srv->obindtodevice) {
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(param->srv->obindtodevice);
|
||||||
|
if(!idx || (*SAFAMILY(¶m->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
||||||
|
return 12;
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if(*SAFAMILY(¶m->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -127,7 +127,6 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
clidatasock = INVALID_SOCKET;
|
clidatasock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||||
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
|
||||||
*SAPORT(¶m->sincl) = 0;
|
*SAPORT(¶m->sincl) = 0;
|
||||||
if(param->srv->so._bind(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, SASIZE(¶m->sincl))){RETURN(822);}
|
if(param->srv->so._bind(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, SASIZE(¶m->sincl))){RETURN(822);}
|
||||||
if (pasv) {
|
if (pasv) {
|
||||||
|
|||||||
@ -369,9 +369,6 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
|
|||||||
int readconfig(FILE * fp);
|
int readconfig(FILE * fp);
|
||||||
void initcommands(void);
|
void initcommands(void);
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||||
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
|
||||||
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
|
||||||
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t myrand(void);
|
uint32_t myrand(void);
|
||||||
|
|||||||
@ -844,11 +844,29 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
#if defined SO_BINDTODEVICE
|
||||||
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
if(srv.ibindtodevice && srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1)) {
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
return -12;
|
return -12;
|
||||||
}
|
}
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
if(srv.ibindtodevice){
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(srv.ibindtodevice);
|
||||||
|
if(!idx || (*SAFAMILY(&srv.intsa) == AF_INET && setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
return -12;
|
||||||
|
}
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
return -12;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
@ -1002,15 +1020,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
setopts(new_sock, srv.cbcsockopts);
|
setopts(new_sock, srv.cbcsockopts);
|
||||||
|
|
||||||
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
/* as for a listening socket, an interface that cannot be
|
|
||||||
bound to is not worth retrying */
|
|
||||||
if(bindtodevice(&so, so.state, new_sock, srv.ibindtodevice, *SAFAMILY(&defparam.sincr))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
so._closesocket(so.state, new_sock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
||||||
so._closesocket(so.state, new_sock);
|
so._closesocket(so.state, new_sock);
|
||||||
new_sock = INVALID_SOCKET;
|
new_sock = INVALID_SOCKET;
|
||||||
@ -1321,16 +1330,7 @@ void srvfree(struct srvparam * srv){
|
|||||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||||
srv->cbsock = INVALID_SOCKET;
|
srv->cbsock = INVALID_SOCKET;
|
||||||
srv->service = S_ZOMBIE;
|
srv->service = S_ZOMBIE;
|
||||||
/* under the mutex, so the last child has let go of it before it is destroyed */
|
while(srv->child) usleep(SLEEPTIME * 100);
|
||||||
for(;;){
|
|
||||||
struct clientparam *child;
|
|
||||||
|
|
||||||
_3proxy_mutex_lock(&srv->counter_mutex);
|
|
||||||
child = srv->child;
|
|
||||||
_3proxy_mutex_unlock(&srv->counter_mutex);
|
|
||||||
if(!child) break;
|
|
||||||
usleep(SLEEPTIME * 100);
|
|
||||||
}
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(srv->filter){
|
if(srv->filter){
|
||||||
while(srv->nfilters){
|
while(srv->nfilters){
|
||||||
@ -1372,13 +1372,22 @@ void srvfree(struct srvparam * srv){
|
|||||||
void freeparam(struct clientparam * param) {
|
void freeparam(struct clientparam * param) {
|
||||||
if(param->srv){
|
if(param->srv){
|
||||||
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
||||||
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(param->srv->service == S_UDPPM){
|
if(param->srv->service == S_UDPPM) hashdelete(&udp_table, param);
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
|
||||||
hashdelete(&udp_table, param);
|
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
if(param->prev || param->next || param->srv->child == param){
|
||||||
|
if(param->prev){
|
||||||
|
param->prev->next = param->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
param->srv->child = param->next;
|
||||||
|
if(param->next){
|
||||||
|
param->next->prev = param->prev;
|
||||||
|
}
|
||||||
|
(param->srv->childcount)--;
|
||||||
|
}
|
||||||
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
}
|
}
|
||||||
if(param->clibuf) free(param->clibuf);
|
if(param->clibuf) free(param->clibuf);
|
||||||
if(param->srvbuf) free(param->srvbuf);
|
if(param->srvbuf) free(param->srvbuf);
|
||||||
@ -1418,24 +1427,6 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
if(param->connlim) stopconnlims(param);
|
if(param->connlim) stopconnlims(param);
|
||||||
#endif
|
#endif
|
||||||
/* Leaving the service comes last. Once its last child is gone, srvfree()
|
|
||||||
frees the service along with its socket functions, filters and mutex,
|
|
||||||
and a close above may have lingered for seconds before getting here. */
|
|
||||||
if(param->srv){
|
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
|
||||||
if(param->prev || param->next || param->srv->child == param){
|
|
||||||
if(param->prev){
|
|
||||||
param->prev->next = param->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
param->srv->child = param->next;
|
|
||||||
if(param->next){
|
|
||||||
param->next->prev = param->prev;
|
|
||||||
}
|
|
||||||
(param->srv->childcount)--;
|
|
||||||
}
|
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
|
||||||
}
|
|
||||||
if(param->hostname) free(param->hostname);
|
if(param->hostname) free(param->hostname);
|
||||||
if(param->username) free(param->username);
|
if(param->username) free(param->username);
|
||||||
if(param->password) free(param->password);
|
if(param->password) free(param->password);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
|||||||
if(conf.timetoexit) return EOF;
|
if(conf.timetoexit) return EOF;
|
||||||
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
||||||
if (res<1) return 0;
|
if (res<1) return 0;
|
||||||
sasize = sizeof(PROXYSOCKADDRTYPE);
|
sasize = SASIZE(sin);
|
||||||
do {
|
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, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
|
||||||
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
||||||
|
|||||||
@ -185,7 +185,6 @@ void * sockschild(struct clientparam* param) {
|
|||||||
if(command == 2){
|
if(command == 2){
|
||||||
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
||||||
setopts(param->remsock, param->srv->lissockopts);
|
setopts(param->remsock, param->srv->lissockopts);
|
||||||
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -242,7 +241,6 @@ fflush(stderr);
|
|||||||
#else
|
#else
|
||||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
|
||||||
sin = param->sincl;
|
sin = param->sincl;
|
||||||
*SAPORT(&sin) = 0;
|
*SAPORT(&sin) = 0;
|
||||||
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
|
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
|
||||||
|
|||||||
@ -121,11 +121,6 @@ int udpbind(struct clientparam *param)
|
|||||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
param->remsock = s;
|
param->remsock = s;
|
||||||
if (extbindtodevice(param, param->remsock)) {
|
|
||||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
|
||||||
param->remsock = INVALID_SOCKET;
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
if (param->srv->so._bind(param->sostate, param->remsock,
|
if (param->srv->so._bind(param->sostate, param->remsock,
|
||||||
(struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) {
|
(struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) {
|
||||||
*SAPORT(¶m->sinsl) = 0;
|
*SAPORT(¶m->sinsl) = 0;
|
||||||
@ -289,12 +284,6 @@ int udpsockmap(struct clientparam *param, int timeo)
|
|||||||
}
|
}
|
||||||
default: return 997;
|
default: return 997;
|
||||||
}
|
}
|
||||||
/* As for TCP requests, a literal address is the host name,
|
|
||||||
otherwise an ACL with host names only matches any address */
|
|
||||||
if (!dstname) {
|
|
||||||
myinet_ntop(*SAFAMILY(&dst), SAADDR(&dst), dstnamebuf, sizeof(dstnamebuf));
|
|
||||||
dstname = dstnamebuf;
|
|
||||||
}
|
|
||||||
memcpy(SAPORT(&dst), base + i, 2);
|
memcpy(SAPORT(&dst), base + i, 2);
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "3proxy-0.9.9.1"
|
#define VERSION "3proxy-0.9.9.0"
|
||||||
#endif
|
#endif
|
||||||
#ifndef BUILDDATE
|
#ifndef BUILDDATE
|
||||||
#define BUILDDATE "261010165717"
|
#define BUILDDATE ""
|
||||||
#endif
|
#endif
|
||||||
#define MAJOR3PROXY 0
|
#define MAJOR3PROXY 0
|
||||||
#define SUBMAJOR3PROXY 9
|
#define SUBMAJOR3PROXY 9
|
||||||
#define MINOR3PROXY 9
|
#define MINOR3PROXY 9
|
||||||
#define SUBMINOR3PROXY 1
|
#define SUBMINOR3PROXY 0
|
||||||
#define RELEASE3PROXY "3proxy-0.9.9.1(" BUILDDATE ")\0"
|
#define RELEASE3PROXY "3proxy-0.9.9.0(" BUILDDATE ")\0"
|
||||||
#ifndef YEAR3PROXY
|
#ifndef YEAR3PROXY
|
||||||
#define YEAR3PROXY "2026"
|
#define YEAR3PROXY "2026"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user