#include #include #include #include #include #include #include #include /* Translate an IP number (ascii) into four number Return -1 if the IP number is invalid. */ static int ipnum_aip24 (const char *aip, int num4[4]) { int ret = 0; for (int i=0; i<4; i++){ if (!isdigit(aip[0])){ ret = -1; break; }else{ int no = num4[i] = atoi(aip); if (no < 0 || no > 255) ret = -1; while (isdigit(*aip)) aip++; if (i < 3){ if (*aip != '.'){ ret = -1; break; } aip++; } } } if (*aip != '\0' && !isspace(*aip)) ret = -1; return ret; } /* Check is a string is valid IP number. if (ishost), check if the IP is not a broadcast or a network address. */ static bool ipnum_validip(const char *aip, bool ishost) { int num4[4]; bool ret = false; if (ipnum_aip24(aip,num4) != -1){ ret = true; if (ishost && (num4[3] == 0 || num4[3] == 255)){ ret = false; } } return ret; } /* Compute an IP number from a string. */ static unsigned long ipnum_aip2l (const char *aip) { unsigned long ret = 0xffffffffl; int n[4]; if (ipnum_aip24(aip,n) != -1){ ret = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3]; } return ret; } static int repeat_sinconnect (struct sockaddr_in &sin, int nbretry) { int ret = -1; for (int i=0; i= 0) { fprintf (stderr,"avantconnect %d\n",s); if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) == -1){ if (i==0){ fprintf (stderr,"Can't connect %d(%s)\n",errno ,strerror(errno)); } close (s); sleep(1); }else{ ret = s; break; } }else{ fprintf (stderr,"Can't build the socket %d(%s)\n",errno ,strerror(errno)); } } return ret; } static int repeat_connect (const char *servname, int port) { int ret = -1; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(port); if (ipnum_validip (servname,true)){ long addr = htonl(ipnum_aip2l (servname)); memcpy (&sin.sin_addr,&addr, sizeof(addr)); ret = repeat_sinconnect (sin,3); }else{ struct hostent *h = (struct hostent *) gethostbyname(servname); if (h == NULL){ fprintf (stderr,"No server \"%s\" defined",servname); }else{ memcpy (&sin.sin_addr,h->h_addr, h->h_length); ret = repeat_sinconnect (sin,3); } } return ret; } static int repeat_setlisten (int port) { int listen_handle = socket (AF_INET, SOCK_DGRAM, 0); struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(port); if (listen_handle == -1){ fprintf (stderr,"listen_handle %d(%s)\n" ,errno,strerror(errno)); #if 0 int opt = 1; }else if (reuseadr && setsockopt(listen_handle,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1){ fprintf (stderr,"Can't set socket option SO_REUSEADDR (%s)\n" ,strerror (errno)); #endif }else if (bind (listen_handle,(struct sockaddr *) &sin, sizeof (sin)) == -1){ fprintf (stderr,"bind %d(%s)\n",errno,strerror(errno)); }else if (listen (listen_handle,5) == -1){ fprintf (stderr,"listen %d(%s)\n",errno,strerror(errno)); }else{ printf ("bind ok\n"); } return listen_handle; } static void usage () { fprintf (stderr,"repeat local_port remote_host remote_port\n"); } int main (int argc, char *argv[]) { if (argc != 4){ usage(); }else{ int fdin = repeat_setlisten (atoi(argv[1])); int fdout = repeat_connect (argv[2],atoi(argv[3])); //printf ("fdin = %d, fdout = %d\n",fdin,fdout); while (1){ char buf[10000]; //int n = read (fdin,buf,sizeof(buf)); struct sockaddr from; int len; int n = recvfrom (fdin,buf,sizeof(buf),0,&from,&len); if (n > 0){ write (fdout,buf,n); }else{ fprintf(stderr,"erreur %d %d (%s)\n",n,errno,strerror(errno)); } } } return 0; }