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