xref: /onnv-gate/usr/src/cmd/tsol/tnchkdb/tnchkdb.c (revision 9530:f2568b726186)
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*9530STon.Nguyen@Sun.COM  *  Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
244746Srica  *  Use is subject to license terms.
254746Srica  */
264746Srica 
274746Srica /*
284746Srica  * tnchkdb.c - Trusted network database checking utility
294746Srica  */
304746Srica #include <stdio.h>
314746Srica #include <stdlib.h>
324746Srica #include <errno.h>
334746Srica #include <locale.h>
344746Srica #include <malloc.h>
354746Srica #include <string.h>
364746Srica #include <libtsnet.h>
374746Srica #include <netinet/in.h>
384746Srica #include <nss_dbdefs.h>
394746Srica 
404746Srica static void usage(void);
414746Srica static void check_tnrhtp(const char *);
424746Srica static void check_tnrhdb(const char *);
434746Srica static void check_tnzonecfg(const char *);
444746Srica 
454746Srica static boolean_t tnrhtp_bad;
464746Srica static int exitval;
474746Srica 
484746Srica struct tsol_name_list {
494746Srica 	struct tsol_name_list *next;
504746Srica 	int linenum;
514746Srica 	char name[TNTNAMSIZ];
524746Srica };
534746Srica 
544746Srica struct tsol_addr_list {
554746Srica 	struct tsol_addr_list *next;
564746Srica 	int linenum;
574746Srica 	int prefix_len;
584746Srica 	in6_addr_t addr;
594746Srica };
604746Srica 
614746Srica static struct tsol_name_list *tp_list_head;
624746Srica static struct tsol_addr_list *rh_list_head;
634746Srica static struct tsol_name_list *zc_list_head;
644746Srica 
654746Srica typedef struct mlp_info_list_s {
664746Srica 	struct mlp_info_list_s *next;
674746Srica 	int linenum;
684746Srica 	tsol_mlp_t mlp;
694746Srica 	char name[TNTNAMSIZ];
704746Srica } mlp_info_list_t;
714746Srica 
724746Srica static mlp_info_list_t *global_mlps;
734746Srica 
744746Srica static void
add_name(struct tsol_name_list ** head,const char * name,int linenum)754746Srica add_name(struct tsol_name_list **head, const char *name, int linenum)
764746Srica {
774746Srica 	int err;
784746Srica 	struct tsol_name_list *entry;
794746Srica 
804746Srica 	entry = malloc(sizeof (struct tsol_name_list));
814746Srica 	if (entry == NULL) {
824746Srica 		err = errno;
834746Srica 
844746Srica 		(void) fprintf(stderr,
854746Srica 		    gettext("tnchkdb: allocating name list: %s\n"),
864746Srica 		    strerror(err));
874746Srica 		exit(1);
884746Srica 	}
894746Srica 	(void) strlcpy(entry->name, name, sizeof (entry->name));
904746Srica 	entry->next = *head;
914746Srica 	entry->linenum = linenum;
924746Srica 	*head = entry;
934746Srica }
944746Srica 
954746Srica static struct tsol_name_list *
find_name(struct tsol_name_list * head,const char * name)964746Srica find_name(struct tsol_name_list *head, const char *name)
974746Srica {
984746Srica 	struct tsol_name_list *entry;
994746Srica 
1004746Srica 	for (entry = head; entry != NULL; entry = entry->next)
1014746Srica 		if (strcmp(entry->name, name) == 0)
1024746Srica 			break;
1034746Srica 	return (entry);
1044746Srica }
1054746Srica 
1064746Srica static void
add_addr(struct tsol_addr_list ** head,int prefix_len,in6_addr_t addr,int linenum)1074746Srica add_addr(struct tsol_addr_list **head, int prefix_len, in6_addr_t addr,
1084746Srica     int linenum)
1094746Srica {
1104746Srica 	int err;
1114746Srica 	struct tsol_addr_list *entry;
1124746Srica 
1134746Srica 	entry = malloc(sizeof (struct tsol_addr_list));
1144746Srica 	if (entry == NULL) {
1154746Srica 		err = errno;
1164746Srica 
1174746Srica 		(void) fprintf(stderr,
1184746Srica 		    gettext("tnchkdb: allocating addr list: %s\n"),
1194746Srica 		    strerror(err));
1204746Srica 		exit(2);
1214746Srica 	}
1224746Srica 	entry->prefix_len = prefix_len;
1234746Srica 	entry->addr = addr;
1244746Srica 	entry->next = *head;
1254746Srica 	entry->linenum = linenum;
1264746Srica 	*head = entry;
1274746Srica }
1284746Srica 
1294746Srica static struct tsol_addr_list *
find_addr(struct tsol_addr_list * head,int prefix_len,in6_addr_t addr)1304746Srica find_addr(struct tsol_addr_list *head, int prefix_len, in6_addr_t addr)
1314746Srica {
1324746Srica 	struct tsol_addr_list *entry;
1334746Srica 
1344746Srica 	for (entry = head; entry != NULL; entry = entry->next)
1354746Srica 		if (entry->prefix_len == prefix_len &&
1364746Srica 		    IN6_ARE_ADDR_EQUAL(&entry->addr, &addr))
1374746Srica 			break;
1384746Srica 	return (entry);
1394746Srica }
1404746Srica 
1414746Srica static void
add_template(const char * name,int linenum)1424746Srica add_template(const char *name, int linenum)
1434746Srica {
1444746Srica 	add_name(&tp_list_head, name, linenum);
1454746Srica }
1464746Srica 
1474746Srica static struct tsol_name_list *
find_template(const char * name)1484746Srica find_template(const char *name)
1494746Srica {
1504746Srica 	return (find_name(tp_list_head, name));
1514746Srica }
1524746Srica 
1534746Srica static void
add_host(int prefix_len,in6_addr_t addr,int linenum)1544746Srica add_host(int prefix_len, in6_addr_t addr, int linenum)
1554746Srica {
1564746Srica 	add_addr(&rh_list_head, prefix_len, addr, linenum);
1574746Srica }
1584746Srica 
1594746Srica static struct tsol_addr_list *
find_host(int prefix_len,in6_addr_t addr)1604746Srica find_host(int prefix_len, in6_addr_t addr)
1614746Srica {
1624746Srica 	return (find_addr(rh_list_head, prefix_len, addr));
1634746Srica }
1644746Srica 
1654746Srica static void
add_zone(const char * name,int linenum)1664746Srica add_zone(const char *name, int linenum)
1674746Srica {
1684746Srica 	add_name(&zc_list_head, name, linenum);
1694746Srica }
1704746Srica 
1714746Srica static struct tsol_name_list *
find_zone(const char * name)1724746Srica find_zone(const char *name)
1734746Srica {
1744746Srica 	return (find_name(zc_list_head, name));
1754746Srica }
1764746Srica 
1774746Srica int
main(int argc,char ** argv)1784746Srica main(int argc, char **argv)
1794746Srica {
1804746Srica 	const char *tnrhdb_file = TNRHDB_PATH;
1814746Srica 	const char *tnrhtp_file = TNRHTP_PATH;
1824746Srica 	const char *tnzonecfg_file = TNZONECFG_PATH;
1834746Srica 	int chr;
1844746Srica 
1854746Srica 	/* set the locale for only the messages system (all else is clean) */
1864746Srica 	(void) setlocale(LC_ALL, "");
1874746Srica #ifndef TEXT_DOMAIN		/* Should be defined by cc -D */
1884746Srica #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
1894746Srica #endif
1904746Srica 	(void) textdomain(TEXT_DOMAIN);
1914746Srica 
1924746Srica 	while ((chr = getopt(argc, argv, "h:t:z:")) != EOF) {
1934746Srica 		switch (chr) {
1944746Srica 		case 'h':
1954746Srica 			tnrhdb_file = optarg;
1964746Srica 			break;
1974746Srica 		case 't':
1984746Srica 			tnrhtp_file = optarg;
1994746Srica 			break;
2004746Srica 		case 'z':
2014746Srica 			tnzonecfg_file = optarg;
2024746Srica 			break;
2034746Srica 		default:
2044746Srica 			usage();
2054746Srica 		}
2064746Srica 	}
2074746Srica 
2084746Srica 	check_tnrhtp(tnrhtp_file);
2094746Srica 	check_tnrhdb(tnrhdb_file);
2104746Srica 	check_tnzonecfg(tnzonecfg_file);
2114746Srica 
2124746Srica 	return (exitval);
2134746Srica }
2144746Srica 
2154746Srica static void
usage(void)2164746Srica usage(void)
2174746Srica {
2184746Srica 	(void) fprintf(stderr, gettext(
2194746Srica 	    "usage: tnchkdb [-h path] [-t path] [-z path]\n"));
2204746Srica 	exit(2);
2214746Srica }
2224746Srica 
2234746Srica static void
print_error(int linenum,int err,const char * errstr)2244746Srica print_error(int linenum, int err, const char *errstr)
2254746Srica {
2264746Srica 	(void) fprintf(stderr, gettext("line %1$d: %2$s: %.32s\n"), linenum,
2274746Srica 	    tsol_strerror(err, errno), errstr);
2284746Srica }
2294746Srica 
2304746Srica static void
cipso_representable(const bslabel_t * lab,int linenum,const char * template,const char * name)2314746Srica cipso_representable(const bslabel_t *lab, int linenum, const char *template,
2324746Srica     const char *name)
2334746Srica {
2344746Srica 	const _blevel_impl_t *blab = (const _blevel_impl_t *)lab;
2354746Srica 	int lclass;
2364746Srica 	uint32_t c8;
2374746Srica 
2384746Srica 	if (!bltype(lab, SUN_SL_ID)) {
2394746Srica 		(void) fprintf(stderr, gettext("tnchkdb: "
2404746Srica 		    "%1$s type %2$d is invalid for cipso labels: "
2414746Srica 		    "line %3$d entry %4$s\n"), name, GETBLTYPE(lab), linenum,
2424746Srica 		    template);
2434746Srica 		exitval = 1;
2444746Srica 	}
2454746Srica 	lclass = LCLASS(blab);
2464746Srica 	if (lclass & 0xff00) {
2474746Srica 		(void) fprintf(stderr, gettext("tnchkdb: "
2484746Srica 		    "%1$s classification %2$x is invalid for cipso labels: "
2494746Srica 		    "line %3$d entry %4$s\n"), name, lclass, linenum,
2504746Srica 		    template);
2514746Srica 		exitval = 1;
2524746Srica 	}
2534746Srica 	c8 = blab->compartments.c8;
2544746Srica #ifdef  _BIG_ENDIAN
2554746Srica 	if (c8 & 0x0000ffff) {
2564746Srica #else
2574746Srica 	if (c8 & 0xffff0000) {
2584746Srica #endif
2594746Srica 		(void) fprintf(stderr, gettext("tnchkdb: %1$s "
2604746Srica 		    "compartments 241-256 must be zero for cipso labels: "
2614746Srica 		    "line %2$d entry %3$s\n"), name, linenum, template);
2624746Srica 		exitval = 1;
2634746Srica 	}
2644746Srica }
2654746Srica 
2664746Srica static void
2674746Srica check_tnrhtp(const char *file)
2684746Srica {
2694746Srica 	tsol_tpent_t *tpentp;
2704746Srica 	tsol_tpstr_t tpstr;
2714746Srica 	int err;
2724746Srica 	char *errstr;
2734746Srica 	FILE *fp;
2744746Srica 	blevel_t *l1, *l2;
2754746Srica 	char line[2048], *cp;
2764746Srica 	int linenum = 0;
2774746Srica 	struct tsol_name_list *tnl;
2784746Srica 	char buf[NSS_BUFLEN_TSOL_TP];
2794746Srica 	uint32_t initial_doi = 0;
2804746Srica 	boolean_t multiple_doi_found = B_FALSE;
2814746Srica 	boolean_t doi_zero_found = B_FALSE;
2824746Srica 
2834746Srica 	(void) printf(gettext("checking %s ...\n"), file);
2844746Srica 
2854746Srica 	if ((fp = fopen(file, "r")) == NULL) {
2864746Srica 		err = errno;
2874746Srica 		(void) fprintf(stderr,
2884910Ston 		    gettext("tnchkdb: failed to open %1$s: %2$s\n"), file,
2894746Srica 		    strerror(err));
2904746Srica 		exitval = 2;
2914746Srica 		tnrhtp_bad = B_TRUE;
2924746Srica 		return;
2934746Srica 	}
2944746Srica 
2954746Srica 	while (fgets(line, sizeof (line), fp) != NULL) {
2964746Srica 		linenum++;
2974746Srica 		if (line[0] == '#')
2984746Srica 			continue;
2994746Srica 		if ((cp = strchr(line, '\n')) != NULL)
3004746Srica 			*cp = '\0';
3014746Srica 		(void) str_to_tpstr(line, strlen(line), &tpstr, buf,
3024746Srica 		    sizeof (buf));
3034746Srica 		tpentp = tpstr_to_ent(&tpstr, &err, &errstr);
3044746Srica 		if (tpentp == NULL) {
3054746Srica 			if (err == LTSNET_EMPTY)
3064746Srica 				continue;
3074746Srica 			print_error(linenum, err, errstr);
3084746Srica 			exitval = 1;
3094746Srica 			/*
3104746Srica 			 * Flag is set *only* for parsing errors, which result
3114746Srica 			 * in omitting the entry from tsol_name_list.
3124746Srica 			 */
3134746Srica 			tnrhtp_bad = B_TRUE;
3144746Srica 			continue;
3154746Srica 		}
3164746Srica 
3174746Srica 		switch (tpentp->host_type) {
3184746Srica 		case UNLABELED:
3194746Srica 			/*
3204746Srica 			 * check doi
3214746Srica 			 */
3224746Srica 			if (initial_doi == 0)
3234746Srica 				initial_doi = tpentp->tp_cipso_doi_unl;
3244746Srica 			if (tpentp->tp_cipso_doi_unl != initial_doi)
3254746Srica 				multiple_doi_found = B_TRUE;
3264746Srica 			if (tpentp->tp_cipso_doi_unl == 0)
3274746Srica 				doi_zero_found = B_TRUE;
3284746Srica 
3294746Srica 			cipso_representable(&tpentp->tp_def_label, linenum,
3304746Srica 			    tpentp->name, TP_DEFLABEL);
3314746Srica 
3324746Srica 			/*
3334746Srica 			 * check max_sl dominates min_sl
3344746Srica 			 */
3354746Srica 			l1 = &tpentp->tp_gw_sl_range.lower_bound;
3364746Srica 			l2 = &tpentp->tp_gw_sl_range.upper_bound;
3374746Srica 			if (!bldominates(l2, l1)) {
3384746Srica 				(void) fprintf(stderr,
3394746Srica 				    gettext("tnchkdb: max_sl does not "
340*9530STon.Nguyen@Sun.COM 				    "dominate min_sl: line %1$d entry %2$s\n"),
3414746Srica 				    linenum, tpentp->name);
3424746Srica 				exitval = 1;
3434746Srica 			}
3444746Srica 
3454746Srica 			cipso_representable(l1, linenum, tpentp->name,
3464746Srica 			    TP_MINLABEL);
3474746Srica 			l1 = (blevel_t *)&tpentp->tp_gw_sl_set[0];
3484746Srica 			l2 = (blevel_t *)&tpentp->tp_gw_sl_set[NSLS_MAX];
3494746Srica 			for (; l1 < l2; l1++) {
3504746Srica 				if (bisinvalid(l1))
3514746Srica 					break;
3524746Srica 				cipso_representable(l1, linenum, tpentp->name,
3534746Srica 				    TP_SET);
3544746Srica 			}
3554746Srica 			break;
3564746Srica 
3574746Srica 		case SUN_CIPSO:
3584746Srica 			/*
3594746Srica 			 * check max_sl dominates min_sl
3604746Srica 			 */
3614746Srica 			l1 = &tpentp->tp_sl_range_cipso.lower_bound;
3624746Srica 			l2 = &tpentp->tp_sl_range_cipso.upper_bound;
3634746Srica 			if (!bldominates(l2, l1)) {
3644746Srica 				(void) fprintf(stderr,
3654746Srica 				    gettext("tnchkdb: max_sl does not "
366*9530STon.Nguyen@Sun.COM 				    "dominate min_sl: line %1$d entry %2$s\n"),
3674746Srica 				    linenum, tpentp->name);
3684746Srica 				exitval = 1;
3694746Srica 			}
3704746Srica 
3714746Srica 			cipso_representable(l1, linenum, tpentp->name,
3724746Srica 			    TP_MINLABEL);
3734746Srica 
3744746Srica 			l1 = (blevel_t *)&tpentp->tp_sl_set_cipso[0];
3754746Srica 			l2 = (blevel_t *)&tpentp->tp_sl_set_cipso[NSLS_MAX];
3764746Srica 			for (; l1 < l2; l1++) {
3774746Srica 				if (bisinvalid(l1))
3784746Srica 					break;
3794746Srica 				cipso_representable(l1, linenum, tpentp->name,
3804746Srica 				    TP_SET);
3814746Srica 			}
3824746Srica 
3834746Srica 			/*
3844746Srica 			 * check doi
3854746Srica 			 */
3864746Srica 			if (initial_doi == 0)
3874746Srica 				initial_doi = tpentp->tp_cipso_doi_cipso;
3884746Srica 			if (tpentp->tp_cipso_doi_cipso != initial_doi)
3894746Srica 				multiple_doi_found = B_TRUE;
3904746Srica 			if (tpentp->tp_cipso_doi_cipso == 0)
3914746Srica 				doi_zero_found = B_TRUE;
3924746Srica 			break;
3934746Srica 
3944746Srica 		default:
3954746Srica 			(void) fprintf(stderr, gettext("tnchkdb: unknown host "
396*9530STon.Nguyen@Sun.COM 			    "type %1$d: line %2$d entry %3$s\n"),
3974746Srica 			    tpentp->host_type, linenum, tpentp->name);
3984746Srica 			exitval = 1;
3994746Srica 		} /* switch */
4004746Srica 
4014746Srica 		/*
4024746Srica 		 * check if a duplicated entry
4034746Srica 		 */
4044746Srica 		if ((tnl = find_template(tpentp->name)) != NULL) {
4054746Srica 			(void) fprintf(stderr, gettext("tnchkdb: duplicated "
4064746Srica 			    "entry: %1$s at lines %2$d and %3$d\n"),
4074746Srica 			    tpentp->name, tnl->linenum, linenum);
4084746Srica 			exitval = 1;
4094746Srica 		} else {
4104746Srica 			add_template(tpentp->name, linenum);
4114746Srica 		}
4124746Srica 		tsol_freetpent(tpentp);
4134746Srica 	}
4144746Srica 	if (multiple_doi_found == B_TRUE) {
4154746Srica 		(void) fprintf(stderr,
4164746Srica 		    gettext("tnchkdb: Warning: tnrhtp entries do not all "
4174746Srica 		    "contain the same DOI value\n"));
4184746Srica 	}
4194746Srica 	if (doi_zero_found == B_TRUE) {
4204746Srica 		(void) fprintf(stderr,
4214746Srica 		    gettext("tnchkdb: Warning: DOI=0 found in some "
4224746Srica 		    "tnrhtp entries\n"));
4234746Srica 	}
4244746Srica 	(void) fclose(fp);
4254746Srica }
4264746Srica 
4274746Srica static void
4284746Srica check_tnrhdb(const char *file)
4294746Srica {
4304746Srica 	tsol_rhent_t *rhentp;
4314746Srica 	tsol_rhstr_t rhstr;
4324746Srica 	int err;
4334746Srica 	char *errstr;
4344746Srica 	FILE *fp;
4354746Srica 	char line[2048], *cp;
4364746Srica 	int linenum;
4374746Srica 	in6_addr_t addr;
4384746Srica 	struct tsol_addr_list *tal;
4394746Srica 	char buf[NSS_BUFLEN_TSOL_RH];
4404746Srica 
4414746Srica 	(void) printf(gettext("checking %s ...\n"), file);
4424746Srica 
4434746Srica 	if ((fp = fopen(file, "r")) == NULL) {
4444746Srica 		err = errno;
4454746Srica 		(void) fprintf(stderr,
4464746Srica 		    gettext("tnchkdb: failed to open %s: %s\n"), file,
4474746Srica 		    strerror(err));
4484746Srica 		exitval = 2;
4494746Srica 		return;
4504746Srica 	}
4514746Srica 
4524746Srica 	/*
4534746Srica 	 * check that all templates used in tnrhdb file are defined by tnrhtp
4544746Srica 	 */
4554746Srica 	linenum = 0;
4564746Srica 	while (fgets(line, sizeof (line), fp) != NULL) {
4574746Srica 		linenum++;
4584746Srica 		if (line[0] == '#')
4594746Srica 			continue;
4604746Srica 		if ((cp = strchr(line, '\n')) != NULL)
4614746Srica 			*cp = '\0';
4624746Srica 		(void) str_to_rhstr(line, strlen(line), &rhstr, buf,
4634746Srica 		    sizeof (buf));
4644746Srica 		rhentp = rhstr_to_ent(&rhstr, &err, &errstr);
4654746Srica 		if (rhentp == NULL) {
4664746Srica 			if (err == LTSNET_EMPTY)
4674746Srica 				continue;
4684746Srica 			print_error(linenum, err, errstr);
4694746Srica 			exitval = 1;
4704746Srica 			continue;
4714746Srica 		}
4724746Srica 
4734746Srica 		if (rhentp->rh_address.ta_family == AF_INET) {
4744746Srica 			IN6_INADDR_TO_V4MAPPED(&rhentp->rh_address.ta_addr_v4,
4754746Srica 			    &addr);
4764746Srica 		} else {
4774746Srica 			addr = rhentp->rh_address.ta_addr_v6;
4784746Srica 		}
4794746Srica 		if ((tal = find_host(rhentp->rh_prefix, addr)) != NULL) {
4804746Srica 			(void) fprintf(stderr,
4814746Srica 			    gettext("tnchkdb: duplicate entry: lines %1$d and "
4824746Srica 			    "%2$d\n"), tal->linenum, linenum);
4834746Srica 			exitval = 1;
4844746Srica 		} else {
4854746Srica 			add_host(rhentp->rh_prefix, addr, linenum);
4864746Srica 		}
4874746Srica 
4884746Srica 		if (!tnrhtp_bad && find_template(rhentp->rh_template) == NULL) {
4894746Srica 			(void) fprintf(stderr,
4904746Srica 			    gettext("tnchkdb: unknown template name: %1$s at "
4914746Srica 			    "line %2$d\n"), rhentp->rh_template, linenum);
4924746Srica 			exitval = 1;
4934746Srica 		}
4944746Srica 
4954746Srica 		tsol_freerhent(rhentp);
4964746Srica 	}
4974746Srica 	(void) fclose(fp);
4984746Srica }
4994746Srica 
5004746Srica static void
5014746Srica check_mlp_conflicts(tsol_mlp_t *mlps, boolean_t isglobal, const char *name,
5024746Srica     int linenum)
5034746Srica {
5044746Srica 	tsol_mlp_t *mlpptr, *mlp2;
5054746Srica 	mlp_info_list_t *mil;
5064746Srica 
5074746Srica 	for (mlpptr = mlps; !TSOL_MLP_END(mlpptr); mlpptr++) {
5084746Srica 		if (mlpptr->mlp_port_upper == 0)
5094746Srica 			mlpptr->mlp_port_upper = mlpptr->mlp_port;
5104746Srica 
5114746Srica 		/* First, validate against self for duplicates */
5124746Srica 		for (mlp2 = mlps; mlp2 < mlpptr; mlp2++) {
5134746Srica 			if (mlp2->mlp_ipp == mlpptr->mlp_ipp &&
5144746Srica 			    !(mlp2->mlp_port_upper < mlpptr->mlp_port ||
5154746Srica 			    mlp2->mlp_port > mlpptr->mlp_port_upper))
5164746Srica 				break;
5174746Srica 		}
5184746Srica 
5194746Srica 		if (mlp2 < mlpptr) {
5204746Srica 			(void) fprintf(stderr, gettext("tnchkdb: self-overlap "
5214746Srica 			    "of %1$s MLP protocol %2$d port %3$d-%4$d with "
5224746Srica 			    "%5$d-%6$d: zone %7$s line %8$d\n"),
5234746Srica 			    gettext(isglobal ? "global" : "zone-specific"),
5244746Srica 			    mlpptr->mlp_ipp, mlpptr->mlp_port,
5254746Srica 			    mlpptr->mlp_port_upper, mlp2->mlp_port,
5264746Srica 			    mlp2->mlp_port_upper, name, linenum);
5274746Srica 			exitval = 1;
5284746Srica 		}
5294746Srica 
5304746Srica 		if (isglobal) {
5314746Srica 			/* Next, validate against list for duplicates */
5324746Srica 			for (mil = global_mlps; mil != NULL; mil = mil->next) {
5334746Srica 				if (strcmp(mil->name, name) == 0)
5344746Srica 					continue;
5354746Srica 				if (mil->mlp.mlp_ipp == mlpptr->mlp_ipp &&
5364746Srica 				    !(mil->mlp.mlp_port_upper <
5374746Srica 				    mlpptr->mlp_port ||
5384746Srica 				    mil->mlp.mlp_port >
5394746Srica 				    mlpptr->mlp_port_upper))
5404746Srica 					break;
5414746Srica 			}
5424746Srica 
5434746Srica 			if (mil != NULL) {
5444746Srica 				(void) fprintf(stderr, gettext("tnchkdb: "
545*9530STon.Nguyen@Sun.COM 				    "overlap of global MLP protocol %1$d port "
546*9530STon.Nguyen@Sun.COM 				    "%2$d-%3$d with zone %4$s %5$d-%6$d: zone "
547*9530STon.Nguyen@Sun.COM 				    "%7$s lines %8$d and %9$d\n"),
5484746Srica 				    mlpptr->mlp_ipp, mlpptr->mlp_port,
5494746Srica 				    mlpptr->mlp_port_upper, mil->name,
5504746Srica 				    mil->mlp.mlp_port, mil->mlp.mlp_port_upper,
5514746Srica 				    name, mil->linenum, linenum);
5524746Srica 				exitval = 1;
5534746Srica 			}
5544746Srica 
5554746Srica 			/* Now throw into list */
5564746Srica 			if ((mil = malloc(sizeof (*mil))) == NULL) {
5574746Srica 				(void) fprintf(stderr, gettext("tnchkdb: "
5584746Srica 				    "malloc error: %s\n"), strerror(errno));
5594746Srica 				exit(2);
5604746Srica 			}
5614746Srica 			(void) strlcpy(mil->name, name, sizeof (mil->name));
5624746Srica 			mil->linenum = linenum;
5634746Srica 			mil->mlp = *mlpptr;
5644746Srica 			mil->next = global_mlps;
5654746Srica 			global_mlps = mil;
5664746Srica 		}
5674746Srica 	}
5684746Srica }
5694746Srica 
5704746Srica static void
5714746Srica check_tnzonecfg(const char *file)
5724746Srica {
5734746Srica 	tsol_zcent_t *zc;
5744746Srica 	int err;
5754746Srica 	char *errstr;
5764746Srica 	FILE *fp;
5774746Srica 	char line[2048], *cp;
5784746Srica 	int linenum;
5794746Srica 	boolean_t saw_global;
5804746Srica 	struct tsol_name_list *tnl;
5814746Srica 
5824746Srica 	(void) printf(gettext("checking %s ...\n"), file);
5834746Srica 
5844746Srica 	if ((fp = fopen(file, "r")) == NULL) {
5854746Srica 		err = errno;
5864746Srica 		(void) fprintf(stderr,
5874746Srica 		    gettext("tnchkdb: failed to open %s: %s\n"), file,
5884746Srica 		    strerror(err));
5894746Srica 		exitval = 2;
5904746Srica 		return;
5914746Srica 	}
5924746Srica 
5934746Srica 	saw_global = B_FALSE;
5944746Srica 	linenum = 0;
5954746Srica 	while (fgets(line, sizeof (line), fp) != NULL) {
5964746Srica 		if ((cp = strchr(line, '\n')) != NULL)
5974746Srica 			*cp = '\0';
5984746Srica 
5994746Srica 		linenum++;
6004746Srica 		if ((zc = tsol_sgetzcent(line, &err, &errstr)) == NULL) {
6014746Srica 			if (err == LTSNET_EMPTY)
6024746Srica 				continue;
6034746Srica 			print_error(linenum, err, errstr);
6044746Srica 			exitval = 1;
6054746Srica 			continue;
6064746Srica 		}
6074746Srica 
6084746Srica 		cipso_representable(&zc->zc_label, linenum, zc->zc_name,
6094746Srica 		    "label");
6104746Srica 
6114746Srica 		if (strcmp(zc->zc_name, "global") == 0)
6124746Srica 			saw_global = B_TRUE;
6134746Srica 
6144746Srica 		if ((tnl = find_zone(zc->zc_name)) != NULL) {
6154746Srica 			(void) fprintf(stderr,
6164746Srica 			    gettext("tnchkdb: duplicate zones: %1$s at lines "
6174746Srica 			    "%2$d and %3$d\n"), zc->zc_name, tnl->linenum,
6184746Srica 			    linenum);
6194746Srica 			exitval = 1;
6204746Srica 		} else {
6214746Srica 			add_zone(zc->zc_name, linenum);
6224746Srica 		}
6234746Srica 
6244746Srica 		if (zc->zc_private_mlp != NULL)
6254746Srica 			check_mlp_conflicts(zc->zc_private_mlp, B_FALSE,
6264746Srica 			    zc->zc_name, linenum);
6274746Srica 		if (zc->zc_shared_mlp != NULL)
6284746Srica 			check_mlp_conflicts(zc->zc_shared_mlp, B_TRUE,
6294746Srica 			    zc->zc_name, linenum);
6304746Srica 
6314746Srica 		tsol_freezcent(zc);
6324746Srica 	}
6334746Srica 	(void) fclose(fp);
6344746Srica 
6354746Srica 	if (!saw_global) {
6364746Srica 		(void) fprintf(stderr, gettext("tnchkdb: missing required "
6374746Srica 		    "entry for global zone in %s\n"), file);
6384746Srica 		exitval = 1;
6394746Srica 	}
6404746Srica }
641