14746Srica /* 24746Srica * CDDL HEADER START 34746Srica * 44746Srica * The contents of this file are subject to the terms of the 54746Srica * Common Development and Distribution License (the "License"). 64746Srica * You may not use this file except in compliance with the License. 74746Srica * 84746Srica * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94746Srica * or http://www.opensolaris.org/os/licensing. 104746Srica * See the License for the specific language governing permissions 114746Srica * and limitations under the License. 124746Srica * 134746Srica * When distributing Covered Code, include this CDDL HEADER in each 144746Srica * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154746Srica * If applicable, add the following below this CDDL HEADER, with the 164746Srica * fields enclosed by brackets "[]" replaced with your own identifying 174746Srica * information: Portions Copyright [yyyy] [name of copyright owner] 184746Srica * 194746Srica * CDDL HEADER END 204746Srica */ 214746Srica 224746Srica /* 23*6509Ston * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 244746Srica * Use is subject to license terms. 254746Srica */ 264746Srica 274746Srica #pragma ident "%Z%%M% %I% %E% SMI" 284746Srica 294746Srica /* 304746Srica * tnctl.c - 314746Srica * Trusted Network control utility 324746Srica */ 334746Srica #include <stdio.h> 344746Srica #include <stdlib.h> 354746Srica #include <stddef.h> 364746Srica #include <unistd.h> 374746Srica #include <string.h> 384746Srica #include <errno.h> 394746Srica #include <locale.h> 404746Srica #include <fcntl.h> 414746Srica #include <sys/types.h> 424746Srica #include <sys/param.h> 434746Srica #include <sys/socket.h> 444746Srica #include <netinet/in.h> 454746Srica #include <arpa/inet.h> 464746Srica #include <netdb.h> 474746Srica #include <libtsnet.h> 484746Srica #include <zone.h> 494746Srica #include <nss_dbdefs.h> 504746Srica 514746Srica static void process_rh(const char *); 524746Srica static void process_rhl(const char *); 534746Srica static void process_mlp(const char *); 544746Srica static void process_tp(const char *); 554746Srica static void process_tpl(const char *); 564746Srica static void process_tnzone(const char *); 574746Srica static void usage(void); 585250Ston static void translate_inet_addr(tsol_rhent_t *, int *, char [], int); 594746Srica 604746Srica static boolean_t verbose_mode; 614746Srica static boolean_t delete_mode; 624746Srica static boolean_t flush_mode; 634746Srica 644746Srica int 654746Srica main(int argc, char **argv) 664746Srica { 674746Srica extern char *optarg; 684746Srica int chr; 694746Srica 704746Srica /* Don't do anything if labeling is not active. */ 714746Srica if (!is_system_labeled()) 724746Srica return (0); 734746Srica 744746Srica /* set the locale for only the messages system (all else is clean) */ 754746Srica (void) setlocale(LC_ALL, ""); 764746Srica #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ 774746Srica #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 784746Srica #endif 794746Srica 804746Srica (void) textdomain(TEXT_DOMAIN); 814746Srica 824746Srica while ((chr = getopt(argc, argv, "dfh:H:m:t:T:vz:")) != EOF) { 834746Srica switch (chr) { 844746Srica case 'd': 854746Srica delete_mode = B_TRUE; 864746Srica break; 874746Srica case 'f': 884746Srica flush_mode = B_TRUE; 894746Srica break; 904746Srica case 'h': 914746Srica process_rh(optarg); 924746Srica break; 934746Srica case 'H': 944746Srica process_rhl(optarg); 954746Srica break; 964746Srica case 'm': 974746Srica process_mlp(optarg); 984746Srica break; 994746Srica case 't': 1004746Srica process_tp(optarg); 1014746Srica break; 1024746Srica case 'T': 1034746Srica process_tpl(optarg); 1044746Srica break; 1054746Srica case 'v': 1064746Srica verbose_mode = B_TRUE; 1074746Srica break; 1084746Srica case 'z': 1094746Srica process_tnzone(optarg); 1104746Srica break; 1114746Srica case '?': 1124746Srica usage(); 1134746Srica } 1144746Srica } 1154746Srica return (0); 1164746Srica } 1174746Srica 1184746Srica static void 1194746Srica print_error(int linenum, int err, const char *errstr) 1204746Srica { 1214746Srica if (linenum > 0) 1224746Srica (void) fprintf(stderr, gettext("line %1$d: %2$s:\n"), linenum, 1234746Srica tsol_strerror(err, errno)); 1244746Srica else 1254746Srica (void) fprintf(stderr, gettext("tnctl: parsing error: %s\n"), 1264746Srica tsol_strerror(err, errno)); 1274746Srica (void) fprintf(stderr, "%.32s\n", errstr); 1284746Srica } 1294746Srica 1304746Srica /* 1315250Ston * Produce ascii format of address and prefix length 1325250Ston */ 1335250Ston static void 1345250Ston translate_inet_addr(tsol_rhent_t *rhentp, int *alen, char abuf[], int abuflen) 1355250Ston { 1365250Ston void *aptr; 1375250Ston tsol_rhent_t rhent; 1385250Ston struct in6_addr ipv6addr; 1395250Ston char tmpbuf[20]; 1405250Ston 1415250Ston (void) snprintf(tmpbuf, sizeof (tmpbuf), "/%d", rhentp->rh_prefix); 1425250Ston 1435250Ston if (rhentp->rh_address.ta_family == AF_INET6) { 1445250Ston aptr = &(rhentp->rh_address.ta_addr_v6); 1455250Ston *alen = sizeof (ipv6addr); 1465250Ston (void) inet_ntop(rhentp->rh_address.ta_family, aptr, abuf, 1475250Ston abuflen); 1485250Ston if (rhentp->rh_prefix != 128) { 1495250Ston if (strlcat(abuf, tmpbuf, abuflen) >= abuflen) 1505250Ston (void) fprintf(stderr, gettext( 1515250Ston "tnctl: buffer overflow detected: %s\n"), 1525250Ston abuf); 1535250Ston } 1545250Ston } else { 1555250Ston aptr = &(rhentp->rh_address.ta_addr_v4); 1565250Ston *alen = sizeof (rhent.rh_address.ta_addr_v4); 1575250Ston (void) inet_ntop(rhentp->rh_address.ta_family, aptr, abuf, 1585250Ston abuflen); 1595250Ston if (rhentp->rh_prefix != 32) { 1605250Ston if (strlcat(abuf, tmpbuf, abuflen) >= abuflen) 1615250Ston (void) fprintf(stderr, gettext( 1625250Ston "tnctl: buffer overflow detected: %s\n"), 1635250Ston abuf); 1645250Ston } 1655250Ston } 1665250Ston } 1675250Ston 1685250Ston /* 1694746Srica * Load remote host entries from the designated file. 1704746Srica */ 1714746Srica static void 1724746Srica process_rhl(const char *file) 1734746Srica { 174*6509Ston boolean_t error = B_FALSE; 1754746Srica boolean_t success = B_FALSE; 1764746Srica tsol_rhent_t *rhentp = NULL; 1774746Srica FILE *fp; 1785250Ston int alen; 1795250Ston /* abuf holds: <numeric-ip-addr>'/'<prefix-length>'\0' */ 1805250Ston char abuf[INET6_ADDRSTRLEN+5]; 1814746Srica 1824746Srica if ((fp = fopen(file, "r")) == NULL) { 1834746Srica (void) fprintf(stderr, 1844746Srica gettext("tnctl: failed to open %1$s: %2$s\n"), 1854746Srica file, strerror(errno)); 1864746Srica exit(1); 1874746Srica } 1884746Srica 1894746Srica tsol_setrhent(1); 190*6509Ston while (rhentp = tsol_fgetrhent(fp, &error)) { 1914746Srica /* First time through the loop, flush it all */ 1924746Srica if (!success && flush_mode) 1934746Srica (void) tnrh(TNDB_FLUSH, NULL); 1944746Srica success = B_TRUE; 1954746Srica 1964746Srica if (verbose_mode) 1974746Srica (void) printf("loading rh entry...\n"); 1984746Srica 1994746Srica if (tnrh(TNDB_LOAD, rhentp) != 0) { 2004746Srica (void) fclose(fp); 2014746Srica if (errno == EFAULT) 2024746Srica perror("tnrh"); 2034746Srica else 2045250Ston translate_inet_addr(rhentp, &alen, abuf, 2055250Ston sizeof (abuf)); 2064746Srica (void) fprintf(stderr, 2074746Srica gettext("tnctl: load of remote-host entry " 2084746Srica "%1$s into kernel cache failed: %2$s\n"), 2095250Ston abuf, strerror(errno)); 2104746Srica tsol_endrhent(); 2114746Srica exit(1); 2124746Srica } 2134746Srica tsol_freerhent(rhentp); 2144746Srica } 2154746Srica if (!success) { 2164746Srica (void) fprintf(stderr, 2174746Srica gettext("tnctl: No valid tnrhdb entries found in %s\n"), 2184746Srica file); 2194746Srica } 2204746Srica (void) fclose(fp); 2214746Srica tsol_endrhent(); 222*6509Ston 223*6509Ston if (error) 224*6509Ston exit(1); 2254746Srica } 2264746Srica 2274746Srica /* 2284746Srica * The argument can be either a host name, an address 2294746Srica * in tnrhdb address format, or a complete tnrhdb entry. 2304746Srica */ 2314746Srica static void 2324746Srica process_rh(const char *hostname) 2334746Srica { 2344746Srica tsol_rhstr_t rhstr; 2354746Srica tsol_rhent_t rhent; 2364746Srica tsol_rhent_t *rhentp; 2374746Srica int err; 2384746Srica int alen; 2394746Srica char *errstr; 2404746Srica /* abuf holds: <numeric-ip-addr>'/'<prefix-length>'\0' */ 2414746Srica char abuf[INET6_ADDRSTRLEN+5]; 2424746Srica const char *cp; 2434746Srica char *cp1; 2444746Srica char *cp2; 2454746Srica void *aptr; 2464746Srica char buf[NSS_BUFLEN_TSOL_RH]; 2474746Srica struct in6_addr ipv6addr; 2484746Srica 2494746Srica /* was a template name provided on the command line? */ 2504746Srica if ((cp = strrchr(hostname, ':')) != NULL && cp != hostname && 2514746Srica cp[-1] != '\\') { 2524746Srica /* use common tnrhdb line conversion function */ 2534746Srica (void) str_to_rhstr(hostname, strlen(hostname), &rhstr, buf, 2544746Srica sizeof (buf)); 2554746Srica rhentp = rhstr_to_ent(&rhstr, &err, &errstr); 2564746Srica if (rhentp == NULL) { 2574746Srica print_error(0, err, errstr); 2584746Srica exit(1); 2594746Srica } 2604746Srica } else { 2614746Srica char *hostname_p; 2624746Srica char *prefix_p; 2634746Srica struct hostent *hp; 2644746Srica 2654746Srica /* Check for a subnet prefix length */ 2664746Srica if ((prefix_p = strchr(hostname, '/')) != NULL) { 2674746Srica cp1 = prefix_p + 1; 2684746Srica errno = 0; 2694746Srica rhent.rh_prefix = strtol(cp1, &cp2, 0); 2704746Srica if (*cp2 != '\0' || errno != 0 || rhent.rh_prefix < 0) { 2714746Srica (void) fprintf(stderr, gettext("tnct: invalid " 2724746Srica "prefix length: %s\n"), cp); 2734746Srica exit(2); 2744746Srica } 2754746Srica } else { 2764746Srica rhent.rh_prefix = -1; 2774746Srica } 2784746Srica 2794746Srica /* Strip any backslashes from numeric address */ 2804746Srica hostname_p = malloc(strlen(hostname)+1); 2814746Srica if (hostname_p == NULL) { 2824746Srica perror("tnctl"); 2834746Srica exit(2); 2844746Srica } 2854746Srica cp1 = hostname_p; 2864746Srica while (*hostname != '\0' && *hostname != '/') { 2874746Srica *cp1 = *hostname++; 2884746Srica if (*cp1 != '\\') 2894746Srica cp1++; 2904746Srica } 2914746Srica *cp1 = '\0'; 2924746Srica 2934746Srica /* Convert address or hostname to binary af_inet6 format */ 2944746Srica hp = getipnodebyname(hostname_p, AF_INET6, 2954746Srica AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &err); 2964746Srica if (hp == NULL) { 2974746Srica (void) fprintf(stderr, gettext("tnctl: unknown host " 2984746Srica "or invalid literal address: %s\n"), hostname_p); 2994746Srica if (err == TRY_AGAIN) 3004746Srica (void) fprintf(stderr, 3014746Srica gettext("\t(try again later)\n")); 3024746Srica exit(2); 3034746Srica } 3044746Srica free(hostname_p); 3054746Srica (void) memcpy(&ipv6addr, hp->h_addr, hp->h_length); 3064746Srica 3074746Srica /* if ipv4 address, convert to af_inet format */ 3084746Srica if (IN6_IS_ADDR_V4MAPPED(&ipv6addr)) { 3094746Srica rhent.rh_address.ta_family = AF_INET; 3104746Srica IN6_V4MAPPED_TO_INADDR(&ipv6addr, 3114746Srica &rhent.rh_address.ta_addr_v4); 3124746Srica if (rhent.rh_prefix == -1) 3134746Srica rhent.rh_prefix = 32; 3144746Srica } else { 3154746Srica rhent.rh_address.ta_family = AF_INET6; 3164746Srica rhent.rh_address.ta_addr_v6 = ipv6addr; 3174746Srica if (rhent.rh_prefix == -1) 3184746Srica rhent.rh_prefix = 128; 3194746Srica } 3204746Srica rhent.rh_template[0] = '\0'; 3214746Srica rhentp = &rhent; 3224746Srica } 3234746Srica 3244746Srica /* produce ascii format of address and prefix length */ 3255250Ston translate_inet_addr(rhentp, &alen, abuf, sizeof (abuf)); 3264746Srica 3274746Srica /* 3284746Srica * look up the entry from ldap or tnrhdb if this is a load 3294746Srica * request and a template name was not provided. 3304746Srica */ 3314746Srica if (!delete_mode && 3324746Srica rhentp->rh_template[0] == '\0' && 3334746Srica (rhentp = tsol_getrhbyaddr(abuf, alen, 3344746Srica rhent.rh_address.ta_family)) == NULL) { 3354746Srica (void) fprintf(stderr, 3364746Srica gettext("tnctl: database lookup failed for %s\n"), 3374746Srica abuf); 3384746Srica exit(1); 3394746Srica } 3404746Srica 3414746Srica if (verbose_mode) 3424746Srica (void) printf("%s rh entry %s\n", delete_mode ? "deleting" : 3434746Srica "loading", abuf); 3444746Srica 3454746Srica /* update the tnrhdb entry in the kernel */ 3464746Srica if (tnrh(delete_mode ? TNDB_DELETE : TNDB_LOAD, rhentp) != 0) { 3474746Srica if (errno == EFAULT) 3484746Srica perror("tnrh"); 3494746Srica else if (errno == ENOENT) 3504746Srica (void) fprintf(stderr, 3514746Srica gettext("tnctl: %1$s of remote-host kernel cache " 3524746Srica "entry %2$s failed: no such entry\n"), 3534746Srica delete_mode ? gettext("delete") : gettext("load"), 3544746Srica abuf); 3554746Srica else 3564746Srica (void) fprintf(stderr, 3574746Srica gettext("tnctl: %1$s of remote-host kernel cache " 3584746Srica "entry %2$s failed: %3$s\n"), 3594746Srica delete_mode ? gettext("delete") : gettext("load"), 3604746Srica abuf, strerror(errno)); 3614746Srica exit(1); 3624746Srica } 3634746Srica if (rhentp != &rhent) 3644746Srica tsol_freerhent(rhentp); 3654746Srica } 3664746Srica 3674746Srica static void 3684746Srica handle_mlps(zoneid_t zoneid, tsol_mlp_t *mlp, int flags, int cmd) 3694746Srica { 3704746Srica tsol_mlpent_t tsme; 3714746Srica 3724746Srica tsme.tsme_zoneid = zoneid; 3734746Srica tsme.tsme_flags = flags; 3744746Srica while (!TSOL_MLP_END(mlp)) { 3754746Srica tsme.tsme_mlp = *mlp; 3764746Srica if (tnmlp(cmd, &tsme) != 0) { 3774746Srica /* 3784746Srica * Usage of ?: here is ugly, but helps with 3794746Srica * localization. 3804746Srica */ 3814746Srica (void) fprintf(stderr, 3824746Srica flags & TSOL_MEF_SHARED ? 3834746Srica gettext("tnctl: cannot set " 3844746Srica "shared MLP on %1$d-%2$d/%3$d: %4$s\n") : 3854746Srica gettext("tnctl: cannot set " 3864746Srica "zone-specific MLP on %1$d-%2$d/%3$d: %4$s\n"), 3874746Srica mlp->mlp_port, mlp->mlp_port_upper, mlp->mlp_ipp, 3884746Srica strerror(errno)); 3894746Srica exit(1); 3904746Srica } 3914746Srica mlp++; 3924746Srica } 3934746Srica } 3944746Srica 3954746Srica /* 3964746Srica * This reads the configuration for the global zone out of tnzonecfg 3974746Srica * and sets it in the kernel. The non-global zones are configured 3984746Srica * by zoneadmd. 3994746Srica */ 4004746Srica static void 4014746Srica process_tnzone(const char *file) 4024746Srica { 4034746Srica tsol_zcent_t *zc; 4044746Srica tsol_mlpent_t tsme; 4054746Srica int err; 4064746Srica char *errstr; 4074746Srica FILE *fp; 4084746Srica char line[2048], *cp; 4094746Srica int linenum, errors; 4104746Srica 4114746Srica if ((fp = fopen(file, "r")) == NULL) { 4124746Srica (void) fprintf(stderr, 4134746Srica gettext("tnctl: failed to open %s: %s\n"), file, 4144746Srica strerror(errno)); 4154746Srica exit(1); 4164746Srica } 4174746Srica 4184746Srica linenum = errors = 0; 4194746Srica zc = NULL; 4204746Srica while (fgets(line, sizeof (line), fp) != NULL) { 4214746Srica if ((cp = strchr(line, '\n')) != NULL) 4224746Srica *cp = '\0'; 4234746Srica 4244746Srica linenum++; 4254746Srica if ((zc = tsol_sgetzcent(line, &err, &errstr)) == NULL) { 4264746Srica if (err == LTSNET_EMPTY) 4274746Srica continue; 4284746Srica if (errors == 0) { 4294746Srica int errtmp = errno; 4304746Srica 4314746Srica (void) fprintf(stderr, gettext("tnctl: errors " 4324746Srica "parsing %s:\n"), file); 4334746Srica errno = errtmp; 4344746Srica } 4354746Srica print_error(linenum, err, errstr); 4364746Srica errors++; 4374746Srica continue; 4384746Srica } 4394746Srica 4404746Srica if (strcasecmp(zc->zc_name, "global") == 0) 4414746Srica break; 4424746Srica tsol_freezcent(zc); 4434746Srica } 4444746Srica (void) fclose(fp); 4454746Srica 4464746Srica if (zc == NULL) { 4474746Srica (void) fprintf(stderr, 4484746Srica gettext("tnctl: cannot find global zone in %s\n"), file); 4494746Srica exit(1); 4504746Srica } 4514746Srica 4524746Srica tsme.tsme_zoneid = GLOBAL_ZONEID; 4534746Srica tsme.tsme_flags = 0; 4544746Srica if (flush_mode) 4554746Srica (void) tnmlp(TNDB_FLUSH, &tsme); 4564746Srica 4574746Srica handle_mlps(GLOBAL_ZONEID, zc->zc_private_mlp, 0, TNDB_LOAD); 4584746Srica handle_mlps(GLOBAL_ZONEID, zc->zc_shared_mlp, TSOL_MEF_SHARED, 4594746Srica TNDB_LOAD); 4604746Srica 4614746Srica tsol_freezcent(zc); 4624746Srica } 4634746Srica 4644746Srica static void 4654746Srica process_tpl(const char *file) 4664746Srica { 4674746Srica FILE *fp; 468*6509Ston boolean_t error = B_FALSE; 4694746Srica boolean_t success = B_FALSE; 4704746Srica tsol_tpent_t *tpentp; 4714746Srica 4724746Srica if ((fp = fopen(file, "r")) == NULL) { 4734746Srica (void) fprintf(stderr, 4744746Srica gettext("tnctl: failed to open %s: %s\n"), file, 4754746Srica strerror(errno)); 4764746Srica exit(1); 4774746Srica } 4784746Srica 4794746Srica tsol_settpent(1); 480*6509Ston while (tpentp = tsol_fgettpent(fp, &error)) { 4814746Srica /* First time through the loop, flush it all */ 4824746Srica if (!success && flush_mode) 4834746Srica (void) tnrhtp(TNDB_FLUSH, NULL); 4844746Srica 4854746Srica success = B_TRUE; 4864746Srica 4874746Srica if (verbose_mode) 4884746Srica (void) printf("tnctl: loading rhtp entry ...\n"); 4894746Srica 4904746Srica if (tnrhtp(TNDB_LOAD, tpentp) != 0) { 4914746Srica (void) fclose(fp); 4924746Srica if (errno == EFAULT) 4934746Srica perror("tnrhtp"); 4944746Srica else 4954746Srica (void) fprintf(stderr, gettext("tnctl: load " 4964746Srica "of remote-host template %1$s into kernel " 4974746Srica "cache failed: %2$s\n"), tpentp->name, 4984746Srica strerror(errno)); 4994746Srica tsol_endtpent(); 5004746Srica exit(1); 5014746Srica } 5024746Srica tsol_freetpent(tpentp); 5034746Srica } 5044746Srica if (!success) { 5054746Srica (void) fprintf(stderr, 5064746Srica gettext("tnctl: No valid tnrhtp entries found in %s\n"), 5074746Srica file); 5084746Srica } 5094746Srica (void) fclose(fp); 5104746Srica tsol_endtpent(); 511*6509Ston 512*6509Ston if (error) 513*6509Ston exit(1); 5144746Srica } 5154746Srica 5164746Srica static void 5174746Srica process_tp(const char *template) 5184746Srica { 5194746Srica tsol_tpstr_t tpstr; 5204746Srica tsol_tpent_t tpent; 5214746Srica tsol_tpent_t *tpentp; 5224746Srica int err; 5234746Srica char *errstr; 5244746Srica char buf[NSS_BUFLEN_TSOL_TP]; 5254746Srica 5264746Srica if (strchr(template, ':') != NULL) { 5274746Srica (void) str_to_tpstr(template, strlen(template), &tpstr, buf, 5284746Srica sizeof (buf)); 5294746Srica tpentp = tpstr_to_ent(&tpstr, &err, &errstr); 5304746Srica if (tpentp == NULL) { 5314746Srica print_error(0, err, errstr); 5324746Srica exit(1); 5334746Srica } 5344746Srica } else if (delete_mode) { 5354746Srica (void) memset(&tpent, 0, sizeof (tpent)); 5364746Srica tpentp = &tpent; 5374746Srica (void) strlcpy(tpentp->name, template, sizeof (tpentp->name)); 5384746Srica } else if ((tpentp = tsol_gettpbyname(template)) == NULL) { 5394746Srica (void) fprintf(stderr, 5404746Srica gettext("tnctl: template %s not found\n"), template); 5414746Srica exit(1); 5424746Srica } 5434746Srica 5444746Srica if (verbose_mode) 5454746Srica (void) printf("%s rhtp entry ...\n", delete_mode ? "deleting" : 5464746Srica "loading"); 5474746Srica 5484746Srica if (tnrhtp(delete_mode ? TNDB_DELETE : TNDB_LOAD, tpentp) != 0) { 5494746Srica if (errno == EFAULT) 5504746Srica perror("tnrhtp"); 5514746Srica else if (errno == ENOENT) 5524746Srica (void) fprintf(stderr, 5534746Srica gettext("tnctl: %1$s of remote-host template " 5544746Srica "kernel cache entry %2$s failed: no such " 5554746Srica "entry\n"), 5564746Srica delete_mode ? gettext("delete") : gettext("load"), 5574746Srica tpentp->name); 5584746Srica else 5594746Srica (void) fprintf(stderr, 5604746Srica gettext("tnctl: %1$s of remote-host template " 5614746Srica "kernel cache entry %2$s failed: %3$s\n"), 5624746Srica delete_mode ? gettext("delete") : gettext("load"), 5634746Srica tpentp->name, strerror(errno)); 5644746Srica exit(1); 5654746Srica } 5664746Srica if (tpentp != &tpent) 5674746Srica tsol_freetpent(tpentp); 5684746Srica } 5694746Srica 5704746Srica static void 5714746Srica process_mlp(const char *str) 5724746Srica { 5734746Srica const char *cp; 5744746Srica char zonename[ZONENAME_MAX]; 5754746Srica zoneid_t zoneid; 5764746Srica tsol_zcent_t *zc; 5774746Srica int err; 5784746Srica char *errstr; 5794746Srica char *sbuf; 5804746Srica 5814746Srica if ((cp = strchr(str, ':')) == NULL) { 5824746Srica if (!delete_mode) { 5834746Srica (void) fprintf(stderr, 5844746Srica gettext("tnctl: need MLP list to insert\n")); 5854746Srica exit(2); 5864746Srica } 5874746Srica (void) strlcpy(zonename, str, sizeof (zonename)); 5884746Srica } else if (cp - str >= ZONENAME_MAX) { 5894746Srica (void) fprintf(stderr, gettext("tnctl: illegal zone name\n")); 5904746Srica exit(2); 5914746Srica } else { 5924746Srica (void) memcpy(zonename, str, cp - str); 5934746Srica zonename[cp - str] = '\0'; 5944746Srica str = cp + 1; 5954746Srica } 5964746Srica 5974746Srica if ((zoneid = getzoneidbyname(zonename)) == -1) { 5984746Srica (void) fprintf(stderr, gettext("tninfo: zone '%s' unknown\n"), 5994746Srica zonename); 6004746Srica exit(1); 6014746Srica } 6024746Srica 6034746Srica sbuf = malloc(strlen(zonename) + sizeof (":ADMIN_LOW:0:") + 6044746Srica strlen(str)); 6054746Srica if (sbuf == NULL) { 6064746Srica perror("malloc"); 6074746Srica exit(1); 6084746Srica } 6094746Srica /* LINTED: sprintf is known not to be unbounded here */ 6104746Srica (void) sprintf(sbuf, "%s:ADMIN_LOW:0:%s", zonename, str); 6114746Srica if ((zc = tsol_sgetzcent(sbuf, &err, &errstr)) == NULL) { 6124746Srica (void) fprintf(stderr, 6134746Srica gettext("tnctl: unable to parse MLPs\n")); 6144746Srica exit(1); 6154746Srica } 6164746Srica handle_mlps(zoneid, zc->zc_private_mlp, 0, 6174746Srica delete_mode ? TNDB_DELETE : TNDB_LOAD); 6184746Srica handle_mlps(zoneid, zc->zc_shared_mlp, TSOL_MEF_SHARED, 6194746Srica delete_mode ? TNDB_DELETE : TNDB_LOAD); 6204746Srica tsol_freezcent(zc); 6214746Srica } 6224746Srica 6234746Srica static void 6244746Srica usage(void) 6254746Srica { 6264746Srica (void) fprintf(stderr, gettext("usage: tnctl [-dfv] " 6274746Srica "[-h host[/prefix][:tmpl]] [-m zone:priv:share]\n\t" 6284746Srica "[-t tmpl[:key=val[;key=val]]] [-[HTz] file]\n")); 6294746Srica 6304746Srica exit(1); 6314746Srica } 632