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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <arpa/inet.h> /* inet_addr() */ 27 #include <ctype.h> 28 #include <libscf.h> 29 #include <netdb.h> /* hostent */ 30 #include <netinet/in.h> /* ip_addr_t */ 31 #include <stdio.h> 32 #include <errno.h> 33 #include <limits.h> 34 #include <stdlib.h> 35 #include <fcntl.h> 36 #include <strings.h> 37 #include <sys/varargs.h> 38 #include "ksslcfg.h" 39 40 /* 41 * ksslcfg(1M) 42 * 43 * ksslcfg manages smf(5) instances for the Kernel SSL proxy module. 44 * It makes use of kssladm(1M) which does the grunt work. 45 */ 46 47 /* 48 * This version number is rather meaningless. In any case, 49 * version 2.0 adds support for IPv6 addresses. 50 */ 51 #define KSSLCFG_VERSION "Version 2.0" 52 53 boolean_t verbose = B_FALSE; 54 const char *SERVICE_NAME = "network/ssl/proxy"; 55 56 void 57 KSSL_DEBUG(const char *format, ...) 58 { 59 va_list ap; 60 61 if (verbose) { 62 va_start(ap, format); 63 (void) vprintf(format, ap); 64 va_end(ap); 65 } 66 } 67 68 int 69 get_portnum(const char *s, ushort_t *rport) 70 { 71 unsigned long port; 72 73 errno = 0; 74 port = strtoul(s, NULL, 10); 75 if (port > USHRT_MAX || port == 0 || errno != 0) { 76 return (0); 77 } 78 79 if (rport != NULL) 80 *rport = (ushort_t)port; 81 return (1); 82 } 83 84 #define ANY_ADDR "INADDR_ANY" 85 86 /* 87 * An instance name is formed using either the host name in the fully 88 * qualified domain name form (FQDN) which should map to a specific IP address 89 * or using INADDR_ANY which means all IP addresses. 90 * 91 * We do a lookup or reverse lookup to get the host name. It is assumed that 92 * the returned name is in the FQDN form. i.e. DNS is used. 93 */ 94 char * 95 create_instance_name(const char *arg, char **inaddr_any_name, 96 boolean_t is_create) 97 { 98 int len; 99 uint16_t port; 100 char *cname; 101 char *instance_name; 102 const char *prefix = "kssl-"; 103 char *first_space; 104 105 first_space = strchr(arg, ' '); 106 if (first_space == NULL) { /* No host name. Use INADDR_ANY. */ 107 if (get_portnum(arg, &port) == 0) { 108 (void) fprintf(stderr, 109 gettext("Error: Invalid port value -- %s\n"), 110 arg); 111 return (NULL); 112 } 113 KSSL_DEBUG("port=%d\n", port); 114 if ((cname = strdup(ANY_ADDR)) == NULL) 115 return (NULL); 116 } else { 117 char *temp_str; 118 char *ptr; 119 struct hostent *hp; 120 boolean_t do_warn; 121 int error_num; 122 in_addr_t v4addr; 123 in6_addr_t v6addr; 124 125 if (get_portnum(first_space + 1, &port) == 0) { 126 (void) fprintf(stderr, 127 gettext("Error: Invalid port value -- %s\n"), 128 first_space + 1); 129 return (NULL); 130 } 131 KSSL_DEBUG("port=%d\n", port); 132 133 if ((temp_str = strdup(arg)) == NULL) 134 return (NULL); 135 *(strchr(temp_str, ' ')) = '\0'; 136 137 if (inet_pton(AF_INET6, temp_str, &v6addr) == 1) { 138 /* Do a reverse lookup for the IPv6 address */ 139 hp = getipnodebyaddr(&v6addr, sizeof (v6addr), 140 AF_INET6, &error_num); 141 } else if (inet_pton(AF_INET, temp_str, &v4addr) == 1) { 142 /* Do a reverse lookup for the IPv4 address */ 143 hp = getipnodebyaddr(&v4addr, sizeof (v4addr), 144 AF_INET, &error_num); 145 } else { 146 /* Do a lookup for the host name */ 147 hp = getipnodebyname(temp_str, AF_INET6, AI_DEFAULT, 148 &error_num); 149 } 150 151 if (hp == NULL) { 152 (void) fprintf(stderr, 153 gettext("Error: Unknown host -- %s\n"), temp_str); 154 free(temp_str); 155 return (NULL); 156 } 157 158 if ((ptr = cname = strdup(hp->h_name)) == NULL) { 159 freehostent(hp); 160 free(temp_str); 161 return (NULL); 162 } 163 164 freehostent(hp); 165 166 do_warn = B_TRUE; 167 /* "s/./-/g" */ 168 while ((ptr = strchr(ptr, '.')) != NULL) { 169 if (do_warn) 170 do_warn = B_FALSE; 171 *ptr = '-'; 172 ptr++; 173 } 174 175 if (do_warn && is_create) { 176 (void) fprintf(stderr, 177 gettext("Warning: %s does not appear to have a" 178 " registered DNS name.\n"), temp_str); 179 } 180 181 free(temp_str); 182 } 183 184 KSSL_DEBUG("Cannonical host name =%s\n", cname); 185 186 len = strlen(prefix) + strlen(cname) + 10; 187 if ((instance_name = malloc(len)) == NULL) { 188 (void) fprintf(stderr, 189 gettext("Error: memory allocation failure.\n")); 190 return (NULL); 191 } 192 (void) snprintf(instance_name, len, "%s%s-%d", prefix, cname, port); 193 194 if (is_create) { 195 len = strlen(prefix) + strlen(ANY_ADDR) + 10; 196 if ((*inaddr_any_name = malloc(len)) == NULL) { 197 (void) fprintf(stderr, 198 gettext("Error: memory allocation failure.\n")); 199 free(cname); 200 return (NULL); 201 } 202 203 (void) snprintf(*inaddr_any_name, len, 204 "%s%s-%d", prefix, ANY_ADDR, port); 205 } 206 207 free(cname); 208 KSSL_DEBUG("instance_name=%s\n", instance_name); 209 return (instance_name); 210 } 211 212 static void 213 usage_all(void) 214 { 215 (void) fprintf(stderr, gettext("Usage:\n")); 216 usage_create(B_FALSE); 217 usage_delete(B_FALSE); 218 (void) fprintf(stderr, "ksslcfg -V\n"); 219 (void) fprintf(stderr, "ksslcfg -?\n"); 220 } 221 222 223 int 224 main(int argc, char **argv) 225 { 226 int rv = SUCCESS; 227 228 (void) setlocale(LC_ALL, ""); 229 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 230 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 231 #endif 232 (void) textdomain(TEXT_DOMAIN); 233 234 if (argc < 2) { 235 usage_all(); 236 return (ERROR_USAGE); 237 } 238 239 if (strcmp(argv[1], "create") == 0) { 240 rv = do_create(argc, argv); 241 } else if (strcmp(argv[1], "delete") == 0) { 242 rv = do_delete(argc, argv); 243 } else if (strcmp(argv[1], "-V") == 0) { 244 (void) printf("%s\n", KSSLCFG_VERSION); 245 } else if (strcmp(argv[1], "-?") == 0) { 246 usage_all(); 247 } else { 248 (void) fprintf(stderr, 249 gettext("Error: Unknown subcommand -- %s\n"), argv[1]); 250 usage_all(); 251 rv = ERROR_USAGE; 252 } 253 254 return (rv); 255 } 256