1f875b4ebSrica /* 2f875b4ebSrica * CDDL HEADER START 3f875b4ebSrica * 4f875b4ebSrica * The contents of this file are subject to the terms of the 5f875b4ebSrica * Common Development and Distribution License (the "License"). 6f875b4ebSrica * You may not use this file except in compliance with the License. 7f875b4ebSrica * 8f875b4ebSrica * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f875b4ebSrica * or http://www.opensolaris.org/os/licensing. 10f875b4ebSrica * See the License for the specific language governing permissions 11f875b4ebSrica * and limitations under the License. 12f875b4ebSrica * 13f875b4ebSrica * When distributing Covered Code, include this CDDL HEADER in each 14f875b4ebSrica * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f875b4ebSrica * If applicable, add the following below this CDDL HEADER, with the 16f875b4ebSrica * fields enclosed by brackets "[]" replaced with your own identifying 17f875b4ebSrica * information: Portions Copyright [yyyy] [name of copyright owner] 18f875b4ebSrica * 19f875b4ebSrica * CDDL HEADER END 20f875b4ebSrica */ 21f875b4ebSrica 22f875b4ebSrica /* 23*5ccb772aSTony Nguyen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24f875b4ebSrica * Use is subject to license terms. 25f875b4ebSrica */ 26f875b4ebSrica 27f875b4ebSrica /* 28f875b4ebSrica * tnctl.c - 29f875b4ebSrica * Trusted Network control utility 30f875b4ebSrica */ 31f875b4ebSrica #include <stdio.h> 32f875b4ebSrica #include <stdlib.h> 33f875b4ebSrica #include <stddef.h> 34f875b4ebSrica #include <unistd.h> 35f875b4ebSrica #include <string.h> 36f875b4ebSrica #include <errno.h> 37f875b4ebSrica #include <locale.h> 38f875b4ebSrica #include <fcntl.h> 39f875b4ebSrica #include <sys/types.h> 40f875b4ebSrica #include <sys/param.h> 41f875b4ebSrica #include <sys/socket.h> 42f875b4ebSrica #include <netinet/in.h> 43f875b4ebSrica #include <arpa/inet.h> 44f875b4ebSrica #include <netdb.h> 45f875b4ebSrica #include <libtsnet.h> 46f875b4ebSrica #include <zone.h> 47f875b4ebSrica #include <nss_dbdefs.h> 48f875b4ebSrica 49f875b4ebSrica static void process_rh(const char *); 50f875b4ebSrica static void process_rhl(const char *); 51f875b4ebSrica static void process_mlp(const char *); 52f875b4ebSrica static void process_tp(const char *); 53f875b4ebSrica static void process_tpl(const char *); 54f875b4ebSrica static void process_tnzone(const char *); 55f875b4ebSrica static void usage(void); 561f041b17Ston static void translate_inet_addr(tsol_rhent_t *, int *, char [], int); 57f875b4ebSrica 58f875b4ebSrica static boolean_t verbose_mode; 59f875b4ebSrica static boolean_t delete_mode; 60f875b4ebSrica static boolean_t flush_mode; 61f875b4ebSrica 62f875b4ebSrica int 63f875b4ebSrica main(int argc, char **argv) 64f875b4ebSrica { 65f875b4ebSrica extern char *optarg; 66f875b4ebSrica int chr; 67f875b4ebSrica 68f875b4ebSrica /* Don't do anything if labeling is not active. */ 69f875b4ebSrica if (!is_system_labeled()) 70f875b4ebSrica return (0); 71f875b4ebSrica 72f875b4ebSrica /* set the locale for only the messages system (all else is clean) */ 73f875b4ebSrica (void) setlocale(LC_ALL, ""); 74f875b4ebSrica #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ 75f875b4ebSrica #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 76f875b4ebSrica #endif 77f875b4ebSrica 78f875b4ebSrica (void) textdomain(TEXT_DOMAIN); 79f875b4ebSrica 80f875b4ebSrica while ((chr = getopt(argc, argv, "dfh:H:m:t:T:vz:")) != EOF) { 81f875b4ebSrica switch (chr) { 82f875b4ebSrica case 'd': 83f875b4ebSrica delete_mode = B_TRUE; 84f875b4ebSrica break; 85f875b4ebSrica case 'f': 86f875b4ebSrica flush_mode = B_TRUE; 87f875b4ebSrica break; 88f875b4ebSrica case 'h': 89f875b4ebSrica process_rh(optarg); 90f875b4ebSrica break; 91f875b4ebSrica case 'H': 92f875b4ebSrica process_rhl(optarg); 93f875b4ebSrica break; 94f875b4ebSrica case 'm': 95f875b4ebSrica process_mlp(optarg); 96f875b4ebSrica break; 97f875b4ebSrica case 't': 98f875b4ebSrica process_tp(optarg); 99f875b4ebSrica break; 100f875b4ebSrica case 'T': 101f875b4ebSrica process_tpl(optarg); 102f875b4ebSrica break; 103f875b4ebSrica case 'v': 104f875b4ebSrica verbose_mode = B_TRUE; 105f875b4ebSrica break; 106f875b4ebSrica case 'z': 107f875b4ebSrica process_tnzone(optarg); 108f875b4ebSrica break; 109f875b4ebSrica case '?': 110f875b4ebSrica usage(); 111f875b4ebSrica } 112f875b4ebSrica } 113f875b4ebSrica return (0); 114f875b4ebSrica } 115f875b4ebSrica 116f875b4ebSrica static void 117f875b4ebSrica print_error(int linenum, int err, const char *errstr) 118f875b4ebSrica { 119f875b4ebSrica if (linenum > 0) 120f875b4ebSrica (void) fprintf(stderr, gettext("line %1$d: %2$s:\n"), linenum, 121f875b4ebSrica tsol_strerror(err, errno)); 122f875b4ebSrica else 123f875b4ebSrica (void) fprintf(stderr, gettext("tnctl: parsing error: %s\n"), 124f875b4ebSrica tsol_strerror(err, errno)); 125f875b4ebSrica (void) fprintf(stderr, "%.32s\n", errstr); 126f875b4ebSrica } 127f875b4ebSrica 128f875b4ebSrica /* 1291f041b17Ston * Produce ascii format of address and prefix length 1301f041b17Ston */ 1311f041b17Ston static void 1321f041b17Ston translate_inet_addr(tsol_rhent_t *rhentp, int *alen, char abuf[], int abuflen) 1331f041b17Ston { 1341f041b17Ston void *aptr; 1351f041b17Ston tsol_rhent_t rhent; 1361f041b17Ston struct in6_addr ipv6addr; 1371f041b17Ston char tmpbuf[20]; 1381f041b17Ston 1391f041b17Ston (void) snprintf(tmpbuf, sizeof (tmpbuf), "/%d", rhentp->rh_prefix); 1401f041b17Ston 1411f041b17Ston if (rhentp->rh_address.ta_family == AF_INET6) { 1421f041b17Ston aptr = &(rhentp->rh_address.ta_addr_v6); 1431f041b17Ston (void) inet_ntop(rhentp->rh_address.ta_family, aptr, abuf, 1441f041b17Ston abuflen); 1451f041b17Ston if (rhentp->rh_prefix != 128) { 1461f041b17Ston if (strlcat(abuf, tmpbuf, abuflen) >= abuflen) 1471f041b17Ston (void) fprintf(stderr, gettext( 1481f041b17Ston "tnctl: buffer overflow detected: %s\n"), 1491f041b17Ston abuf); 1501f041b17Ston } 151*5ccb772aSTony Nguyen *alen = strlen(abuf); 1521f041b17Ston } else { 1531f041b17Ston aptr = &(rhentp->rh_address.ta_addr_v4); 1541f041b17Ston (void) inet_ntop(rhentp->rh_address.ta_family, aptr, abuf, 1551f041b17Ston abuflen); 1561f041b17Ston if (rhentp->rh_prefix != 32) { 1571f041b17Ston if (strlcat(abuf, tmpbuf, abuflen) >= abuflen) 1581f041b17Ston (void) fprintf(stderr, gettext( 1591f041b17Ston "tnctl: buffer overflow detected: %s\n"), 1601f041b17Ston abuf); 1611f041b17Ston } 162*5ccb772aSTony Nguyen *alen = strlen(abuf); 1631f041b17Ston } 1641f041b17Ston } 1651f041b17Ston 1661f041b17Ston /* 167f875b4ebSrica * Load remote host entries from the designated file. 168f875b4ebSrica */ 169f875b4ebSrica static void 170f875b4ebSrica process_rhl(const char *file) 171f875b4ebSrica { 172909c1a33Ston boolean_t error = B_FALSE; 173f875b4ebSrica boolean_t success = B_FALSE; 174f875b4ebSrica tsol_rhent_t *rhentp = NULL; 175f875b4ebSrica FILE *fp; 1761f041b17Ston int alen; 1771f041b17Ston /* abuf holds: <numeric-ip-addr>'/'<prefix-length>'\0' */ 1781f041b17Ston char abuf[INET6_ADDRSTRLEN+5]; 179f875b4ebSrica 180f875b4ebSrica if ((fp = fopen(file, "r")) == NULL) { 181f875b4ebSrica (void) fprintf(stderr, 182f875b4ebSrica gettext("tnctl: failed to open %1$s: %2$s\n"), 183f875b4ebSrica file, strerror(errno)); 184f875b4ebSrica exit(1); 185f875b4ebSrica } 186f875b4ebSrica 187f875b4ebSrica tsol_setrhent(1); 188909c1a33Ston while (rhentp = tsol_fgetrhent(fp, &error)) { 189f875b4ebSrica /* First time through the loop, flush it all */ 190f875b4ebSrica if (!success && flush_mode) 191f875b4ebSrica (void) tnrh(TNDB_FLUSH, NULL); 192f875b4ebSrica success = B_TRUE; 193f875b4ebSrica 194f875b4ebSrica if (verbose_mode) 195f875b4ebSrica (void) printf("loading rh entry...\n"); 196f875b4ebSrica 197f875b4ebSrica if (tnrh(TNDB_LOAD, rhentp) != 0) { 198f875b4ebSrica (void) fclose(fp); 199f875b4ebSrica if (errno == EFAULT) 200f875b4ebSrica perror("tnrh"); 201f875b4ebSrica else 2021f041b17Ston translate_inet_addr(rhentp, &alen, abuf, 2031f041b17Ston sizeof (abuf)); 204f875b4ebSrica (void) fprintf(stderr, 205f875b4ebSrica gettext("tnctl: load of remote-host entry " 206f875b4ebSrica "%1$s into kernel cache failed: %2$s\n"), 2071f041b17Ston abuf, strerror(errno)); 208f875b4ebSrica tsol_endrhent(); 209f875b4ebSrica exit(1); 210f875b4ebSrica } 211f875b4ebSrica tsol_freerhent(rhentp); 212f875b4ebSrica } 213f875b4ebSrica if (!success) { 214f875b4ebSrica (void) fprintf(stderr, 215f875b4ebSrica gettext("tnctl: No valid tnrhdb entries found in %s\n"), 216f875b4ebSrica file); 217f875b4ebSrica } 218f875b4ebSrica (void) fclose(fp); 219f875b4ebSrica tsol_endrhent(); 220909c1a33Ston 221909c1a33Ston if (error) 222909c1a33Ston exit(1); 223f875b4ebSrica } 224f875b4ebSrica 225f875b4ebSrica /* 226f875b4ebSrica * The argument can be either a host name, an address 227f875b4ebSrica * in tnrhdb address format, or a complete tnrhdb entry. 228f875b4ebSrica */ 229f875b4ebSrica static void 230f875b4ebSrica process_rh(const char *hostname) 231f875b4ebSrica { 232f875b4ebSrica tsol_rhstr_t rhstr; 233f875b4ebSrica tsol_rhent_t rhent; 234f875b4ebSrica tsol_rhent_t *rhentp; 235f875b4ebSrica int err; 236f875b4ebSrica int alen; 237f875b4ebSrica char *errstr; 238f875b4ebSrica /* abuf holds: <numeric-ip-addr>'/'<prefix-length>'\0' */ 239f875b4ebSrica char abuf[INET6_ADDRSTRLEN+5]; 240f875b4ebSrica const char *cp; 241f875b4ebSrica char *cp1; 242f875b4ebSrica char *cp2; 243f875b4ebSrica void *aptr; 244f875b4ebSrica char buf[NSS_BUFLEN_TSOL_RH]; 245f875b4ebSrica struct in6_addr ipv6addr; 246f875b4ebSrica 247f875b4ebSrica /* was a template name provided on the command line? */ 248f875b4ebSrica if ((cp = strrchr(hostname, ':')) != NULL && cp != hostname && 249f875b4ebSrica cp[-1] != '\\') { 250f875b4ebSrica /* use common tnrhdb line conversion function */ 251f875b4ebSrica (void) str_to_rhstr(hostname, strlen(hostname), &rhstr, buf, 252f875b4ebSrica sizeof (buf)); 253f875b4ebSrica rhentp = rhstr_to_ent(&rhstr, &err, &errstr); 254f875b4ebSrica if (rhentp == NULL) { 255f875b4ebSrica print_error(0, err, errstr); 256f875b4ebSrica exit(1); 257f875b4ebSrica } 258f875b4ebSrica } else { 259f875b4ebSrica char *hostname_p; 260f875b4ebSrica char *prefix_p; 261f875b4ebSrica struct hostent *hp; 262f875b4ebSrica 263f875b4ebSrica /* Check for a subnet prefix length */ 264f875b4ebSrica if ((prefix_p = strchr(hostname, '/')) != NULL) { 265f875b4ebSrica cp1 = prefix_p + 1; 266f875b4ebSrica errno = 0; 267f875b4ebSrica rhent.rh_prefix = strtol(cp1, &cp2, 0); 268f875b4ebSrica if (*cp2 != '\0' || errno != 0 || rhent.rh_prefix < 0) { 269f875b4ebSrica (void) fprintf(stderr, gettext("tnct: invalid " 270f875b4ebSrica "prefix length: %s\n"), cp); 271f875b4ebSrica exit(2); 272f875b4ebSrica } 273f875b4ebSrica } else { 274f875b4ebSrica rhent.rh_prefix = -1; 275f875b4ebSrica } 276f875b4ebSrica 277f875b4ebSrica /* Strip any backslashes from numeric address */ 278f875b4ebSrica hostname_p = malloc(strlen(hostname)+1); 279f875b4ebSrica if (hostname_p == NULL) { 280f875b4ebSrica perror("tnctl"); 281f875b4ebSrica exit(2); 282f875b4ebSrica } 283f875b4ebSrica cp1 = hostname_p; 284f875b4ebSrica while (*hostname != '\0' && *hostname != '/') { 285f875b4ebSrica *cp1 = *hostname++; 286f875b4ebSrica if (*cp1 != '\\') 287f875b4ebSrica cp1++; 288f875b4ebSrica } 289f875b4ebSrica *cp1 = '\0'; 290f875b4ebSrica 291f875b4ebSrica /* Convert address or hostname to binary af_inet6 format */ 292f875b4ebSrica hp = getipnodebyname(hostname_p, AF_INET6, 293f875b4ebSrica AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &err); 294f875b4ebSrica if (hp == NULL) { 295f875b4ebSrica (void) fprintf(stderr, gettext("tnctl: unknown host " 296f875b4ebSrica "or invalid literal address: %s\n"), hostname_p); 297f875b4ebSrica if (err == TRY_AGAIN) 298f875b4ebSrica (void) fprintf(stderr, 299f875b4ebSrica gettext("\t(try again later)\n")); 300f875b4ebSrica exit(2); 301f875b4ebSrica } 302f875b4ebSrica free(hostname_p); 303f875b4ebSrica (void) memcpy(&ipv6addr, hp->h_addr, hp->h_length); 304f875b4ebSrica 305f875b4ebSrica /* if ipv4 address, convert to af_inet format */ 306f875b4ebSrica if (IN6_IS_ADDR_V4MAPPED(&ipv6addr)) { 307f875b4ebSrica rhent.rh_address.ta_family = AF_INET; 308f875b4ebSrica IN6_V4MAPPED_TO_INADDR(&ipv6addr, 309f875b4ebSrica &rhent.rh_address.ta_addr_v4); 310f875b4ebSrica if (rhent.rh_prefix == -1) 311f875b4ebSrica rhent.rh_prefix = 32; 312f875b4ebSrica } else { 313f875b4ebSrica rhent.rh_address.ta_family = AF_INET6; 314f875b4ebSrica rhent.rh_address.ta_addr_v6 = ipv6addr; 315f875b4ebSrica if (rhent.rh_prefix == -1) 316f875b4ebSrica rhent.rh_prefix = 128; 317f875b4ebSrica } 318f875b4ebSrica rhent.rh_template[0] = '\0'; 319f875b4ebSrica rhentp = &rhent; 320f875b4ebSrica } 321f875b4ebSrica 322f875b4ebSrica /* produce ascii format of address and prefix length */ 3231f041b17Ston translate_inet_addr(rhentp, &alen, abuf, sizeof (abuf)); 324f875b4ebSrica 325f875b4ebSrica /* 326f875b4ebSrica * look up the entry from ldap or tnrhdb if this is a load 327f875b4ebSrica * request and a template name was not provided. 328f875b4ebSrica */ 329f875b4ebSrica if (!delete_mode && 330f875b4ebSrica rhentp->rh_template[0] == '\0' && 331*5ccb772aSTony Nguyen (rhentp = tsol_getrhbyaddr(abuf, alen+1, 332f875b4ebSrica rhent.rh_address.ta_family)) == NULL) { 333f875b4ebSrica (void) fprintf(stderr, 334f875b4ebSrica gettext("tnctl: database lookup failed for %s\n"), 335f875b4ebSrica abuf); 336f875b4ebSrica exit(1); 337f875b4ebSrica } 338f875b4ebSrica 339f875b4ebSrica if (verbose_mode) 340f875b4ebSrica (void) printf("%s rh entry %s\n", delete_mode ? "deleting" : 341f875b4ebSrica "loading", abuf); 342f875b4ebSrica 343f875b4ebSrica /* update the tnrhdb entry in the kernel */ 344f875b4ebSrica if (tnrh(delete_mode ? TNDB_DELETE : TNDB_LOAD, rhentp) != 0) { 345f875b4ebSrica if (errno == EFAULT) 346f875b4ebSrica perror("tnrh"); 347f875b4ebSrica else if (errno == ENOENT) 348f875b4ebSrica (void) fprintf(stderr, 349f875b4ebSrica gettext("tnctl: %1$s of remote-host kernel cache " 350f875b4ebSrica "entry %2$s failed: no such entry\n"), 351f875b4ebSrica delete_mode ? gettext("delete") : gettext("load"), 352f875b4ebSrica abuf); 353f875b4ebSrica else 354f875b4ebSrica (void) fprintf(stderr, 355f875b4ebSrica gettext("tnctl: %1$s of remote-host kernel cache " 356f875b4ebSrica "entry %2$s failed: %3$s\n"), 357f875b4ebSrica delete_mode ? gettext("delete") : gettext("load"), 358f875b4ebSrica abuf, strerror(errno)); 359f875b4ebSrica exit(1); 360f875b4ebSrica } 361f875b4ebSrica if (rhentp != &rhent) 362f875b4ebSrica tsol_freerhent(rhentp); 363f875b4ebSrica } 364f875b4ebSrica 365f875b4ebSrica static void 366f875b4ebSrica handle_mlps(zoneid_t zoneid, tsol_mlp_t *mlp, int flags, int cmd) 367f875b4ebSrica { 368f875b4ebSrica tsol_mlpent_t tsme; 369f875b4ebSrica 370f875b4ebSrica tsme.tsme_zoneid = zoneid; 371f875b4ebSrica tsme.tsme_flags = flags; 372f875b4ebSrica while (!TSOL_MLP_END(mlp)) { 373f875b4ebSrica tsme.tsme_mlp = *mlp; 374f875b4ebSrica if (tnmlp(cmd, &tsme) != 0) { 375f875b4ebSrica /* 376f875b4ebSrica * Usage of ?: here is ugly, but helps with 377f875b4ebSrica * localization. 378f875b4ebSrica */ 379f875b4ebSrica (void) fprintf(stderr, 380f875b4ebSrica flags & TSOL_MEF_SHARED ? 381f875b4ebSrica gettext("tnctl: cannot set " 382f875b4ebSrica "shared MLP on %1$d-%2$d/%3$d: %4$s\n") : 383f875b4ebSrica gettext("tnctl: cannot set " 384f875b4ebSrica "zone-specific MLP on %1$d-%2$d/%3$d: %4$s\n"), 385f875b4ebSrica mlp->mlp_port, mlp->mlp_port_upper, mlp->mlp_ipp, 386f875b4ebSrica strerror(errno)); 387f875b4ebSrica exit(1); 388f875b4ebSrica } 389f875b4ebSrica mlp++; 390f875b4ebSrica } 391f875b4ebSrica } 392f875b4ebSrica 393f875b4ebSrica /* 394f875b4ebSrica * This reads the configuration for the global zone out of tnzonecfg 395f875b4ebSrica * and sets it in the kernel. The non-global zones are configured 396f875b4ebSrica * by zoneadmd. 397f875b4ebSrica */ 398f875b4ebSrica static void 399f875b4ebSrica process_tnzone(const char *file) 400f875b4ebSrica { 401f875b4ebSrica tsol_zcent_t *zc; 402f875b4ebSrica tsol_mlpent_t tsme; 403f875b4ebSrica int err; 404f875b4ebSrica char *errstr; 405f875b4ebSrica FILE *fp; 406f875b4ebSrica char line[2048], *cp; 407f875b4ebSrica int linenum, errors; 408f875b4ebSrica 409f875b4ebSrica if ((fp = fopen(file, "r")) == NULL) { 410f875b4ebSrica (void) fprintf(stderr, 411f875b4ebSrica gettext("tnctl: failed to open %s: %s\n"), file, 412f875b4ebSrica strerror(errno)); 413f875b4ebSrica exit(1); 414f875b4ebSrica } 415f875b4ebSrica 416f875b4ebSrica linenum = errors = 0; 417f875b4ebSrica zc = NULL; 418f875b4ebSrica while (fgets(line, sizeof (line), fp) != NULL) { 419f875b4ebSrica if ((cp = strchr(line, '\n')) != NULL) 420f875b4ebSrica *cp = '\0'; 421f875b4ebSrica 422f875b4ebSrica linenum++; 423f875b4ebSrica if ((zc = tsol_sgetzcent(line, &err, &errstr)) == NULL) { 424f875b4ebSrica if (err == LTSNET_EMPTY) 425f875b4ebSrica continue; 426f875b4ebSrica if (errors == 0) { 427f875b4ebSrica int errtmp = errno; 428f875b4ebSrica 429f875b4ebSrica (void) fprintf(stderr, gettext("tnctl: errors " 430f875b4ebSrica "parsing %s:\n"), file); 431f875b4ebSrica errno = errtmp; 432f875b4ebSrica } 433f875b4ebSrica print_error(linenum, err, errstr); 434f875b4ebSrica errors++; 435f875b4ebSrica continue; 436f875b4ebSrica } 437f875b4ebSrica 438f875b4ebSrica if (strcasecmp(zc->zc_name, "global") == 0) 439f875b4ebSrica break; 440f875b4ebSrica tsol_freezcent(zc); 441f875b4ebSrica } 442f875b4ebSrica (void) fclose(fp); 443f875b4ebSrica 444f875b4ebSrica if (zc == NULL) { 445f875b4ebSrica (void) fprintf(stderr, 446f875b4ebSrica gettext("tnctl: cannot find global zone in %s\n"), file); 447f875b4ebSrica exit(1); 448f875b4ebSrica } 449f875b4ebSrica 450f875b4ebSrica tsme.tsme_zoneid = GLOBAL_ZONEID; 451f875b4ebSrica tsme.tsme_flags = 0; 452f875b4ebSrica if (flush_mode) 453f875b4ebSrica (void) tnmlp(TNDB_FLUSH, &tsme); 454f875b4ebSrica 455f875b4ebSrica handle_mlps(GLOBAL_ZONEID, zc->zc_private_mlp, 0, TNDB_LOAD); 456f875b4ebSrica handle_mlps(GLOBAL_ZONEID, zc->zc_shared_mlp, TSOL_MEF_SHARED, 457f875b4ebSrica TNDB_LOAD); 458f875b4ebSrica 459f875b4ebSrica tsol_freezcent(zc); 460f875b4ebSrica } 461f875b4ebSrica 462f875b4ebSrica static void 463f875b4ebSrica process_tpl(const char *file) 464f875b4ebSrica { 465f875b4ebSrica FILE *fp; 466909c1a33Ston boolean_t error = B_FALSE; 467f875b4ebSrica boolean_t success = B_FALSE; 468f875b4ebSrica tsol_tpent_t *tpentp; 469f875b4ebSrica 470f875b4ebSrica if ((fp = fopen(file, "r")) == NULL) { 471f875b4ebSrica (void) fprintf(stderr, 472f875b4ebSrica gettext("tnctl: failed to open %s: %s\n"), file, 473f875b4ebSrica strerror(errno)); 474f875b4ebSrica exit(1); 475f875b4ebSrica } 476f875b4ebSrica 477f875b4ebSrica tsol_settpent(1); 478909c1a33Ston while (tpentp = tsol_fgettpent(fp, &error)) { 479f875b4ebSrica /* First time through the loop, flush it all */ 480f875b4ebSrica if (!success && flush_mode) 481f875b4ebSrica (void) tnrhtp(TNDB_FLUSH, NULL); 482f875b4ebSrica 483f875b4ebSrica success = B_TRUE; 484f875b4ebSrica 485f875b4ebSrica if (verbose_mode) 486f875b4ebSrica (void) printf("tnctl: loading rhtp entry ...\n"); 487f875b4ebSrica 488f875b4ebSrica if (tnrhtp(TNDB_LOAD, tpentp) != 0) { 489f875b4ebSrica (void) fclose(fp); 490f875b4ebSrica if (errno == EFAULT) 491f875b4ebSrica perror("tnrhtp"); 492f875b4ebSrica else 493f875b4ebSrica (void) fprintf(stderr, gettext("tnctl: load " 494f875b4ebSrica "of remote-host template %1$s into kernel " 495f875b4ebSrica "cache failed: %2$s\n"), tpentp->name, 496f875b4ebSrica strerror(errno)); 497f875b4ebSrica tsol_endtpent(); 498f875b4ebSrica exit(1); 499f875b4ebSrica } 500f875b4ebSrica tsol_freetpent(tpentp); 501f875b4ebSrica } 502f875b4ebSrica if (!success) { 503f875b4ebSrica (void) fprintf(stderr, 504f875b4ebSrica gettext("tnctl: No valid tnrhtp entries found in %s\n"), 505f875b4ebSrica file); 506f875b4ebSrica } 507f875b4ebSrica (void) fclose(fp); 508f875b4ebSrica tsol_endtpent(); 509909c1a33Ston 510909c1a33Ston if (error) 511909c1a33Ston exit(1); 512f875b4ebSrica } 513f875b4ebSrica 514f875b4ebSrica static void 515f875b4ebSrica process_tp(const char *template) 516f875b4ebSrica { 517f875b4ebSrica tsol_tpstr_t tpstr; 518f875b4ebSrica tsol_tpent_t tpent; 519f875b4ebSrica tsol_tpent_t *tpentp; 520f875b4ebSrica int err; 521f875b4ebSrica char *errstr; 522f875b4ebSrica char buf[NSS_BUFLEN_TSOL_TP]; 523f875b4ebSrica 524f875b4ebSrica if (strchr(template, ':') != NULL) { 525f875b4ebSrica (void) str_to_tpstr(template, strlen(template), &tpstr, buf, 526f875b4ebSrica sizeof (buf)); 527f875b4ebSrica tpentp = tpstr_to_ent(&tpstr, &err, &errstr); 528f875b4ebSrica if (tpentp == NULL) { 529f875b4ebSrica print_error(0, err, errstr); 530f875b4ebSrica exit(1); 531f875b4ebSrica } 532f875b4ebSrica } else if (delete_mode) { 533f875b4ebSrica (void) memset(&tpent, 0, sizeof (tpent)); 534f875b4ebSrica tpentp = &tpent; 535f875b4ebSrica (void) strlcpy(tpentp->name, template, sizeof (tpentp->name)); 536f875b4ebSrica } else if ((tpentp = tsol_gettpbyname(template)) == NULL) { 537f875b4ebSrica (void) fprintf(stderr, 538f875b4ebSrica gettext("tnctl: template %s not found\n"), template); 539f875b4ebSrica exit(1); 540f875b4ebSrica } 541f875b4ebSrica 542f875b4ebSrica if (verbose_mode) 543f875b4ebSrica (void) printf("%s rhtp entry ...\n", delete_mode ? "deleting" : 544f875b4ebSrica "loading"); 545f875b4ebSrica 546f875b4ebSrica if (tnrhtp(delete_mode ? TNDB_DELETE : TNDB_LOAD, tpentp) != 0) { 547f875b4ebSrica if (errno == EFAULT) 548f875b4ebSrica perror("tnrhtp"); 549f875b4ebSrica else if (errno == ENOENT) 550f875b4ebSrica (void) fprintf(stderr, 551f875b4ebSrica gettext("tnctl: %1$s of remote-host template " 552f875b4ebSrica "kernel cache entry %2$s failed: no such " 553f875b4ebSrica "entry\n"), 554f875b4ebSrica delete_mode ? gettext("delete") : gettext("load"), 555f875b4ebSrica tpentp->name); 556f875b4ebSrica else 557f875b4ebSrica (void) fprintf(stderr, 558f875b4ebSrica gettext("tnctl: %1$s of remote-host template " 559f875b4ebSrica "kernel cache entry %2$s failed: %3$s\n"), 560f875b4ebSrica delete_mode ? gettext("delete") : gettext("load"), 561f875b4ebSrica tpentp->name, strerror(errno)); 562f875b4ebSrica exit(1); 563f875b4ebSrica } 564f875b4ebSrica if (tpentp != &tpent) 565f875b4ebSrica tsol_freetpent(tpentp); 566f875b4ebSrica } 567f875b4ebSrica 568f875b4ebSrica static void 569f875b4ebSrica process_mlp(const char *str) 570f875b4ebSrica { 571f875b4ebSrica const char *cp; 572f875b4ebSrica char zonename[ZONENAME_MAX]; 573f875b4ebSrica zoneid_t zoneid; 574f875b4ebSrica tsol_zcent_t *zc; 575f875b4ebSrica int err; 576f875b4ebSrica char *errstr; 577f875b4ebSrica char *sbuf; 578f875b4ebSrica 579f875b4ebSrica if ((cp = strchr(str, ':')) == NULL) { 580f875b4ebSrica if (!delete_mode) { 581f875b4ebSrica (void) fprintf(stderr, 582f875b4ebSrica gettext("tnctl: need MLP list to insert\n")); 583f875b4ebSrica exit(2); 584f875b4ebSrica } 585f875b4ebSrica (void) strlcpy(zonename, str, sizeof (zonename)); 586f875b4ebSrica } else if (cp - str >= ZONENAME_MAX) { 587f875b4ebSrica (void) fprintf(stderr, gettext("tnctl: illegal zone name\n")); 588f875b4ebSrica exit(2); 589f875b4ebSrica } else { 590f875b4ebSrica (void) memcpy(zonename, str, cp - str); 591f875b4ebSrica zonename[cp - str] = '\0'; 592f875b4ebSrica str = cp + 1; 593f875b4ebSrica } 594f875b4ebSrica 595f875b4ebSrica if ((zoneid = getzoneidbyname(zonename)) == -1) { 596f875b4ebSrica (void) fprintf(stderr, gettext("tninfo: zone '%s' unknown\n"), 597f875b4ebSrica zonename); 598f875b4ebSrica exit(1); 599f875b4ebSrica } 600f875b4ebSrica 601f875b4ebSrica sbuf = malloc(strlen(zonename) + sizeof (":ADMIN_LOW:0:") + 602f875b4ebSrica strlen(str)); 603f875b4ebSrica if (sbuf == NULL) { 604f875b4ebSrica perror("malloc"); 605f875b4ebSrica exit(1); 606f875b4ebSrica } 607f875b4ebSrica /* LINTED: sprintf is known not to be unbounded here */ 608f875b4ebSrica (void) sprintf(sbuf, "%s:ADMIN_LOW:0:%s", zonename, str); 609f875b4ebSrica if ((zc = tsol_sgetzcent(sbuf, &err, &errstr)) == NULL) { 610f875b4ebSrica (void) fprintf(stderr, 611f875b4ebSrica gettext("tnctl: unable to parse MLPs\n")); 612f875b4ebSrica exit(1); 613f875b4ebSrica } 614f875b4ebSrica handle_mlps(zoneid, zc->zc_private_mlp, 0, 615f875b4ebSrica delete_mode ? TNDB_DELETE : TNDB_LOAD); 616f875b4ebSrica handle_mlps(zoneid, zc->zc_shared_mlp, TSOL_MEF_SHARED, 617f875b4ebSrica delete_mode ? TNDB_DELETE : TNDB_LOAD); 618f875b4ebSrica tsol_freezcent(zc); 619f875b4ebSrica } 620f875b4ebSrica 621f875b4ebSrica static void 622f875b4ebSrica usage(void) 623f875b4ebSrica { 624f875b4ebSrica (void) fprintf(stderr, gettext("usage: tnctl [-dfv] " 625f875b4ebSrica "[-h host[/prefix][:tmpl]] [-m zone:priv:share]\n\t" 626f875b4ebSrica "[-t tmpl[:key=val[;key=val]]] [-[HTz] file]\n")); 627f875b4ebSrica 628f875b4ebSrica exit(1); 629f875b4ebSrica } 630