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(¶m->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 *)¶m->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(¶m->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 *)¶m->sinsl, &size)) {RETURN(21);};
66 if(so._bind(param->clisock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) {
67 RETURN(822);
68 }
69 #else
70 param->clisock = param->srv->srvsock;
71 #endif
72
73 #ifndef NOIPV6
74 memcpy(¶m->sinsl, *SAFAMILY(¶m->req) == AF_INET? (struct sockaddr *)¶m->srv->extsa : (struct sockaddr *)¶m->srv->extsa6, SASIZE(¶m->req));
75 #else
76 memcpy(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req));
77 #endif
78 *SAPORT(¶m->sinsl) = 0;
79 if ((param->remsock=so._socket(SASOCK(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
80 if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->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(¶m->sinsr, ¶m->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