1*96c8483aSYuri Pankov /*
2*96c8483aSYuri Pankov  * CDDL HEADER START
3*96c8483aSYuri Pankov  *
4*96c8483aSYuri Pankov  * The contents of this file are subject to the terms of the
5*96c8483aSYuri Pankov  * Common Development and Distribution License (the "License").
6*96c8483aSYuri Pankov  * You may not use this file except in compliance with the License.
7*96c8483aSYuri Pankov  *
8*96c8483aSYuri Pankov  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*96c8483aSYuri Pankov  * or http://www.opensolaris.org/os/licensing.
10*96c8483aSYuri Pankov  * See the License for the specific language governing permissions
11*96c8483aSYuri Pankov  * and limitations under the License.
12*96c8483aSYuri Pankov  *
13*96c8483aSYuri Pankov  * When distributing Covered Code, include this CDDL HEADER in each
14*96c8483aSYuri Pankov  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*96c8483aSYuri Pankov  * If applicable, add the following below this CDDL HEADER, with the
16*96c8483aSYuri Pankov  * fields enclosed by brackets "[]" replaced with your own identifying
17*96c8483aSYuri Pankov  * information: Portions Copyright [yyyy] [name of copyright owner]
18*96c8483aSYuri Pankov  *
19*96c8483aSYuri Pankov  * CDDL HEADER END
20*96c8483aSYuri Pankov  */
21*96c8483aSYuri Pankov 
22*96c8483aSYuri Pankov /*
23*96c8483aSYuri Pankov  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*96c8483aSYuri Pankov  */
25*96c8483aSYuri Pankov 
26*96c8483aSYuri Pankov /*
27*96c8483aSYuri Pankov  * Test helper to abort TCP connections to some server;
28*96c8483aSYuri Pankov  * either all of the, or those to a specified port.
29*96c8483aSYuri Pankov  */
30*96c8483aSYuri Pankov 
31*96c8483aSYuri Pankov #include <sys/types.h>
32*96c8483aSYuri Pankov #include <sys/socket.h>
33*96c8483aSYuri Pankov #include <sys/sockio.h>
34*96c8483aSYuri Pankov #include <sys/stropts.h>
35*96c8483aSYuri Pankov 
36*96c8483aSYuri Pankov #include <inet/tcp.h>
37*96c8483aSYuri Pankov #include <arpa/inet.h>
38*96c8483aSYuri Pankov #include <netinet/in.h>
39*96c8483aSYuri Pankov #include <netdb.h>
40*96c8483aSYuri Pankov 
41*96c8483aSYuri Pankov #include <errno.h>
42*96c8483aSYuri Pankov #include <fcntl.h>
43*96c8483aSYuri Pankov #include <stdio.h>
44*96c8483aSYuri Pankov #include <stdlib.h>
45*96c8483aSYuri Pankov #include <string.h>
46*96c8483aSYuri Pankov #include <unistd.h>
47*96c8483aSYuri Pankov #include <zone.h>
48*96c8483aSYuri Pankov 
49*96c8483aSYuri Pankov /*
50*96c8483aSYuri Pankov  * Abort all connections to the passed address.
51*96c8483aSYuri Pankov  */
52*96c8483aSYuri Pankov static void
tcp_abort_connections(struct sockaddr * rsa)53*96c8483aSYuri Pankov tcp_abort_connections(struct sockaddr *rsa)
54*96c8483aSYuri Pankov {
55*96c8483aSYuri Pankov 	tcp_ioc_abort_conn_t conn;
56*96c8483aSYuri Pankov 	struct strioctl ioc;
57*96c8483aSYuri Pankov 	struct sockaddr *lsa;
58*96c8483aSYuri Pankov 	int fd;
59*96c8483aSYuri Pankov 
60*96c8483aSYuri Pankov 	(void) memset(&conn, 0, sizeof (conn));
61*96c8483aSYuri Pankov 	lsa = (void *)&conn.ac_local;
62*96c8483aSYuri Pankov 	lsa->sa_family = rsa->sa_family;
63*96c8483aSYuri Pankov 	(void) memcpy(&conn.ac_remote, rsa, sizeof (*rsa));
64*96c8483aSYuri Pankov 	conn.ac_start = TCPS_SYN_SENT;
65*96c8483aSYuri Pankov 	conn.ac_end = TCPS_CLOSE_WAIT;
66*96c8483aSYuri Pankov 	conn.ac_zoneid = ALL_ZONES;
67*96c8483aSYuri Pankov 
68*96c8483aSYuri Pankov 	ioc.ic_cmd = TCP_IOC_ABORT_CONN;
69*96c8483aSYuri Pankov 	ioc.ic_timout = -1; /* infinite timeout */
70*96c8483aSYuri Pankov 	ioc.ic_len = sizeof (conn);
71*96c8483aSYuri Pankov 	ioc.ic_dp = (char *)&conn;
72*96c8483aSYuri Pankov 
73*96c8483aSYuri Pankov 	if ((fd = open("/dev/tcp", O_RDONLY)) < 0) {
74*96c8483aSYuri Pankov 		(void) fprintf(stderr, "unable to open %s", "/dev/tcp");
75*96c8483aSYuri Pankov 		return;
76*96c8483aSYuri Pankov 	}
77*96c8483aSYuri Pankov 
78*96c8483aSYuri Pankov 	if (ioctl(fd, I_STR, &ioc) < 0)
79*96c8483aSYuri Pankov 		if (errno != ENOENT)	/* ENOENT is not an error */
80*96c8483aSYuri Pankov 			perror("ioctl");
81*96c8483aSYuri Pankov 
82*96c8483aSYuri Pankov 	(void) close(fd);
83*96c8483aSYuri Pankov }
84*96c8483aSYuri Pankov 
85*96c8483aSYuri Pankov static void
usage(char * arg0)86*96c8483aSYuri Pankov usage(char *arg0)
87*96c8483aSYuri Pankov {
88*96c8483aSYuri Pankov 	(void) fprintf(stderr, "usage: %s [-p <PORT>] <ADDR>\n", arg0);
89*96c8483aSYuri Pankov 	exit(1);
90*96c8483aSYuri Pankov }
91*96c8483aSYuri Pankov 
92*96c8483aSYuri Pankov int
main(int argc,char ** argv)93*96c8483aSYuri Pankov main(int argc, char **argv)
94*96c8483aSYuri Pankov {
95*96c8483aSYuri Pankov 	extern char *optarg;
96*96c8483aSYuri Pankov 	extern int optind, optopt;
97*96c8483aSYuri Pankov 	struct addrinfo hints, *res, *ai;
98*96c8483aSYuri Pankov 	char *addr_str = NULL;
99*96c8483aSYuri Pankov 	char *port_str = NULL;
100*96c8483aSYuri Pankov 	int errflag = 0;
101*96c8483aSYuri Pankov 	int c, gaierr;
102*96c8483aSYuri Pankov 
103*96c8483aSYuri Pankov 	while ((c = getopt(argc, argv, "p:")) != -1) {
104*96c8483aSYuri Pankov 		switch (c) {
105*96c8483aSYuri Pankov 		case 'p':
106*96c8483aSYuri Pankov 			port_str = optarg;
107*96c8483aSYuri Pankov 			break;
108*96c8483aSYuri Pankov 		case ':':
109*96c8483aSYuri Pankov 			(void) fprintf(stderr,
110*96c8483aSYuri Pankov 			    "Option -%c requires an operand\n", optopt);
111*96c8483aSYuri Pankov 			errflag++;
112*96c8483aSYuri Pankov 			break;
113*96c8483aSYuri Pankov 		case '?':
114*96c8483aSYuri Pankov 			(void) fprintf(stderr,
115*96c8483aSYuri Pankov 			    "Unrecognized option: -%c\n", optopt);
116*96c8483aSYuri Pankov 			errflag++;
117*96c8483aSYuri Pankov 			break;
118*96c8483aSYuri Pankov 		}
119*96c8483aSYuri Pankov 	}
120*96c8483aSYuri Pankov 	if (errflag)
121*96c8483aSYuri Pankov 		usage(argv[0]);
122*96c8483aSYuri Pankov 	if (argc <= optind) {
123*96c8483aSYuri Pankov 		(void) fprintf(stderr, "No address specified\n");
124*96c8483aSYuri Pankov 		usage(argv[0]);
125*96c8483aSYuri Pankov 	}
126*96c8483aSYuri Pankov 	addr_str = argv[optind];
127*96c8483aSYuri Pankov 
128*96c8483aSYuri Pankov 	/*
129*96c8483aSYuri Pankov 	 * Lookup the IP address
130*96c8483aSYuri Pankov 	 */
131*96c8483aSYuri Pankov 	(void) memset(&hints, 0, sizeof (hints));
132*96c8483aSYuri Pankov 	hints.ai_family = PF_UNSPEC;
133*96c8483aSYuri Pankov 	hints.ai_socktype = SOCK_STREAM;
134*96c8483aSYuri Pankov 	gaierr = getaddrinfo(addr_str, port_str, &hints, &res);
135*96c8483aSYuri Pankov 	if (gaierr != 0) {
136*96c8483aSYuri Pankov 		(void) fprintf(stderr, "%s: %s\n", addr_str,
137*96c8483aSYuri Pankov 		    gai_strerror(gaierr));
138*96c8483aSYuri Pankov 		return (1);
139*96c8483aSYuri Pankov 	}
140*96c8483aSYuri Pankov 
141*96c8483aSYuri Pankov 	for (ai = res; ai != NULL; ai = ai->ai_next) {
142*96c8483aSYuri Pankov 		tcp_abort_connections(ai->ai_addr);
143*96c8483aSYuri Pankov 	}
144*96c8483aSYuri Pankov 
145*96c8483aSYuri Pankov 	return (0);
146*96c8483aSYuri Pankov }
147