mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-15 16:15:49 +08:00
Fix missing device binding for few cases
This commit is contained in:
parent
36ae10ad16
commit
5e71f7daff
63
src/common.c
63
src/common.c
@ -683,6 +683,49 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa,
|
||||
|
||||
static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries);
|
||||
|
||||
/* -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){
|
||||
SASIZETYPE size;
|
||||
|
||||
@ -732,25 +775,7 @@ int doconnect(struct clientparam * param){
|
||||
setopts(param->remsock, param->srv->srvsockopts);
|
||||
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||
#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
|
||||
if(extbindtodevice(param, param->remsock)) return 12;
|
||||
#ifdef WITH_UN
|
||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||
#endif
|
||||
|
||||
@ -129,6 +129,7 @@ void * ftpprchild(struct clientparam* param) {
|
||||
clidatasock = INVALID_SOCKET;
|
||||
}
|
||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
||||
*SAPORT(¶m->sincl) = 0;
|
||||
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
||||
if (pasv) {
|
||||
|
||||
@ -391,6 +391,9 @@ int readconfig(FILE * fp);
|
||||
void initcommands(void);
|
||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||
int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range);
|
||||
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);
|
||||
#ifdef WITH_PCRE
|
||||
/* One regular expression implementation for the whole program: the pcre
|
||||
commands and every pattern that carries a pcre: prefix. */
|
||||
|
||||
@ -856,29 +856,11 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
#if defined SO_BINDTODEVICE
|
||||
if(srv.ibindtodevice && srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1)) {
|
||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||
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
|
||||
}
|
||||
#ifdef WITH_UN
|
||||
@ -1032,6 +1014,15 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
setopts(new_sock, srv.cbcsockopts);
|
||||
|
||||
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)) {
|
||||
so._closesocket(so.state, new_sock);
|
||||
new_sock = INVALID_SOCKET;
|
||||
|
||||
@ -185,6 +185,7 @@ void * sockschild(struct clientparam* param) {
|
||||
if(command == 2){
|
||||
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);
|
||||
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -244,6 +245,7 @@ fflush(stderr);
|
||||
#else
|
||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||
#endif
|
||||
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
||||
sin = param->sincl;
|
||||
*SAPORT(&sin) = 0;
|
||||
/* the port the client is told to send its datagrams to */
|
||||
|
||||
@ -121,6 +121,11 @@ int udpbind(struct clientparam *param)
|
||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||
#endif
|
||||
param->remsock = s;
|
||||
if (extbindtodevice(param, param->remsock)) {
|
||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||
param->remsock = INVALID_SOCKET;
|
||||
return 12;
|
||||
}
|
||||
if (bindwithrange(param, param->remsock, ¶m->sinsl, param->extport)) {
|
||||
if (param->extport) {
|
||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user