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