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