00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <sys/types.h>
00019 #include <sys/time.h>
00020 #include <string.h>
00021 #include <ctype.h>
00022 #include <time.h>
00023 #include <unistd.h>
00024 #include <netdb.h>
00025 #include <sys/socket.h>
00026
00027 #include <sys/utsname.h>
00028
00029 #include <regex.h>
00030 regex_t* regexp;
00031
00032 #define RESIZE 1024
00033 #define BUFSIZE 1600
00034 #define VIA_BEGIN_STR "Via: SIP/2.0/UDP "
00035 #define VIA_BEGIN_STR_LEN 17
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 long getaddress(char *host)
00051 {
00052 int i, dotcount=0;
00053 char *p = host;
00054 struct hostent* pent;
00055 long l, *lp;
00056
00057
00058
00059
00060 while (*p)
00061 {
00062 for (i = 0; i < 3; i++, p++)
00063 if (!isdigit(*p))
00064 break;
00065 if (*p != '.')
00066 break;
00067 p++;
00068 dotcount++;
00069 }
00070
00071
00072 if (dotcount == 3 && i > 0 && i <= 3)
00073 return inet_addr(host);
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 pent = gethostbyname(host);
00088 if (!pent) {
00089 perror("no gethostbyname");
00090 exit(2);
00091 }
00092
00093 lp = (long *) (pent->h_addr);
00094 l = *lp;
00095 return l;
00096 }
00097
00098
00099 add_via(char *mes)
00100 {
00101 struct utsname myname;
00102 char *via_line, *via, *backup;
00103
00104
00105 if (uname (&myname) <0){
00106 printf("cannot determine hostname\n");
00107 exit(2);
00108 }
00109 #ifdef DEBUG
00110 printf("determined hostname: %s\n", myname.nodename);
00111 #endif
00112
00113 via_line = malloc(VIA_BEGIN_STR_LEN + strlen(myname.nodename) + 3);
00114 strcat(via_line, VIA_BEGIN_STR);
00115 strcat(via_line, myname.nodename);
00116 strcat(via_line, "\r\n");
00117 #ifdef DEBUG
00118 printf("our Via-Line: %s\n", via_line);
00119 #endif
00120
00121 if (strlen(mes)+strlen(via_line)>= BUFSIZE){
00122 printf("can't add our Via Header Line because file is too big\n");
00123 exit(2);
00124 }
00125 if ((via=strstr(mes,"Via:"))==NULL){
00126
00127
00128 via=strchr(mes,'\n');
00129 via++;
00130 }
00131 backup=malloc(strlen(via));
00132 strncpy(backup, via, strlen(via));
00133 strncpy(via, via_line, strlen(via_line));
00134 strncpy(via+strlen(via_line), backup, strlen(backup));
00135 #ifdef DEBUG
00136 printf("New message:\n%s", mes);
00137 #endif
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 void shoot(char *buff, long address, int lport, int rport )
00157 {
00158 struct sockaddr_in addr;
00159
00160 struct sockaddr_in sockname;
00161 int ssock;
00162
00163
00164
00165
00166 int retryAfter = 500;
00167 int nretries = 10;
00168 int sock, i, len, ret;
00169 struct timeval tv;
00170 fd_set fd;
00171 char reply[1600];
00172
00173
00174 sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00175 if (sock==-1) {
00176 perror("no client socket");
00177 exit(2);
00178 }
00179
00180
00181 ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00182 if (ssock==-1) {
00183 perror("no server socket");
00184 exit(2);
00185 }
00186
00187 sockname.sin_family=AF_INET;
00188 sockname.sin_addr.s_addr = htonl( INADDR_ANY );
00189 sockname.sin_port = htons((short)lport);
00190 if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
00191 perror("no bind");
00192 exit(2);
00193 }
00194
00195
00196
00197 regexp=(regex_t*)malloc(sizeof(regex_t));
00198 regcomp(regexp, "^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE);
00199
00200
00201
00202
00203 addr.sin_addr.s_addr = address;
00204 addr.sin_port = htons((short)rport);
00205 addr.sin_family = AF_INET;
00206
00207
00208
00209
00210 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
00211 if (ret==-1) {
00212 perror("no connect");
00213 exit(2);
00214 }
00215
00216
00217 add_via(buff);
00218
00219 for (i = 0; i < nretries; i++)
00220 {
00221 puts("/* request */");
00222 puts(buff);
00223 putchar('\n');
00224
00225 ret = send(sock, buff, strlen(buff), 0);
00226 if (ret==-1) {
00227 perror("send failure");
00228 exit( 1 );
00229 }
00230
00231
00232 tv.tv_sec = retryAfter/1000;
00233 tv.tv_usec = (retryAfter % 1000) * 1000;
00234
00235 FD_ZERO(&fd);
00236 FD_SET(ssock, &fd);
00237
00238
00239
00240
00241
00242 ret = select(6, &fd, NULL, NULL, &tv);
00243 if (ret == 0)
00244 {
00245 puts("\n/* timeout */\n");
00246 retryAfter = retryAfter * 2;
00247 if (retryAfter > 5000)
00248 retryAfter = 5000;
00249
00250
00251
00252
00253 continue;
00254 } else if ( ret == -1 ) {
00255 perror("select error");
00256 exit(2);
00257 }
00258 else if (FD_ISSET(ssock, &fd)) {
00259 puts ("\nmessage received\n");
00260 } else {
00261 puts("\nselect returned successfully, nothing received\n");
00262 continue;
00263 }
00264
00265
00266 len = sizeof(addr);
00267 ret = recv(ssock, reply, 1500, 0);
00268 if(ret > 0)
00269 {
00270 reply[ret] = 0;
00271 puts("/* reply */");
00272 puts(reply);
00273 putchar('\n');
00274
00275 if (regexec((regex_t*)regexp, reply, 0, 0, 0)==0) {
00276 puts(" provisional received; still waiting for a final response\n ");
00277 continue;
00278 } else {
00279 puts(" final received; congratulations!\n ");
00280 exit(0);
00281 }
00282
00283 }
00284 else {
00285 perror("recv error");
00286 exit(2);
00287 }
00288 }
00289
00290 puts("/* I give up retransmission....");
00291 exit(1);
00292 }
00293
00294 int main(int argc, char *argv[])
00295 {
00296 long address;
00297 FILE *pf;
00298 char buff[BUFSIZE];
00299 int length;
00300 int lport=0;
00301 int rport=5060;
00302 char *delim, *delim2;
00303
00304 if (! (argc >= 3 && argc <= 5))
00305 {
00306 puts("usage: shoot file host rport [lport]");
00307 puts("usage: shoot file sip:[user@]hostname[:rport]");
00308 exit(2);
00309 }
00310
00311
00312 if (argc==3){
00313 if ((delim=strchr(argv[2],':'))!=NULL){
00314 delim++;
00315 if (!strncmp(argv[2],"sip",3)){
00316 if ((delim2=strchr(delim,'@'))!=NULL){
00317
00318 delim2++;
00319 delim=delim2;
00320 }
00321 if ((delim2=strchr(delim,':'))!=NULL){
00322 *delim2 = '\0';
00323 delim2++;
00324 rport = atoi(delim2);
00325 if (!rport) {
00326 puts("error: non-numerical remote port number");
00327 exit(2);
00328 }
00329 }
00330 address = getaddress(delim);
00331 if (!address){
00332 puts("error:unable to determine the remote host address.");
00333 exit(2);
00334 }
00335 }
00336 else{
00337 puts("sip:uri doesn't not begin with sip");
00338 exit(2);
00339 }
00340 }
00341 else{
00342 puts("sip:uri doesn't contain a : ?!");
00343 exit(2);
00344 }
00345 }
00346 else{
00347 address = getaddress(argv[2]);
00348 if (!address){
00349 puts("error:unable to determine the remote host address.");
00350 exit(2);
00351 }
00352
00353
00354 if (argc >= 4){
00355 rport = atoi(argv[3]);
00356 if (!rport) {
00357 puts("error: non-numerical remote port number");
00358 exit(2);
00359 }
00360 if (argc==5) {
00361 lport=atoi(argv[4]);
00362 if (!lport) {
00363 puts("error: non-numerical local port number");
00364 exit(2);
00365 }
00366 }
00367 }
00368 }
00369
00370
00371 pf = fopen(argv[1], "rb");
00372 if (!pf)
00373 {
00374 puts("unable to open the file.\n");
00375 return 1;
00376 }
00377 length = fread(buff, 1, sizeof(buff), pf);
00378 if (length >= sizeof(buff))
00379 {
00380 printf("error:the file is too big. try files of less than %i bytes.\n", BUFSIZE);
00381 puts(" or recompile the program with bigger BUFSIZE defined.");
00382 return 1;
00383 }
00384 fclose(pf);
00385 buff[length] = 0;
00386
00387 shoot(buff, address, lport, rport );
00388
00389
00390
00391
00392
00393
00394
00395 return 0;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409