1 /*
2    3APA3A simpliest proxy server
3    (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
4 
5    please read License Agreement
6 
7 */
8 
9 #include "proxy.h"
10 
11 #ifndef PORTMAP
12 #define PORTMAP
13 #endif
14 #ifndef UDP
15 #define UDP
16 #endif
17 #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
18 
19 
20 struct udpmap {
21 	struct udpmap *next;
22 	time_t updated;
23 	SOCKET s;
24 	int single;
25 	unsigned long cliip;
26 	unsigned short cliport;
27 };
28 
29 
udppmchild(struct clientparam * param)30 void * udppmchild(struct clientparam* param) {
31  unsigned char *buf = NULL;
32  int res, i;
33 #ifdef _WIN32
34  SASIZETYPE size;
35  unsigned long ul = 1;
36 #endif
37  struct udpmap *udpmappings = NULL;
38  struct pollfd fds[256];
39 
40 
41  if(!param->hostname && parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) RETURN(100);
42  if (SAISNULL(&param->req)) {
43 	param->srv->fds.events = POLLIN;
44 	RETURN (100);
45  }
46  if(!param->clibuf && (!(param->clibuf=myalloc(UDPBUFSIZE)) || !(param->clibufsize = UDPBUFSIZE))){
47 	param->srv->fds.events = POLLIN;
48 	RETURN (21);
49  }
50  param->cliinbuf = param->clioffset = 0;
51  i = sockrecvfrom(param->srv->srvsock, (struct sockaddr *)&param->sincr, param->clibuf, param->clibufsize, 0);
52  if(i<=0){
53 	param->srv->fds.events = POLLIN;
54 	RETURN (214);
55  }
56  param->cliinbuf = i;
57 
58 #ifdef _WIN32
59 	if((param->clisock=so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
60 		RETURN(818);
61 	}
62 	if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (char *)&ul, sizeof(int))) {RETURN(820);};
63 	ioctlsocket(param->clisock, FIONBIO, &ul);
64 	size = sizeof(param->sinsl);
65 	if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sinsl, &size)) {RETURN(21);};
66 	if(so._bind(param->clisock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {
67 		RETURN(822);
68 	}
69 #else
70 	param->clisock = param->srv->srvsock;
71 #endif
72 
73 #ifndef NOIPV6
74  memcpy(&param->sinsl, *SAFAMILY(&param->req) == AF_INET? (struct sockaddr *)&param->srv->extsa : (struct sockaddr *)&param->srv->extsa6, SASIZE(&param->req));
75 #else
76  memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req));
77 #endif
78  *SAPORT(&param->sinsl) = 0;
79  if ((param->remsock=so._socket(SASOCK(&param->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
80  if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {RETURN (12);}
81 #ifdef _WIN32
82 	ioctlsocket(param->remsock, FIONBIO, &ul);
83 #else
84 	fcntl(param->remsock,F_SETFL,O_NONBLOCK | fcntl(param->remsock,F_GETFL));
85 #endif
86  memcpy(&param->sinsr, &param->req, sizeof(param->req));
87 
88  param->operation = UDPASSOC;
89  if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
90  if(param->srv->singlepacket) {
91 	param->srv->fds.events = POLLIN;
92  }
93 
94  param->res = mapsocket(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]);
95  if(!param->srv->singlepacket) {
96 	param->srv->fds.events = POLLIN;
97  }
98 
99 CLEANRET:
100 
101  if(buf)myfree(buf);
102  dolog(param, NULL);
103 #ifndef _WIN32
104  param->clisock = INVALID_SOCKET;
105 #endif
106  freeparam(param);
107  return (NULL);
108 }
109 
110 #ifdef WITHMAIN
111 struct proxydef childdef = {
112 	udppmchild,
113 	0,
114 	1,
115 	S_UDPPM,
116 	" -s single packet UDP service for request/reply (DNS-like) services\n"
117 };
118 #include "proxymain.c"
119 #endif
120