protoshoot.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /* $Id$ */
  2. /*
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /*
  28. * History:
  29. * 2005-09-09 basic tcp support added (andrei)
  30. */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <errno.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include <netdb.h>
  37. #include <unistd.h>
  38. #include <sys/types.h>
  39. #include <fcntl.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <netinet/tcp.h>
  43. #ifdef USE_SCTP
  44. #include <netinet/sctp.h>
  45. #endif /* USE_SCTP */
  46. #include <arpa/inet.h>
  47. #include <signal.h>
  48. static char *id="$Id$";
  49. static char *version="protoshoot 0.4";
  50. static char* help_msg="\
  51. Usage: protoshoot -f file -d address -p port -c count [-v]\n\
  52. Options:\n\
  53. -f file file with the content of the udp packet (max 65k)\n\
  54. -d address destination address\n\
  55. -p port destination port\n\
  56. -c count number of packets to be sent\n\
  57. -s usec microseconds to sleep before sending \"throttle\" packets\n\
  58. -t throttle number of packets to send before sleeping\n\
  59. -r sleep randomly up to -s usec packets (see -s) \n\
  60. -T use tcp instead of udp \n\
  61. -S use sctp instead of udp \n\
  62. -1 use sctp in one to one mode \n\
  63. -n no tcp connection number \n\
  64. -R close the tcp connections with RST (SO_LINGER) \n\
  65. -v increase verbosity level\n\
  66. -V version number\n\
  67. -h this help message\n\
  68. ";
  69. #define BUF_SIZE 65535
  70. enum protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_SCTP };
  71. int main (int argc, char** argv)
  72. {
  73. int fd;
  74. int sock;
  75. char c;
  76. int n,r;
  77. char* tmp;
  78. char buf[BUF_SIZE];
  79. struct hostent* he;
  80. struct sockaddr_in addr;
  81. int count;
  82. int verbose;
  83. char *fname;
  84. char *dst;
  85. int port;
  86. unsigned long usec;
  87. int throttle;
  88. int random_sleep;
  89. enum protos proto;
  90. int sctp_o2o;
  91. int tcp_rst;
  92. int con_no;
  93. int t;
  94. struct linger t_linger;
  95. int k;
  96. int err;
  97. /* init */
  98. count=1;
  99. verbose=0;
  100. fname=0;
  101. dst="127.0.0.1";
  102. port=5060;
  103. usec=0;
  104. throttle=0;
  105. random_sleep=0;
  106. proto=PROTO_UDP;
  107. tcp_rst=0;
  108. con_no=1;
  109. sctp_o2o=0;
  110. err=0;
  111. opterr=0;
  112. while ((c=getopt(argc,argv, "f:c:d:p:s:t:n:rTS1RvhV"))!=-1){
  113. switch(c){
  114. case 'f':
  115. fname=optarg;
  116. break;
  117. case 'v':
  118. verbose++;
  119. break;
  120. case 'd':
  121. dst=optarg;
  122. break;
  123. case 'p':
  124. port=strtol(optarg, &tmp, 10);
  125. if ((tmp==0)||(*tmp)){
  126. fprintf(stderr, "bad port number: -p %s\n", optarg);
  127. goto error;
  128. }
  129. break;
  130. case 'c':
  131. count=strtol(optarg, &tmp, 10);
  132. if ((tmp==0)||(*tmp)){
  133. fprintf(stderr, "bad count: -c %s\n", optarg);
  134. goto error;
  135. }
  136. break;
  137. case 's':
  138. usec=strtol(optarg, &tmp, 10);
  139. if ((tmp==0)||(*tmp)){
  140. fprintf(stderr, "bad count: -c %s\n", optarg);
  141. goto error;
  142. }
  143. break;
  144. case 't':
  145. throttle=strtol(optarg, &tmp, 10);
  146. if ((tmp==0)||(*tmp)){
  147. fprintf(stderr, "bad count: -c %s\n", optarg);
  148. goto error;
  149. }
  150. break;
  151. case 'n':
  152. con_no=strtol(optarg, &tmp, 10);
  153. if ((tmp==0)||(*tmp)||(con_no<1)){
  154. fprintf(stderr, "bad count: -c %s\n", optarg);
  155. goto error;
  156. }
  157. break;
  158. case 'r':
  159. random_sleep=1;
  160. break;
  161. case 'T':
  162. proto=PROTO_TCP;
  163. break;
  164. case 'S':
  165. #ifdef USE_SCTP
  166. proto=PROTO_SCTP;
  167. #else
  168. fprintf(stderr, "sctp not supported (recompile with "
  169. "-DUSE_SCTP)\n");
  170. goto error;
  171. #endif /* USE_SCTP */
  172. break;
  173. case '1':
  174. sctp_o2o=1;
  175. break;
  176. case 'R':
  177. tcp_rst=1;
  178. break;
  179. case 'V':
  180. printf("version: %s\n", version);
  181. printf("%s\n",id);
  182. exit(0);
  183. break;
  184. case 'h':
  185. printf("version: %s\n", version);
  186. printf("%s", help_msg);
  187. exit(0);
  188. break;
  189. case '?':
  190. if (isprint(optopt))
  191. fprintf(stderr, "Unknown option '-%c'\n", optopt);
  192. else
  193. fprintf(stderr, "Unknown character '\\x%x'\n", optopt);
  194. goto error;
  195. case ':':
  196. fprintf(stderr, "Option '-%c' requires an argument.\n",
  197. optopt);
  198. goto error;
  199. break;
  200. default:
  201. abort();
  202. }
  203. }
  204. /* check if all the required params are present */
  205. if (fname==0){
  206. fprintf(stderr, "Missing -f file\n");
  207. exit(-1);
  208. }
  209. if (dst==0){
  210. fprintf(stderr, "Missing destination (-d ...)\n");
  211. exit(-1);
  212. }
  213. if(port==0){
  214. fprintf(stderr, "Missing port number (-p port)\n");
  215. exit(-1);
  216. }else if(port<0){
  217. fprintf(stderr, "Invalid port number (-p %d)\n", port);
  218. exit(-1);
  219. }
  220. if(count==0){
  221. fprintf(stderr, "Missing packet count (-c number)\n");
  222. exit(-1);
  223. }else if(count<0){
  224. fprintf(stderr, "Invalid packet count (-c %d)\n", count);
  225. exit(-1);
  226. }
  227. if (proto==PROTO_UDP || (proto==PROTO_SCTP && !sctp_o2o)) con_no=1;
  228. /* ignore sigpipe */
  229. if (signal(SIGPIPE, SIG_IGN)==SIG_ERR){
  230. fprintf(stderr, "failed to ignore SIGPIPE: %s\n", strerror(errno));
  231. exit(-1);
  232. }
  233. /* open packet file */
  234. fd=open(fname, O_RDONLY);
  235. if (fd<0){
  236. fprintf(stderr, "ERROR: loading packet-file(%s): %s\n", fname,
  237. strerror(errno));
  238. goto error;
  239. }
  240. n=read(fd, buf, BUF_SIZE);
  241. if (n<0){
  242. fprintf(stderr, "ERROR: reading file(%s): %s\n", fname,
  243. strerror(errno));
  244. goto error;
  245. }
  246. if (verbose) printf("read %d bytes from file %s\n", n, fname);
  247. close(fd);
  248. /* resolve destination */
  249. he=gethostbyname(dst);
  250. if (he==0){
  251. fprintf(stderr, "ERROR: could not resolve %s\n", dst);
  252. goto error;
  253. }
  254. /* open socket*/
  255. addr.sin_family=he->h_addrtype;
  256. addr.sin_port=htons(port);
  257. #ifdef HAVE_SOCKADDR_SA_LEN
  258. addr.sin_len=sizeof(struct sockaddr_in);
  259. #endif
  260. memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
  261. for (k=0; k<con_no; k++){
  262. switch(proto){
  263. case PROTO_UDP:
  264. sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
  265. break;
  266. case PROTO_TCP:
  267. sock = socket(he->h_addrtype, SOCK_STREAM, 0);
  268. break;
  269. #ifdef USE_SCTP
  270. case PROTO_SCTP:
  271. sock = socket(he->h_addrtype,
  272. sctp_o2o?SOCK_STREAM:SOCK_SEQPACKET,
  273. IPPROTO_SCTP);
  274. break;
  275. #endif /* USE_SCTP */
  276. default:
  277. fprintf(stderr, "BUG: unkown proto %d\n", proto);
  278. goto error;
  279. }
  280. if (sock==-1){
  281. fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
  282. goto error;
  283. }
  284. if (proto==PROTO_TCP){
  285. t=1;
  286. if (setsockopt(sock, IPPROTO_TCP , TCP_NODELAY, &t, sizeof(t))<0){
  287. fprintf(stderr, "ERROR: could not disable Nagle: %s\n",
  288. strerror(errno));
  289. }
  290. if (tcp_rst){
  291. t_linger.l_onoff=1;
  292. t_linger.l_linger=0;
  293. if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &t_linger,
  294. sizeof(t_linger))<0){
  295. fprintf(stderr, "ERROR: could not set SO_LINGER: %s\n",
  296. strerror(errno));
  297. }
  298. }
  299. }
  300. #ifdef USE_SCTP
  301. else if (proto==PROTO_SCTP){
  302. t=1;
  303. if (setsockopt(sock, IPPROTO_SCTP, SCTP_NODELAY, &t, sizeof(t))<0){
  304. fprintf(stderr, "ERROR: could not disable Nagle: %s\n",
  305. strerror(errno));
  306. }
  307. }
  308. #endif /* USE_SCTP */
  309. if (
  310. #ifdef USE_SCTP
  311. (proto!=PROTO_SCTP || sctp_o2o) &&
  312. #endif /* USE_SCTP */
  313. (connect(sock, (struct sockaddr*) &addr,
  314. sizeof(struct sockaddr))!=0)){
  315. fprintf(stderr, "ERROR: connect: %s\n", strerror(errno));
  316. goto error;
  317. }
  318. /* flood loop */
  319. t=throttle;
  320. for (r=0; r<count; r++){
  321. if ((verbose>1)&&((r%1000)==999)){ putchar('.'); fflush(stdout); }
  322. #ifdef USE_SCTP
  323. if (proto==PROTO_SCTP && !sctp_o2o){
  324. if (sctp_sendmsg(sock, buf, n, (struct sockaddr*) &addr,
  325. sizeof(struct sockaddr), 0, SCTP_UNORDERED,
  326. 0, 0, 0)==-1){
  327. fprintf(stderr, "Error(%d): send: %s\n", err,
  328. strerror(errno));
  329. err++;;
  330. }
  331. }else
  332. #endif /* USE_SCTP */
  333. {
  334. if (send(sock, buf, n, 0)==-1) {
  335. fprintf(stderr, "Error(%d): send: %s\n", err,
  336. strerror(errno));
  337. err++;;
  338. }
  339. }
  340. if (usec){
  341. t--;
  342. if (t==0){
  343. usleep(random_sleep?
  344. (unsigned long)((double)usec*rand()/RAND_MAX):usec);
  345. t=throttle;
  346. }
  347. }
  348. }
  349. close(sock);
  350. if ((verbose) && (k%1000==999)) { putchar('#'); fflush(stdout); }
  351. }
  352. if (proto==PROTO_TCP || proto==PROTO_SCTP){
  353. printf("\n%d packets sent on %d %s connections (%d on each of them),"
  354. " %d bytes each => total %d bytes\n",
  355. count*con_no-err, con_no, (proto==PROTO_TCP)?"tcp":"sctp",
  356. count, n,
  357. (con_no*count-err)*n);
  358. }else{
  359. printf("\n%d packets sent, %d bytes each => total %d bytes\n",
  360. count-err, n, n*(count-err));
  361. }
  362. if (err) printf("%d errors\n", err);
  363. exit(0);
  364. error:
  365. fprintf(stderr, "exiting due to error (%s)\n", strerror(errno));
  366. exit(-1);
  367. }