xref: /illumos-gate/usr/src/cmd/tsol/tnctl/tnctl.c (revision 0890d2f3)
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 /*
235ccb772aSTony 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
main(int argc,char ** argv)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
print_error(int linenum,int err,const char * errstr)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 
1281f041b17Ston /*
1291f041b17Ston  * Produce ascii format of address and prefix length
1301f041b17Ston  */
1311f041b17Ston static void
translate_inet_addr(tsol_rhent_t * rhentp,int * alen,char abuf[],int abuflen)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 		}
1515ccb772aSTony 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 		}
1625ccb772aSTony Nguyen 		*alen = strlen(abuf);
1631f041b17Ston 	}
1641f041b17Ston }
1651f041b17Ston 
166f875b4ebSrica /*
167f875b4ebSrica  * Load remote host entries from the designated file.
168f875b4ebSrica  */
169f875b4ebSrica static void
process_rhl(const char * file)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);
199*0890d2f3SToomas Soome 			if (errno == EFAULT) {
200f875b4ebSrica 				perror("tnrh");
201*0890d2f3SToomas Soome 			} 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));
208*0890d2f3SToomas Soome 			}
209f875b4ebSrica 			tsol_endrhent();
210f875b4ebSrica 			exit(1);
211f875b4ebSrica 		}
212f875b4ebSrica 		tsol_freerhent(rhentp);
213f875b4ebSrica 	}
214f875b4ebSrica 	if (!success) {
215f875b4ebSrica 		(void) fprintf(stderr,
216f875b4ebSrica 		    gettext("tnctl: No valid tnrhdb entries found in %s\n"),
217f875b4ebSrica 		    file);
218f875b4ebSrica 	}
219f875b4ebSrica 	(void) fclose(fp);
220f875b4ebSrica 	tsol_endrhent();
221909c1a33Ston 
222909c1a33Ston 	if (error)
223909c1a33Ston 		exit(1);
224f875b4ebSrica }
225f875b4ebSrica 
226f875b4ebSrica /*
227f875b4ebSrica  * The argument can be either a host name, an address
228f875b4ebSrica  * in tnrhdb address format, or a complete tnrhdb entry.
229f875b4ebSrica  */
230f875b4ebSrica static void
process_rh(const char * hostname)231f875b4ebSrica process_rh(const char *hostname)
232f875b4ebSrica {
233f875b4ebSrica 	tsol_rhstr_t rhstr;
234f875b4ebSrica 	tsol_rhent_t rhent;
235f875b4ebSrica 	tsol_rhent_t *rhentp;
236f875b4ebSrica 	int err;
237f875b4ebSrica 	int alen;
238f875b4ebSrica 	char *errstr;
239f875b4ebSrica 	/* abuf holds: <numeric-ip-addr>'/'<prefix-length>'\0' */
240f875b4ebSrica 	char abuf[INET6_ADDRSTRLEN+5];
241f875b4ebSrica 	const char *cp;
242f875b4ebSrica 	char *cp1;
243f875b4ebSrica 	char *cp2;
244f875b4ebSrica 	void *aptr;
245f875b4ebSrica 	char buf[NSS_BUFLEN_TSOL_RH];
246f875b4ebSrica 	struct in6_addr ipv6addr;
247f875b4ebSrica 
248f875b4ebSrica 	/* was a template name provided on the command line? */
249f875b4ebSrica 	if ((cp = strrchr(hostname, ':')) != NULL && cp != hostname &&
250f875b4ebSrica 	    cp[-1] != '\\') {
251f875b4ebSrica 		/* use common tnrhdb line conversion function */
252f875b4ebSrica 		(void) str_to_rhstr(hostname, strlen(hostname), &rhstr, buf,
253f875b4ebSrica 		    sizeof (buf));
254f875b4ebSrica 		rhentp = rhstr_to_ent(&rhstr, &err, &errstr);
255f875b4ebSrica 		if (rhentp == NULL) {
256f875b4ebSrica 			print_error(0, err, errstr);
257f875b4ebSrica 			exit(1);
258f875b4ebSrica 		}
259f875b4ebSrica 	} else {
260f875b4ebSrica 		char *hostname_p;
261f875b4ebSrica 		char *prefix_p;
262f875b4ebSrica 		struct hostent *hp;
263f875b4ebSrica 
264f875b4ebSrica 		/* Check for a subnet prefix length */
265f875b4ebSrica 		if ((prefix_p = strchr(hostname, '/')) != NULL) {
266f875b4ebSrica 			cp1 = prefix_p + 1;
267f875b4ebSrica 			errno = 0;
268f875b4ebSrica 			rhent.rh_prefix = strtol(cp1, &cp2, 0);
269f875b4ebSrica 			if (*cp2 != '\0' || errno != 0 || rhent.rh_prefix < 0) {
270f875b4ebSrica 				(void) fprintf(stderr, gettext("tnct: invalid "
271f875b4ebSrica 				    "prefix length: %s\n"), cp);
272f875b4ebSrica 				exit(2);
273f875b4ebSrica 			}
274f875b4ebSrica 		} else {
275f875b4ebSrica 			rhent.rh_prefix = -1;
276f875b4ebSrica 		}
277f875b4ebSrica 
278f875b4ebSrica 		/* Strip any backslashes from numeric address */
279f875b4ebSrica 		hostname_p = malloc(strlen(hostname)+1);
280f875b4ebSrica 		if (hostname_p == NULL) {
281f875b4ebSrica 			perror("tnctl");
282f875b4ebSrica 			exit(2);
283f875b4ebSrica 		}
284f875b4ebSrica 		cp1 = hostname_p;
285f875b4ebSrica 		while (*hostname != '\0' && *hostname != '/') {
286f875b4ebSrica 			*cp1 = *hostname++;
287f875b4ebSrica 			if (*cp1 != '\\')
288f875b4ebSrica 				cp1++;
289f875b4ebSrica 		}
290f875b4ebSrica 		*cp1 = '\0';
291f875b4ebSrica 
292f875b4ebSrica 		/* Convert address or hostname to binary af_inet6 format */
293f875b4ebSrica 		hp = getipnodebyname(hostname_p, AF_INET6,
294f875b4ebSrica 		    AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &err);
295f875b4ebSrica 		if (hp == NULL) {
296f875b4ebSrica 			(void) fprintf(stderr, gettext("tnctl: unknown host "
297f875b4ebSrica 			    "or invalid literal address: %s\n"), hostname_p);
298f875b4ebSrica 			if (err == TRY_AGAIN)
299f875b4ebSrica 				(void) fprintf(stderr,
300f875b4ebSrica 				    gettext("\t(try again later)\n"));
301f875b4ebSrica 			exit(2);
302f875b4ebSrica 		}
303f875b4ebSrica 		free(hostname_p);
304f875b4ebSrica 		(void) memcpy(&ipv6addr, hp->h_addr, hp->h_length);
305f875b4ebSrica 
306f875b4ebSrica 		/* if ipv4 address, convert to af_inet format */
307f875b4ebSrica 		if (IN6_IS_ADDR_V4MAPPED(&ipv6addr)) {
308f875b4ebSrica 			rhent.rh_address.ta_family = AF_INET;
309f875b4ebSrica 			IN6_V4MAPPED_TO_INADDR(&ipv6addr,
310f875b4ebSrica 			    &rhent.rh_address.ta_addr_v4);
311f875b4ebSrica 			if (rhent.rh_prefix == -1)
312f875b4ebSrica 				rhent.rh_prefix = 32;
313f875b4ebSrica 		} else {
314f875b4ebSrica 			rhent.rh_address.ta_family = AF_INET6;
315f875b4ebSrica 			rhent.rh_address.ta_addr_v6 = ipv6addr;
316f875b4ebSrica 			if (rhent.rh_prefix == -1)
317f875b4ebSrica 				rhent.rh_prefix = 128;
318f875b4ebSrica 		}
319f875b4ebSrica 		rhent.rh_template[0] = '\0';
320f875b4ebSrica 		rhentp = &rhent;
321f875b4ebSrica 	}
322f875b4ebSrica 
323f875b4ebSrica 	/* produce ascii format of address and prefix length */
3241f041b17Ston 	translate_inet_addr(rhentp, &alen, abuf, sizeof (abuf));
325f875b4ebSrica 
326f875b4ebSrica 	/*
327f875b4ebSrica 	 * look up the entry from ldap or tnrhdb if this is a load
328f875b4ebSrica 	 * request and a template name was not provided.
329f875b4ebSrica 	 */
330f875b4ebSrica 	if (!delete_mode &&
331f875b4ebSrica 	    rhentp->rh_template[0] == '\0' &&
3325ccb772aSTony Nguyen 	    (rhentp = tsol_getrhbyaddr(abuf, alen+1,
333f875b4ebSrica 	    rhent.rh_address.ta_family)) == NULL) {
334f875b4ebSrica 		(void) fprintf(stderr,
335f875b4ebSrica 		    gettext("tnctl: database lookup failed for %s\n"),
336f875b4ebSrica 		    abuf);
337f875b4ebSrica 		exit(1);
338f875b4ebSrica 	}
339f875b4ebSrica 
340f875b4ebSrica 	if (verbose_mode)
341f875b4ebSrica 		(void) printf("%s rh entry %s\n", delete_mode ? "deleting" :
342f875b4ebSrica 		    "loading", abuf);
343f875b4ebSrica 
344f875b4ebSrica 	/* update the tnrhdb entry in the kernel */
345f875b4ebSrica 	if (tnrh(delete_mode ? TNDB_DELETE : TNDB_LOAD, rhentp) != 0) {
346f875b4ebSrica 		if (errno == EFAULT)
347f875b4ebSrica 			perror("tnrh");
348f875b4ebSrica 		else if (errno == ENOENT)
349f875b4ebSrica 			(void) fprintf(stderr,
350f875b4ebSrica 			    gettext("tnctl: %1$s of remote-host kernel cache "
351f875b4ebSrica 			    "entry %2$s failed: no such entry\n"),
352f875b4ebSrica 			    delete_mode ? gettext("delete") : gettext("load"),
353f875b4ebSrica 			    abuf);
354f875b4ebSrica 		else
355f875b4ebSrica 			(void) fprintf(stderr,
356f875b4ebSrica 			    gettext("tnctl: %1$s of remote-host kernel cache "
357f875b4ebSrica 			    "entry %2$s failed: %3$s\n"),
358f875b4ebSrica 			    delete_mode ? gettext("delete") : gettext("load"),
359f875b4ebSrica 			    abuf, strerror(errno));
360f875b4ebSrica 		exit(1);
361f875b4ebSrica 	}
362f875b4ebSrica 	if (rhentp != &rhent)
363f875b4ebSrica 		tsol_freerhent(rhentp);
364f875b4ebSrica }
365f875b4ebSrica 
366f875b4ebSrica static void
handle_mlps(zoneid_t zoneid,tsol_mlp_t * mlp,int flags,int cmd)367f875b4ebSrica handle_mlps(zoneid_t zoneid, tsol_mlp_t *mlp, int flags, int cmd)
368f875b4ebSrica {
369f875b4ebSrica 	tsol_mlpent_t tsme;
370f875b4ebSrica 
371f875b4ebSrica 	tsme.tsme_zoneid = zoneid;
372f875b4ebSrica 	tsme.tsme_flags = flags;
373f875b4ebSrica 	while (!TSOL_MLP_END(mlp)) {
374f875b4ebSrica 		tsme.tsme_mlp = *mlp;
375f875b4ebSrica 		if (tnmlp(cmd, &tsme) != 0) {
376f875b4ebSrica 			/*
377f875b4ebSrica 			 * Usage of ?: here is ugly, but helps with
378f875b4ebSrica 			 * localization.
379f875b4ebSrica 			 */
380f875b4ebSrica 			(void) fprintf(stderr,
381f875b4ebSrica 			    flags & TSOL_MEF_SHARED ?
382f875b4ebSrica 			    gettext("tnctl: cannot set "
383f875b4ebSrica 			    "shared MLP on %1$d-%2$d/%3$d: %4$s\n") :
384f875b4ebSrica 			    gettext("tnctl: cannot set "
385f875b4ebSrica 			    "zone-specific MLP on %1$d-%2$d/%3$d: %4$s\n"),
386f875b4ebSrica 			    mlp->mlp_port, mlp->mlp_port_upper, mlp->mlp_ipp,
387f875b4ebSrica 			    strerror(errno));
388f875b4ebSrica 			exit(1);
389f875b4ebSrica 		}
390f875b4ebSrica 		mlp++;
391f875b4ebSrica 	}
392f875b4ebSrica }
393f875b4ebSrica 
394f875b4ebSrica /*
395f875b4ebSrica  * This reads the configuration for the global zone out of tnzonecfg
396f875b4ebSrica  * and sets it in the kernel.  The non-global zones are configured
397f875b4ebSrica  * by zoneadmd.
398f875b4ebSrica  */
399f875b4ebSrica static void
process_tnzone(const char * file)400f875b4ebSrica process_tnzone(const char *file)
401f875b4ebSrica {
402f875b4ebSrica 	tsol_zcent_t *zc;
403f875b4ebSrica 	tsol_mlpent_t tsme;
404f875b4ebSrica 	int err;
405f875b4ebSrica 	char *errstr;
406f875b4ebSrica 	FILE *fp;
407f875b4ebSrica 	char line[2048], *cp;
408f875b4ebSrica 	int linenum, errors;
409f875b4ebSrica 
410f875b4ebSrica 	if ((fp = fopen(file, "r")) == NULL) {
411f875b4ebSrica 		(void) fprintf(stderr,
412f875b4ebSrica 		    gettext("tnctl: failed to open %s: %s\n"), file,
413f875b4ebSrica 		    strerror(errno));
414f875b4ebSrica 		exit(1);
415f875b4ebSrica 	}
416f875b4ebSrica 
417f875b4ebSrica 	linenum = errors = 0;
418f875b4ebSrica 	zc = NULL;
419f875b4ebSrica 	while (fgets(line, sizeof (line), fp) != NULL) {
420f875b4ebSrica 		if ((cp = strchr(line, '\n')) != NULL)
421f875b4ebSrica 			*cp = '\0';
422f875b4ebSrica 
423f875b4ebSrica 		linenum++;
424f875b4ebSrica 		if ((zc = tsol_sgetzcent(line, &err, &errstr)) == NULL) {
425f875b4ebSrica 			if (err == LTSNET_EMPTY)
426f875b4ebSrica 				continue;
427f875b4ebSrica 			if (errors == 0) {
428f875b4ebSrica 				int errtmp = errno;
429f875b4ebSrica 
430f875b4ebSrica 				(void) fprintf(stderr, gettext("tnctl: errors "
431f875b4ebSrica 				    "parsing %s:\n"), file);
432f875b4ebSrica 				errno = errtmp;
433f875b4ebSrica 			}
434f875b4ebSrica 			print_error(linenum, err, errstr);
435f875b4ebSrica 			errors++;
436f875b4ebSrica 			continue;
437f875b4ebSrica 		}
438f875b4ebSrica 
439f875b4ebSrica 		if (strcasecmp(zc->zc_name, "global") == 0)
440f875b4ebSrica 			break;
441f875b4ebSrica 		tsol_freezcent(zc);
442f875b4ebSrica 	}
443f875b4ebSrica 	(void) fclose(fp);
444f875b4ebSrica 
445f875b4ebSrica 	if (zc == NULL) {
446f875b4ebSrica 		(void) fprintf(stderr,
447f875b4ebSrica 		    gettext("tnctl: cannot find global zone in %s\n"), file);
448f875b4ebSrica 		exit(1);
449f875b4ebSrica 	}
450f875b4ebSrica 
451f875b4ebSrica 	tsme.tsme_zoneid = GLOBAL_ZONEID;
452f875b4ebSrica 	tsme.tsme_flags = 0;
453f875b4ebSrica 	if (flush_mode)
454f875b4ebSrica 		(void) tnmlp(TNDB_FLUSH, &tsme);
455f875b4ebSrica 
456f875b4ebSrica 	handle_mlps(GLOBAL_ZONEID, zc->zc_private_mlp, 0, TNDB_LOAD);
457f875b4ebSrica 	handle_mlps(GLOBAL_ZONEID, zc->zc_shared_mlp, TSOL_MEF_SHARED,
458f875b4ebSrica 	    TNDB_LOAD);
459f875b4ebSrica 
460f875b4ebSrica 	tsol_freezcent(zc);
461f875b4ebSrica }
462f875b4ebSrica 
463f875b4ebSrica static void
process_tpl(const char * file)464f875b4ebSrica process_tpl(const char *file)
465f875b4ebSrica {
466f875b4ebSrica 	FILE		*fp;
467909c1a33Ston 	boolean_t	error = B_FALSE;
468f875b4ebSrica 	boolean_t	success = B_FALSE;
469f875b4ebSrica 	tsol_tpent_t	*tpentp;
470f875b4ebSrica 
471f875b4ebSrica 	if ((fp = fopen(file, "r")) == NULL) {
472f875b4ebSrica 		(void) fprintf(stderr,
473f875b4ebSrica 		    gettext("tnctl: failed to open %s: %s\n"), file,
474f875b4ebSrica 		    strerror(errno));
475f875b4ebSrica 		exit(1);
476f875b4ebSrica 	}
477f875b4ebSrica 
478f875b4ebSrica 	tsol_settpent(1);
479909c1a33Ston 	while (tpentp = tsol_fgettpent(fp, &error)) {
480f875b4ebSrica 		/* First time through the loop, flush it all */
481f875b4ebSrica 		if (!success && flush_mode)
482f875b4ebSrica 			(void) tnrhtp(TNDB_FLUSH, NULL);
483f875b4ebSrica 
484f875b4ebSrica 		success = B_TRUE;
485f875b4ebSrica 
486f875b4ebSrica 		if (verbose_mode)
487f875b4ebSrica 			(void) printf("tnctl: loading rhtp entry ...\n");
488f875b4ebSrica 
489f875b4ebSrica 		if (tnrhtp(TNDB_LOAD, tpentp) != 0) {
490f875b4ebSrica 			(void) fclose(fp);
491f875b4ebSrica 			if (errno == EFAULT)
492f875b4ebSrica 				perror("tnrhtp");
493f875b4ebSrica 			else
494f875b4ebSrica 				(void) fprintf(stderr, gettext("tnctl: load "
495f875b4ebSrica 				    "of remote-host template %1$s into kernel "
496f875b4ebSrica 				    "cache failed: %2$s\n"), tpentp->name,
497f875b4ebSrica 				    strerror(errno));
498f875b4ebSrica 			tsol_endtpent();
499f875b4ebSrica 			exit(1);
500f875b4ebSrica 		}
501f875b4ebSrica 		tsol_freetpent(tpentp);
502f875b4ebSrica 	}
503f875b4ebSrica 	if (!success) {
504f875b4ebSrica 		(void) fprintf(stderr,
505f875b4ebSrica 		    gettext("tnctl: No valid tnrhtp entries found in %s\n"),
506f875b4ebSrica 		    file);
507f875b4ebSrica 	}
508f875b4ebSrica 	(void) fclose(fp);
509f875b4ebSrica 	tsol_endtpent();
510909c1a33Ston 
511909c1a33Ston 	if (error)
512909c1a33Ston 		exit(1);
513f875b4ebSrica }
514f875b4ebSrica 
515f875b4ebSrica static void
process_tp(const char * template)516f875b4ebSrica process_tp(const char *template)
517f875b4ebSrica {
518f875b4ebSrica 	tsol_tpstr_t tpstr;
519f875b4ebSrica 	tsol_tpent_t tpent;
520f875b4ebSrica 	tsol_tpent_t *tpentp;
521f875b4ebSrica 	int err;
522f875b4ebSrica 	char *errstr;
523f875b4ebSrica 	char buf[NSS_BUFLEN_TSOL_TP];
524f875b4ebSrica 
525f875b4ebSrica 	if (strchr(template, ':') != NULL) {
526f875b4ebSrica 		(void) str_to_tpstr(template, strlen(template), &tpstr, buf,
527f875b4ebSrica 		    sizeof (buf));
528f875b4ebSrica 		tpentp = tpstr_to_ent(&tpstr, &err, &errstr);
529f875b4ebSrica 		if (tpentp == NULL) {
530f875b4ebSrica 			print_error(0, err, errstr);
531f875b4ebSrica 			exit(1);
532f875b4ebSrica 		}
533f875b4ebSrica 	} else if (delete_mode) {
534f875b4ebSrica 		(void) memset(&tpent, 0, sizeof (tpent));
535f875b4ebSrica 		tpentp = &tpent;
536f875b4ebSrica 		(void) strlcpy(tpentp->name, template, sizeof (tpentp->name));
537f875b4ebSrica 	} else if ((tpentp = tsol_gettpbyname(template)) == NULL) {
538f875b4ebSrica 		(void) fprintf(stderr,
539f875b4ebSrica 		    gettext("tnctl: template %s not found\n"), template);
540f875b4ebSrica 		exit(1);
541f875b4ebSrica 	}
542f875b4ebSrica 
543f875b4ebSrica 	if (verbose_mode)
544f875b4ebSrica 		(void) printf("%s rhtp entry ...\n", delete_mode ? "deleting" :
545f875b4ebSrica 		    "loading");
546f875b4ebSrica 
547f875b4ebSrica 	if (tnrhtp(delete_mode ? TNDB_DELETE : TNDB_LOAD, tpentp) != 0) {
548f875b4ebSrica 		if (errno == EFAULT)
549f875b4ebSrica 			perror("tnrhtp");
550f875b4ebSrica 		else if (errno == ENOENT)
551f875b4ebSrica 			(void) fprintf(stderr,
552f875b4ebSrica 			    gettext("tnctl: %1$s of remote-host template "
553f875b4ebSrica 			    "kernel cache entry %2$s failed: no such "
554f875b4ebSrica 			    "entry\n"),
555f875b4ebSrica 			    delete_mode ? gettext("delete") : gettext("load"),
556f875b4ebSrica 			    tpentp->name);
557f875b4ebSrica 		else
558f875b4ebSrica 			(void) fprintf(stderr,
559f875b4ebSrica 			    gettext("tnctl: %1$s of remote-host template "
560f875b4ebSrica 			    "kernel cache entry %2$s failed: %3$s\n"),
561f875b4ebSrica 			    delete_mode ? gettext("delete") : gettext("load"),
562f875b4ebSrica 			    tpentp->name, strerror(errno));
563f875b4ebSrica 		exit(1);
564f875b4ebSrica 	}
565f875b4ebSrica 	if (tpentp != &tpent)
566f875b4ebSrica 		tsol_freetpent(tpentp);
567f875b4ebSrica }
568f875b4ebSrica 
569f875b4ebSrica static void
process_mlp(const char * str)570f875b4ebSrica process_mlp(const char *str)
571f875b4ebSrica {
572f875b4ebSrica 	const char *cp;
573f875b4ebSrica 	char zonename[ZONENAME_MAX];
574f875b4ebSrica 	zoneid_t zoneid;
575f875b4ebSrica 	tsol_zcent_t *zc;
576f875b4ebSrica 	int err;
577f875b4ebSrica 	char *errstr;
578f875b4ebSrica 	char *sbuf;
579f875b4ebSrica 
580f875b4ebSrica 	if ((cp = strchr(str, ':')) == NULL) {
581f875b4ebSrica 		if (!delete_mode) {
582f875b4ebSrica 			(void) fprintf(stderr,
583f875b4ebSrica 			    gettext("tnctl: need MLP list to insert\n"));
584f875b4ebSrica 			exit(2);
585f875b4ebSrica 		}
586f875b4ebSrica 		(void) strlcpy(zonename, str, sizeof (zonename));
587f875b4ebSrica 	} else if (cp - str >= ZONENAME_MAX) {
588f875b4ebSrica 		(void) fprintf(stderr, gettext("tnctl: illegal zone name\n"));
589f875b4ebSrica 		exit(2);
590f875b4ebSrica 	} else {
591f875b4ebSrica 		(void) memcpy(zonename, str, cp - str);
592f875b4ebSrica 		zonename[cp - str] = '\0';
593f875b4ebSrica 		str = cp + 1;
594f875b4ebSrica 	}
595f875b4ebSrica 
596f875b4ebSrica 	if ((zoneid = getzoneidbyname(zonename)) == -1) {
597f875b4ebSrica 		(void) fprintf(stderr, gettext("tninfo: zone '%s' unknown\n"),
598f875b4ebSrica 		    zonename);
599f875b4ebSrica 		exit(1);
600f875b4ebSrica 	}
601f875b4ebSrica 
602f875b4ebSrica 	sbuf = malloc(strlen(zonename) + sizeof (":ADMIN_LOW:0:") +
603f875b4ebSrica 	    strlen(str));
604f875b4ebSrica 	if (sbuf == NULL) {
605f875b4ebSrica 		perror("malloc");
606f875b4ebSrica 		exit(1);
607f875b4ebSrica 	}
608f875b4ebSrica 	/* LINTED: sprintf is known not to be unbounded here */
609f875b4ebSrica 	(void) sprintf(sbuf, "%s:ADMIN_LOW:0:%s", zonename, str);
610f875b4ebSrica 	if ((zc = tsol_sgetzcent(sbuf, &err, &errstr)) == NULL) {
611f875b4ebSrica 		(void) fprintf(stderr,
612f875b4ebSrica 		    gettext("tnctl: unable to parse MLPs\n"));
613f875b4ebSrica 		exit(1);
614f875b4ebSrica 	}
615f875b4ebSrica 	handle_mlps(zoneid, zc->zc_private_mlp, 0,
616f875b4ebSrica 	    delete_mode ? TNDB_DELETE : TNDB_LOAD);
617f875b4ebSrica 	handle_mlps(zoneid, zc->zc_shared_mlp, TSOL_MEF_SHARED,
618f875b4ebSrica 	    delete_mode ? TNDB_DELETE : TNDB_LOAD);
619f875b4ebSrica 	tsol_freezcent(zc);
620f875b4ebSrica }
621f875b4ebSrica 
622f875b4ebSrica static void
usage(void)623f875b4ebSrica usage(void)
624f875b4ebSrica {
625f875b4ebSrica 	(void) fprintf(stderr, gettext("usage: tnctl [-dfv] "
626f875b4ebSrica 	    "[-h host[/prefix][:tmpl]] [-m zone:priv:share]\n\t"
627f875b4ebSrica 	    "[-t tmpl[:key=val[;key=val]]] [-[HTz] file]\n"));
628f875b4ebSrica 
629f875b4ebSrica 	exit(1);
630f875b4ebSrica }
631