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