1 /* 2 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "test_locl.h" 35 36 RCSID("$Id: common.c,v 1.9 1999/12/16 10:29:18 assar Exp $"); 37 38 static int help_flag; 39 static int version_flag; 40 static char *port_str; 41 char *service = SERVICE; 42 43 static struct getargs args[] = { 44 { "port", 'p', arg_string, &port_str, "port to listen to", "port" }, 45 { "service", 's', arg_string, &service, "service to use", "service" }, 46 { "help", 'h', arg_flag, &help_flag }, 47 { "version", 0, arg_flag, &version_flag } 48 }; 49 50 static int num_args = sizeof(args) / sizeof(args[0]); 51 52 static void 53 server_usage(int code, struct getargs *args, int num_args) 54 { 55 arg_printusage(args, num_args, NULL, ""); 56 exit(code); 57 } 58 59 static void 60 client_usage(int code, struct getargs *args, int num_args) 61 { 62 arg_printusage(args, num_args, NULL, "host"); 63 exit(code); 64 } 65 66 67 static int 68 common_setup(krb5_context *context, int *argc, char **argv, 69 void (*usage)(int, struct getargs*, int)) 70 { 71 int port = 0; 72 *argc = krb5_program_setup(context, *argc, argv, args, num_args, usage); 73 74 if(help_flag) 75 (*usage)(0, args, num_args); 76 if(version_flag) { 77 print_version(NULL); 78 exit(0); 79 } 80 81 if(port_str){ 82 struct servent *s = roken_getservbyname(port_str, "tcp"); 83 if(s) 84 port = s->s_port; 85 else { 86 char *ptr; 87 88 port = strtol (port_str, &ptr, 10); 89 if (port == 0 && ptr == port_str) 90 errx (1, "Bad port `%s'", port_str); 91 port = htons(port); 92 } 93 } 94 95 if (port == 0) 96 port = krb5_getportbyname (*context, PORT, "tcp", 4711); 97 98 return port; 99 } 100 101 int 102 server_setup(krb5_context *context, int argc, char **argv) 103 { 104 int port = common_setup(context, &argc, argv, server_usage); 105 if(argv[argc] != NULL) 106 server_usage(1, args, num_args); 107 return port; 108 } 109 110 int 111 client_setup(krb5_context *context, int *argc, char **argv) 112 { 113 int optind = *argc; 114 int port = common_setup(context, &optind, argv, client_usage); 115 if(*argc - optind != 1) 116 client_usage(1, args, num_args); 117 *argc = optind; 118 return port; 119 } 120 121 int 122 client_doit (const char *hostname, int port, const char *service, 123 int (*func)(int, const char *hostname, const char *service)) 124 { 125 struct addrinfo *ai, *a; 126 struct addrinfo hints; 127 int error; 128 char portstr[NI_MAXSERV]; 129 130 memset (&hints, 0, sizeof(hints)); 131 hints.ai_socktype = SOCK_STREAM; 132 hints.ai_protocol = IPPROTO_TCP; 133 134 snprintf (portstr, sizeof(portstr), "%u", ntohs(port)); 135 136 error = getaddrinfo (hostname, portstr, &hints, &ai); 137 if (error) { 138 errx (1, "%s: %s", hostname, gai_strerror(error)); 139 return -1; 140 } 141 142 for (a = ai; a != NULL; a = a->ai_next) { 143 int s; 144 145 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 146 if (s < 0) 147 continue; 148 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 149 warn ("connect(%s)", hostname); 150 close (s); 151 continue; 152 } 153 freeaddrinfo (ai); 154 return (*func) (s, hostname, service); 155 } 156 warnx ("failed to contact %s", hostname); 157 freeaddrinfo (ai); 158 return 1; 159 } 160