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