udp_test_proxy.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * $Id$
  3. *
  4. *
  5. * Copyright (C) 2001-2003 FhG Fokus
  6. *
  7. * This file is part of ser, a free SIP server.
  8. *
  9. * ser is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * For a license to use the ser software under conditions
  15. * other than those described here, or to purchase support for this
  16. * software, please contact iptel.org by e-mail at the following addresses:
  17. * [email protected]
  18. *
  19. * ser is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27. */
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <errno.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <netdb.h>
  34. #include <unistd.h>
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <arpa/inet.h>
  39. static char *id="$Id$";
  40. static char *version="udp_test_proxy 0.1";
  41. static char* help_msg="\
  42. Usage: udp_test_proxy -l address -s port -d address -p port [-n no] [-v]\n\
  43. Options:\n\
  44. -l address listen address\n\
  45. -s port listen(source) port\n\
  46. -d address destination address\n\
  47. -p port destination port\n\
  48. -n no number of processes\n\
  49. -2 use a different socket for sending\n\
  50. -v increase verbosity level\n\
  51. -V version number\n\
  52. -h this help message\n\
  53. ";
  54. #define BUF_SIZE 65535
  55. static char buf[BUF_SIZE];
  56. int main(int argc, char** argv)
  57. {
  58. int sock;
  59. int s_sock;
  60. pid_t pid;
  61. struct sockaddr_in addr;
  62. struct sockaddr_in to;
  63. int r, n, len;
  64. char c;
  65. struct hostent* he;
  66. int verbose;
  67. int sport, dport;
  68. char *dst;
  69. char *src;
  70. char* tmp;
  71. int use_diff_ssock;
  72. /* init */
  73. verbose=0;
  74. dst=0;
  75. sport=dport=0;
  76. src=dst=0;
  77. n=0;
  78. use_diff_ssock=0;
  79. opterr=0;
  80. while ((c=getopt(argc,argv, "l:p:d:s:n:2vhV"))!=-1){
  81. switch(c){
  82. case '2':
  83. use_diff_ssock=1;
  84. break;
  85. case 'v':
  86. verbose++;
  87. break;
  88. case 'd':
  89. dst=optarg;
  90. break;
  91. case 'l':
  92. src=optarg;
  93. break;
  94. case 'p':
  95. dport=strtol(optarg, &tmp, 10);
  96. if ((tmp==0)||(*tmp)){
  97. fprintf(stderr, "bad port number: -p %s\n", optarg);
  98. goto error;
  99. }
  100. break;
  101. case 's':
  102. sport=strtol(optarg, &tmp, 10);
  103. if ((tmp==0)||(*tmp)){
  104. fprintf(stderr, "bad port number: -s %s\n", optarg);
  105. goto error;
  106. }
  107. break;
  108. case 'n':
  109. n=strtol(optarg, &tmp, 10);
  110. if ((tmp==0)||(*tmp)){
  111. fprintf(stderr, "bad process number: -n %s\n", optarg);
  112. goto error;
  113. }
  114. break;
  115. case 'V':
  116. printf("version: %s\n", version);
  117. printf("%s\n",id);
  118. exit(0);
  119. break;
  120. case 'h':
  121. printf("version: %s\n", version);
  122. printf("%s", help_msg);
  123. exit(0);
  124. break;
  125. case '?':
  126. if (isprint(optopt))
  127. fprintf(stderr, "Unknown option `-%c´\n", optopt);
  128. else
  129. fprintf(stderr, "Unknown character `\\x%x´\n", optopt);
  130. goto error;
  131. case ':':
  132. fprintf(stderr, "Option `-%c´ requires an argument.\n",
  133. optopt);
  134. goto error;
  135. break;
  136. default:
  137. abort();
  138. }
  139. }
  140. /* check if all the required params are present */
  141. if (dst==0){
  142. fprintf(stderr, "Missing destination (-d ...)\n");
  143. exit(-1);
  144. }
  145. if (src==0){
  146. fprintf(stderr, "Missing listen address (-l ...)\n");
  147. exit(-1);
  148. }
  149. if(sport==0){
  150. fprintf(stderr, "Missing source port number (-s port)\n");
  151. exit(-1);
  152. }else if(sport<0){
  153. fprintf(stderr, "Invalid source port number (-s %d)\n", sport);
  154. exit(-1);
  155. }
  156. if(dport==0){
  157. fprintf(stderr, "Missing destination port number (-p port)\n");
  158. exit(-1);
  159. }else if(dport<0){
  160. fprintf(stderr, "Invalid destination port number (-p %d)\n", dport);
  161. exit(-1);
  162. }
  163. if(n<0){
  164. fprintf(stderr, "Invalid process no (-n %d)\n", n);
  165. exit(-1);
  166. }
  167. /* resolve destination */
  168. he=gethostbyname(dst);
  169. if (he==0){
  170. fprintf(stderr, "ERROR: could not resolve %s\n", dst);
  171. goto error;
  172. }
  173. /* set to*/
  174. to.sin_family=he->h_addrtype;
  175. to.sin_port=htons(dport);
  176. memcpy(&to.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
  177. /* resolve source/listen */
  178. he=gethostbyname(src);
  179. if (he==0){
  180. fprintf(stderr, "ERROR: could not resolve %s\n", dst);
  181. goto error;
  182. }
  183. /* open socket*/
  184. addr.sin_family=he->h_addrtype;
  185. addr.sin_port=htons(sport);
  186. memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
  187. s_sock=-1;
  188. sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
  189. if (use_diff_ssock && (sock!=-1))
  190. s_sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
  191. else
  192. s_sock=sock;
  193. if ((sock==-1)||(s_sock==-1)){
  194. fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
  195. goto error;
  196. }
  197. if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in))==-1){
  198. fprintf(stderr, "ERROR: bind: %s\n", strerror(errno));
  199. goto error;
  200. }
  201. if (use_diff_ssock){
  202. if (connect(s_sock, (struct sockaddr*) &to,
  203. sizeof(struct sockaddr_in))==-1){
  204. fprintf(stderr, "ERROR: connect: %s\n", strerror(errno));
  205. goto error;
  206. }
  207. }
  208. for(r=1; r<n; r++){
  209. if ((pid=fork())==-1){
  210. fprintf(stderr, "ERROR: fork: %s\n", strerror(errno));
  211. goto error;
  212. }
  213. if (pid==0) break; /* child, skip */
  214. }
  215. if (verbose>3) printf("process starting\n");
  216. for(;;){
  217. len=read(sock, buf, BUF_SIZE);
  218. if (len==-1){
  219. fprintf(stderr, "ERROR: read: %s\n", strerror(errno));
  220. continue;
  221. }
  222. if (verbose>2) putchar('r');
  223. /* send it back*/
  224. if (use_diff_ssock)
  225. len=send(s_sock, buf, len, 0);
  226. else
  227. len=sendto(s_sock, buf, len, 0,
  228. (struct sockaddr*) &to, sizeof(struct sockaddr_in));
  229. if (len==-1){
  230. fprintf(stderr, "ERROR: send: %s\n", strerror(errno));
  231. continue;
  232. }
  233. if (verbose>1) putchar('.');
  234. }
  235. error:
  236. exit(-1);
  237. }