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