/* pipeudp.c * * a little utility to redirect udp packets to a predifined host. * * Created: Thy May 11 01:34:40 2006 eak * Modified: Wed Aug 30 17:49:27 CEST 2006 eak, added lib_gc */ #include #include #include #include #include #include #include #include #include #include #include #include #include "lib_gc.h" #define uchar unsigned char #define uint unsigned int #define ushort unsigned short #define ulong unsigned long #define false 1 #define true 0 /*#define BUFsz 65535-(8+20) * la taille maximal determine par defaut est de 4096, donc on change ca. */ #define BUFsz 4096 #define TIMEOUT 1000 uint verbose=false; struct Connection { uchar *data; size_t data_len; int sockin; struct sockaddr_in in; int sockout; struct sockaddr_in out; }; void SigINT(void) { exit(1); } char *now() { char *buf; time_t t; struct tm *tptr; buf=malloc(32); t=time(NULL); tptr=localtime(&t); strftime(buf, 32, "%Y%m%d-%H%M%S", tptr); return buf; } void LogCon(char sens, struct sockaddr_in *sin) { fprintf(stdout, "%s %c 0x%08X : %d\n", GC(&LogCon, now()), \ sens, sin->sin_addr.s_addr, ntohs(sin->sin_port)); GCclean(&LogCon); } void Usage(char *prog) { fprintf(stdout, "Usage: %s [-v]\n", prog); } /* send the packet to the remote end, * receive the response * send it back to the source */ int RelayUDP(struct Connection *thisC) { int i; socklen_t sockaddr_len=sizeof(struct sockaddr); struct sockaddr_in base, in; size_t bufsz; thisC->sockout=socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (thisC->sockout<0) { perror("socket"); return -1; } i=TIMEOUT; setsockopt(thisC->sockout, SOL_SOCKET, SO_RCVTIMEO, (char*)&i, sizeof(i)); base.sin_family=AF_INET; base.sin_port=htons(0); base.sin_addr.s_addr=htonl(INADDR_ANY); i=bind(thisC->sockout, (struct sockaddr*)&base, sizeof(struct sockaddr)); if (i!=0) { perror("bind"); return -1; } //////////////////// i=sendto(thisC->sockout, thisC->data, thisC->data_len, 0, (struct sockaddr*)&thisC->out, sockaddr_len); if (i<1) { perror("sendto"); return -1; } if ( verbose ) { LogCon('>', (struct sockaddr_in*)&thisC->out); } //verbose ( LogCon('>', (struct sockaddr_in*)&thisC->out) ); //////////////////// bufsz=recvfrom(thisC->sockout, thisC->data, BUFsz, 0, (struct sockaddr*)&in, &sockaddr_len); if (bufsz<1) { perror("recvfrom"); } close(thisC->sockout); if ( verbose ) { LogCon('<', (struct sockaddr_in*)&in); } //////////////////// i=sendto(thisC->sockin, thisC->data, bufsz, 0, (struct sockaddr*)&thisC->in, sockaddr_len); if (i<1) { perror("sendto"); return -1; } return true; } int main(int ac, char **av) { struct sockaddr_in server, in, out; uchar *buf; int i; size_t bufsz=0; socklen_t sockaddr_len=sizeof(struct sockaddr); struct Connection thisconn; int gsock; if (ac<3) { Usage(av[0]); exit(255); } verbose=0; if (ac>4) { if (av[4][1]=='v') { verbose=1; } } GCinit(); signal(SIGINT, (void*)&SigINT); setvbuf(stdout, (void*)NULL, _IOLBF, 0); out.sin_family=AF_INET; out.sin_port=htons(atoi(av[3])); out.sin_addr.s_addr=inet_addr(av[2]); server.sin_family=AF_INET; server.sin_port=htons(atoi(av[1])); server.sin_addr.s_addr=htonl(INADDR_ANY); gsock=socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); i=bind(gsock, (struct sockaddr*)&server, sizeof(struct sockaddr)); if (i!=0) { perror("bind"); close(gsock); exit(i); } listen(gsock, 5); buf=GC(&main, malloc(BUFsz)); if (buf==NULL) { perror("malloc"); close(gsock); exit(1); } while ( (bufsz=recvfrom(gsock, buf, BUFsz, 0, (struct sockaddr*)&in, &sockaddr_len)) > 0 ) { if (verbose) { LogCon('+', (struct sockaddr_in*)&in); } thisconn.data=buf; thisconn.data_len=bufsz; thisconn.in=in; thisconn.out=out; thisconn.sockin=gsock; thisconn.sockout=0; i=RelayUDP((struct Connection*)&thisconn); if (i