3 International Computer Science Institute
6 This file may contain software code originally developed for the
7 Sting project. The Sting software carries the following copyright:
9 Copyright (c) 1998, 1999
10 Stefan Savage and the University of Washington.
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21 3. All advertising materials mentioning features or use of this software
22 must display the following acknowledgment:
23 This product includes software developed by ACIRI, the AT&T
24 Center for Internet Research at ICSI (the International Computer
25 Science Institute). This product may also include software developed
26 by Stefan Savage at the University of Washington.
27 4. The names of ACIRI, ICSI, Stefan Savage and University of Washington
28 may not be used to endorse or promote products derived from this software
29 without specific prior written permission.
31 THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
32 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
35 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #include <sys/types.h>
45 #include <sys/param.h>
50 #include <sys/socket.h>
54 #include <arpa/inet.h>
64 extern struct TcpSession session
;
66 void usage (char *name
);
67 int GetCannonicalInfo(char *string
, u_int32_t
*address
);
68 int BindTcpPort(int sockfd
) ;
70 void usage(char *name
)
72 printf("%s [options]\n", name
);
73 printf("\t-n <target hostname | ipaddress>\n");
74 printf("\t-p <target port>\n");
75 printf("\t-m <mss>\n");
76 printf("\t-M <mtu>\n");
77 printf("\t-w <sourcePort>\n");
78 printf("\t-s <source hostname or ip address>\n");
79 printf("\t-f <file-name to get>\n");
80 printf("\t-d <interface name>\n");
81 printf("\t-C for CE path check\n");
85 void SetupFirewall(u_int32_t targetIP
, u_int16_t port
, char *dev
)
88 char *pf_file_name
= "/tmp/pf.conf";
93 bzero(pfcmd
, sizeof(pfcmd
));
95 bzero(args
, sizeof(args
));
96 sprintf(pfcmd
, "block in quick on %s inet proto tcp from %s port %u\n",
97 dev
, InetAddress(targetIP
), port
);
98 if (session
.debug
>= SESSION_DEBUG_LOW
)
99 printf("PF rule: %s\n", pfcmd
);
101 pf_fd
= open(pf_file_name
, O_RDWR
|O_TRUNC
|O_CREAT
);
103 perror("failed to open pf file");
106 bytes
= write(pf_fd
, pfcmd
, strlen(pfcmd
) + 1);
111 rc
= posix_spawn(NULL
, "/sbin/pfctl", NULL
, NULL
, args
, NULL
);
113 printf("Failed to exec: pfctl -d: %d\n", rc
);
118 args
[2] = pf_file_name
;
120 rc
= posix_spawn(NULL
, "/sbin/pfctl", NULL
, NULL
, args
, NULL
);
122 printf("Failed to exec: pfctl -f /tmp/pf.conf: %d\n", rc
);
128 rc
= posix_spawn(NULL
, "/sbin/pfctl", NULL
, NULL
, args
, NULL
);
130 printf("Failed to exec: pfctl -e: %d\n", rc
);
139 if (session
.initSession
> 0) {
140 shutdown(session
.socket
, 2);
143 if (session
.initCapture
> 0) {
149 rc
= posix_spawn(NULL
, "/sbin/pfctl", NULL
, NULL
, args
, NULL
);
151 printf("Failed to exec: pfctl -d: %d\n", rc
);
165 void SigHandle(int signo
)
173 int GetCannonicalInfo(char *string
, u_int32_t
*address
)
176 /* Is string in dotted decimal format? */
177 if ((*address
= inet_addr(string
)) == INADDR_NONE
) {
178 /* No, then lookup IP address */
179 if ((hp
= gethostbyname(string
)) == NULL
) {
180 /* Can't find IP address */
181 printf("ERROR: Couldn't obtain address for %s\n"
182 "RETURN CODE: %d\n", string
, FAIL
);
185 strncpy(string
, hp
->h_name
, MAXHOSTNAMELEN
-1);
186 memcpy((void *)address
, (void *)hp
->h_addr
,
190 if ((hp
= gethostbyaddr((char *)address
, sizeof(*address
),
193 * Can't get cannonical hostname, so just use
197 printf("WARNING: Couldn't obtain cannonical"
198 " name for %s\nRETURN CODE: %d",
199 string
, NO_SRC_CANON_INFO
);
201 /* strncpy(name, string, MAXHOSTNAMELEN - 1);*/
203 /* strncpy(name, hp->h_name, MAXHOSTNAMELEN - 1);*/
209 int BindTcpPort(int sockfd
)
211 struct sockaddr_in sockName
;
215 #define START_PORT (50*1024)
216 #define END_PORT (0xFFFF)
219 * Choose random offset to reduce likelihood of
220 * collision with last run
222 randomOffset
= (int)(1000.0*drand48());
224 /* Try to find a free port in the range START_PORT+1..END_PORT */
225 port
= START_PORT
+randomOffset
;
228 sockName
.sin_addr
.s_addr
= INADDR_ANY
;
229 sockName
.sin_family
= AF_INET
;
230 sockName
.sin_port
= htons(port
);
231 result
= bind(sockfd
, (struct sockaddr
*)&sockName
,
233 } while ((result
< 0) && (port
< END_PORT
));
246 int main(int argc
, char **argv
)
248 u_int32_t targetIpAddress
= 0;
249 u_int16_t targetPort
= DEFAULT_TARGETPORT
;
250 u_int16_t sourcePort
= 0;
251 u_int32_t sourceIpAddress
= 0;
252 int mss
= DEFAULT_MSS
;
253 int mtu
= DEFAULT_MTU
;
254 int fd
, opt
, usedev
= 0, rc
= 0, path_check
= 0;
255 struct sockaddr_in saddr
;
256 char dev
[11]; /* device name for pcap init */
257 struct ifaddrs
*ifap
, *tmp
;
259 bzero(&session
, sizeof(session
));
260 while ((opt
= getopt(argc
, argv
, "n:p:w:m:M:s:d:f:-C")) != -1) {
263 if (strlen(optarg
) > (MAXHOSTNAMELEN
- 1)) {
264 printf("Target host name too long, max %u chars\n", MAXHOSTNAMELEN
);
267 strncpy(session
.targetHostName
, optarg
,
269 strncpy(session
.targetName
, session
.targetHostName
,
273 targetPort
= atoi(optarg
);
282 sourcePort
= atoi(optarg
);
285 if (strlen(optarg
) > (MAXHOSTNAMELEN
- 1)) {
286 printf("Source host name too long, max %u chars\n", MAXHOSTNAMELEN
);
289 strncpy(session
.sourceHostName
, optarg
,
293 if (strlen(optarg
) > (sizeof(dev
) - 1)) {
294 printf("Interface nae is too large, max %lu chars\n", (sizeof(dev
) - 1));
297 bzero(dev
, sizeof(dev
));
298 strncpy(dev
, optarg
, (sizeof(dev
) - 1));
302 if (strlen(optarg
) > 0) {
303 session
.filename
= strndup(optarg
, strlen(optarg
) + 1);
305 printf("Invalid file name \n");
316 signal(SIGTERM
, SigHandle
);
317 signal(SIGINT
, SigHandle
);
318 signal(SIGHUP
, SigHandle
);
320 if (GetCannonicalInfo(session
.targetHostName
, &targetIpAddress
) < 0)
322 printf("Failed to convert targetIP address\n");
323 Quit(NO_TARGET_CANON_INFO
);
326 if (GetCannonicalInfo(session.sourceHostName, &sourceIpAddress) < 0)
328 printf("Failed to convert source IP address\n");
329 Quit(NO_TARGET_CANON_INFO);
332 rc
= getifaddrs(&ifap
);
333 if (rc
!= 0 || ifap
== NULL
) {
334 printf("Failed to get source addresswith getifaddrs: %d\n", rc
);
339 bzero(session
.sourceHostName
, MAXHOSTNAMELEN
);
340 for (tmp
= ifap
; tmp
!= NULL
; tmp
= tmp
->ifa_next
) {
341 struct sockaddr_in
*sin
;
342 if (tmp
->ifa_addr
== NULL
)
344 if (tmp
->ifa_addr
->sa_family
!= PF_INET
)
347 /* we know which interface to use */
348 if (strcmp(dev
, tmp
->ifa_name
) == 0) {
349 sin
= (struct sockaddr_in
*)tmp
->ifa_addr
;
350 sourceIpAddress
= sin
->sin_addr
.s_addr
;
351 strncpy(session
.sourceHostName
,
352 inet_ntoa(sin
->sin_addr
),
358 /* pick the first address */
359 bzero(dev
, sizeof(dev
));
360 sin
= (struct sockaddr_in
*)tmp
->ifa_addr
;
361 sourceIpAddress
= sin
->sin_addr
.s_addr
;
362 strncpy(session
.sourceHostName
,
363 inet_ntoa(sin
->sin_addr
),
365 strncpy(dev
, tmp
->ifa_name
, sizeof(dev
));
369 if (sourceIpAddress
== 0) {
370 printf("Failed to get source Ip address\n");
374 if (sourcePort
== 0) {
375 bzero(&saddr
, sizeof(saddr
));
376 saddr
.sin_family
= AF_INET
;
377 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
378 printf("Can't open socket\n");
381 if ((sourcePort
= BindTcpPort(fd
)) == 0) {
382 printf("Can't bind to port\n");
386 CaptureInit(sourceIpAddress
, sourcePort
, targetIpAddress
,
388 session
.initCapture
= 1;
390 printf("Source: %s:%d\n", session
.sourceHostName
, sourcePort
);
391 printf("Destination: %s:%d\n", session
.targetHostName
, targetPort
);
393 SetupFirewall(targetIpAddress
, targetPort
, dev
);
395 printf("Starting ECN test\n");
397 ECNPathCheckTest(sourceIpAddress
, sourcePort
, targetIpAddress
,
400 ECNTest(sourceIpAddress
, sourcePort
, targetIpAddress
,
404 close(session
.socket
);