udp.c

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2002-2003 FhG Fokus
00005  *
00006  * This file is sipsak, a free sip testing tool.
00007  *
00008  * sipsak is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * sipsak is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * Copyright (C) 2001-2003 FhG Fokus
00019  *
00020  * This file is part of ser, a free SIP server.
00021  *
00022  * ser is free software; you can redistribute it and/or modify
00023  * it under the terms of the GNU General Public License as published by
00024  * the Free Software Foundation; either version 2 of the License, or
00025  * (at your option) any later version
00026  *
00027  * For a license to use the ser software under conditions
00028  * other than those described here, or to purchase support for this
00029  * software, please contact iptel.org by e-mail at the following addresses:
00030  *    info@iptel.org
00031  *
00032  * ser is distributed in the hope that it will be useful,
00033  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00034  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00035  * GNU General Public License for more details.
00036  *
00037  * You should have received a copy of the GNU General Public License 
00038  * along with this program; if not, write to the Free Software 
00039  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00040  */
00041 
00042 
00043 /* sipsak written by nils ohlmeier (develop@ohlmeier.de).
00044    based up on a modified version of shoot.
00045    set DEBUG on compile will produce much more output. primarily
00046    it will print out the sent and received messages before or after
00047    every network action.
00048 */
00049 
00050 /* changes by jiri@iptel.org; now messages can be really received;
00051    status code returned is 2 for some local errors , 0 for success
00052    and 1 for remote error -- ICMP/timeout; can be used to test if
00053    a server is alive; 1xx messages are now ignored; windows support
00054    dropped
00055 */
00056 
00057 /*
00058 shot written by ashhar farhan, is not bound by any licensing at all.
00059 you are free to use this code as you deem fit. just dont blame the author
00060 for any problems you may have using it.
00061 bouquets and brickbats to farhan@hotfoon.com
00062 */
00063 
00064 /* TO-DO:
00065    - support for short notation
00066    - support for IPv6
00067 */
00068 
00069 //set ts=4 :-)
00070 
00071 #include <stdlib.h>
00072 #include <stdio.h>
00073 #include <sys/types.h>
00074 #include <sys/time.h>
00075 #include <string.h>
00076 #include <ctype.h>
00077 #include <time.h>
00078 #include <unistd.h>
00079 #include <netdb.h>
00080 #include <sys/socket.h>
00081 #include <sys/utsname.h>
00082 
00083 #include <regex.h>
00084 #include <netinet/in.h>
00085 #include <arpa/inet.h>
00086 #include <sys/poll.h>
00087 
00088 #include <errno.h>
00089 
00090 /* this is the main function with the loops and modes */
00091 void shoot()
00092 {
00093         struct sockaddr_in      addr, sockname;
00094         struct timeval  tv, sendtime, recvtime, firstsendt;
00095         struct timezone tz;
00096         struct pollfd sockerr;
00097         int ssock, redirected, retryAfter;
00098         int sock, i, len, ret, usrlocstep, randretrys;
00099         int dontsend, cseqcmp, cseqtmp;
00100         int rem_rand, rem_namebeg;
00101         char *contact, *crlf, *foo, *bar;
00102         fd_set  fd;
00103         socklen_t slen;
00104         regex_t redexp, proexp, okexp, tmhexp, errexp;
00105         int bsd_compat, opt_size;
00106 
00107         int nretries=3;
00108         char *buff="MiniTest";
00109 
00110 
00111         /* create a sending socket */
00112         sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00113         if (sock==-1) {
00114                 perror("no client socket");
00115                 exit(2);
00116         }
00117 
00118 
00119 #ifndef _NO_LISTENER
00120     /* create a listening socket */
00121     ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00122     if (ssock==-1) {
00123         perror("no server socket");
00124         exit(2);
00125     }
00126 
00127     sockname.sin_family=AF_INET;
00128     sockname.sin_addr.s_addr = htonl( INADDR_ANY );
00129     sockname.sin_port = htons((short)47437);
00130     if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
00131         perror("no bind");
00132         exit(2);
00133     }
00134 #endif
00135 
00136 
00137         /* destination socket init here because it could be changed in a 
00138            case of a redirect */
00139         addr.sin_addr.s_addr = inet_addr("192.168.99.100");
00140         addr.sin_port = htons((short)888);
00141         addr.sin_family = AF_INET;
00142 
00143         /* if we dont connect, even on Linux, nothing will happen */
00144 
00145 #ifdef CONNECTED        
00146         /* we connect as per the RFC 2543 recommendations
00147            modified from sendto/recvfrom */
00148         ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
00149         if (ret==-1) {
00150                 perror("no connect");
00151                 exit(2);
00152         }
00153 #endif
00154 
00155         if (getsockopt( sock, SOL_SOCKET, SO_BSDCOMPAT, &bsd_compat, &opt_size )==-1) {
00156                 perror("ERROR");
00157                 exit(1);
00158         }
00159         printf("BSD compat: %d\n", bsd_compat);
00160 
00161         /* here we go for the number of nretries which heavily depends on the 
00162            mode */
00163         for (i = 0; i <= nretries; i++)
00164         {
00165                 /* lets fire the request to the server and store when we did */
00166 
00167                 /* if we send too fast, ICMP will arrive back when we are already
00168                    done and we wont be able to recognize an error
00169                 */
00170 #ifdef CONNECTED
00171                 ret = send(sock, buff, strlen(buff), 0);
00172 #else
00173                 ret=sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&addr, sizeof(addr));
00174 #endif
00175                 /* wait 1/10 sec to be safe we receive ICMP */
00176                 usleep(100000);
00177                 if (ret==-1) {
00178                         perror("send failure");
00179                         exit( 1 );
00180                 }
00181         }
00182 
00183         exit(0);
00184 }
00185 
00186 int main(int argc, char *argv[])
00187 {
00188         shoot();
00189 }
00190