/*
   3APA3A simpliest proxy server
   (c) 2002 by ZARAZA <3APA3A@security.nnov.ru>

   please read License Agreement

   $Id: udppm.c,v 1.1.1.1 2003/07/19 11:18:19 vlad Exp $
*/

#include "proxy.h"

#ifndef PORTMAP
#define PORTMAP
#endif
#ifndef UDP
#define UDP
#endif
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }

#define child udppmchild

#define SERVICE S_UDPPM

#define BUFSIZE 65536

void * child(void * data) {
#define param ((struct clientparam*)data)
 unsigned long ip;
 unsigned char *buf=NULL;
 SASIZETYPE size;
 int res, i;

 ip=getip(param->target);
 if (! ip) {RETURN (100);}
 param->sins.sin_family = AF_INET;
 param->sins.sin_port = htons(0);
 param->sins.sin_addr.s_addr = param->extip;
 if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
 if(bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {RETURN (12);}
 param->sins.sin_addr.s_addr = ip;
 param->sins.sin_port = htons(param->targetport);
 size = sizeof(param->sinc);
 if(!(buf = malloc(BUFSIZE))){RETURN (21);}
 i = recvfrom(param->clisock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sinc, &size);
 if(param->singlepacket) FD_SET(param->clisock, param->srvfds);
 if(i<=0){RETURN (214);}
 param->statscli+=i;
 param->operation = UDPASSOC;
 if((res = (*param->authfunc)(param))) {RETURN(res);}
 res=sendto(param->remsock, buf, i, 0, (struct sockaddr *)&param->sins, sizeof(param->sins));
 if(res <= 0) {RETURN (215);}

 RETURN (sockmap(param, timeouts[(param->singlepacket)?SINGLEBYTE_L:STRING_L]));
CLEANRET:

 if(buf) free(buf);
 if(!param->singlepacket) FD_SET(param->clisock, param->srvfds);
 (*param->logfunc)(param, NULL);
 param->clisock = INVALID_SOCKET;
 freeparam(param);
 return (NULL);
}

#ifdef WITHMAIN
#include "proxymain.c"
#endif
