/* udp_repeater - Copyright (C) 1999,2006 Robin Gareus This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: repeater_udp.c,v 1.1.1.1 2006/07/16 11:24:50 rgareus Exp $ */ #include #include #include #include #include #include #include #include #include #include typedef struct { int sock; struct sockaddr_in server, from; char *hostname; // debug info int port; // debug info } remoteconnection; void usage (char *name) { fprintf(stderr, " usage: %s -d \n",name); fprintf(stderr, " UDP dumper - listen on a local UDP port and dump\n raw data to STDOUT\n"); fprintf(stderr, " usage: %s [host]: [ [host]: ]* \n",name); fprintf(stderr, " UDP repeater - this program listens on a local UDP port and \n forwards messages to one or more UDP ports.\n Not specifiying a hostname is equivalent to 'localhost'\n example: %s 3333 :3334 :3335 192.168.6.66:666 receiver.jails.org:3333\n", name); exit(0); } int splithp (char *arg, char **host, int *port) { char *tmp = strchr(arg,':'); if (!tmp) return (1); *tmp=0; if (port) *port= atoi(tmp+1); if (host) { if (arg == tmp) *host=strdup("localhost"); else *host= strdup(arg); } *tmp=':'; return (0); } void error(const char *format,...) { va_list arglist; char text[BUFSIZ]; va_start(arglist, format); vsnprintf(text, BUFSIZ, format, arglist); va_end(arglist); text[BUFSIZ -1] =0; perror(text); exit(0); } int open_rc(remoteconnection *rc, char *host, int port) { struct hostent *hp; rc->sock= socket(AF_INET, SOCK_DGRAM, 0); if (rc->sock < 0) error("socket"); rc->server.sin_family = AF_INET; hp = gethostbyname(host); if (hp==0) error("Unknown host: '%s'",host); memmove((char *)&rc->server.sin_addr,(char *)hp->h_addr, hp->h_length); rc->server.sin_port = htons(port); return(0); } int send_rc (remoteconnection *rc, char *buffer, size_t len) { int n; socklen_t length = sizeof(struct sockaddr_in); n=sendto(rc->sock,buffer, len,0,(struct sockaddr *)&(rc->server),length); if (n < 0) error("Sendto (%s:%i)",rc->hostname,rc->port); return (0); } int main(int argc, char *argv[]) { int want_dump = 0; int sock, n; size_t length, fromlen; struct sockaddr_in server; struct sockaddr_in from; char buf[BUFSIZ]; int lport = 3333; int i = 2; remoteconnection *rc = NULL; if (argc < 3) { usage(argv[0]); } lport = atoi(argv[1]); // printf(" read from ANY LOCAL INTERFACE p:%i\n",lport); rc=calloc((argc-2),sizeof(remoteconnection)); if (argc == 3 && !strncmp(argv[2],"-d",2)) { want_dump = 1; printf("raw data dump mode!\n"); argc=2; } for (i=2; i < argc; i++) { char *hostname=NULL; int port=0; if(!splithp(argv[i],&hostname,&port)) { open_rc(&(rc[(i-2)]),hostname,port); rc[(i-2)].port=port; rc[(i-2)].hostname=hostname; //printf(" dup to h:%s p:%i\n",hostname,port); //free(hostname); } } sock=socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) error("Opening socket"); length = sizeof(server); bzero(&server,length); server.sin_family=AF_INET; server.sin_addr.s_addr=INADDR_ANY; server.sin_port=htons(lport); if (bind(sock,(struct sockaddr *)&server,length)<0) error("binding to port %i failed.",lport); fromlen = sizeof(struct sockaddr_in); while (1) { n = recvfrom(sock,buf,BUFSIZ,0,(struct sockaddr *)&from,&fromlen); if (want_dump) { write(1,"Received a datagram: ",21); write(1,buf,n); printf("\n"); } if (n < 0) error("recvfrom"); for (i=2; i < argc; i++) { send_rc(&(rc[i-2]),buf,n); } } return (0); }