xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/ipqosconf/ipqosconf.c (revision 85280f08e3cfa2e404951ad6817bbb974b576858)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
234bc0a2efScasper  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /* enable debug output and some debug asserts */
287c478bd9Sstevel@tonic-gate #undef	_IPQOS_CONF_DEBUG
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <libintl.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <strings.h>
357c478bd9Sstevel@tonic-gate #include <sys/nvpair.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <netinet/in.h>
387c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
397c478bd9Sstevel@tonic-gate #include <ctype.h>
407c478bd9Sstevel@tonic-gate #include <sys/socket.h>
417c478bd9Sstevel@tonic-gate #include <limits.h>
427c478bd9Sstevel@tonic-gate #include <netdb.h>
437c478bd9Sstevel@tonic-gate #include <fcntl.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/stat.h>
467c478bd9Sstevel@tonic-gate #include <errno.h>
477c478bd9Sstevel@tonic-gate #include <libipp.h>
487c478bd9Sstevel@tonic-gate #include <ipp/ipp_config.h>
497c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/ipgpc.h>
507c478bd9Sstevel@tonic-gate #include <ipp/ipp.h>
517c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
527c478bd9Sstevel@tonic-gate #include <assert.h>
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
557c478bd9Sstevel@tonic-gate #include <syslog.h>
567c478bd9Sstevel@tonic-gate #include <stdarg.h>
577c478bd9Sstevel@tonic-gate #include <libintl.h>
587c478bd9Sstevel@tonic-gate #include <locale.h>
597c478bd9Sstevel@tonic-gate #include <pwd.h>
607c478bd9Sstevel@tonic-gate #include "ipqosconf.h"
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #if	defined(_IPQOS_CONF_DEBUG)
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /* debug level */
657c478bd9Sstevel@tonic-gate static int ipqosconf_dbg_flgs =
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate RBK |
697c478bd9Sstevel@tonic-gate MHME |
707c478bd9Sstevel@tonic-gate KRET |
717c478bd9Sstevel@tonic-gate DIFF |
727c478bd9Sstevel@tonic-gate APPLY |
737c478bd9Sstevel@tonic-gate L2 |
747c478bd9Sstevel@tonic-gate L1 |
757c478bd9Sstevel@tonic-gate L0 |
767c478bd9Sstevel@tonic-gate 0;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #define	IPQOSCDBG0(lvl, x)\
817c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
827c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x)
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #define	IPQOSCDBG1(lvl, x, y)\
857c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
867c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x, y)
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #define	IPQOSCDBG2(lvl, x, y, z)\
897c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
907c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x, y, z)
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	IPQOSCDBG3(lvl, x, y, z, a)\
937c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
947c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x, y, z, a)
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #define	IPQOSCDBG4(lvl, x, y, z, a, b)\
977c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
987c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x, y, z, a, b)
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	IPQOSCDBG5(lvl, x, y, z, a, b, c)\
1017c478bd9Sstevel@tonic-gate 	if (lvl & ipqosconf_dbg_flgs)\
1027c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, x, y, z, a, b, c)
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #else	/* defined(_IPQOS_CONF_DEBUG) && !defined(lint) */
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate #define	IPQOSCDBG0(lvl, x)
1077c478bd9Sstevel@tonic-gate #define	IPQOSCDBG1(lvl, x, y)
1087c478bd9Sstevel@tonic-gate #define	IPQOSCDBG2(lvl, x, y, z)
1097c478bd9Sstevel@tonic-gate #define	IPQOSCDBG3(lvl, x, y, z, a)
1107c478bd9Sstevel@tonic-gate #define	IPQOSCDBG4(lvl, x, y, z, a, b)
1117c478bd9Sstevel@tonic-gate #define	IPQOSCDBG5(lvl, x, y, z, a, b, c)
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #endif	/* defined(_IPQOS_CONF_DEBUG) */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /* function prototypes */
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate static int modify_params(char *, nvlist_t **, int, boolean_t);
1207c478bd9Sstevel@tonic-gate static int add_class(char *, char *, int, boolean_t, char *);
1217c478bd9Sstevel@tonic-gate static int modify_class(char *, char *, int, boolean_t, char *,
1227c478bd9Sstevel@tonic-gate     enum ipp_flags);
1237c478bd9Sstevel@tonic-gate static int remove_class(char *, char *, int, enum ipp_flags);
1247c478bd9Sstevel@tonic-gate static int add_filter(char *, ipqos_conf_filter_t *, int);
1257c478bd9Sstevel@tonic-gate static int modify_filter(char *, ipqos_conf_filter_t *, int);
1267c478bd9Sstevel@tonic-gate static int remove_filter(char *, char *, int, int);
1277c478bd9Sstevel@tonic-gate static boolean_t arrays_equal(int *, int *, uint32_t);
1287c478bd9Sstevel@tonic-gate static int diffclass(ipqos_conf_class_t *, ipqos_conf_class_t *);
1297c478bd9Sstevel@tonic-gate static int diffparams(ipqos_conf_params_t *, ipqos_conf_params_t *, char *);
1307c478bd9Sstevel@tonic-gate static int difffilter(ipqos_conf_filter_t *, ipqos_conf_filter_t *, char *);
1317c478bd9Sstevel@tonic-gate static int add_filters(ipqos_conf_filter_t *, char *, int, boolean_t);
1327c478bd9Sstevel@tonic-gate static int add_classes(ipqos_conf_class_t *, char *,  int, boolean_t);
1337c478bd9Sstevel@tonic-gate static int modify_items(ipqos_conf_action_t *);
1347c478bd9Sstevel@tonic-gate static int add_items(ipqos_conf_action_t *, boolean_t);
1357c478bd9Sstevel@tonic-gate static int add_item(ipqos_conf_action_t *, boolean_t);
1367c478bd9Sstevel@tonic-gate static int remove_items(ipqos_conf_action_t *, boolean_t);
1377c478bd9Sstevel@tonic-gate static int remove_item(ipqos_conf_action_t *, boolean_t);
1387c478bd9Sstevel@tonic-gate static int undo_modifys(ipqos_conf_action_t *, ipqos_conf_action_t *);
1397c478bd9Sstevel@tonic-gate static int applydiff(ipqos_conf_action_t *, ipqos_conf_action_t *);
1407c478bd9Sstevel@tonic-gate static int rollback(ipqos_conf_action_t *, ipqos_conf_action_t *);
1417c478bd9Sstevel@tonic-gate static int rollback_recover(ipqos_conf_action_t *);
1427c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *classexist(char *, ipqos_conf_class_t *);
1437c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *filterexist(char *, int, ipqos_conf_filter_t *);
1447c478bd9Sstevel@tonic-gate static ipqos_conf_action_t *actionexist(char *, ipqos_conf_action_t *);
1457c478bd9Sstevel@tonic-gate static int diffnvlists(nvlist_t *, nvlist_t *, char *, int *, place_t);
1467c478bd9Sstevel@tonic-gate static int diffaction(ipqos_conf_action_t *, ipqos_conf_action_t *);
1477c478bd9Sstevel@tonic-gate static int diffconf(ipqos_conf_action_t *, ipqos_conf_action_t *);
1487c478bd9Sstevel@tonic-gate static int readllong(char *, long long *, char **);
1497c478bd9Sstevel@tonic-gate static int readuint8(char *, uint8_t *, char **);
1507c478bd9Sstevel@tonic-gate static int readuint16(char *, uint16_t *, char **);
1517c478bd9Sstevel@tonic-gate static int readint16(char *, int16_t *, char **);
1527c478bd9Sstevel@tonic-gate static int readint32(char *, int *, char **);
1537c478bd9Sstevel@tonic-gate static int readuint32(char *, uint32_t *, char **);
1547c478bd9Sstevel@tonic-gate static int readbool(char *, boolean_t *);
1557c478bd9Sstevel@tonic-gate static void setmask(int, in6_addr_t *, int);
1567c478bd9Sstevel@tonic-gate static int readtoken(FILE *, char **);
1577c478bd9Sstevel@tonic-gate static nvpair_t *find_nvpair(nvlist_t *, char *);
1587c478bd9Sstevel@tonic-gate static char *prepend_module_name(char *, char *);
1597c478bd9Sstevel@tonic-gate static int readnvpair(FILE *, FILE *, nvlist_t **, nvpair_t **,
1607c478bd9Sstevel@tonic-gate     ipqos_nvtype_t *, place_t, char *);
1617c478bd9Sstevel@tonic-gate static int add_aref(ipqos_conf_act_ref_t **, char *, char *);
1627c478bd9Sstevel@tonic-gate static int readparams(FILE *, FILE *, char *, ipqos_conf_params_t *);
1637c478bd9Sstevel@tonic-gate static int readclass(FILE *, char *, ipqos_conf_class_t **, char **, int);
1647c478bd9Sstevel@tonic-gate static int readfilter(FILE *, FILE *, char *, ipqos_conf_filter_t **, char **,
1657c478bd9Sstevel@tonic-gate     int);
1667c478bd9Sstevel@tonic-gate static FILE *validmod(char *, int *);
1677c478bd9Sstevel@tonic-gate static int readaction(FILE *, ipqos_conf_action_t **);
1687c478bd9Sstevel@tonic-gate static int actions_unique(ipqos_conf_action_t *, char **);
1697c478bd9Sstevel@tonic-gate static int validconf(ipqos_conf_action_t *, int);
1707c478bd9Sstevel@tonic-gate static int readconf(FILE *, ipqos_conf_action_t **);
1717c478bd9Sstevel@tonic-gate static int flush(boolean_t *);
1727c478bd9Sstevel@tonic-gate static int atomic_flush(boolean_t);
1737c478bd9Sstevel@tonic-gate static int flushconf();
1747c478bd9Sstevel@tonic-gate static int writeconf(ipqos_conf_action_t *, char *);
1757c478bd9Sstevel@tonic-gate static int commitconf();
1767c478bd9Sstevel@tonic-gate static int applyconf(char *ifile);
1777c478bd9Sstevel@tonic-gate static int block_all_signals();
1787c478bd9Sstevel@tonic-gate static int restore_all_signals();
1797c478bd9Sstevel@tonic-gate static int unlock(int fd);
1807c478bd9Sstevel@tonic-gate static int lock();
1817c478bd9Sstevel@tonic-gate static int viewconf(int);
1827c478bd9Sstevel@tonic-gate static void usage();
1837c478bd9Sstevel@tonic-gate static int valid_name(char *);
1847c478bd9Sstevel@tonic-gate static int in_cycle(ipqos_conf_action_t *);
1857c478bd9Sstevel@tonic-gate static int readtype(FILE *, char *, char *, ipqos_nvtype_t *, str_val_nd_t **,
1867c478bd9Sstevel@tonic-gate     char *, boolean_t, place_t *);
1877c478bd9Sstevel@tonic-gate static int read_int_array_info(char *, str_val_nd_t **, uint32_t *, int *,
1887c478bd9Sstevel@tonic-gate     int *, char *);
1897c478bd9Sstevel@tonic-gate static str_val_nd_t *read_enum_nvs(char *, char *);
1907c478bd9Sstevel@tonic-gate static int add_str_val_entry(str_val_nd_t **, char *, uint32_t);
1917c478bd9Sstevel@tonic-gate static void free_str_val_entrys(str_val_nd_t *);
1927c478bd9Sstevel@tonic-gate static void get_str_val_value_range(str_val_nd_t *, int *, int *);
1937c478bd9Sstevel@tonic-gate static int read_enum_value(FILE *, char *, str_val_nd_t *, uint32_t *);
1947c478bd9Sstevel@tonic-gate static int read_mapped_values(FILE *, nvlist_t **, char *, char *,
1957c478bd9Sstevel@tonic-gate     int);
1967c478bd9Sstevel@tonic-gate static int read_int_array(FILE *, char *, int **, uint32_t, int, int,
1977c478bd9Sstevel@tonic-gate     str_val_nd_t *);
1987c478bd9Sstevel@tonic-gate static int str_val_list_lookup(str_val_nd_t *, char *, uint32_t *);
1997c478bd9Sstevel@tonic-gate static int parse_kparams(char *, ipqos_conf_params_t *, nvlist_t *);
2007c478bd9Sstevel@tonic-gate static int parse_kclass(ipqos_conf_class_t *, nvlist_t *);
2017c478bd9Sstevel@tonic-gate static int parse_kfilter(ipqos_conf_filter_t *, nvlist_t *);
2027c478bd9Sstevel@tonic-gate static int parse_kaction(nvlist_t *, ipqos_actinfo_prm_t *);
2037c478bd9Sstevel@tonic-gate static int readkconf(ipqos_conf_action_t **);
2047c478bd9Sstevel@tonic-gate static void print_int_array(FILE *, int *, uint32_t, int, int, str_val_nd_t *,
2057c478bd9Sstevel@tonic-gate     int);
2067c478bd9Sstevel@tonic-gate static void printrange(FILE *fp, uint32_t, uint32_t);
2077c478bd9Sstevel@tonic-gate static void printenum(FILE *, uint32_t, str_val_nd_t *);
2087c478bd9Sstevel@tonic-gate static void printproto(FILE *, uint8_t);
2097c478bd9Sstevel@tonic-gate static void printport(FILE *, uint16_t);
2107c478bd9Sstevel@tonic-gate static int printnvlist(FILE *, char *, nvlist_t *, int, ipqos_conf_filter_t *,
2117c478bd9Sstevel@tonic-gate     int, place_t);
2127c478bd9Sstevel@tonic-gate static int virtual_action(char *);
2137c478bd9Sstevel@tonic-gate static void free_arefs(ipqos_conf_act_ref_t *);
2147c478bd9Sstevel@tonic-gate static void print_action_nm(FILE *, char *);
2157c478bd9Sstevel@tonic-gate static int add_orig_ipqosconf(nvlist_t *);
2167c478bd9Sstevel@tonic-gate static char *get_originator_nm(uint32_t);
2177c478bd9Sstevel@tonic-gate static void mark_classes_filters_new(ipqos_conf_action_t *);
2187c478bd9Sstevel@tonic-gate static void mark_classes_filters_del(ipqos_conf_action_t *);
2197c478bd9Sstevel@tonic-gate static void mark_config_new(ipqos_conf_action_t *);
2207c478bd9Sstevel@tonic-gate static int printifname(FILE *, int);
2217c478bd9Sstevel@tonic-gate static int readifindex(char *, int *);
2227c478bd9Sstevel@tonic-gate static void cleanup_string_table(char **, int);
2237c478bd9Sstevel@tonic-gate static int domultihome(ipqos_conf_filter_t *, ipqos_conf_filter_t **,
2247c478bd9Sstevel@tonic-gate     boolean_t);
2257c478bd9Sstevel@tonic-gate static int dup_filter(ipqos_conf_filter_t *, ipqos_conf_filter_t **, int, int,
2267c478bd9Sstevel@tonic-gate     void *, void *, int);
2277c478bd9Sstevel@tonic-gate static void free_actions(ipqos_conf_action_t *);
2287c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *alloc_filter();
2297c478bd9Sstevel@tonic-gate static void free_filter(ipqos_conf_filter_t *);
2307c478bd9Sstevel@tonic-gate static int read_curl_begin(FILE *);
2317c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *alloc_class(void);
2327c478bd9Sstevel@tonic-gate static int diffclasses(ipqos_conf_action_t *old, ipqos_conf_action_t *new);
2337c478bd9Sstevel@tonic-gate static int difffilters(ipqos_conf_action_t *old, ipqos_conf_action_t *new);
2347c478bd9Sstevel@tonic-gate static int dup_class(ipqos_conf_class_t *src, ipqos_conf_class_t **dst);
2357c478bd9Sstevel@tonic-gate static int add_action(ipqos_conf_action_t *act);
2367c478bd9Sstevel@tonic-gate static int masktocidr(int af, in6_addr_t *mask);
2377c478bd9Sstevel@tonic-gate static int read_perm_items(int, FILE *, char *, char ***, int *);
2387c478bd9Sstevel@tonic-gate static int in_string_table(char *stable[], int size, char *string);
2397c478bd9Sstevel@tonic-gate static void list_end(ipqos_list_el_t **listp, ipqos_list_el_t ***lendpp);
2407c478bd9Sstevel@tonic-gate static void add_to_list(ipqos_list_el_t **listp, ipqos_list_el_t *el);
2417c478bd9Sstevel@tonic-gate static int read_cfile_ver(FILE *, char *);
2427c478bd9Sstevel@tonic-gate static char *quote_ws_string(const char *);
2437c478bd9Sstevel@tonic-gate static int read_tfile_ver(FILE *, char *, char *);
2447c478bd9Sstevel@tonic-gate static int ver_str_to_int(char *);
2457c478bd9Sstevel@tonic-gate static void printuser(FILE *fp, uid_t uid);
2467c478bd9Sstevel@tonic-gate static int readuser(char *str, uid_t *uid);
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate  * macros to call list functions with the more complex list element type
2507c478bd9Sstevel@tonic-gate  * cast to the skeletal type iqpos_list_el_t.
2517c478bd9Sstevel@tonic-gate  */
252*85280f08SToomas Soome #define	GET_LIST_END(list, end)\
2537c478bd9Sstevel@tonic-gate 	list_end((ipqos_list_el_t **)list,  (ipqos_list_el_t ***)end)
2547c478bd9Sstevel@tonic-gate #define	ADD_TO_LIST(list, el)\
2557c478bd9Sstevel@tonic-gate 	add_to_list((ipqos_list_el_t **)list, (ipqos_list_el_t *)el)
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  *	Macros to produce a quoted string containing the value of a
2597c478bd9Sstevel@tonic-gate  *	preprocessor macro. For example, if SIZE is defined to be 256,
2607c478bd9Sstevel@tonic-gate  *	VAL2STR(SIZE) is "256". This is used to construct format
2617c478bd9Sstevel@tonic-gate  *	strings for scanf-family functions below.
2627c478bd9Sstevel@tonic-gate  */
2637c478bd9Sstevel@tonic-gate #define	QUOTE(x)	#x
2647c478bd9Sstevel@tonic-gate #define	VAL2STR(x)	QUOTE(x)
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /* globals */
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /* table of supported parameter types and enum value */
2707c478bd9Sstevel@tonic-gate static str_val_t nv_types[] = {
2717c478bd9Sstevel@tonic-gate {"uint8",		IPQOS_DATA_TYPE_UINT8},
2727c478bd9Sstevel@tonic-gate {"int16",		IPQOS_DATA_TYPE_INT16},
2737c478bd9Sstevel@tonic-gate {"uint16",		IPQOS_DATA_TYPE_UINT16},
2747c478bd9Sstevel@tonic-gate {"int32",		IPQOS_DATA_TYPE_INT32},
2757c478bd9Sstevel@tonic-gate {"uint32",		IPQOS_DATA_TYPE_UINT32},
2767c478bd9Sstevel@tonic-gate {"boolean",		IPQOS_DATA_TYPE_BOOLEAN},
2777c478bd9Sstevel@tonic-gate {"string",		IPQOS_DATA_TYPE_STRING},
2787c478bd9Sstevel@tonic-gate {"action",		IPQOS_DATA_TYPE_ACTION},
2797c478bd9Sstevel@tonic-gate {"address",		IPQOS_DATA_TYPE_ADDRESS},
2807c478bd9Sstevel@tonic-gate {"port",		IPQOS_DATA_TYPE_PORT},
2817c478bd9Sstevel@tonic-gate {"protocol",		IPQOS_DATA_TYPE_PROTO},
2827c478bd9Sstevel@tonic-gate {"enum",		IPQOS_DATA_TYPE_ENUM},
2837c478bd9Sstevel@tonic-gate {"ifname",		IPQOS_DATA_TYPE_IFNAME},
2847c478bd9Sstevel@tonic-gate {"mindex",		IPQOS_DATA_TYPE_M_INDEX},
2857c478bd9Sstevel@tonic-gate {"int_array",		IPQOS_DATA_TYPE_INT_ARRAY},
2867c478bd9Sstevel@tonic-gate {"user",		IPQOS_DATA_TYPE_USER},
2877c478bd9Sstevel@tonic-gate {"",			0}
2887c478bd9Sstevel@tonic-gate };
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate /* table of name to id mappings for originator field */
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate static str_val_t originators[] = {
2937c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_PERMANENT,	IPP_CONFIG_PERMANENT},
2947c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_IPQOSCONF,	IPP_CONFIG_IPQOSCONF},
2957c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_FTPCL,		IPP_CONFIG_FTPCL},
2967c478bd9Sstevel@tonic-gate {"", -1}
2977c478bd9Sstevel@tonic-gate };
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate /* current parse line */
3007c478bd9Sstevel@tonic-gate static int lineno;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate /* verbose output flag */
3037c478bd9Sstevel@tonic-gate static int verbose;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate /* use syslog for msg reporting flag */
3067c478bd9Sstevel@tonic-gate static int use_syslog;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate  * flag used to indicate that a rollback should be carried out regardless.
3117c478bd9Sstevel@tonic-gate  * Only settable during debug.
3127c478bd9Sstevel@tonic-gate  */
3137c478bd9Sstevel@tonic-gate static int force_rback = 0;
3147c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate  * delivers messages to either syslog or stderr, dependant upon the
3187c478bd9Sstevel@tonic-gate  * the state of the flags use_syslog and verbose. The type
3197c478bd9Sstevel@tonic-gate  * of the msg as given in msg_type is indicated in the output msg.
3207c478bd9Sstevel@tonic-gate  *
3217c478bd9Sstevel@tonic-gate  * valid message types are:
3227c478bd9Sstevel@tonic-gate  * o  MT_ERROR (standard error message)
3237c478bd9Sstevel@tonic-gate  * o  MT_ENOSTR (error message with system error string appended)
3247c478bd9Sstevel@tonic-gate  * o  MT_WARNING (warning message)
3257c478bd9Sstevel@tonic-gate  * o  MT_LOG (logging message)
3267c478bd9Sstevel@tonic-gate  *
3277c478bd9Sstevel@tonic-gate  * Log messages only go to syslog. Warning messages only go to stderr
3287c478bd9Sstevel@tonic-gate  * and only when the verbose flag is set. All other messages go by default
3297c478bd9Sstevel@tonic-gate  * to the console; to syslog if syslog flag set, and to both if both
3307c478bd9Sstevel@tonic-gate  * syslog and verbose are set.
3317c478bd9Sstevel@tonic-gate  *
3327c478bd9Sstevel@tonic-gate  */
3337c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
3347c478bd9Sstevel@tonic-gate static void
3357c478bd9Sstevel@tonic-gate ipqos_msg(enum msg_type msgt, char *format, ...)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate 	va_list ap;
3387c478bd9Sstevel@tonic-gate 	char str_buf[IPQOS_MSG_BUF_SZ];
3397c478bd9Sstevel@tonic-gate 	char fmt_buf[IPQOS_MSG_BUF_SZ];
3407c478bd9Sstevel@tonic-gate 	char *cp;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In ipqos_msg:\n");
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	va_start(ap, format);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	/*
3477c478bd9Sstevel@tonic-gate 	 * send msgs to syslog if use_syslog set (except warning msgs),
3487c478bd9Sstevel@tonic-gate 	 * or a log msg.
3497c478bd9Sstevel@tonic-gate 	 */
3507c478bd9Sstevel@tonic-gate 	if ((use_syslog && (msgt != MT_WARNING)) || msgt == MT_LOG) {
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		/* fill in format string */
3537c478bd9Sstevel@tonic-gate 		(void) vsnprintf(str_buf, IPQOS_MSG_BUF_SZ, format, ap);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		/*
3567c478bd9Sstevel@tonic-gate 		 * print message to syslog with appropriate severity
3577c478bd9Sstevel@tonic-gate 		 */
3587c478bd9Sstevel@tonic-gate 		if (msgt == MT_ERROR) {
3597c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, str_buf);
3607c478bd9Sstevel@tonic-gate 		} else if (msgt == MT_LOG) {
3617c478bd9Sstevel@tonic-gate 			syslog(LOG_INFO, str_buf);
3627c478bd9Sstevel@tonic-gate 		/*
3637c478bd9Sstevel@tonic-gate 		 * for errno message type suffix with %m for syslog to
3647c478bd9Sstevel@tonic-gate 		 * interpret.
3657c478bd9Sstevel@tonic-gate 		 */
3667c478bd9Sstevel@tonic-gate 		} else if (msgt == MT_ENOSTR) {
3677c478bd9Sstevel@tonic-gate 			/*
3687c478bd9Sstevel@tonic-gate 			 * remove any newline in message parameter.
3697c478bd9Sstevel@tonic-gate 			 * syslog will reapply a newline for us later.
3707c478bd9Sstevel@tonic-gate 			 */
3717c478bd9Sstevel@tonic-gate 			if ((cp = strchr(str_buf, '\n')) != NULL)
3727c478bd9Sstevel@tonic-gate 				*cp = '\0';
3737c478bd9Sstevel@tonic-gate 			(void) strlcat(str_buf, ": %m", IPQOS_MSG_BUF_SZ);
3747c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, str_buf);
3757c478bd9Sstevel@tonic-gate 		}
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/*
3797c478bd9Sstevel@tonic-gate 	 * send msgs to stderr if use_syslog not set (except log msgs), or
3807c478bd9Sstevel@tonic-gate 	 * if verbose set.
3817c478bd9Sstevel@tonic-gate 	 */
3827c478bd9Sstevel@tonic-gate 	if ((!use_syslog && (msgt != MT_LOG)) || (verbose)) {
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		/*
3857c478bd9Sstevel@tonic-gate 		 * prefix message with appropriate severity string
3867c478bd9Sstevel@tonic-gate 		 */
3877c478bd9Sstevel@tonic-gate 		if (msgt == MT_ERROR) {
3887c478bd9Sstevel@tonic-gate 			(void) strlcpy(fmt_buf, gettext("Error: "),
3897c478bd9Sstevel@tonic-gate 			    IPQOS_MSG_BUF_SZ);
3907c478bd9Sstevel@tonic-gate 		} else if (msgt == MT_WARNING) {
3917c478bd9Sstevel@tonic-gate 			if (!verbose) { /* don't show warn msg if !verbose */
3927c478bd9Sstevel@tonic-gate 				va_end(ap);
3937c478bd9Sstevel@tonic-gate 				return;
3947c478bd9Sstevel@tonic-gate 			}
3957c478bd9Sstevel@tonic-gate 			(void) strlcpy(fmt_buf, gettext("Warning: "),
3967c478bd9Sstevel@tonic-gate 			    IPQOS_MSG_BUF_SZ);
3977c478bd9Sstevel@tonic-gate 		} else if (msgt == MT_ENOSTR) {
3987c478bd9Sstevel@tonic-gate 			(void) strlcpy(fmt_buf, gettext("Error: "),
3997c478bd9Sstevel@tonic-gate 			    IPQOS_MSG_BUF_SZ);
4007c478bd9Sstevel@tonic-gate 		} else if (msgt == MT_LOG) {
4017c478bd9Sstevel@tonic-gate 			(void) strlcpy(fmt_buf, gettext("Notice: "),
4027c478bd9Sstevel@tonic-gate 			    IPQOS_MSG_BUF_SZ);
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 		(void) strlcat(fmt_buf, format, IPQOS_MSG_BUF_SZ);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		/*
4077c478bd9Sstevel@tonic-gate 		 * for errno message type suffix message with errno string
4087c478bd9Sstevel@tonic-gate 		 */
4097c478bd9Sstevel@tonic-gate 		if (msgt == MT_ENOSTR) {
4107c478bd9Sstevel@tonic-gate 			/*
4117c478bd9Sstevel@tonic-gate 			 * get rid of any newline in passed message.
4127c478bd9Sstevel@tonic-gate 			 * we'll apply another later.
4137c478bd9Sstevel@tonic-gate 			 */
4147c478bd9Sstevel@tonic-gate 			if ((cp = strchr(fmt_buf, '\n')) != NULL)
4157c478bd9Sstevel@tonic-gate 				*cp = '\0';
4167c478bd9Sstevel@tonic-gate 			(void) strlcat(fmt_buf, ": ", IPQOS_MSG_BUF_SZ);
4177c478bd9Sstevel@tonic-gate 			(void) strlcat(fmt_buf, strerror(errno),
4187c478bd9Sstevel@tonic-gate 			    IPQOS_MSG_BUF_SZ);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 		/*
4227c478bd9Sstevel@tonic-gate 		 * append a newline to message if not one already.
4237c478bd9Sstevel@tonic-gate 		 */
4247c478bd9Sstevel@tonic-gate 		if ((cp = strchr(fmt_buf, '\n')) == NULL)
4257c478bd9Sstevel@tonic-gate 			(void) strlcat(fmt_buf, "\n", IPQOS_MSG_BUF_SZ);
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		(void) vfprintf(stderr, fmt_buf, ap);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	va_end(ap);
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate /* **************** kernel filter/class/params manipulation fns *********** */
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate /*
4377c478bd9Sstevel@tonic-gate  * modify the kernel parameters of the action action_nm using the nvlist
4387c478bd9Sstevel@tonic-gate  * parameter nvl and setting the stats according to stats_enable.
4397c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate static int
4437c478bd9Sstevel@tonic-gate modify_params(
4447c478bd9Sstevel@tonic-gate char *action_name,
4457c478bd9Sstevel@tonic-gate nvlist_t **nvl,
4467c478bd9Sstevel@tonic-gate int module_version,
4477c478bd9Sstevel@tonic-gate boolean_t stats_enable)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	int res;
4517c478bd9Sstevel@tonic-gate 	int created = 0;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(APPLY, "In modify_params: action: %s\n", action_name);
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	/* create nvlist if NULL */
4567c478bd9Sstevel@tonic-gate 	if (*nvl == NULL) {
4577c478bd9Sstevel@tonic-gate 		created++;
4587c478bd9Sstevel@tonic-gate 		res = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
4597c478bd9Sstevel@tonic-gate 		if (res != 0) {
4607c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_alloc");
4617c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
4627c478bd9Sstevel@tonic-gate 		}
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/* add params modify config type */
4667c478bd9Sstevel@tonic-gate 	res = nvlist_add_byte(*nvl, IPP_CONFIG_TYPE, IPP_SET);
4677c478bd9Sstevel@tonic-gate 	if (res != 0) {
4687c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
4697c478bd9Sstevel@tonic-gate 		goto fail;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/*
4737c478bd9Sstevel@tonic-gate 	 * add module version
4747c478bd9Sstevel@tonic-gate 	 */
4757c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(*nvl, IPP_MODULE_VERSION,
4767c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
4777c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
4787c478bd9Sstevel@tonic-gate 		goto fail;
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/* add stats_enable */
4827c478bd9Sstevel@tonic-gate 	res = nvlist_add_uint32(*nvl, IPP_ACTION_STATS_ENABLE,
4837c478bd9Sstevel@tonic-gate 	    (uint32_t)stats_enable);
4847c478bd9Sstevel@tonic-gate 	if (res != 0) {
4857c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
4867c478bd9Sstevel@tonic-gate 		goto fail;
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	/* add ipqosconf as originator */
4907c478bd9Sstevel@tonic-gate 	res = add_orig_ipqosconf(*nvl);
4917c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
4927c478bd9Sstevel@tonic-gate 		goto fail;
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	/* call lib to do modify */
4967c478bd9Sstevel@tonic-gate 	res = ipp_action_modify(action_name, nvl, 0);
4977c478bd9Sstevel@tonic-gate 	if (res != 0) {
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 		/* invalid parameters */
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 		if (errno == EINVAL) {
5027c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
5037c478bd9Sstevel@tonic-gate 			    gettext("Invalid parameters for action %s.\n"),
5047c478bd9Sstevel@tonic-gate 			    action_name);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 		} else if (errno == ENOENT) {
5087c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
5097c478bd9Sstevel@tonic-gate 			    gettext("Mandatory parameter missing for "
5107c478bd9Sstevel@tonic-gate 			    "action %s.\n"), action_name);
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		} else {	/* unexpected error */
5147c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Failed to modify action "
5157c478bd9Sstevel@tonic-gate 			    "%s parameters: %s.\n"), action_name,
5167c478bd9Sstevel@tonic-gate 			    strerror(errno));
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		goto fail;
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
5237c478bd9Sstevel@tonic-gate fail:
5247c478bd9Sstevel@tonic-gate 	if (created && *nvl != NULL) {
5257c478bd9Sstevel@tonic-gate 		nvlist_free(*nvl);
5267c478bd9Sstevel@tonic-gate 		*nvl = NULL;
5277c478bd9Sstevel@tonic-gate 	}
5287c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate  * add a class to the kernel action action_name called class_name with
5337c478bd9Sstevel@tonic-gate  * stats set according to stats_enable and the first action set to
5347c478bd9Sstevel@tonic-gate  * first_action.
5357c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
5367c478bd9Sstevel@tonic-gate  */
5377c478bd9Sstevel@tonic-gate static int
5387c478bd9Sstevel@tonic-gate add_class(
5397c478bd9Sstevel@tonic-gate char *action_name,
5407c478bd9Sstevel@tonic-gate char *class_name,
5417c478bd9Sstevel@tonic-gate int module_version,
5427c478bd9Sstevel@tonic-gate boolean_t stats_enable,
5437c478bd9Sstevel@tonic-gate char *first_action)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(APPLY, "add_class: action: %s, class: %s, "
5497c478bd9Sstevel@tonic-gate 	    "first_action: %s, stats: %s\n", action_name, class_name,
5507c478bd9Sstevel@tonic-gate 	    first_action, (stats_enable == B_TRUE ? "true" : "false"));
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/* create nvlist */
5547c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
5557c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_alloc");
5567c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	/* add 'add class' config type */
5607c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_ADD_CLASS) != 0) {
5617c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
5627c478bd9Sstevel@tonic-gate 		goto fail;
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	/*
5667c478bd9Sstevel@tonic-gate 	 * add module version
5677c478bd9Sstevel@tonic-gate 	 */
5687c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
5697c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
5707c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
5717c478bd9Sstevel@tonic-gate 		goto fail;
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	/* add class name */
5757c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) {
5767c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
5777c478bd9Sstevel@tonic-gate 		goto fail;
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	/* add next action */
5817c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_NEXT_ACTION, first_action) != 0) {
5827c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
5837c478bd9Sstevel@tonic-gate 		goto fail;
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	/* add stats_enable */
5877c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE,
5887c478bd9Sstevel@tonic-gate 	    (uint32_t)stats_enable) != 0) {
5897c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
5907c478bd9Sstevel@tonic-gate 		goto fail;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/* add ipqosconf as originator */
5947c478bd9Sstevel@tonic-gate 	if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) {
5957c478bd9Sstevel@tonic-gate 		goto fail;
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/* call lib to do modify */
5997c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &nvl, 0) != 0) {
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 		/* ipgpc max classes */
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 		if (errno == ENOSPC &&
6047c478bd9Sstevel@tonic-gate 		    strcmp(action_name, IPGPC_CLASSIFY) == 0) {
6057c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
6067c478bd9Sstevel@tonic-gate 			    gettext("Max number of classes reached in %s.\n"),
6077c478bd9Sstevel@tonic-gate 			    IPGPC_NAME);
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 		/* other errors */
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 		} else {
6127c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
6137c478bd9Sstevel@tonic-gate 			    gettext("Failed to create class %s in action "
6147c478bd9Sstevel@tonic-gate 			    "%s: %s.\n"), class_name, action_name,
6157c478bd9Sstevel@tonic-gate 			    strerror(errno));
6167c478bd9Sstevel@tonic-gate 		}
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		goto fail;
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
6227c478bd9Sstevel@tonic-gate fail:
6237c478bd9Sstevel@tonic-gate 	nvlist_free(nvl);
6247c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate /*
6297c478bd9Sstevel@tonic-gate  * modify the class in the kernel action action_name called class_name with
6307c478bd9Sstevel@tonic-gate  * stats set according to stats_enable and the first action set to
6317c478bd9Sstevel@tonic-gate  * first_action.
6327c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
6337c478bd9Sstevel@tonic-gate  */
6347c478bd9Sstevel@tonic-gate static int
6357c478bd9Sstevel@tonic-gate modify_class(
6367c478bd9Sstevel@tonic-gate char *action_name,
6377c478bd9Sstevel@tonic-gate char *class_name,
6387c478bd9Sstevel@tonic-gate int module_version,
6397c478bd9Sstevel@tonic-gate boolean_t stats_enable,
6407c478bd9Sstevel@tonic-gate char *first_action,
6417c478bd9Sstevel@tonic-gate enum ipp_flags flags)
6427c478bd9Sstevel@tonic-gate {
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	IPQOSCDBG5(APPLY, "modify_class: action: %s, class: %s, first: %s, "
6477c478bd9Sstevel@tonic-gate 	    "stats: %s, flags: %x\n", action_name, class_name, first_action,
6487c478bd9Sstevel@tonic-gate 	    stats_enable == B_TRUE ? "true" : "false", flags);
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/* create nvlist */
6527c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6537c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_alloc");
6547c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	/* add 'modify class' config type */
6587c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_MODIFY_CLASS) !=
6597c478bd9Sstevel@tonic-gate 	    0) {
6607c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
6617c478bd9Sstevel@tonic-gate 		goto fail;
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	/*
6657c478bd9Sstevel@tonic-gate 	 * add module version
6667c478bd9Sstevel@tonic-gate 	 */
6677c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
6687c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
6697c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
6707c478bd9Sstevel@tonic-gate 		goto fail;
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	/* add class name */
6747c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) {
6757c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
6767c478bd9Sstevel@tonic-gate 		goto fail;
6777c478bd9Sstevel@tonic-gate 	}
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	/* add next action */
6807c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_NEXT_ACTION, first_action) != 0) {
6817c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
6827c478bd9Sstevel@tonic-gate 		goto fail;
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	/* add stats enable */
6867c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE,
6877c478bd9Sstevel@tonic-gate 	    (uint32_t)stats_enable) != 0) {
6887c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
6897c478bd9Sstevel@tonic-gate 		goto fail;
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	/* add originator ipqosconf */
6937c478bd9Sstevel@tonic-gate 	if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) {
6947c478bd9Sstevel@tonic-gate 		goto fail;
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	/* call lib to do modify */
6987c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &nvl, flags) != 0) {
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		/* generic error message */
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
7037c478bd9Sstevel@tonic-gate 		    gettext("Modifying class %s in action %s failed: %s.\n"),
7047c478bd9Sstevel@tonic-gate 		    class_name, action_name, strerror(errno));
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 		goto fail;
7077c478bd9Sstevel@tonic-gate 	}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
7107c478bd9Sstevel@tonic-gate fail:
7117c478bd9Sstevel@tonic-gate 	nvlist_free(nvl);
7127c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate /*
7167c478bd9Sstevel@tonic-gate  * removes the class class_name from the kernel action action_name. The
7177c478bd9Sstevel@tonic-gate  * flags argument can currently be set to IPP_ACTION_DESTROY which will
7187c478bd9Sstevel@tonic-gate  * result in the action this class references being destroyed.
7197c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
7207c478bd9Sstevel@tonic-gate  */
7217c478bd9Sstevel@tonic-gate static int
7227c478bd9Sstevel@tonic-gate remove_class(
7237c478bd9Sstevel@tonic-gate char *action_name,
7247c478bd9Sstevel@tonic-gate char *class_name,
7257c478bd9Sstevel@tonic-gate int module_version,
7267c478bd9Sstevel@tonic-gate enum ipp_flags flags)
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	IPQOSCDBG3(APPLY, "remove_class: action: %s, class: %s, "
7327c478bd9Sstevel@tonic-gate 	    "flags: %x\n", action_name, class_name, flags);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	/* allocate nvlist */
7357c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
7367c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_alloc");
7377c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
7387c478bd9Sstevel@tonic-gate 	}
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	/* add 'remove class' config type */
7417c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_REMOVE_CLASS) !=
7427c478bd9Sstevel@tonic-gate 	    0) {
7437c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
7447c478bd9Sstevel@tonic-gate 		goto fail;
7457c478bd9Sstevel@tonic-gate 	}
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	/*
7487c478bd9Sstevel@tonic-gate 	 * add module version
7497c478bd9Sstevel@tonic-gate 	 */
7507c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
7517c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
7527c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
7537c478bd9Sstevel@tonic-gate 		goto fail;
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/* add class name */
7577c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) {
7587c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
7597c478bd9Sstevel@tonic-gate 		goto fail;
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &nvl, flags) != 0) {
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 		/* generic error message */
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
7677c478bd9Sstevel@tonic-gate 		    gettext("Removing class %s in action %s failed: %s.\n"),
7687c478bd9Sstevel@tonic-gate 		    class_name, action_name, strerror(errno));
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 		goto fail;
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
7747c478bd9Sstevel@tonic-gate fail:
7757c478bd9Sstevel@tonic-gate 	nvlist_free(nvl);
7767c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate /*
7807c478bd9Sstevel@tonic-gate  * add the filter flt to the kernel action named action_name.
7817c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
7827c478bd9Sstevel@tonic-gate  */
7837c478bd9Sstevel@tonic-gate static int
7847c478bd9Sstevel@tonic-gate add_filter(
7857c478bd9Sstevel@tonic-gate char *action_name,
7867c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt,
7877c478bd9Sstevel@tonic-gate int module_version)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	nvlist_t *nvl = flt->nvlist;
7917c478bd9Sstevel@tonic-gate 	char ipvsbuf[IPQOS_INT_STR_LEN];
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(APPLY, "add_filter: action: %s, filter: %s, "
7947c478bd9Sstevel@tonic-gate 	    "instance: %d, class: %s\n", action_name, flt->name,
7957c478bd9Sstevel@tonic-gate 	    flt->instance, flt->class_name);
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	/* add 'add filter' config type to filter nvlist */
7997c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_ADD_FILTER) != 0) {
8007c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
8017c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8027c478bd9Sstevel@tonic-gate 	}
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	/*
8057c478bd9Sstevel@tonic-gate 	 * add module version
8067c478bd9Sstevel@tonic-gate 	 */
8077c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
8087c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
8097c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
8107c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	/* add filter name to nvlist */
8147c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, flt->name) != 0) {
8157c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
8167c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8177c478bd9Sstevel@tonic-gate 	}
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	/* add class name to nvlist */
8207c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, flt->class_name) !=
8217c478bd9Sstevel@tonic-gate 	    0) {
8227c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
8237c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8247c478bd9Sstevel@tonic-gate 	}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	/* add ipqosconf as originator to nvlist */
8277c478bd9Sstevel@tonic-gate 	if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) {
8287c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8297c478bd9Sstevel@tonic-gate 	}
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	/* add ipgpc specific nv entrys */
8327c478bd9Sstevel@tonic-gate 	if (strcmp(action_name, IPGPC_CLASSIFY) == 0) {
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		/* add src and dst nodes to nvlist if present */
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 		if (flt->src_nd_name != NULL &&
8377c478bd9Sstevel@tonic-gate 		    nvlist_add_string(nvl, IPGPC_SADDR_HOSTNAME,
8387c478bd9Sstevel@tonic-gate 		    flt->src_nd_name) != 0) {
8397c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_string");
8407c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
8417c478bd9Sstevel@tonic-gate 		}
8427c478bd9Sstevel@tonic-gate 		if (flt->dst_nd_name != NULL &&
8437c478bd9Sstevel@tonic-gate 		    nvlist_add_string(nvl, IPGPC_DADDR_HOSTNAME,
8447c478bd9Sstevel@tonic-gate 		    flt->dst_nd_name) != 0) {
8457c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_string");
8467c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
8477c478bd9Sstevel@tonic-gate 		}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 		/*
8507c478bd9Sstevel@tonic-gate 		 * add ip_version to private list element if present.
8517c478bd9Sstevel@tonic-gate 		 * NOTE: this value is of only real use to ipqosconf so
8527c478bd9Sstevel@tonic-gate 		 * it is placed in this opaque private field.
8537c478bd9Sstevel@tonic-gate 		 */
8547c478bd9Sstevel@tonic-gate 		if (flt->ip_versions != 0) {
8557c478bd9Sstevel@tonic-gate 			(void) sprintf(ipvsbuf, "%d", flt->ip_versions);
8567c478bd9Sstevel@tonic-gate 			if (nvlist_add_string(nvl, IPGPC_FILTER_PRIVATE,
8577c478bd9Sstevel@tonic-gate 			    ipvsbuf) != 0) {
8587c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "nvlist_add_string");
8597c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
8607c478bd9Sstevel@tonic-gate 			}
8617c478bd9Sstevel@tonic-gate 		}
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 		/* add filter instance if present */
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 		if (nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE,
8667c478bd9Sstevel@tonic-gate 		    flt->instance) != 0) {
8677c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_int32");
8687c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
8697c478bd9Sstevel@tonic-gate 		}
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &flt->nvlist, 0) != 0) {
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 		/* invalid parameters */
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 		if (errno == EINVAL) {
8777c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
8787c478bd9Sstevel@tonic-gate 			    gettext("Invalid/missing parameters for filter "
8797c478bd9Sstevel@tonic-gate 			    "%s in action %s.\n"), flt->name, action_name);
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 		/* max ipgpc filters/classes */
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 		} else if (errno == ENOSPC &&
8847c478bd9Sstevel@tonic-gate 		    strcmp(action_name, IPGPC_CLASSIFY) == 0) {
8857c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Max number of filters "
8867c478bd9Sstevel@tonic-gate 			    "reached in action %s.\n"), IPGPC_NAME);
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 		/* anything other errnos */
8897c478bd9Sstevel@tonic-gate 		} else {
8907c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
8917c478bd9Sstevel@tonic-gate 			    gettext("Failed to create filter %s in action "
8927c478bd9Sstevel@tonic-gate 			    "%s: %s.\n"), flt->name, action_name,
8937c478bd9Sstevel@tonic-gate 			    strerror(errno));
8947c478bd9Sstevel@tonic-gate 		}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate /*
9047c478bd9Sstevel@tonic-gate  * modify the filter flt in the kernel action named action_name.
9057c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
9067c478bd9Sstevel@tonic-gate  */
9077c478bd9Sstevel@tonic-gate static int
9087c478bd9Sstevel@tonic-gate modify_filter(
9097c478bd9Sstevel@tonic-gate char *action_name,
9107c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt,
9117c478bd9Sstevel@tonic-gate int module_version)
9127c478bd9Sstevel@tonic-gate {
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	nvlist_t *nvl = flt->nvlist;
9157c478bd9Sstevel@tonic-gate 	char ipvsbuf[IPQOS_INT_STR_LEN];
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(APPLY, "modify_filter: action: %s, filter: %s, "
9187c478bd9Sstevel@tonic-gate 	    "instance: %d, class: %s\n", action_name, flt->name,
9197c478bd9Sstevel@tonic-gate 	    flt->instance, flt->class_name);
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate /* show src address and dst address if present */
9227c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
9237c478bd9Sstevel@tonic-gate 	if (ipqosconf_dbg_flgs & APPLY) {
9247c478bd9Sstevel@tonic-gate 		uint_t tmp;
9257c478bd9Sstevel@tonic-gate 		in6_addr_t *add;
9267c478bd9Sstevel@tonic-gate 		char st[100];
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 		if (nvlist_lookup_uint32_array(nvl, IPGPC_SADDR,
9297c478bd9Sstevel@tonic-gate 		    (uint32_t **)&add, &tmp) == 0) {
9307c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "saddr: %s\n",
9317c478bd9Sstevel@tonic-gate 			    inet_ntop(AF_INET6, add, st, 100));
9327c478bd9Sstevel@tonic-gate 		}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		if (nvlist_lookup_uint32_array(nvl, IPGPC_DADDR,
9357c478bd9Sstevel@tonic-gate 		    (uint32_t **)&add, &tmp) == 0) {
9367c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "daddr: %s\n",
9377c478bd9Sstevel@tonic-gate 			    inet_ntop(AF_INET6, add, st, 100));
9387c478bd9Sstevel@tonic-gate 		}
9397c478bd9Sstevel@tonic-gate 	}
9407c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	/* add 'modify filter' config type to filters nvlist */
9437c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE,
9447c478bd9Sstevel@tonic-gate 	    CLASSIFIER_MODIFY_FILTER) != 0) {
9457c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
9467c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
9477c478bd9Sstevel@tonic-gate 	}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	/*
9507c478bd9Sstevel@tonic-gate 	 * add module version
9517c478bd9Sstevel@tonic-gate 	 */
9527c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
9537c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
9547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
9557c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	/* add filter name to nvlist */
9597c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, flt->name) != 0) {
9607c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
9617c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
9627c478bd9Sstevel@tonic-gate 	}
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	/* add class name to nvlist */
9657c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, flt->class_name) !=
9667c478bd9Sstevel@tonic-gate 	    0) {
9677c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
9687c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	/* add originator ipqosconf to nvlist */
9727c478bd9Sstevel@tonic-gate 	if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) {
9737c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
9747c478bd9Sstevel@tonic-gate 	}
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	/* add ipgpc specific nvpairs */
9777c478bd9Sstevel@tonic-gate 	if (strcmp(action_name, IPGPC_CLASSIFY) == 0) {
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 		/* add src and dst nodes to nvlist if present */
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 		if (flt->src_nd_name &&
9827c478bd9Sstevel@tonic-gate 		    nvlist_add_string(nvl, IPGPC_SADDR_HOSTNAME,
9837c478bd9Sstevel@tonic-gate 		    flt->src_nd_name) != 0) {
9847c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_string");
9857c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
9867c478bd9Sstevel@tonic-gate 		}
9877c478bd9Sstevel@tonic-gate 		if (flt->dst_nd_name &&
9887c478bd9Sstevel@tonic-gate 		    nvlist_add_string(nvl, IPGPC_DADDR_HOSTNAME,
9897c478bd9Sstevel@tonic-gate 		    flt->dst_nd_name) != 0) {
9907c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_string");
9917c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
9927c478bd9Sstevel@tonic-gate 		}
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		/*
9957c478bd9Sstevel@tonic-gate 		 * add ip_version to private list element if present.
9967c478bd9Sstevel@tonic-gate 		 * NOTE: this value is of only real use to ipqosconf so
9977c478bd9Sstevel@tonic-gate 		 * it is placed in this opaque private field.
9987c478bd9Sstevel@tonic-gate 		 */
9997c478bd9Sstevel@tonic-gate 		if (flt->ip_versions != 0) {
10007c478bd9Sstevel@tonic-gate 			(void) sprintf(ipvsbuf, "%d", flt->ip_versions);
10017c478bd9Sstevel@tonic-gate 			if (nvlist_add_string(nvl, IPGPC_FILTER_PRIVATE,
10027c478bd9Sstevel@tonic-gate 			    ipvsbuf) != 0) {
10037c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "nvlist_add_string");
10047c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
10057c478bd9Sstevel@tonic-gate 			}
10067c478bd9Sstevel@tonic-gate 		}
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 		/* add filter instance if present */
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 		if (nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE,
10117c478bd9Sstevel@tonic-gate 		    flt->instance) != 0) {
10127c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_int32");
10137c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
10147c478bd9Sstevel@tonic-gate 		}
10157c478bd9Sstevel@tonic-gate 	}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &flt->nvlist, 0) != 0) {
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 		/* invalid parameters */
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 		if (errno == EINVAL) {
10227c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Missing/Invalid "
10237c478bd9Sstevel@tonic-gate 			    "parameter for filter %s in action %s.\n"),
10247c478bd9Sstevel@tonic-gate 			    flt->name, action_name);
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 		/* any other errnos */
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 		} else {
10297c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
10307c478bd9Sstevel@tonic-gate 			    gettext("Failed to modify filter %s in action %s: "
10317c478bd9Sstevel@tonic-gate 			    "%s.\n"), flt->name, action_name, strerror(errno));
10327c478bd9Sstevel@tonic-gate 		}
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10357c478bd9Sstevel@tonic-gate 	}
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
10387c478bd9Sstevel@tonic-gate }
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate  * remove the filter named filter_name instance number instance from the
10427c478bd9Sstevel@tonic-gate  * kernel action action_name.
10437c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
10447c478bd9Sstevel@tonic-gate  */
10457c478bd9Sstevel@tonic-gate static int
10467c478bd9Sstevel@tonic-gate remove_filter(
10477c478bd9Sstevel@tonic-gate char *action_name,
10487c478bd9Sstevel@tonic-gate char *filter_name,
10497c478bd9Sstevel@tonic-gate int instance,
10507c478bd9Sstevel@tonic-gate int module_version)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(APPLY, "remove_filter: action: %s, filter: %s\n",
10567c478bd9Sstevel@tonic-gate 	    action_name, filter_name);
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	/* create nvlist */
10597c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
10607c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_alloc");
10617c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10627c478bd9Sstevel@tonic-gate 	}
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	/* add 'remove filter' config type to list */
10657c478bd9Sstevel@tonic-gate 	if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_REMOVE_FILTER)
10667c478bd9Sstevel@tonic-gate 	!= 0) {
10677c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
10687c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10697c478bd9Sstevel@tonic-gate 	}
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 	/*
10727c478bd9Sstevel@tonic-gate 	 * add module version
10737c478bd9Sstevel@tonic-gate 	 */
10747c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION,
10757c478bd9Sstevel@tonic-gate 	    (uint32_t)module_version) != 0) {
10767c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
10777c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10787c478bd9Sstevel@tonic-gate 	}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	/* add filter name to list */
10817c478bd9Sstevel@tonic-gate 	if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, filter_name) != 0) {
10827c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_string");
10837c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10847c478bd9Sstevel@tonic-gate 	}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	/* add instance number if part of multi-instance filter */
10877c478bd9Sstevel@tonic-gate 	if (instance != -1 && nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE,
10887c478bd9Sstevel@tonic-gate 	    instance) != 0) {
10897c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_int32");
10907c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
10917c478bd9Sstevel@tonic-gate 	}
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	/* call into lib to remove */
10947c478bd9Sstevel@tonic-gate 	if (ipp_action_modify(action_name, &nvl, 0) != 0) {
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 		/* generic error message */
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
10997c478bd9Sstevel@tonic-gate 		    gettext("Removing filter %s in action %s failed: %s.\n"),
11007c478bd9Sstevel@tonic-gate 		    filter_name, action_name, strerror(errno));
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
11037c478bd9Sstevel@tonic-gate 	}
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate /* ******************************************************************* */
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate  * add originator nvpair set to ipqosconf to nvl.
11137c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
11147c478bd9Sstevel@tonic-gate  */
11157c478bd9Sstevel@tonic-gate static int
11167c478bd9Sstevel@tonic-gate add_orig_ipqosconf(nvlist_t *nvl)
11177c478bd9Sstevel@tonic-gate {
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(nvl, IPP_CONFIG_ORIGINATOR,
11207c478bd9Sstevel@tonic-gate 	    IPP_CONFIG_IPQOSCONF) != 0) {
11217c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32: originator:");
11227c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
11237c478bd9Sstevel@tonic-gate 	}
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate /* ************************* differencing functions ************************ */
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate /*
11327c478bd9Sstevel@tonic-gate  * compares the contents of arrays array1 and array2, both of size size, and
11337c478bd9Sstevel@tonic-gate  * returns B_TRUE or B_FALSE if they're equal or not respectively.
11347c478bd9Sstevel@tonic-gate  * RETURNS: B_TRUE if equal, else B_FALSE.
11357c478bd9Sstevel@tonic-gate  */
11367c478bd9Sstevel@tonic-gate static boolean_t
11377c478bd9Sstevel@tonic-gate arrays_equal(
11387c478bd9Sstevel@tonic-gate int array1[],
11397c478bd9Sstevel@tonic-gate int array2[],
11407c478bd9Sstevel@tonic-gate uint32_t size)
11417c478bd9Sstevel@tonic-gate {
11427c478bd9Sstevel@tonic-gate 	int x;
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	for (x = 0; x < size; x++) {
11457c478bd9Sstevel@tonic-gate 		if (array1[x] != array2[x])
11467c478bd9Sstevel@tonic-gate 			return (B_FALSE);
11477c478bd9Sstevel@tonic-gate 	}
11487c478bd9Sstevel@tonic-gate 	return (B_TRUE);
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate /*
11527c478bd9Sstevel@tonic-gate  * difference class old against class new. It marks the new class as
11537c478bd9Sstevel@tonic-gate  * modified if it is different.
11547c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_SUCCESS.
11557c478bd9Sstevel@tonic-gate  */
11567c478bd9Sstevel@tonic-gate static int
11577c478bd9Sstevel@tonic-gate diffclass(
11587c478bd9Sstevel@tonic-gate ipqos_conf_class_t *old,
11597c478bd9Sstevel@tonic-gate ipqos_conf_class_t *new)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In diffclass:\n");
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	/* two different spec'd actions */
11657c478bd9Sstevel@tonic-gate 	if (strcmp(old->alist->name, new->alist->name) != 0) {
11667c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "marking class %s as modified\n", new->name);
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
11697c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
11707c478bd9Sstevel@tonic-gate 	}
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	/* different stats values */
11737c478bd9Sstevel@tonic-gate 	if (old->stats_enable != new->stats_enable) {
11747c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "marking class %s as modified\n", new->name);
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
11777c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
11817c478bd9Sstevel@tonic-gate }
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate /*
11847c478bd9Sstevel@tonic-gate  * difference params set old against params set new of module module_name. It
11857c478bd9Sstevel@tonic-gate  * marks the new params as modified if different.
11867c478bd9Sstevel@tonic-gate  * RETURNS: if error IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS.
11877c478bd9Sstevel@tonic-gate  */
11887c478bd9Sstevel@tonic-gate static int
11897c478bd9Sstevel@tonic-gate diffparams(
11907c478bd9Sstevel@tonic-gate ipqos_conf_params_t *old,
11917c478bd9Sstevel@tonic-gate ipqos_conf_params_t *new,
11927c478bd9Sstevel@tonic-gate char *module_name)
11937c478bd9Sstevel@tonic-gate {
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	int diff;
11967c478bd9Sstevel@tonic-gate 	int res;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In diffparams\n");
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	/* diff stats */
12017c478bd9Sstevel@tonic-gate 	if (old->stats_enable != new->stats_enable) {
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
12047c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
12057c478bd9Sstevel@tonic-gate 	}
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	/* diff module specific params */
12087c478bd9Sstevel@tonic-gate 	res = diffnvlists(old->nvlist, new->nvlist, module_name, &diff,
12097c478bd9Sstevel@tonic-gate 	    PL_PARAMS);
12107c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
12117c478bd9Sstevel@tonic-gate 		return (res);
12127c478bd9Sstevel@tonic-gate 	}
12137c478bd9Sstevel@tonic-gate 	if (diff) {
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
12167c478bd9Sstevel@tonic-gate 	}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate  * differences filter old against filter new of module module_name. It marks
12237c478bd9Sstevel@tonic-gate  * filter new as different if so.
12247c478bd9Sstevel@tonic-gate  * RETURNS: if error IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS.
12257c478bd9Sstevel@tonic-gate  */
12267c478bd9Sstevel@tonic-gate static int
12277c478bd9Sstevel@tonic-gate difffilter(
12287c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *old,
12297c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *new,
12307c478bd9Sstevel@tonic-gate char *module_name)
12317c478bd9Sstevel@tonic-gate {
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 	int res;
12347c478bd9Sstevel@tonic-gate 	int diff;
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In difffilter\n");
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 	/* compare class name */
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	if (strcmp(old->class_name, new->class_name) != 0) {
12417c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "Marking filter %s as modified\n", new->name);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
12447c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
12457c478bd9Sstevel@tonic-gate 	}
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	/* compare module specific params */
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	res = diffnvlists(old->nvlist, new->nvlist, module_name, &diff,
12507c478bd9Sstevel@tonic-gate 	    PL_FILTER);
12517c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
12527c478bd9Sstevel@tonic-gate 		return (res);
12537c478bd9Sstevel@tonic-gate 	}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	if (diff) {
12567c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "Marking filter %s as modified\n", new->name);
12577c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
12587c478bd9Sstevel@tonic-gate 	}
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate /*
12657c478bd9Sstevel@tonic-gate  * mark all the filters and classes in parameter action either
12667c478bd9Sstevel@tonic-gate  * for deletion (if they are ipqosconf originated) or for modification.
12677c478bd9Sstevel@tonic-gate  */
12687c478bd9Sstevel@tonic-gate static void
12697c478bd9Sstevel@tonic-gate mark_classes_filters_del(ipqos_conf_action_t *action)
12707c478bd9Sstevel@tonic-gate {
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
12737c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In mark_classes_filters_del: action: %s\n",
12767c478bd9Sstevel@tonic-gate 	    action->name);
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	/* mark all non-permanent filters for del and permanent to modify */
12797c478bd9Sstevel@tonic-gate 	for (flt = action->filters; flt; flt = flt->next) {
12807c478bd9Sstevel@tonic-gate 		if (flt->originator == IPP_CONFIG_PERMANENT) {
12817c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking prm filter %s as modified.\n",
12827c478bd9Sstevel@tonic-gate 			    flt->name);
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 			flt->modified = B_TRUE;
12857c478bd9Sstevel@tonic-gate 		} else {
12867c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking filter %s as del.\n",
12877c478bd9Sstevel@tonic-gate 			    flt->name);
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 			flt->todel = B_TRUE;
12907c478bd9Sstevel@tonic-gate 		}
12917c478bd9Sstevel@tonic-gate 	}
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	/* mark all non-permanent classes for del and permanent to modify */
12947c478bd9Sstevel@tonic-gate 	for (cls = action->classes; cls; cls = cls->next) {
12957c478bd9Sstevel@tonic-gate 		if (cls->originator == IPP_CONFIG_PERMANENT) {
12967c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking prm class %s as modified.\n",
12977c478bd9Sstevel@tonic-gate 			    cls->name);
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 			cls->modified = B_TRUE;
13007c478bd9Sstevel@tonic-gate 		} else {
13017c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking class %s as del.\n",
13027c478bd9Sstevel@tonic-gate 			    cls->name);
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 			cls->todel = B_TRUE;
13057c478bd9Sstevel@tonic-gate 		}
13067c478bd9Sstevel@tonic-gate 	}
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate  * mark all classes and filters either new (non-permanent) or modified.
13117c478bd9Sstevel@tonic-gate  */
13127c478bd9Sstevel@tonic-gate static void
13137c478bd9Sstevel@tonic-gate mark_classes_filters_new(ipqos_conf_action_t *action)
13147c478bd9Sstevel@tonic-gate {
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
13177c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In mark_classes_filters_new: action: %s\n",
13207c478bd9Sstevel@tonic-gate 	    action->name);
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 	/* mark all permanent filters as modified and all others new */
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 	for (flt = action->filters; flt; flt = flt->next) {
13257c478bd9Sstevel@tonic-gate 		if (flt->originator == IPP_CONFIG_PERMANENT) {
13267c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking prm filter %s as modified.\n",
13277c478bd9Sstevel@tonic-gate 			    flt->name);
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 			flt->modified = B_TRUE;
13307c478bd9Sstevel@tonic-gate 			action->modified = B_TRUE;
13317c478bd9Sstevel@tonic-gate 		} else {
13327c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking filter %s as new.\n",
13337c478bd9Sstevel@tonic-gate 			    flt->name);
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 			flt->new = B_TRUE;
13367c478bd9Sstevel@tonic-gate 		}
13377c478bd9Sstevel@tonic-gate 	}
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 	/* mark all permanent classes as modified and all others new */
13407c478bd9Sstevel@tonic-gate 	for (cls = action->classes; cls; cls = cls->next) {
13417c478bd9Sstevel@tonic-gate 		if (cls->originator == IPP_CONFIG_PERMANENT) {
13427c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking prm class %s as modified.\n",
13437c478bd9Sstevel@tonic-gate 			    cls->name);
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 			cls->modified = B_TRUE;
13467c478bd9Sstevel@tonic-gate 			action->modified = B_TRUE;
13477c478bd9Sstevel@tonic-gate 		} else {
13487c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "Marking class %s as new.\n",
13497c478bd9Sstevel@tonic-gate 			    cls->name);
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 			cls->new = B_TRUE;
13527c478bd9Sstevel@tonic-gate 		}
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate }
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate /*
13577c478bd9Sstevel@tonic-gate  * Marks all the actions and their constituent elements in conf
13587c478bd9Sstevel@tonic-gate  * as new.
13597c478bd9Sstevel@tonic-gate  */
13607c478bd9Sstevel@tonic-gate static void
13617c478bd9Sstevel@tonic-gate mark_config_new(
13627c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf)
13637c478bd9Sstevel@tonic-gate {
13647c478bd9Sstevel@tonic-gate 	while (conf != NULL) {
13657c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "Marking action %s as new\n", conf->name);
13667c478bd9Sstevel@tonic-gate 		mark_classes_filters_new(conf);
13677c478bd9Sstevel@tonic-gate 		conf->new = B_TRUE;
13687c478bd9Sstevel@tonic-gate 		conf->visited = 0;
13697c478bd9Sstevel@tonic-gate 		conf = conf->next;
13707c478bd9Sstevel@tonic-gate 	}
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate  * differences the configuration  in new against old marking the actions
13757c478bd9Sstevel@tonic-gate  * and their contents appropriately.
13767c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
13777c478bd9Sstevel@tonic-gate  */
13787c478bd9Sstevel@tonic-gate static int
13797c478bd9Sstevel@tonic-gate diffconf(
13807c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old,
13817c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new)
13827c478bd9Sstevel@tonic-gate {
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	int res;
13857c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
13867c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *tmp;
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	IPQOSCDBG0((L0 | DIFF), "In diffconf\n");
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate 	/* check the new actions against the old */
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 	for (act = new; act; act = act->next) {
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 		/* if action not in old mark it and it's contents as new */
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 		if ((tmp = actionexist(act->name, old)) == NULL) {
13977c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "marking act %s as new\n", act->name);
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 			act->new = B_TRUE;
14007c478bd9Sstevel@tonic-gate 			mark_classes_filters_new(act);
14017c478bd9Sstevel@tonic-gate 			continue;
14027c478bd9Sstevel@tonic-gate 		}
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 		/* if action in old diff old against new */
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 		res = diffaction(tmp, act);
14077c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
14087c478bd9Sstevel@tonic-gate 			return (res);
14097c478bd9Sstevel@tonic-gate 		}
14107c478bd9Sstevel@tonic-gate 	}
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	/*
14137c478bd9Sstevel@tonic-gate 	 * mark actions, and their contents, in old but not new that were
14147c478bd9Sstevel@tonic-gate 	 * created by us for del.
14157c478bd9Sstevel@tonic-gate 	 */
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate 	for (act = old; act; act = act->next) {
14187c478bd9Sstevel@tonic-gate 		if (act->params->originator == IPP_CONFIG_IPQOSCONF &&
14197c478bd9Sstevel@tonic-gate 		    actionexist(act->name, new) == NULL) {
14207c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "marking act %s for del\n", act->name);
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 			act->todel = B_TRUE;
14237c478bd9Sstevel@tonic-gate 			mark_classes_filters_del(act);
14247c478bd9Sstevel@tonic-gate 		}
14257c478bd9Sstevel@tonic-gate 	}
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
14287c478bd9Sstevel@tonic-gate }
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate /*
14317c478bd9Sstevel@tonic-gate  * differences action old against action new, comparing its classes, filters
14327c478bd9Sstevel@tonic-gate  * and parameters. If it is different the new action is marked as modified
14337c478bd9Sstevel@tonic-gate  * and it's different sub-objects are also marked approriately.
14347c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS.
14357c478bd9Sstevel@tonic-gate  */
14367c478bd9Sstevel@tonic-gate static int
14377c478bd9Sstevel@tonic-gate diffaction(
14387c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old,
14397c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new)
14407c478bd9Sstevel@tonic-gate {
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 	int res;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In diffaction\n");
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	/* compare and mark classes */
14477c478bd9Sstevel@tonic-gate 	res = diffclasses(old, new);
14487c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
14497c478bd9Sstevel@tonic-gate 		return (res);
14507c478bd9Sstevel@tonic-gate 	}
14517c478bd9Sstevel@tonic-gate 
14527c478bd9Sstevel@tonic-gate 	/* compare and mark filters */
14537c478bd9Sstevel@tonic-gate 	res = difffilters(old, new);
14547c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
14557c478bd9Sstevel@tonic-gate 		return (res);
14567c478bd9Sstevel@tonic-gate 	}
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	/* compare and mark parameters */
14597c478bd9Sstevel@tonic-gate 	res = diffparams(old->params, new->params, old->module);
14607c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
14617c478bd9Sstevel@tonic-gate 		return (res);
14627c478bd9Sstevel@tonic-gate 	}
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	/* mark action as modified if params are */
14657c478bd9Sstevel@tonic-gate 	if (new->params->modified == B_TRUE) {
14667c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(DIFF, "Marking params for action %s modified\n",
14677c478bd9Sstevel@tonic-gate 		    new->name);
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 		new->modified = B_TRUE;
14707c478bd9Sstevel@tonic-gate 	}
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate 
14757c478bd9Sstevel@tonic-gate /*
14767c478bd9Sstevel@tonic-gate  * differences the set of classes in new against those in old, marking any
14777c478bd9Sstevel@tonic-gate  * that are new/modified, approriately in the new class, and any removed
14787c478bd9Sstevel@tonic-gate  * in the old class appropriately. Also marks the action which has had an
14797c478bd9Sstevel@tonic-gate  * object within marked, as modified.
14807c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
14817c478bd9Sstevel@tonic-gate  */
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate static int
14847c478bd9Sstevel@tonic-gate diffclasses(
14857c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old,
14867c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
14917c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *tmpc;
14927c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *ncls;
14937c478bd9Sstevel@tonic-gate 	int res;
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	/* loop through old classes checking for classes not present in new */
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 	for (cls = old->classes; cls; cls = cls->next) {
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 		if (classexist(cls->name, new->classes) == NULL) {
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate 			/* if we created original class mark for deletion */
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 			if (cls->originator == IPP_CONFIG_IPQOSCONF) {
15057c478bd9Sstevel@tonic-gate 				IPQOSCDBG1(DIFF, "marking class %s for del\n",
15067c478bd9Sstevel@tonic-gate 				    cls->name);
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 				cls->todel = B_TRUE;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 				/* mark old action */
15117c478bd9Sstevel@tonic-gate 				old->modified = B_TRUE;
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 			/*
15147c478bd9Sstevel@tonic-gate 			 * if permanent class and next action created by us
15157c478bd9Sstevel@tonic-gate 			 * copy it, set it's next action to continue and
15167c478bd9Sstevel@tonic-gate 			 * add it to new action. This will cause the class
15177c478bd9Sstevel@tonic-gate 			 * to be marked as and modified. This returns the class
15187c478bd9Sstevel@tonic-gate 			 * to an assumed default state and prevents the
15197c478bd9Sstevel@tonic-gate 			 * case where the class is pointing at an action
15207c478bd9Sstevel@tonic-gate 			 * we want to remove and therefore couldn't without
15217c478bd9Sstevel@tonic-gate 			 * this forced modify.
15227c478bd9Sstevel@tonic-gate 			 */
15237c478bd9Sstevel@tonic-gate 			} else if (cls->originator == IPP_CONFIG_PERMANENT &&
15247c478bd9Sstevel@tonic-gate 			    cls->alist->action &&	/* not virtual action */
15257c478bd9Sstevel@tonic-gate 			    cls->alist->action->params->originator ==
15267c478bd9Sstevel@tonic-gate 			    IPP_CONFIG_IPQOSCONF) {
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 				/* copy class */
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 				res = dup_class(cls, &ncls);
15317c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
15327c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
15337c478bd9Sstevel@tonic-gate 				}
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 				/* set next action to continue */
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 				(void) strcpy(ncls->alist->name,
15387c478bd9Sstevel@tonic-gate 				    IPP_ANAME_CONT);
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 				/* add to news classes to be diffed below */
15417c478bd9Sstevel@tonic-gate 				ADD_TO_LIST(&new->classes, ncls);
15427c478bd9Sstevel@tonic-gate 			}
15437c478bd9Sstevel@tonic-gate 		}
15447c478bd9Sstevel@tonic-gate 	}
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 	/* loop through new classes checking for new / modified classes */
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 	for (cls = new->classes; cls; cls = cls->next) {
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 		/* new ipqosconf class */
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 		if ((tmpc = classexist(cls->name, old->classes)) == NULL ||
15537c478bd9Sstevel@tonic-gate 		    (tmpc->originator != IPP_CONFIG_IPQOSCONF &&
15547c478bd9Sstevel@tonic-gate 		    tmpc->originator != IPP_CONFIG_PERMANENT)) {
15557c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "marking class %s new\n",
15567c478bd9Sstevel@tonic-gate 			    cls->name);
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 			cls->new = B_TRUE;
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 			new->modified = B_TRUE;	/* mark new action */
15617c478bd9Sstevel@tonic-gate 			continue;
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 		/* existing ipqosconf/perm class */
15647c478bd9Sstevel@tonic-gate 		} else {
15657c478bd9Sstevel@tonic-gate 			res = diffclass(tmpc, cls);
15667c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
15677c478bd9Sstevel@tonic-gate 				return (res);
15687c478bd9Sstevel@tonic-gate 			}
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 			if (cls->modified == B_TRUE) {
15717c478bd9Sstevel@tonic-gate 				new->modified = B_TRUE;
15727c478bd9Sstevel@tonic-gate 			}
15737c478bd9Sstevel@tonic-gate 		}
15747c478bd9Sstevel@tonic-gate 	}
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate /*
15807c478bd9Sstevel@tonic-gate  * differences the set of filters in new against those in old, marking any
15817c478bd9Sstevel@tonic-gate  * that are new/modified, approriately in the new filter/s, and any removed
15827c478bd9Sstevel@tonic-gate  * in the old filter appropriately. Also marks the action which has had an
15837c478bd9Sstevel@tonic-gate  * object within marked, as modified.
15847c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_SUCCESS (we return an int for symmetry with diffclasses
15857c478bd9Sstevel@tonic-gate  * and difffparams).
15867c478bd9Sstevel@tonic-gate  */
15877c478bd9Sstevel@tonic-gate static int
15887c478bd9Sstevel@tonic-gate difffilters(
15897c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old,
15907c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new)
15917c478bd9Sstevel@tonic-gate {
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
15947c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *tmpf;
15957c478bd9Sstevel@tonic-gate 	int maxi;
15967c478bd9Sstevel@tonic-gate 	int newi;
15977c478bd9Sstevel@tonic-gate 	int res;
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate 	/* check for new/modified filters */
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate 	for (flt = new->filters; flt; flt = flt->next) {
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 		/* new ipqosconf filter */
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate 		if ((tmpf = filterexist(flt->name, -1, old->filters)) == NULL) {
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 			/* mark all instances of this filter as new */
16087c478bd9Sstevel@tonic-gate 			for (;;) {
16097c478bd9Sstevel@tonic-gate 				IPQOSCDBG1(DIFF, "Marking filter %s as "
16107c478bd9Sstevel@tonic-gate 				    "new\n", flt->name);
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 				flt->new = B_TRUE;
16137c478bd9Sstevel@tonic-gate 
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 				if (flt->next == NULL ||
16167c478bd9Sstevel@tonic-gate 				    strcmp(flt->next->name, flt->name) != 0) {
16177c478bd9Sstevel@tonic-gate 					break;
16187c478bd9Sstevel@tonic-gate 				}
16197c478bd9Sstevel@tonic-gate 				flt = flt->next;
16207c478bd9Sstevel@tonic-gate 			}
16217c478bd9Sstevel@tonic-gate 			new->modified = B_TRUE;	/* mark new action */
16227c478bd9Sstevel@tonic-gate 
16237c478bd9Sstevel@tonic-gate 		/* ipqosconf/permanent filter existed */
16247c478bd9Sstevel@tonic-gate 		} else {
16257c478bd9Sstevel@tonic-gate 			/*
16267c478bd9Sstevel@tonic-gate 			 * if ip node name force filter refresh - ie. mark
16277c478bd9Sstevel@tonic-gate 			 * all old filter instances as todel and all new new.
16287c478bd9Sstevel@tonic-gate 			 */
16297c478bd9Sstevel@tonic-gate 			if (tmpf->src_nd_name || tmpf->dst_nd_name ||
16307c478bd9Sstevel@tonic-gate 			    flt->src_nd_name || flt->dst_nd_name) {
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 				/* init max previous filter instance */
16337c478bd9Sstevel@tonic-gate 				maxi = tmpf->instance;
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 				/* mark old instances for deletion */
16367c478bd9Sstevel@tonic-gate 				do {
16377c478bd9Sstevel@tonic-gate 					IPQOSCDBG2(DIFF, "Marking filter "
16387c478bd9Sstevel@tonic-gate 					    "%s, instance %d for del\n",
16397c478bd9Sstevel@tonic-gate 					    tmpf->name, tmpf->instance);
16407c478bd9Sstevel@tonic-gate 
16417c478bd9Sstevel@tonic-gate 					tmpf->todel = B_TRUE;
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 					/*
16447c478bd9Sstevel@tonic-gate 					 * check and update previous instance
16457c478bd9Sstevel@tonic-gate 					 * max.
16467c478bd9Sstevel@tonic-gate 					 */
16477c478bd9Sstevel@tonic-gate 					if (tmpf->instance > maxi) {
16487c478bd9Sstevel@tonic-gate 						maxi = tmpf->instance;
16497c478bd9Sstevel@tonic-gate 					}
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 					tmpf = tmpf->next;
16527c478bd9Sstevel@tonic-gate 				} while (tmpf != NULL &&
16537c478bd9Sstevel@tonic-gate 					strcmp(tmpf->name, flt->name) == 0);
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 				/*
16567c478bd9Sstevel@tonic-gate 				 * use the max previous instance + 1 for
16577c478bd9Sstevel@tonic-gate 				 * the start of the new instance numbers.
16587c478bd9Sstevel@tonic-gate 				 */
16597c478bd9Sstevel@tonic-gate 				newi = (uint32_t)++maxi % INT_MAX;
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 				/*
16627c478bd9Sstevel@tonic-gate 				 * mark new instances for addition and
16637c478bd9Sstevel@tonic-gate 				 * give new instance number.
16647c478bd9Sstevel@tonic-gate 				 */
16657c478bd9Sstevel@tonic-gate 				for (;;) {
16667c478bd9Sstevel@tonic-gate 					IPQOSCDBG2(DIFF, "Marking filter "
16677c478bd9Sstevel@tonic-gate 					    "%s, instance %d as new\n",
16687c478bd9Sstevel@tonic-gate 					    flt->name, newi);
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 					flt->new = B_TRUE;
16717c478bd9Sstevel@tonic-gate 					flt->instance = newi++;
16727c478bd9Sstevel@tonic-gate 					if (flt->next == NULL ||
16737c478bd9Sstevel@tonic-gate 					    strcmp(flt->next->name,
16747c478bd9Sstevel@tonic-gate 					    flt->name) != 0) {
16757c478bd9Sstevel@tonic-gate 						break;
16767c478bd9Sstevel@tonic-gate 					}
16777c478bd9Sstevel@tonic-gate 					flt = flt->next;
16787c478bd9Sstevel@tonic-gate 				}
16797c478bd9Sstevel@tonic-gate 				new->modified = B_TRUE; /* mark new action */
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 				/* mark old action */
16827c478bd9Sstevel@tonic-gate 				old->modified = B_TRUE;
16837c478bd9Sstevel@tonic-gate 
16847c478bd9Sstevel@tonic-gate 			/* non-node name filter */
16857c478bd9Sstevel@tonic-gate 			} else {
16867c478bd9Sstevel@tonic-gate 				/* compare and mark as modified if diff */
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate 				res = difffilter(tmpf, flt, new->module);
16897c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
16907c478bd9Sstevel@tonic-gate 					return (res);
16917c478bd9Sstevel@tonic-gate 				}
16927c478bd9Sstevel@tonic-gate 				if (flt->modified == B_TRUE) {
16937c478bd9Sstevel@tonic-gate 					/* mark action if diff */
16947c478bd9Sstevel@tonic-gate 					new->modified = B_TRUE;
16957c478bd9Sstevel@tonic-gate 				}
16967c478bd9Sstevel@tonic-gate 			}
16977c478bd9Sstevel@tonic-gate 		}
16987c478bd9Sstevel@tonic-gate 	}
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 	/*
17017c478bd9Sstevel@tonic-gate 	 * Check for deleted ipqosconf created filters and mark
17027c478bd9Sstevel@tonic-gate 	 * any found for deletion.
17037c478bd9Sstevel@tonic-gate 	 * For non-ipqosconf generated filters, including permanent
17047c478bd9Sstevel@tonic-gate 	 * ones (none of these exist at the moment) we just leave
17057c478bd9Sstevel@tonic-gate 	 * the filter unmarked.
17067c478bd9Sstevel@tonic-gate 	 */
17077c478bd9Sstevel@tonic-gate 	for (flt = old->filters; flt; flt = flt->next) {
17087c478bd9Sstevel@tonic-gate 
17097c478bd9Sstevel@tonic-gate 		if (flt->originator == IPP_CONFIG_IPQOSCONF &&
17107c478bd9Sstevel@tonic-gate 		    filterexist(flt->name, -1, new->filters) == NULL) {
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 			/* mark all old instances for deletions */
17137c478bd9Sstevel@tonic-gate 			for (;;) {
17147c478bd9Sstevel@tonic-gate 				IPQOSCDBG2(DIFF, "marking flt %s, inst %d "
17157c478bd9Sstevel@tonic-gate 				    "for del\n", flt->name, flt->instance);
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 				flt->todel = B_TRUE;
17187c478bd9Sstevel@tonic-gate 				old->modified = B_TRUE; /* mark old action */
17197c478bd9Sstevel@tonic-gate 
17207c478bd9Sstevel@tonic-gate 				if (flt->next == NULL ||
17217c478bd9Sstevel@tonic-gate 				    strcmp(flt->next->name, flt->name) != 0) {
17227c478bd9Sstevel@tonic-gate 					break;
17237c478bd9Sstevel@tonic-gate 				}
17247c478bd9Sstevel@tonic-gate 				flt = flt->next;
17257c478bd9Sstevel@tonic-gate 			}
17267c478bd9Sstevel@tonic-gate 		}
17277c478bd9Sstevel@tonic-gate 	}
17287c478bd9Sstevel@tonic-gate 
17297c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
17307c478bd9Sstevel@tonic-gate }
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate 
17337c478bd9Sstevel@tonic-gate /*
17347c478bd9Sstevel@tonic-gate  * differences the elements of nvlists old and new using the types file
17357c478bd9Sstevel@tonic-gate  * for module name to interpret the element types. It sets pdiff to either
17367c478bd9Sstevel@tonic-gate  * 0 or 1 if they are the same or different respectively.
17377c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS.
17387c478bd9Sstevel@tonic-gate  */
17397c478bd9Sstevel@tonic-gate static int
17407c478bd9Sstevel@tonic-gate diffnvlists(
17417c478bd9Sstevel@tonic-gate nvlist_t *old,
17427c478bd9Sstevel@tonic-gate nvlist_t *new,
17437c478bd9Sstevel@tonic-gate char *module_name,
17447c478bd9Sstevel@tonic-gate int *pdiff,
17457c478bd9Sstevel@tonic-gate place_t place)
17467c478bd9Sstevel@tonic-gate {
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 	int first_pass = 1;
17497c478bd9Sstevel@tonic-gate 	nvlist_t *tmp;
17507c478bd9Sstevel@tonic-gate 	int res;
17517c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
17527c478bd9Sstevel@tonic-gate 	FILE *tfp;
17537c478bd9Sstevel@tonic-gate 	str_val_nd_t *enum_nvs;
17547c478bd9Sstevel@tonic-gate 	char dfltst[IPQOS_VALST_MAXLEN+1] = "";
17557c478bd9Sstevel@tonic-gate 	char *lo;
17567c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
17577c478bd9Sstevel@tonic-gate 	char *nme;
17587c478bd9Sstevel@tonic-gate 	int diff;
17597c478bd9Sstevel@tonic-gate 	int openerr;
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate 
17627c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In diffnvlists\n");
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	/* open stream to types file */
17657c478bd9Sstevel@tonic-gate 
17667c478bd9Sstevel@tonic-gate 	tfp = validmod(module_name, &openerr);
17677c478bd9Sstevel@tonic-gate 	if (tfp == NULL) {
17687c478bd9Sstevel@tonic-gate 		if (openerr) {
17697c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "fopen");
17707c478bd9Sstevel@tonic-gate 		}
17717c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
17727c478bd9Sstevel@tonic-gate 	}
17737c478bd9Sstevel@tonic-gate start:
17747c478bd9Sstevel@tonic-gate 	/*
17757c478bd9Sstevel@tonic-gate 	 * loop through each of the elements of the new list comparing
17767c478bd9Sstevel@tonic-gate 	 * it with the old one if present. If the old one isn't present
17777c478bd9Sstevel@tonic-gate 	 * then it is compared with the default value for that type (if
17787c478bd9Sstevel@tonic-gate 	 * set). Any time the values are determined to be different
17797c478bd9Sstevel@tonic-gate 	 * or the default value is to be used but isn't present the diff
17807c478bd9Sstevel@tonic-gate 	 * param is set to 1 and we return.
17817c478bd9Sstevel@tonic-gate 	 *
17827c478bd9Sstevel@tonic-gate 	 * If the loop runs its course then the new and old nvlists are
17837c478bd9Sstevel@tonic-gate 	 * reversed and the loop is entered for a second time.
17847c478bd9Sstevel@tonic-gate 	 */
17857c478bd9Sstevel@tonic-gate 	nvp = nvlist_next_nvpair(new, NULL);
17867c478bd9Sstevel@tonic-gate 	while (nvp != NULL) {
17877c478bd9Sstevel@tonic-gate 
17887c478bd9Sstevel@tonic-gate 		/* get name */
17897c478bd9Sstevel@tonic-gate 		nme = nvpair_name(nvp);
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 		/*
17927c478bd9Sstevel@tonic-gate 		 * get type.
17937c478bd9Sstevel@tonic-gate 		 */
17947c478bd9Sstevel@tonic-gate 		place = PL_ANY;
17957c478bd9Sstevel@tonic-gate 		res = readtype(tfp, module_name, SHORT_NAME(nme), &type,
17967c478bd9Sstevel@tonic-gate 		    &enum_nvs, dfltst, B_TRUE, &place);
17977c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
17987c478bd9Sstevel@tonic-gate 			return (res);
17997c478bd9Sstevel@tonic-gate 		}
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 		/* init diff to 1 */
18027c478bd9Sstevel@tonic-gate 		diff = 1;
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 		switch (type) {
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 		/* interface name */
18077c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_IFINDEX: {
18087c478bd9Sstevel@tonic-gate 			uint32_t ifidx;
18097c478bd9Sstevel@tonic-gate 			uint32_t oifidx;
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 			/* get new value */
18127c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, &ifidx);
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 			/* compare against old if present */
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint32(old, nme, &oifidx);
18177c478bd9Sstevel@tonic-gate 			if (res == 0) {
18187c478bd9Sstevel@tonic-gate 				/* diff values */
18197c478bd9Sstevel@tonic-gate 				diff = (ifidx != oifidx);
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate 			/* not in old so see if new value is default */
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 			} else {
18247c478bd9Sstevel@tonic-gate 				diff = (ifidx != 0);
18257c478bd9Sstevel@tonic-gate 			}
18267c478bd9Sstevel@tonic-gate 			break;
18277c478bd9Sstevel@tonic-gate 		}
18287c478bd9Sstevel@tonic-gate 		/* protocol */
18297c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_PROTO: {
18307c478bd9Sstevel@tonic-gate 			uchar_t proto;
18317c478bd9Sstevel@tonic-gate 			uchar_t oproto;
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 			(void) nvpair_value_byte(nvp, &proto);
18347c478bd9Sstevel@tonic-gate 
18357c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_byte(old, nme, &oproto);
18367c478bd9Sstevel@tonic-gate 			if (res == 0) {
18377c478bd9Sstevel@tonic-gate 				diff = (proto != oproto);
18387c478bd9Sstevel@tonic-gate 			} else {
18397c478bd9Sstevel@tonic-gate 				diff = (proto != 0);
18407c478bd9Sstevel@tonic-gate 			}
18417c478bd9Sstevel@tonic-gate 			break;
18427c478bd9Sstevel@tonic-gate 		}
18437c478bd9Sstevel@tonic-gate 		/* port */
18447c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_PORT: {
18457c478bd9Sstevel@tonic-gate 			uint16_t port;
18467c478bd9Sstevel@tonic-gate 			uint16_t oport;
18477c478bd9Sstevel@tonic-gate 
18487c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint16(nvp, &port);
18497c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint16(old, nme, &oport);
18507c478bd9Sstevel@tonic-gate 			if (res == 0) {
18517c478bd9Sstevel@tonic-gate 				diff = (port != oport);
18527c478bd9Sstevel@tonic-gate 			} else {
18537c478bd9Sstevel@tonic-gate 				diff = (port != 0);
18547c478bd9Sstevel@tonic-gate 			}
18557c478bd9Sstevel@tonic-gate 			break;
18567c478bd9Sstevel@tonic-gate 		}
18577c478bd9Sstevel@tonic-gate 		/* action name / string */
18587c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ACTION:
18597c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_STRING: {
18607c478bd9Sstevel@tonic-gate 			char *str;
18617c478bd9Sstevel@tonic-gate 			char *ostr;
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &str);
18647c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_string(old, nme, &ostr);
18657c478bd9Sstevel@tonic-gate 			if (res == 0) {
18667c478bd9Sstevel@tonic-gate 				diff = strcmp(str, ostr);
18677c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
18687c478bd9Sstevel@tonic-gate 				diff = strcmp(str, dfltst);
18697c478bd9Sstevel@tonic-gate 			}
18707c478bd9Sstevel@tonic-gate 			break;
18717c478bd9Sstevel@tonic-gate 		}
18727c478bd9Sstevel@tonic-gate 		/* address mask / address */
18737c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ADDRESS_MASK:
18747c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ADDRESS: {
18757c478bd9Sstevel@tonic-gate 			in6_addr_t *in6;
18767c478bd9Sstevel@tonic-gate 			in6_addr_t *oin6;
18777c478bd9Sstevel@tonic-gate 			uint_t x;
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate 			/*
18807c478bd9Sstevel@tonic-gate 			 * all addresses are stored as v6 addresses, so
18817c478bd9Sstevel@tonic-gate 			 * a uint32_t[4] array is used.
18827c478bd9Sstevel@tonic-gate 			 */
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 			/* lookup new value */
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32_array(nvp,
18877c478bd9Sstevel@tonic-gate 			    (uint32_t **)&in6, &x);
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 			/* see if there's an old value and diff it */
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint32_array(old, nme,
18927c478bd9Sstevel@tonic-gate 			    (uint32_t **)&oin6, &x);
18937c478bd9Sstevel@tonic-gate 			if (res == 0) {
18947c478bd9Sstevel@tonic-gate 				/* diff each of the 16 v6 address bytes */
18957c478bd9Sstevel@tonic-gate 
18967c478bd9Sstevel@tonic-gate 				for (x = 0; x < 16; x++) {
18977c478bd9Sstevel@tonic-gate 					if (in6->s6_addr[x] !=
18987c478bd9Sstevel@tonic-gate 					    oin6->s6_addr[x]) {
18997c478bd9Sstevel@tonic-gate 						diff++;
19007c478bd9Sstevel@tonic-gate 						break;
19017c478bd9Sstevel@tonic-gate 					}
19027c478bd9Sstevel@tonic-gate 				}
19037c478bd9Sstevel@tonic-gate 			}
19047c478bd9Sstevel@tonic-gate 			break;
19057c478bd9Sstevel@tonic-gate 		}
19067c478bd9Sstevel@tonic-gate 		/* boolean */
19077c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_BOOLEAN: {
19087c478bd9Sstevel@tonic-gate 			boolean_t bl;
19097c478bd9Sstevel@tonic-gate 			boolean_t obl;
19107c478bd9Sstevel@tonic-gate 
19117c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, (uint32_t *)&bl);
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 			/* see if there's an old value and diff it */
19147c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint32(old, nme, (uint32_t *)&obl);
19157c478bd9Sstevel@tonic-gate 			if (res == 0) {
19167c478bd9Sstevel@tonic-gate 				diff = (bl != obl);
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 			/* compare against default if present */
19197c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
19207c478bd9Sstevel@tonic-gate 				res = readbool(dfltst, &obl);
19217c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
19227c478bd9Sstevel@tonic-gate 					diff = (bl != obl);
19237c478bd9Sstevel@tonic-gate 				}
19247c478bd9Sstevel@tonic-gate 			}
19257c478bd9Sstevel@tonic-gate 			break;
19267c478bd9Sstevel@tonic-gate 		}
19277c478bd9Sstevel@tonic-gate 		/* uint 8 */
19287c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT8: {
19297c478bd9Sstevel@tonic-gate 			uint8_t u8;
19307c478bd9Sstevel@tonic-gate 			uint8_t ou8;
19317c478bd9Sstevel@tonic-gate 
19327c478bd9Sstevel@tonic-gate 			(void) nvpair_value_byte(nvp, (uchar_t *)&u8);
19337c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_byte(old, nme, (uchar_t *)&ou8);
19347c478bd9Sstevel@tonic-gate 			if (res == 0) {
19357c478bd9Sstevel@tonic-gate 				diff = (u8 != ou8);
19367c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
19377c478bd9Sstevel@tonic-gate 				res = readuint8(dfltst, &ou8, &lo);
19387c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
19397c478bd9Sstevel@tonic-gate 					diff = (u8 != ou8);
19407c478bd9Sstevel@tonic-gate 				}
19417c478bd9Sstevel@tonic-gate 			}
19427c478bd9Sstevel@tonic-gate 			break;
19437c478bd9Sstevel@tonic-gate 		}
19447c478bd9Sstevel@tonic-gate 		/* int 16 */
19457c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT16: {
19467c478bd9Sstevel@tonic-gate 			int16_t i16;
19477c478bd9Sstevel@tonic-gate 			int16_t oi16;
19487c478bd9Sstevel@tonic-gate 
19497c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int16(nvp, &i16);
19507c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_int16(old, nme, &oi16);
19517c478bd9Sstevel@tonic-gate 			if (res == 0) {
19527c478bd9Sstevel@tonic-gate 				diff = (i16 != oi16);
19537c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
19547c478bd9Sstevel@tonic-gate 				res = readint16(dfltst, &oi16, &lo);
19557c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
19567c478bd9Sstevel@tonic-gate 					diff = (i16 != oi16);
19577c478bd9Sstevel@tonic-gate 				}
19587c478bd9Sstevel@tonic-gate 			}
19597c478bd9Sstevel@tonic-gate 			break;
19607c478bd9Sstevel@tonic-gate 		}
19617c478bd9Sstevel@tonic-gate 		/* uint16 */
19627c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT16: {
19637c478bd9Sstevel@tonic-gate 			uint16_t ui16;
19647c478bd9Sstevel@tonic-gate 			uint16_t oui16;
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint16(nvp, &ui16);
19677c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint16(old, nme, &oui16);
19687c478bd9Sstevel@tonic-gate 			if (res == 0) {
19697c478bd9Sstevel@tonic-gate 				diff = (ui16 != oui16);
19707c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
19717c478bd9Sstevel@tonic-gate 				res = readuint16(dfltst, &oui16, &lo);
19727c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
19737c478bd9Sstevel@tonic-gate 					diff = (ui16 != oui16);
19747c478bd9Sstevel@tonic-gate 				}
19757c478bd9Sstevel@tonic-gate 			}
19767c478bd9Sstevel@tonic-gate 			break;
19777c478bd9Sstevel@tonic-gate 		}
19787c478bd9Sstevel@tonic-gate 		/*
19797c478bd9Sstevel@tonic-gate 		 * int32 and user.
19807c478bd9Sstevel@tonic-gate 		 * Since user uids are stored in an int32 nvpair we can use
19817c478bd9Sstevel@tonic-gate 		 * the same comparison code.
19827c478bd9Sstevel@tonic-gate 		 */
19837c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_USER:
19847c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT32: {
19857c478bd9Sstevel@tonic-gate 			int32_t i32;
19867c478bd9Sstevel@tonic-gate 			int32_t oi32;
19877c478bd9Sstevel@tonic-gate 
19887c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int32(nvp, &i32);
19897c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_int32(old, nme, &oi32);
19907c478bd9Sstevel@tonic-gate 			if (res == 0) {
19917c478bd9Sstevel@tonic-gate 				diff = (i32 != oi32);
19927c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
19937c478bd9Sstevel@tonic-gate 				res = readint32(dfltst, &oi32, &lo);
19947c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
19957c478bd9Sstevel@tonic-gate 					diff = (i32 != oi32);
19967c478bd9Sstevel@tonic-gate 				}
19977c478bd9Sstevel@tonic-gate 			}
19987c478bd9Sstevel@tonic-gate 			break;
19997c478bd9Sstevel@tonic-gate 		}
20007c478bd9Sstevel@tonic-gate 		/* uint32 */
20017c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT32: {
20027c478bd9Sstevel@tonic-gate 			uint32_t ui32;
20037c478bd9Sstevel@tonic-gate 			uint32_t oui32;
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, &ui32);
20067c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint32(old, nme, &oui32);
20077c478bd9Sstevel@tonic-gate 			if (res == 0) {
20087c478bd9Sstevel@tonic-gate 				diff = (ui32 != oui32);
20097c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
20107c478bd9Sstevel@tonic-gate 				res = readuint32(dfltst, &oui32, &lo);
20117c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
20127c478bd9Sstevel@tonic-gate 					diff = (ui32 != oui32);
20137c478bd9Sstevel@tonic-gate 				}
20147c478bd9Sstevel@tonic-gate 			}
20157c478bd9Sstevel@tonic-gate 			break;
20167c478bd9Sstevel@tonic-gate 		}
20177c478bd9Sstevel@tonic-gate 		/* enumeration */
20187c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ENUM: {
20197c478bd9Sstevel@tonic-gate 			uint32_t eval;
20207c478bd9Sstevel@tonic-gate 			uint32_t oeval;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, &eval);
20237c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_uint32(old, nme, &oeval);
20247c478bd9Sstevel@tonic-gate 			if (res == 0) {
20257c478bd9Sstevel@tonic-gate 				diff = (eval != oeval);
20267c478bd9Sstevel@tonic-gate 			} else if (*dfltst) {
20277c478bd9Sstevel@tonic-gate 				res = readuint32(dfltst, &oeval, &lo);
20287c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
20297c478bd9Sstevel@tonic-gate 					diff = (eval != oeval);
20307c478bd9Sstevel@tonic-gate 				}
20317c478bd9Sstevel@tonic-gate 			}
20327c478bd9Sstevel@tonic-gate 			break;
20337c478bd9Sstevel@tonic-gate 		}
20347c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_M_INDEX: {
20357c478bd9Sstevel@tonic-gate 			uint8_t idx, oidx;
20367c478bd9Sstevel@tonic-gate 
20377c478bd9Sstevel@tonic-gate 			(void) nvpair_value_byte(nvp, &idx);
20387c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_byte(old, nme, &oidx);
20397c478bd9Sstevel@tonic-gate 			if (res == 0)
20407c478bd9Sstevel@tonic-gate 				diff = (idx != oidx);
20417c478bd9Sstevel@tonic-gate 			break;
20427c478bd9Sstevel@tonic-gate 		}
20437c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT_ARRAY: {
20447c478bd9Sstevel@tonic-gate 			int *oarr, *arr;
20457c478bd9Sstevel@tonic-gate 			uint32_t osize, size;
20467c478bd9Sstevel@tonic-gate 
20477c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int32_array(nvp, &arr, &size);
20487c478bd9Sstevel@tonic-gate 			res = nvlist_lookup_int32_array(old, nme, &oarr,
20497c478bd9Sstevel@tonic-gate 			    &osize);
20507c478bd9Sstevel@tonic-gate 			if (res == 0)
20517c478bd9Sstevel@tonic-gate 				diff = (arrays_equal(arr, oarr, size) ==
20527c478bd9Sstevel@tonic-gate 				    B_FALSE);
20537c478bd9Sstevel@tonic-gate 			break;
20547c478bd9Sstevel@tonic-gate 		}
20557c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
20567c478bd9Sstevel@tonic-gate 		default: {
20577c478bd9Sstevel@tonic-gate 			/* shouldn't get here as all types should be covered */
20587c478bd9Sstevel@tonic-gate 			assert(1);
20597c478bd9Sstevel@tonic-gate 		}
20607c478bd9Sstevel@tonic-gate #endif
20617c478bd9Sstevel@tonic-gate 		}	/* switch */
20627c478bd9Sstevel@tonic-gate 		if (diff != 0) {
20637c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(DIFF, "parameter %s different\n", nme);
20647c478bd9Sstevel@tonic-gate 			*pdiff = 1;
20657c478bd9Sstevel@tonic-gate 			(void) fclose(tfp);
20667c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_SUCCESS);
20677c478bd9Sstevel@tonic-gate 		}
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate 
20707c478bd9Sstevel@tonic-gate 		nvp = nvlist_next_nvpair(new, nvp);
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 	}
20737c478bd9Sstevel@tonic-gate 
20747c478bd9Sstevel@tonic-gate 	/* now compare all the stuff in the second list with the first */
20757c478bd9Sstevel@tonic-gate 	if (first_pass) {
20767c478bd9Sstevel@tonic-gate 		tmp = old;
20777c478bd9Sstevel@tonic-gate 		old = new;
20787c478bd9Sstevel@tonic-gate 		new = tmp;
20797c478bd9Sstevel@tonic-gate 		first_pass = 0;
20807c478bd9Sstevel@tonic-gate 		goto start;
20817c478bd9Sstevel@tonic-gate 	}
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate 	(void) fclose(tfp);
20847c478bd9Sstevel@tonic-gate 
20857c478bd9Sstevel@tonic-gate 	*pdiff = 0;
20867c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
20877c478bd9Sstevel@tonic-gate }
20887c478bd9Sstevel@tonic-gate 
20897c478bd9Sstevel@tonic-gate 
20907c478bd9Sstevel@tonic-gate 
20917c478bd9Sstevel@tonic-gate /* ************************** difference application *********************** */
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate /*
20967c478bd9Sstevel@tonic-gate  * causes all items marked as requiring change in actions and old_actions
20977c478bd9Sstevel@tonic-gate  * to have the change applied.
20987c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
20997c478bd9Sstevel@tonic-gate  */
21007c478bd9Sstevel@tonic-gate static int
21017c478bd9Sstevel@tonic-gate applydiff(
21027c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
21037c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old_actions)
21047c478bd9Sstevel@tonic-gate {
21057c478bd9Sstevel@tonic-gate 
21067c478bd9Sstevel@tonic-gate 	int res;
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In applydiff:\n");
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 
21117c478bd9Sstevel@tonic-gate 	/* add each item marked as new */
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate 	res = add_items(actions, B_FALSE);
21147c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
21157c478bd9Sstevel@tonic-gate 		return (res);
21167c478bd9Sstevel@tonic-gate 	}
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 	/* modify items marked for modification */
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	res = modify_items(actions);
21217c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
21227c478bd9Sstevel@tonic-gate 		return (res);
21237c478bd9Sstevel@tonic-gate 	}
21247c478bd9Sstevel@tonic-gate 
21257c478bd9Sstevel@tonic-gate 	/* delete items marked for deletion */
21267c478bd9Sstevel@tonic-gate 
21277c478bd9Sstevel@tonic-gate 	res = remove_items(old_actions, B_FALSE);
21287c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
21297c478bd9Sstevel@tonic-gate 		return (res);
21307c478bd9Sstevel@tonic-gate 	}
21317c478bd9Sstevel@tonic-gate 
21327c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate 
21357c478bd9Sstevel@tonic-gate static int
21367c478bd9Sstevel@tonic-gate add_items(
21377c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
21387c478bd9Sstevel@tonic-gate boolean_t rem_undo)
21397c478bd9Sstevel@tonic-gate {
21407c478bd9Sstevel@tonic-gate 
21417c478bd9Sstevel@tonic-gate 	int res;
21427c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
21437c478bd9Sstevel@tonic-gate 
21447c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In add_items, rem_undo: %u\n", rem_undo);
21457c478bd9Sstevel@tonic-gate 
21467c478bd9Sstevel@tonic-gate 	/*
21477c478bd9Sstevel@tonic-gate 	 * we need to create ipgpc action before any others as some actions
21487c478bd9Sstevel@tonic-gate 	 * such as ftpcl which make calls to it depend on it being there on
21497c478bd9Sstevel@tonic-gate 	 * their creation.
21507c478bd9Sstevel@tonic-gate 	 */
21517c478bd9Sstevel@tonic-gate 	act = actionexist(IPGPC_CLASSIFY, actions);
21527c478bd9Sstevel@tonic-gate 	if (act &&
21537c478bd9Sstevel@tonic-gate 	    (rem_undo == B_FALSE && act->new == B_TRUE ||
21547c478bd9Sstevel@tonic-gate 	    rem_undo == B_TRUE && act->deleted == B_TRUE)) {
21557c478bd9Sstevel@tonic-gate 
21567c478bd9Sstevel@tonic-gate 		res = add_action(act);
21577c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
21587c478bd9Sstevel@tonic-gate 			return (res);
21597c478bd9Sstevel@tonic-gate 		}
21607c478bd9Sstevel@tonic-gate 	}
21617c478bd9Sstevel@tonic-gate 
21627c478bd9Sstevel@tonic-gate 	/*
21637c478bd9Sstevel@tonic-gate 	 * loop though action list and add any actions marked as
21647c478bd9Sstevel@tonic-gate 	 * new/modified action and apply any additions there, then return.
21657c478bd9Sstevel@tonic-gate 	 */
21667c478bd9Sstevel@tonic-gate 
21677c478bd9Sstevel@tonic-gate 	for (act = actions; act; act = act->next) {
21687c478bd9Sstevel@tonic-gate 		res = add_item(act, rem_undo);
21697c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
21707c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
21717c478bd9Sstevel@tonic-gate 		}
21727c478bd9Sstevel@tonic-gate 	}
21737c478bd9Sstevel@tonic-gate 
21747c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
21757c478bd9Sstevel@tonic-gate }
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate 
21787c478bd9Sstevel@tonic-gate /*
21797c478bd9Sstevel@tonic-gate  *
21807c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
21817c478bd9Sstevel@tonic-gate  */
21827c478bd9Sstevel@tonic-gate static int
21837c478bd9Sstevel@tonic-gate add_item(
21847c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
21857c478bd9Sstevel@tonic-gate boolean_t rem_undo)
21867c478bd9Sstevel@tonic-gate {
21877c478bd9Sstevel@tonic-gate 
21887c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act = actions;
21897c478bd9Sstevel@tonic-gate 	int res;
21907c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
21917c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *pact;
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "In add_item: action: %s, rem_undo: %u\n",
21947c478bd9Sstevel@tonic-gate 	    actions->name, rem_undo);
21957c478bd9Sstevel@tonic-gate 
21967c478bd9Sstevel@tonic-gate 	/* if already visited return immediately */
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 	if (act->visited == ADD_VISITED) {
21997c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L1, "Early exit due to visited\n");
22007c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
22017c478bd9Sstevel@tonic-gate 	}
22027c478bd9Sstevel@tonic-gate 	act->visited = ADD_VISITED;
22037c478bd9Sstevel@tonic-gate 
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 	/* recurse to last action in tree */
22067c478bd9Sstevel@tonic-gate 
22077c478bd9Sstevel@tonic-gate 	for (cls = act->classes; cls; cls = cls->next) {
22087c478bd9Sstevel@tonic-gate 
22097c478bd9Sstevel@tonic-gate 		/* if not virtual action */
22107c478bd9Sstevel@tonic-gate 
22117c478bd9Sstevel@tonic-gate 		if (cls->alist->action) {
22127c478bd9Sstevel@tonic-gate 			res = add_item(cls->alist->action, rem_undo);
22137c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
22147c478bd9Sstevel@tonic-gate 				return (res);
22157c478bd9Sstevel@tonic-gate 			}
22167c478bd9Sstevel@tonic-gate 		}
22177c478bd9Sstevel@tonic-gate 	}
22187c478bd9Sstevel@tonic-gate 
22197c478bd9Sstevel@tonic-gate 	for (pact = act->params->actions; pact; pact = pact->next) {
22207c478bd9Sstevel@tonic-gate 
22217c478bd9Sstevel@tonic-gate 		/* if not virtual */
22227c478bd9Sstevel@tonic-gate 
22237c478bd9Sstevel@tonic-gate 		if (pact->action) {
22247c478bd9Sstevel@tonic-gate 			res = add_item(pact->action, rem_undo);
22257c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
22267c478bd9Sstevel@tonic-gate 				return (res);
22277c478bd9Sstevel@tonic-gate 			}
22287c478bd9Sstevel@tonic-gate 		}
22297c478bd9Sstevel@tonic-gate 	}
22307c478bd9Sstevel@tonic-gate 
22317c478bd9Sstevel@tonic-gate 
22327c478bd9Sstevel@tonic-gate 	/* if action marked as new and not ipgpc, create */
22337c478bd9Sstevel@tonic-gate 
22347c478bd9Sstevel@tonic-gate 	if (((rem_undo == B_FALSE && act->new == B_TRUE) ||
22357c478bd9Sstevel@tonic-gate 	    (rem_undo == B_TRUE && act->deleted == B_TRUE)) &&
22367c478bd9Sstevel@tonic-gate 	    strcmp(act->name, IPGPC_CLASSIFY) != 0) {
22377c478bd9Sstevel@tonic-gate 		res = add_action(act);
22387c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
22397c478bd9Sstevel@tonic-gate 			return (res);
22407c478bd9Sstevel@tonic-gate 		}
22417c478bd9Sstevel@tonic-gate 	}
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 	/* add any classes and filters marked as new */
22447c478bd9Sstevel@tonic-gate 
22457c478bd9Sstevel@tonic-gate 	if (add_classes(act->classes, act->name, act->module_version,
22467c478bd9Sstevel@tonic-gate 	    rem_undo) != IPQOS_CONF_SUCCESS ||
22477c478bd9Sstevel@tonic-gate 	    add_filters(act->filters, act->name, act->module_version,
22487c478bd9Sstevel@tonic-gate 	    rem_undo) != IPQOS_CONF_SUCCESS) {
22497c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
22507c478bd9Sstevel@tonic-gate 	}
22517c478bd9Sstevel@tonic-gate 
22527c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
22537c478bd9Sstevel@tonic-gate }
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 
22567c478bd9Sstevel@tonic-gate /*
22577c478bd9Sstevel@tonic-gate  * Uses the contents of acts params nvlist and adds an originator
22587c478bd9Sstevel@tonic-gate  * element set to ipqosconf and the stats parameter. This list
22597c478bd9Sstevel@tonic-gate  * is then used as the parameter to a call to ipp_action_create to create
22607c478bd9Sstevel@tonic-gate  * this action in the kernel.
22617c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on err, else IPQOS_CONF_SUCCESS.
22627c478bd9Sstevel@tonic-gate  */
22637c478bd9Sstevel@tonic-gate static int
22647c478bd9Sstevel@tonic-gate add_action(ipqos_conf_action_t *act)
22657c478bd9Sstevel@tonic-gate {
22667c478bd9Sstevel@tonic-gate 
22677c478bd9Sstevel@tonic-gate 	int res;
22687c478bd9Sstevel@tonic-gate 	nvlist_t **nvl;
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(APPLY, "add_action: action: %s, module: %s\n", act->name,
22717c478bd9Sstevel@tonic-gate 	    act->module);
22727c478bd9Sstevel@tonic-gate 
22737c478bd9Sstevel@tonic-gate 	nvl = &act->params->nvlist;
22747c478bd9Sstevel@tonic-gate 
22757c478bd9Sstevel@tonic-gate 	/* alloc params nvlist if not already one */
22767c478bd9Sstevel@tonic-gate 
22777c478bd9Sstevel@tonic-gate 	if (*nvl == NULL) {
22787c478bd9Sstevel@tonic-gate 		res = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
22797c478bd9Sstevel@tonic-gate 		if (res != 0) {
22807c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_alloc");
22817c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
22827c478bd9Sstevel@tonic-gate 		}
22837c478bd9Sstevel@tonic-gate 	}
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate 	/*
22867c478bd9Sstevel@tonic-gate 	 * add module version
22877c478bd9Sstevel@tonic-gate 	 */
22887c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(*nvl, IPP_MODULE_VERSION,
22897c478bd9Sstevel@tonic-gate 	    (uint32_t)act->module_version) != 0) {
22907c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32");
22917c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
22927c478bd9Sstevel@tonic-gate 	}
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 	/* add action stats */
22957c478bd9Sstevel@tonic-gate 
22967c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(*nvl, IPP_ACTION_STATS_ENABLE,
22977c478bd9Sstevel@tonic-gate 	    (uint32_t)act->params->stats_enable) != 0) {
22987c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_uint32: action stats");
22997c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
23007c478bd9Sstevel@tonic-gate 	}
23017c478bd9Sstevel@tonic-gate 
23027c478bd9Sstevel@tonic-gate 	/* add ipqosconf originator id */
23037c478bd9Sstevel@tonic-gate 
23047c478bd9Sstevel@tonic-gate 	if (add_orig_ipqosconf(*nvl) != IPQOS_CONF_SUCCESS) {
23057c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
23067c478bd9Sstevel@tonic-gate 	}
23077c478bd9Sstevel@tonic-gate 
23087c478bd9Sstevel@tonic-gate 	/* call into lib to create action */
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate 	res = ipp_action_create(act->module, act->name, nvl, 0);
23117c478bd9Sstevel@tonic-gate 	if (res != 0) {
23127c478bd9Sstevel@tonic-gate 		IPQOSCDBG2(APPLY, "Create action %s, module %s failed\n",
23137c478bd9Sstevel@tonic-gate 		    act->name, act->module);
23147c478bd9Sstevel@tonic-gate 
23157c478bd9Sstevel@tonic-gate 		/* invalid params */
23167c478bd9Sstevel@tonic-gate 
23177c478bd9Sstevel@tonic-gate 		if (errno == EINVAL) {
23187c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
23197c478bd9Sstevel@tonic-gate 			    gettext("Invalid Parameters for action %s.\n"),
23207c478bd9Sstevel@tonic-gate 			    act->name);
23217c478bd9Sstevel@tonic-gate 
23227c478bd9Sstevel@tonic-gate 		} else if (errno == ENOENT) {
23237c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
23247c478bd9Sstevel@tonic-gate 			    gettext("Missing required parameter for action "
23257c478bd9Sstevel@tonic-gate 			    "%s.\n"), act->name);
23267c478bd9Sstevel@tonic-gate 
23277c478bd9Sstevel@tonic-gate 		} else {	/* unexpected error */
23287c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Failed to create action "
23297c478bd9Sstevel@tonic-gate 			    "%s: %s.\n"), act->name, strerror(errno));
23307c478bd9Sstevel@tonic-gate 		}
23317c478bd9Sstevel@tonic-gate 
23327c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
23337c478bd9Sstevel@tonic-gate 	}
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 	/* mark action as created */
23367c478bd9Sstevel@tonic-gate 	act->cr_mod = B_TRUE;
23377c478bd9Sstevel@tonic-gate 
23387c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
23397c478bd9Sstevel@tonic-gate }
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate /*
23427c478bd9Sstevel@tonic-gate  * for each of the filters in parameter filters if rem_undo is false and
23437c478bd9Sstevel@tonic-gate  * the filter is marked as new or if rem_undo is true and the filter is
23447c478bd9Sstevel@tonic-gate  * marked as deleted then add the filter to the kernel action named by action
23457c478bd9Sstevel@tonic-gate  * and if successful mark as created.
23467c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
23477c478bd9Sstevel@tonic-gate  */
23487c478bd9Sstevel@tonic-gate static int
23497c478bd9Sstevel@tonic-gate add_filters(
23507c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filters,
23517c478bd9Sstevel@tonic-gate char *action,
23527c478bd9Sstevel@tonic-gate int module_version,
23537c478bd9Sstevel@tonic-gate boolean_t rem_undo)
23547c478bd9Sstevel@tonic-gate {
23557c478bd9Sstevel@tonic-gate 
23567c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
23577c478bd9Sstevel@tonic-gate 
23587c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In add_filters\n");
23597c478bd9Sstevel@tonic-gate 
23607c478bd9Sstevel@tonic-gate 	/* loop through filters in filters param */
23617c478bd9Sstevel@tonic-gate 	for (flt = filters; flt; flt = flt->next) {
23627c478bd9Sstevel@tonic-gate 		/*
23637c478bd9Sstevel@tonic-gate 		 * skip filter if in normal mode and not new filter or
23647c478bd9Sstevel@tonic-gate 		 * if doing rollback and filter wasn't previously deleted.
23657c478bd9Sstevel@tonic-gate 		 */
23667c478bd9Sstevel@tonic-gate 		if ((rem_undo == B_FALSE && flt->new == B_FALSE) ||
23677c478bd9Sstevel@tonic-gate 		    (rem_undo == B_TRUE && flt->deleted == B_FALSE)) {
23687c478bd9Sstevel@tonic-gate 			continue;
23697c478bd9Sstevel@tonic-gate 		}
23707c478bd9Sstevel@tonic-gate 
23717c478bd9Sstevel@tonic-gate 		/* add filter to action */
23727c478bd9Sstevel@tonic-gate 		if (add_filter(action, flt, module_version) !=
23737c478bd9Sstevel@tonic-gate 		    IPQOS_CONF_SUCCESS) {
23747c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
23757c478bd9Sstevel@tonic-gate 		}
23767c478bd9Sstevel@tonic-gate 
23777c478bd9Sstevel@tonic-gate 		/* mark as created */
23787c478bd9Sstevel@tonic-gate 		flt->cr_mod = B_TRUE;
23797c478bd9Sstevel@tonic-gate 	}
23807c478bd9Sstevel@tonic-gate 
23817c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
23827c478bd9Sstevel@tonic-gate }
23837c478bd9Sstevel@tonic-gate 
23847c478bd9Sstevel@tonic-gate /*
23857c478bd9Sstevel@tonic-gate  * for each of the classes in parameter classes if rem_undo is false and
23867c478bd9Sstevel@tonic-gate  * the class is marked as new or if rem_undo is true and the class is
23877c478bd9Sstevel@tonic-gate  * marked as deleted then add the class to the kernel action named by action
23887c478bd9Sstevel@tonic-gate  * and if successful mark as created.
23897c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
23907c478bd9Sstevel@tonic-gate  */
23917c478bd9Sstevel@tonic-gate int
23927c478bd9Sstevel@tonic-gate add_classes(
23937c478bd9Sstevel@tonic-gate ipqos_conf_class_t *classes,
23947c478bd9Sstevel@tonic-gate char *action,
23957c478bd9Sstevel@tonic-gate int module_version,
23967c478bd9Sstevel@tonic-gate boolean_t rem_undo) {
23977c478bd9Sstevel@tonic-gate 
23987c478bd9Sstevel@tonic-gate 	int res;
23997c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In add_classes\n");
24027c478bd9Sstevel@tonic-gate 
24037c478bd9Sstevel@tonic-gate 	/* for each class */
24047c478bd9Sstevel@tonic-gate 	for (cls = classes; cls; cls = cls->next) {
24057c478bd9Sstevel@tonic-gate 		/*
24067c478bd9Sstevel@tonic-gate 		 * skip class if in normal mode and not new class or
24077c478bd9Sstevel@tonic-gate 		 * if doing rollback and class wasn't deleted.
24087c478bd9Sstevel@tonic-gate 		 */
24097c478bd9Sstevel@tonic-gate 		if ((rem_undo == B_FALSE && cls->new == B_FALSE) ||
24107c478bd9Sstevel@tonic-gate 		(rem_undo == B_TRUE && cls->deleted == B_FALSE)) {
24117c478bd9Sstevel@tonic-gate 			continue;
24127c478bd9Sstevel@tonic-gate 		}
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate 		/* add class to action */
24157c478bd9Sstevel@tonic-gate 		res = add_class(action, cls->name, module_version,
24167c478bd9Sstevel@tonic-gate 		    cls->stats_enable, cls->alist->name);
24177c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
24187c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
24197c478bd9Sstevel@tonic-gate 		}
24207c478bd9Sstevel@tonic-gate 
24217c478bd9Sstevel@tonic-gate 		/* mark class as created */
24227c478bd9Sstevel@tonic-gate 		cls->cr_mod = B_TRUE;
24237c478bd9Sstevel@tonic-gate 	}
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
24267c478bd9Sstevel@tonic-gate }
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate /*
24297c478bd9Sstevel@tonic-gate  * For each of the actions in actions remove the action if marked as
24307c478bd9Sstevel@tonic-gate  * such or remove any objects within marked as such.
24317c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
24327c478bd9Sstevel@tonic-gate  */
24337c478bd9Sstevel@tonic-gate static int
24347c478bd9Sstevel@tonic-gate remove_items(
24357c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
24367c478bd9Sstevel@tonic-gate boolean_t add_undo)
24377c478bd9Sstevel@tonic-gate {
24387c478bd9Sstevel@tonic-gate 
24397c478bd9Sstevel@tonic-gate 	int res;
24407c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
24417c478bd9Sstevel@tonic-gate 
24427c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "In remove_items, add_undo: %u\n", add_undo);
24437c478bd9Sstevel@tonic-gate 
24447c478bd9Sstevel@tonic-gate 	/*
24457c478bd9Sstevel@tonic-gate 	 * loop through actions removing any actions, or action contents
24467c478bd9Sstevel@tonic-gate 	 * that are marked as such.
24477c478bd9Sstevel@tonic-gate 	 */
24487c478bd9Sstevel@tonic-gate 	for (act = actions; act; act = act->next) {
24497c478bd9Sstevel@tonic-gate 		res = remove_item(act, add_undo);
24507c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
24517c478bd9Sstevel@tonic-gate 			return (res);
24527c478bd9Sstevel@tonic-gate 		}
24537c478bd9Sstevel@tonic-gate 	}
24547c478bd9Sstevel@tonic-gate 
24557c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
24567c478bd9Sstevel@tonic-gate }
24577c478bd9Sstevel@tonic-gate 
24587c478bd9Sstevel@tonic-gate /*
24597c478bd9Sstevel@tonic-gate  * Deletes this action if marked for deletion or any of it's contents marked
24607c478bd9Sstevel@tonic-gate  * for deletion. If the action is marked for deletion any actions referencing
24617c478bd9Sstevel@tonic-gate  * this action are destroyed first if marked or have their contents destroyed
24627c478bd9Sstevel@tonic-gate  * if marked. This is recursive.
24637c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
24647c478bd9Sstevel@tonic-gate  */
24657c478bd9Sstevel@tonic-gate static int
24667c478bd9Sstevel@tonic-gate remove_item(
24677c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act,
24687c478bd9Sstevel@tonic-gate boolean_t add_undo)
24697c478bd9Sstevel@tonic-gate {
24707c478bd9Sstevel@tonic-gate 
24717c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
24727c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
24737c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *dep;
24747c478bd9Sstevel@tonic-gate 	int res;
24757c478bd9Sstevel@tonic-gate 
24767c478bd9Sstevel@tonic-gate 	IPQOSCDBG3(L1, "In remove_item: action: %s, add_undo: %u, mod: %u\n",
24777c478bd9Sstevel@tonic-gate 	    act->name, add_undo, act->modified);
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate 
24807c478bd9Sstevel@tonic-gate 	/* return immmediately if previously visited in remove phase */
24817c478bd9Sstevel@tonic-gate 
24827c478bd9Sstevel@tonic-gate 	if (act->visited == REM_VISITED) {
24837c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L1, "Exit due to REM_VISITED set\n");
24847c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
24857c478bd9Sstevel@tonic-gate 	}
24867c478bd9Sstevel@tonic-gate 	act->visited = REM_VISITED;
24877c478bd9Sstevel@tonic-gate 
24887c478bd9Sstevel@tonic-gate 
24897c478bd9Sstevel@tonic-gate 	/* if this action is to be deleted */
24907c478bd9Sstevel@tonic-gate 
24917c478bd9Sstevel@tonic-gate 	if (add_undo == B_FALSE && act->todel == B_TRUE ||
24927c478bd9Sstevel@tonic-gate 	    add_undo == B_TRUE && act->new == B_TRUE &&
24937c478bd9Sstevel@tonic-gate 	    act->cr_mod == B_TRUE) {
24947c478bd9Sstevel@tonic-gate 
24957c478bd9Sstevel@tonic-gate 		/* modify parent actions first */
24967c478bd9Sstevel@tonic-gate 
24977c478bd9Sstevel@tonic-gate 		for (dep = act->dependencies; dep; dep = dep->next) {
24987c478bd9Sstevel@tonic-gate 			res = remove_item(dep->action, add_undo);
24997c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
25007c478bd9Sstevel@tonic-gate 				return (res);
25017c478bd9Sstevel@tonic-gate 			}
25027c478bd9Sstevel@tonic-gate 		}
25037c478bd9Sstevel@tonic-gate 
25047c478bd9Sstevel@tonic-gate 		/* delete this action */
25057c478bd9Sstevel@tonic-gate 
25067c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(APPLY, "deleting action %s\n", act->name);
25077c478bd9Sstevel@tonic-gate 		res = ipp_action_destroy(act->name, 0);
25087c478bd9Sstevel@tonic-gate 		if (res != 0) {
25097c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(APPLY, "failed to destroy action %s\n",
25107c478bd9Sstevel@tonic-gate 			    act->name);
25117c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
25127c478bd9Sstevel@tonic-gate 		}
25137c478bd9Sstevel@tonic-gate 
25147c478bd9Sstevel@tonic-gate 		/* flag as deleted */
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 		act->deleted = B_TRUE;
25177c478bd9Sstevel@tonic-gate 
25187c478bd9Sstevel@tonic-gate 	/* if modified action */
25197c478bd9Sstevel@tonic-gate 
25207c478bd9Sstevel@tonic-gate 	} else if (act->modified == B_TRUE) {
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 		/* loop through removing any filters marked for del */
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 		for (flt = act->filters; flt; flt = flt->next) {
25257c478bd9Sstevel@tonic-gate 			if ((add_undo == B_FALSE && flt->todel == B_TRUE) ||
25267c478bd9Sstevel@tonic-gate 			    (add_undo == B_TRUE && flt->new == B_TRUE &&
25277c478bd9Sstevel@tonic-gate 			    flt->cr_mod == B_TRUE)) {
25287c478bd9Sstevel@tonic-gate 
25297c478bd9Sstevel@tonic-gate 				/* do deletion */
25307c478bd9Sstevel@tonic-gate 
25317c478bd9Sstevel@tonic-gate 				res = remove_filter(act->name, flt->name,
25327c478bd9Sstevel@tonic-gate 				    flt->instance, act->module_version);
25337c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
25347c478bd9Sstevel@tonic-gate 					IPQOSCDBG2(APPLY, "failed to destroy "
25357c478bd9Sstevel@tonic-gate 					    "filter %s, inst: %d\n", flt->name,
25367c478bd9Sstevel@tonic-gate 					    flt->instance);
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
25397c478bd9Sstevel@tonic-gate 				}
25407c478bd9Sstevel@tonic-gate 
25417c478bd9Sstevel@tonic-gate 				/* flag deleted */
25427c478bd9Sstevel@tonic-gate 
25437c478bd9Sstevel@tonic-gate 				flt->deleted = B_TRUE;
25447c478bd9Sstevel@tonic-gate 			}
25457c478bd9Sstevel@tonic-gate 		}
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 		/* remove any classes marked for del */
25487c478bd9Sstevel@tonic-gate 
25497c478bd9Sstevel@tonic-gate 		for (cls = act->classes; cls; cls = cls->next) {
25507c478bd9Sstevel@tonic-gate 			if ((add_undo == B_FALSE && cls->todel == B_TRUE) ||
25517c478bd9Sstevel@tonic-gate 			    (add_undo == B_TRUE && cls->new == B_TRUE &&
25527c478bd9Sstevel@tonic-gate 			    cls->cr_mod == B_TRUE)) {
25537c478bd9Sstevel@tonic-gate 
25547c478bd9Sstevel@tonic-gate 				/* do deletion */
25557c478bd9Sstevel@tonic-gate 
25567c478bd9Sstevel@tonic-gate 				res = remove_class(act->name, cls->name,
25577c478bd9Sstevel@tonic-gate 				    act->module_version, 0);
25587c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
25597c478bd9Sstevel@tonic-gate 					IPQOSCDBG1(APPLY, "failed to destroy "
25607c478bd9Sstevel@tonic-gate 					    "class %s\n", cls->name);
25617c478bd9Sstevel@tonic-gate 
25627c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
25637c478bd9Sstevel@tonic-gate 				}
25647c478bd9Sstevel@tonic-gate 
25657c478bd9Sstevel@tonic-gate 				/* flag deleted */
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 				cls->deleted = B_TRUE;
25687c478bd9Sstevel@tonic-gate 			}
25697c478bd9Sstevel@tonic-gate 		}
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 		/* mark action as having been modified */
25727c478bd9Sstevel@tonic-gate 
25737c478bd9Sstevel@tonic-gate 		act->cr_mod = B_TRUE;
25747c478bd9Sstevel@tonic-gate 	}
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
25777c478bd9Sstevel@tonic-gate }
25787c478bd9Sstevel@tonic-gate 
25797c478bd9Sstevel@tonic-gate /*
25807c478bd9Sstevel@tonic-gate  * for each of the actions in parameter actions apply any objects marked as
25817c478bd9Sstevel@tonic-gate  * modified as a modification to the kernel action represented.
25827c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on err, else IPQOS_CONF_SUCCESS.
25837c478bd9Sstevel@tonic-gate  */
25847c478bd9Sstevel@tonic-gate static int
25857c478bd9Sstevel@tonic-gate modify_items(ipqos_conf_action_t *actions)
25867c478bd9Sstevel@tonic-gate {
25877c478bd9Sstevel@tonic-gate 
25887c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
25897c478bd9Sstevel@tonic-gate 	int res;
25907c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
25917c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
25927c478bd9Sstevel@tonic-gate 
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In modify_items\n");
25957c478bd9Sstevel@tonic-gate 
25967c478bd9Sstevel@tonic-gate 	/* loop through actions in parameter actions */
25977c478bd9Sstevel@tonic-gate 
25987c478bd9Sstevel@tonic-gate 	for (act = actions; act; act = act->next) {
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate 		/* skip unchanged actions */
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 		if (act->modified == B_FALSE) {
26037c478bd9Sstevel@tonic-gate 			continue;
26047c478bd9Sstevel@tonic-gate 		}
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 		/* apply any parameter mods */
26077c478bd9Sstevel@tonic-gate 
26087c478bd9Sstevel@tonic-gate 		if (act->params->modified) {
26097c478bd9Sstevel@tonic-gate 			res = modify_params(act->name,
26107c478bd9Sstevel@tonic-gate 			    &act->params->nvlist,
26117c478bd9Sstevel@tonic-gate 			    act->module_version, act->params->stats_enable);
26127c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
26137c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
26147c478bd9Sstevel@tonic-gate 			}
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate 			act->params->cr_mod = B_TRUE;
26177c478bd9Sstevel@tonic-gate 		}
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate 		/* apply any class mods */
26207c478bd9Sstevel@tonic-gate 
26217c478bd9Sstevel@tonic-gate 		for (cls = act->classes; cls; cls = cls->next) {
26227c478bd9Sstevel@tonic-gate 			if (cls->modified) {
26237c478bd9Sstevel@tonic-gate 				res = modify_class(act->name, cls->name,
26247c478bd9Sstevel@tonic-gate 				    act->module_version, cls->stats_enable,
26257c478bd9Sstevel@tonic-gate 				    cls->alist->name, 0);
26267c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
26277c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
26287c478bd9Sstevel@tonic-gate 				}
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 				/* mark modification done */
26317c478bd9Sstevel@tonic-gate 				cls->cr_mod = B_TRUE;
26327c478bd9Sstevel@tonic-gate 			}
26337c478bd9Sstevel@tonic-gate 		}
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate 		/* apply any filter mods */
26367c478bd9Sstevel@tonic-gate 
26377c478bd9Sstevel@tonic-gate 		for (flt = act->filters; flt; flt = flt->next) {
26387c478bd9Sstevel@tonic-gate 			if (flt->modified) {
26397c478bd9Sstevel@tonic-gate 				res = modify_filter(act->name, flt,
26407c478bd9Sstevel@tonic-gate 				    act->module_version);
26417c478bd9Sstevel@tonic-gate 				if (res != 0) {
26427c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
26437c478bd9Sstevel@tonic-gate 				}
26447c478bd9Sstevel@tonic-gate 
26457c478bd9Sstevel@tonic-gate 				/* mark modification done */
26467c478bd9Sstevel@tonic-gate 				flt->cr_mod = B_TRUE;
26477c478bd9Sstevel@tonic-gate 			}
26487c478bd9Sstevel@tonic-gate 		}
26497c478bd9Sstevel@tonic-gate 
26507c478bd9Sstevel@tonic-gate 		/* mark action modified */
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate 		act->cr_mod = B_TRUE;
26537c478bd9Sstevel@tonic-gate 	}
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
26567c478bd9Sstevel@tonic-gate }
26577c478bd9Sstevel@tonic-gate 
26587c478bd9Sstevel@tonic-gate /*
26597c478bd9Sstevel@tonic-gate  * For each of the objects of each of the actions in nactions that are
26607c478bd9Sstevel@tonic-gate  * marked as having been modified the object modification is done in
26617c478bd9Sstevel@tonic-gate  * reverse using the same named object from oactions.
26627c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, IPQOS_CONF_SUCCESS otherwise.
26637c478bd9Sstevel@tonic-gate  */
26647c478bd9Sstevel@tonic-gate static int
26657c478bd9Sstevel@tonic-gate undo_modifys(
26667c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oactions,
26677c478bd9Sstevel@tonic-gate ipqos_conf_action_t *nactions)
26687c478bd9Sstevel@tonic-gate {
26697c478bd9Sstevel@tonic-gate 
26707c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
26717c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
26727c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
26737c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *oldact;
26747c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *oldflt;
26757c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *oldcls;
26767c478bd9Sstevel@tonic-gate 	int res;
26777c478bd9Sstevel@tonic-gate 
26787c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In undo_modifys:\n");
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	/* loop throught new actions */
26817c478bd9Sstevel@tonic-gate 
26827c478bd9Sstevel@tonic-gate 	for (act = nactions; act; act = act->next) {
26837c478bd9Sstevel@tonic-gate 		oldact = actionexist(act->name, oactions);
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate 		/*
26867c478bd9Sstevel@tonic-gate 		 * if the action was new then it will be removed and
26877c478bd9Sstevel@tonic-gate 		 * any permamanent items that were marked for modify
26887c478bd9Sstevel@tonic-gate 		 * will dissappear, so ignore action.
26897c478bd9Sstevel@tonic-gate 		 */
26907c478bd9Sstevel@tonic-gate 		if (oldact == NULL) {
26917c478bd9Sstevel@tonic-gate 			continue;
26927c478bd9Sstevel@tonic-gate 		}
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate 		/* if parameters were modified switch them back */
26957c478bd9Sstevel@tonic-gate 
26967c478bd9Sstevel@tonic-gate 		if (act->params->modified == B_TRUE &&
26977c478bd9Sstevel@tonic-gate 		    act->params->cr_mod == B_TRUE) {
26987c478bd9Sstevel@tonic-gate 			res = modify_params(act->name,
26997c478bd9Sstevel@tonic-gate 			    &oldact->params->nvlist,
27007c478bd9Sstevel@tonic-gate 			    act->module_version, act->params->stats_enable);
27017c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
27027c478bd9Sstevel@tonic-gate 				return (res);
27037c478bd9Sstevel@tonic-gate 			}
27047c478bd9Sstevel@tonic-gate 		}
27057c478bd9Sstevel@tonic-gate 
27067c478bd9Sstevel@tonic-gate 		/* for each filter in action if filter modified switch back */
27077c478bd9Sstevel@tonic-gate 
27087c478bd9Sstevel@tonic-gate 		for (flt = act->filters; flt; flt = flt->next) {
27097c478bd9Sstevel@tonic-gate 			if (flt->modified == B_TRUE &&
27107c478bd9Sstevel@tonic-gate 			    flt->cr_mod == B_TRUE) {
27117c478bd9Sstevel@tonic-gate 				oldflt = filterexist(flt->name, -1,
27127c478bd9Sstevel@tonic-gate 				    oldact->filters);
27137c478bd9Sstevel@tonic-gate 				res = modify_filter(act->name, oldflt,
27147c478bd9Sstevel@tonic-gate 				    act->module_version);
27157c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
27167c478bd9Sstevel@tonic-gate 					return (res);
27177c478bd9Sstevel@tonic-gate 				}
27187c478bd9Sstevel@tonic-gate 			}
27197c478bd9Sstevel@tonic-gate 		}
27207c478bd9Sstevel@tonic-gate 
27217c478bd9Sstevel@tonic-gate 		/* for each class in action if class modified switch back */
27227c478bd9Sstevel@tonic-gate 
27237c478bd9Sstevel@tonic-gate 		for (cls = act->classes; cls; cls = cls->next) {
27247c478bd9Sstevel@tonic-gate 			if (cls->modified == B_TRUE &&
27257c478bd9Sstevel@tonic-gate 			    cls->cr_mod == B_TRUE) {
27267c478bd9Sstevel@tonic-gate 				oldcls = classexist(cls->name, oldact->classes);
27277c478bd9Sstevel@tonic-gate 				if (oldcls->alist) {
27287c478bd9Sstevel@tonic-gate 					res = modify_class(act->name,
27297c478bd9Sstevel@tonic-gate 					    cls->name, act->module_version,
27307c478bd9Sstevel@tonic-gate 					    oldcls->stats_enable,
27317c478bd9Sstevel@tonic-gate 					    oldcls->alist->name, 0);
27327c478bd9Sstevel@tonic-gate 				}
27337c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
27347c478bd9Sstevel@tonic-gate 					return (res);
27357c478bd9Sstevel@tonic-gate 				}
27367c478bd9Sstevel@tonic-gate 			}
27377c478bd9Sstevel@tonic-gate 		}
27387c478bd9Sstevel@tonic-gate 	}
27397c478bd9Sstevel@tonic-gate 
27407c478bd9Sstevel@tonic-gate 	/*
27417c478bd9Sstevel@tonic-gate 	 * Go through the old actions modifying perm filters and classes
27427c478bd9Sstevel@tonic-gate 	 * whose action was deleted.
27437c478bd9Sstevel@tonic-gate 	 *
27447c478bd9Sstevel@tonic-gate 	 */
27457c478bd9Sstevel@tonic-gate 	for (act = oactions; act != NULL; act = act->next) {
27467c478bd9Sstevel@tonic-gate 
27477c478bd9Sstevel@tonic-gate 		if (act->deleted == B_FALSE) {
27487c478bd9Sstevel@tonic-gate 			continue;
27497c478bd9Sstevel@tonic-gate 		}
27507c478bd9Sstevel@tonic-gate 
27517c478bd9Sstevel@tonic-gate 		for (flt = act->filters; flt != NULL; flt = flt->next) {
27527c478bd9Sstevel@tonic-gate 			if (flt->originator == IPP_CONFIG_PERMANENT) {
27537c478bd9Sstevel@tonic-gate 				res = modify_filter(act->name, flt,
27547c478bd9Sstevel@tonic-gate 				    act->module_version);
27557c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
27567c478bd9Sstevel@tonic-gate 					return (res);
27577c478bd9Sstevel@tonic-gate 				}
27587c478bd9Sstevel@tonic-gate 			}
27597c478bd9Sstevel@tonic-gate 		}
27607c478bd9Sstevel@tonic-gate 
27617c478bd9Sstevel@tonic-gate 		for (cls = act->classes; cls != NULL; cls = cls->next) {
27627c478bd9Sstevel@tonic-gate 			if (cls->originator == IPP_CONFIG_PERMANENT) {
27637c478bd9Sstevel@tonic-gate 				res = modify_class(act->name, cls->name,
27647c478bd9Sstevel@tonic-gate 				    act->module_version, cls->stats_enable,
27657c478bd9Sstevel@tonic-gate 				    cls->alist->name, 0);
27667c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
27677c478bd9Sstevel@tonic-gate 					return (res);
27687c478bd9Sstevel@tonic-gate 				}
27697c478bd9Sstevel@tonic-gate 			}
27707c478bd9Sstevel@tonic-gate 
27717c478bd9Sstevel@tonic-gate 		}
27727c478bd9Sstevel@tonic-gate 	}
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
27757c478bd9Sstevel@tonic-gate }
27767c478bd9Sstevel@tonic-gate 
27777c478bd9Sstevel@tonic-gate 
27787c478bd9Sstevel@tonic-gate /*
27797c478bd9Sstevel@tonic-gate  * causes all changes marked as being done in actions and old_actions
27807c478bd9Sstevel@tonic-gate  * to be undone.
27817c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
27827c478bd9Sstevel@tonic-gate  */
27837c478bd9Sstevel@tonic-gate static int
27847c478bd9Sstevel@tonic-gate rollback(
27857c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
27867c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old_actions)
27877c478bd9Sstevel@tonic-gate {
27887c478bd9Sstevel@tonic-gate 
27897c478bd9Sstevel@tonic-gate 	int res;
27907c478bd9Sstevel@tonic-gate 
27917c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(RBK, "In rollback:\n");
27927c478bd9Sstevel@tonic-gate 
27937c478bd9Sstevel@tonic-gate 	/* re-add items that were deleted */
27947c478bd9Sstevel@tonic-gate 
27957c478bd9Sstevel@tonic-gate 	res = add_items(old_actions, B_TRUE);
27967c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
27977c478bd9Sstevel@tonic-gate 		return (res);
27987c478bd9Sstevel@tonic-gate 	}
27997c478bd9Sstevel@tonic-gate 
28007c478bd9Sstevel@tonic-gate 	/* change modified items back how they were */
28017c478bd9Sstevel@tonic-gate 
28027c478bd9Sstevel@tonic-gate 	res = undo_modifys(old_actions, actions);
28037c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
28047c478bd9Sstevel@tonic-gate 		return (res);
28057c478bd9Sstevel@tonic-gate 	}
28067c478bd9Sstevel@tonic-gate 
28077c478bd9Sstevel@tonic-gate 	/* remove new items that were added */
28087c478bd9Sstevel@tonic-gate 
28097c478bd9Sstevel@tonic-gate 	res = remove_items(actions, B_TRUE);
28107c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
28117c478bd9Sstevel@tonic-gate 		return (res);
28127c478bd9Sstevel@tonic-gate 	}
28137c478bd9Sstevel@tonic-gate 
28147c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
28157c478bd9Sstevel@tonic-gate }
28167c478bd9Sstevel@tonic-gate 
28177c478bd9Sstevel@tonic-gate /* ******************************* print config **************************** */
28187c478bd9Sstevel@tonic-gate 
28197c478bd9Sstevel@tonic-gate /*
28207c478bd9Sstevel@tonic-gate  * Prints the username of the user with uid 'uid' to 'fp' if the uid belongs
28217c478bd9Sstevel@tonic-gate  * to a known user on the system, otherwise just print 'uid'.
28227c478bd9Sstevel@tonic-gate  */
28237c478bd9Sstevel@tonic-gate static void
28247c478bd9Sstevel@tonic-gate printuser(
28257c478bd9Sstevel@tonic-gate FILE *fp,
28267c478bd9Sstevel@tonic-gate uid_t uid)
28277c478bd9Sstevel@tonic-gate {
28287c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
28297c478bd9Sstevel@tonic-gate 
28307c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In printuser\n");
28317c478bd9Sstevel@tonic-gate 
28327c478bd9Sstevel@tonic-gate 	pwd = getpwuid(uid);
28337c478bd9Sstevel@tonic-gate 	if (pwd != NULL) {
28347c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s\n", pwd->pw_name);
28357c478bd9Sstevel@tonic-gate 	} else {
28367c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%u\n", (int)uid);
28377c478bd9Sstevel@tonic-gate 	}
28387c478bd9Sstevel@tonic-gate }
28397c478bd9Sstevel@tonic-gate 
28407c478bd9Sstevel@tonic-gate /*
28417c478bd9Sstevel@tonic-gate  * print either a single value of start to fp (if start equals end), else
28427c478bd9Sstevel@tonic-gate  * print start'-'end if start is the smaller of the two values, otherwise
28437c478bd9Sstevel@tonic-gate  * print end'-'start.
28447c478bd9Sstevel@tonic-gate  */
28457c478bd9Sstevel@tonic-gate static void
28467c478bd9Sstevel@tonic-gate printrange(
28477c478bd9Sstevel@tonic-gate FILE *fp,
28487c478bd9Sstevel@tonic-gate uint32_t start,
28497c478bd9Sstevel@tonic-gate uint32_t end)
28507c478bd9Sstevel@tonic-gate {
28517c478bd9Sstevel@tonic-gate 	uint32_t tmp;
28527c478bd9Sstevel@tonic-gate 
28537c478bd9Sstevel@tonic-gate 	if (start > end) {
28547c478bd9Sstevel@tonic-gate 		tmp = start;
28557c478bd9Sstevel@tonic-gate 		start = end;
28567c478bd9Sstevel@tonic-gate 		end = tmp;
28577c478bd9Sstevel@tonic-gate 	}
28587c478bd9Sstevel@tonic-gate 
28597c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%u", start);
28607c478bd9Sstevel@tonic-gate 	if (end != start)
28617c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "-%u", end);
28627c478bd9Sstevel@tonic-gate }
28637c478bd9Sstevel@tonic-gate 
28647c478bd9Sstevel@tonic-gate /*
28657c478bd9Sstevel@tonic-gate  * print the contents of the array arr to fp in the form:
28667c478bd9Sstevel@tonic-gate  * {0-6:1;7-12:2;13:3.....} or {0-6:GREEN;7-12:YELLOW:...}
28677c478bd9Sstevel@tonic-gate  * dependant upon whether this is an integer or enumerated array resectively
28687c478bd9Sstevel@tonic-gate  * (if enum_nvs isn't set to NULL this is assumed to be an enumerated array);
28697c478bd9Sstevel@tonic-gate  * where 0-6 is the range of indexes with value 1 (or GREEN), 7-12 the range
28707c478bd9Sstevel@tonic-gate  * with value 2 (or YELLOW), and so forth. size is the array size and llimit
28717c478bd9Sstevel@tonic-gate  * and ulimit are the lower and upper limits of the array values printed
28727c478bd9Sstevel@tonic-gate  * respectively. For enumerated arrays enum_nvs carries the list of name
28737c478bd9Sstevel@tonic-gate  * and value pairs and ulimit and llimit parameters are ignored and instead
28747c478bd9Sstevel@tonic-gate  * determined from the enum_nvs list.
28757c478bd9Sstevel@tonic-gate  */
28767c478bd9Sstevel@tonic-gate static void
28777c478bd9Sstevel@tonic-gate print_int_array(
28787c478bd9Sstevel@tonic-gate FILE *fp,
28797c478bd9Sstevel@tonic-gate int arr[],
28807c478bd9Sstevel@tonic-gate uint32_t size,
28817c478bd9Sstevel@tonic-gate int llimit,
28827c478bd9Sstevel@tonic-gate int ulimit,
28837c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs,
28847c478bd9Sstevel@tonic-gate int tab_inserts)
28857c478bd9Sstevel@tonic-gate {
28867c478bd9Sstevel@tonic-gate 	int x, y;
28877c478bd9Sstevel@tonic-gate 	uint32_t first, last;
28887c478bd9Sstevel@tonic-gate 	boolean_t first_entry;	/* first 'ranges:value' to be printed ? */
28897c478bd9Sstevel@tonic-gate 	boolean_t first_range;	/* first range for a value to be printed ? */
28907c478bd9Sstevel@tonic-gate 	boolean_t found_range;	/* did we find a range for this value ? */
28917c478bd9Sstevel@tonic-gate 
28927c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(L0, "In print_int_array: size: %u, llimit: %u, ulimit: %u, "
28937c478bd9Sstevel@tonic-gate 	    "enum_nvs: %x \n", size, llimit, ulimit, enum_nvs);
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate 	/*
28967c478bd9Sstevel@tonic-gate 	 * if an enumeration retrieve value range.
28977c478bd9Sstevel@tonic-gate 	 */
28987c478bd9Sstevel@tonic-gate 	if (enum_nvs != NULL)
28997c478bd9Sstevel@tonic-gate 		get_str_val_value_range(enum_nvs, &llimit, &ulimit);
29007c478bd9Sstevel@tonic-gate 
29017c478bd9Sstevel@tonic-gate 	/*
29027c478bd9Sstevel@tonic-gate 	 * print opening curl.
29037c478bd9Sstevel@tonic-gate 	 */
29047c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%c\n", CURL_BEGIN);
29057c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
29067c478bd9Sstevel@tonic-gate 
29077c478bd9Sstevel@tonic-gate 	first_entry = B_TRUE;
29087c478bd9Sstevel@tonic-gate 	/*
29097c478bd9Sstevel@tonic-gate 	 * for each value in range.
29107c478bd9Sstevel@tonic-gate 	 */
29117c478bd9Sstevel@tonic-gate 	for (x = llimit; x <= ulimit; x++) {
29127c478bd9Sstevel@tonic-gate 		found_range = B_FALSE;
29137c478bd9Sstevel@tonic-gate 		first_range = B_TRUE;
29147c478bd9Sstevel@tonic-gate 		y = 0;
29157c478bd9Sstevel@tonic-gate 		/*
29167c478bd9Sstevel@tonic-gate 		 * scan array and print ranges of indexes with value x.
29177c478bd9Sstevel@tonic-gate 		 */
29187c478bd9Sstevel@tonic-gate 		while (y < size) {
29197c478bd9Sstevel@tonic-gate 			/*
29207c478bd9Sstevel@tonic-gate 			 * get first occurence of value for this range.
29217c478bd9Sstevel@tonic-gate 			 */
29227c478bd9Sstevel@tonic-gate 			while ((arr[y] != x) && (y < size))
29237c478bd9Sstevel@tonic-gate 				y++;
29247c478bd9Sstevel@tonic-gate 			if (y == size) {
29257c478bd9Sstevel@tonic-gate 				break;
29267c478bd9Sstevel@tonic-gate 			} else {
29277c478bd9Sstevel@tonic-gate 				found_range = B_TRUE;
29287c478bd9Sstevel@tonic-gate 			}
29297c478bd9Sstevel@tonic-gate 			first = y;
29307c478bd9Sstevel@tonic-gate 
29317c478bd9Sstevel@tonic-gate 			/*
29327c478bd9Sstevel@tonic-gate 			 * get last occurence of value for this range.
29337c478bd9Sstevel@tonic-gate 			 */
29347c478bd9Sstevel@tonic-gate 			while ((arr[y] == x) && (y < size))
29357c478bd9Sstevel@tonic-gate 				y++;
29367c478bd9Sstevel@tonic-gate 			last = y - 1;
29377c478bd9Sstevel@tonic-gate 
29387c478bd9Sstevel@tonic-gate 			/*
29397c478bd9Sstevel@tonic-gate 			 * print entry delimiter (semi-colon)? It must be
29407c478bd9Sstevel@tonic-gate 			 * the first range for this value and this mustn't
29417c478bd9Sstevel@tonic-gate 			 * be the first 'ranges:value' entry.
29427c478bd9Sstevel@tonic-gate 			 */
29437c478bd9Sstevel@tonic-gate 			if (!first_entry && first_range) {
29447c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, ";\n");
29457c478bd9Sstevel@tonic-gate 				PRINT_TABS(fp, tab_inserts + 1);
29467c478bd9Sstevel@tonic-gate 			} else {
29477c478bd9Sstevel@tonic-gate 				first_entry = B_FALSE;
29487c478bd9Sstevel@tonic-gate 			}
29497c478bd9Sstevel@tonic-gate 
29507c478bd9Sstevel@tonic-gate 			/*
29517c478bd9Sstevel@tonic-gate 			 * print comma (range delimeter) only if there was
29527c478bd9Sstevel@tonic-gate 			 * a previous range for this value.
29537c478bd9Sstevel@tonic-gate 			 */
29547c478bd9Sstevel@tonic-gate 			if (!first_range) {
29557c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, ",");
29567c478bd9Sstevel@tonic-gate 			} else {
29577c478bd9Sstevel@tonic-gate 				first_range = B_FALSE;
29587c478bd9Sstevel@tonic-gate 			}
29597c478bd9Sstevel@tonic-gate 
29607c478bd9Sstevel@tonic-gate 			/*
29617c478bd9Sstevel@tonic-gate 			 * print range.
29627c478bd9Sstevel@tonic-gate 			 */
29637c478bd9Sstevel@tonic-gate 			printrange(fp, first, last);
29647c478bd9Sstevel@tonic-gate 		}
29657c478bd9Sstevel@tonic-gate 		/*
29667c478bd9Sstevel@tonic-gate 		 * only print a colon and value if we found a range with
29677c478bd9Sstevel@tonic-gate 		 * this value.
29687c478bd9Sstevel@tonic-gate 		 */
29697c478bd9Sstevel@tonic-gate 		if (found_range) {
29707c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, ":");
29717c478bd9Sstevel@tonic-gate 
29727c478bd9Sstevel@tonic-gate 			/*
29737c478bd9Sstevel@tonic-gate 			 * print numeric/symbolic value.
29747c478bd9Sstevel@tonic-gate 			 */
29757c478bd9Sstevel@tonic-gate 			if (enum_nvs) {
29767c478bd9Sstevel@tonic-gate 				printenum(fp, x, enum_nvs);
29777c478bd9Sstevel@tonic-gate 			} else {
29787c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%d", x);
29797c478bd9Sstevel@tonic-gate 			}
29807c478bd9Sstevel@tonic-gate 		}
29817c478bd9Sstevel@tonic-gate 	}
29827c478bd9Sstevel@tonic-gate 
29837c478bd9Sstevel@tonic-gate 	/*
29847c478bd9Sstevel@tonic-gate 	 * print closing curl.
29857c478bd9Sstevel@tonic-gate 	 */
29867c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "\n");
29877c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
29887c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%c\n", CURL_END);
29897c478bd9Sstevel@tonic-gate }
29907c478bd9Sstevel@tonic-gate 
29917c478bd9Sstevel@tonic-gate /* print the protocol name for proto, or if unknown protocol number proto. */
29927c478bd9Sstevel@tonic-gate static void
29937c478bd9Sstevel@tonic-gate printproto(
29947c478bd9Sstevel@tonic-gate FILE *fp,
29957c478bd9Sstevel@tonic-gate uint8_t proto)
29967c478bd9Sstevel@tonic-gate {
29977c478bd9Sstevel@tonic-gate 
29987c478bd9Sstevel@tonic-gate 	struct protoent *pent;
29997c478bd9Sstevel@tonic-gate 
30007c478bd9Sstevel@tonic-gate 	pent = getprotobynumber(proto);
30017c478bd9Sstevel@tonic-gate 	if (pent != NULL) {
30027c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s\n", pent->p_name);
30037c478bd9Sstevel@tonic-gate 	} else {
30047c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%u\n", proto);
30057c478bd9Sstevel@tonic-gate 	}
30067c478bd9Sstevel@tonic-gate }
30077c478bd9Sstevel@tonic-gate 
30087c478bd9Sstevel@tonic-gate /*
30097c478bd9Sstevel@tonic-gate  * prints the name associated with interface with index ifindex to fp.
30107c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
30117c478bd9Sstevel@tonic-gate  */
30127c478bd9Sstevel@tonic-gate static int
30137c478bd9Sstevel@tonic-gate printifname(
30147c478bd9Sstevel@tonic-gate FILE *fp,
30157c478bd9Sstevel@tonic-gate int ifindex)
30167c478bd9Sstevel@tonic-gate {
30177c478bd9Sstevel@tonic-gate 
30187c478bd9Sstevel@tonic-gate 	int s;
30197c478bd9Sstevel@tonic-gate 	struct lifconf lc;
30207c478bd9Sstevel@tonic-gate 	struct lifnum ln;
30217c478bd9Sstevel@tonic-gate 	struct lifreq *lr;
30227c478bd9Sstevel@tonic-gate 	char *buf;
30237c478bd9Sstevel@tonic-gate 	int len;
30247c478bd9Sstevel@tonic-gate 	char *cp;
30257c478bd9Sstevel@tonic-gate 	int ret;
30267c478bd9Sstevel@tonic-gate 	int x;
30277c478bd9Sstevel@tonic-gate 	int idx;
30287c478bd9Sstevel@tonic-gate 
30297c478bd9Sstevel@tonic-gate 	/* open socket */
30307c478bd9Sstevel@tonic-gate 
30317c478bd9Sstevel@tonic-gate 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
30327c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, gettext("opening AF_INET socket"));
30337c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
30347c478bd9Sstevel@tonic-gate 	}
30357c478bd9Sstevel@tonic-gate 
30367c478bd9Sstevel@tonic-gate 	/* get number of lifreq structs that need to be alloc'd for */
30377c478bd9Sstevel@tonic-gate 
30387c478bd9Sstevel@tonic-gate 	ln.lifn_family = AF_UNSPEC;
30397c478bd9Sstevel@tonic-gate 	ln.lifn_flags = 0;
30407c478bd9Sstevel@tonic-gate 	ret = ioctl(s, SIOCGLIFNUM, &ln);
30417c478bd9Sstevel@tonic-gate 	if (ret < 0) {
30427c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "SIOCLIFNUM ioctl");
30437c478bd9Sstevel@tonic-gate 		(void) close(s);
30447c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
30457c478bd9Sstevel@tonic-gate 	}
30467c478bd9Sstevel@tonic-gate 
30477c478bd9Sstevel@tonic-gate 	/* allocate buffer for SIOGLIFCONF ioctl */
30487c478bd9Sstevel@tonic-gate 
30497c478bd9Sstevel@tonic-gate 	len = ln.lifn_count * sizeof (struct lifreq);
30507c478bd9Sstevel@tonic-gate 	buf = malloc(len);
30517c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
30527c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
30537c478bd9Sstevel@tonic-gate 		(void) close(s);
30547c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
30557c478bd9Sstevel@tonic-gate 	}
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate 	/* setup lifconf params for ioctl */
30587c478bd9Sstevel@tonic-gate 
30597c478bd9Sstevel@tonic-gate 	lc.lifc_family = AF_UNSPEC;
30607c478bd9Sstevel@tonic-gate 	lc.lifc_flags = 0;
30617c478bd9Sstevel@tonic-gate 	lc.lifc_len = len;
30627c478bd9Sstevel@tonic-gate 	lc.lifc_buf = buf;
30637c478bd9Sstevel@tonic-gate 
30647c478bd9Sstevel@tonic-gate 	/* do SIOCGLIFCONF ioctl */
30657c478bd9Sstevel@tonic-gate 
30667c478bd9Sstevel@tonic-gate 	ret = ioctl(s, SIOCGLIFCONF, &lc);
30677c478bd9Sstevel@tonic-gate 	if (ret < 0) {
30687c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "SIGLIFCONF");
30697c478bd9Sstevel@tonic-gate 		(void) close(s);
30707c478bd9Sstevel@tonic-gate 		free(buf);
30717c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
30727c478bd9Sstevel@tonic-gate 	}
30737c478bd9Sstevel@tonic-gate 	(void) close(s);
30747c478bd9Sstevel@tonic-gate 
30757c478bd9Sstevel@tonic-gate 	/*
30767c478bd9Sstevel@tonic-gate 	 * for each interface name given in the returned lifreq list get
30777c478bd9Sstevel@tonic-gate 	 * it's index and compare with ifindex param. Break if equal.
30787c478bd9Sstevel@tonic-gate 	 */
30797c478bd9Sstevel@tonic-gate 	for (x = ln.lifn_count, lr = lc.lifc_req; x > 0; x--, lr++) {
30807c478bd9Sstevel@tonic-gate 		ret = readifindex(lr->lifr_name, &idx);
30817c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
30827c478bd9Sstevel@tonic-gate 			free(buf);
30837c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
30847c478bd9Sstevel@tonic-gate 		}
30857c478bd9Sstevel@tonic-gate 		if (idx == ifindex) {
30867c478bd9Sstevel@tonic-gate 			break;
30877c478bd9Sstevel@tonic-gate 		}
30887c478bd9Sstevel@tonic-gate 	}
30897c478bd9Sstevel@tonic-gate 	free(buf);
30907c478bd9Sstevel@tonic-gate 
30917c478bd9Sstevel@tonic-gate 	if (x == 0) {
30927c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(L1, "Failed to find if index %u in returned "
30937c478bd9Sstevel@tonic-gate 		    "if list.\n", ifindex);
30947c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
30957c478bd9Sstevel@tonic-gate 	}
30967c478bd9Sstevel@tonic-gate 	/* truncate any logical suffix */
30977c478bd9Sstevel@tonic-gate 
30987c478bd9Sstevel@tonic-gate 	if ((cp = strchr(lr->lifr_name, '@')) != NULL) {
30997c478bd9Sstevel@tonic-gate 		*cp = NULL;
31007c478bd9Sstevel@tonic-gate 	}
31017c478bd9Sstevel@tonic-gate 
31027c478bd9Sstevel@tonic-gate 	/* print interface name */
31037c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s\n", lr->lifr_name);
31047c478bd9Sstevel@tonic-gate 
31057c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
31067c478bd9Sstevel@tonic-gate }
31077c478bd9Sstevel@tonic-gate 
31087c478bd9Sstevel@tonic-gate /*
31097c478bd9Sstevel@tonic-gate  * print to fp the enumeration clause evaluating to the value val using the
31107c478bd9Sstevel@tonic-gate  * names/values given in enum_nvs.
31117c478bd9Sstevel@tonic-gate  */
31127c478bd9Sstevel@tonic-gate static void
31137c478bd9Sstevel@tonic-gate printenum(
31147c478bd9Sstevel@tonic-gate FILE *fp,
31157c478bd9Sstevel@tonic-gate uint32_t val,
31167c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs)
31177c478bd9Sstevel@tonic-gate {
31187c478bd9Sstevel@tonic-gate 
31197c478bd9Sstevel@tonic-gate 	boolean_t isfirstval = B_TRUE;
31207c478bd9Sstevel@tonic-gate 	str_val_nd_t *name_val = enum_nvs;
31217c478bd9Sstevel@tonic-gate 
31227c478bd9Sstevel@tonic-gate 	/* for each value in enum_nvs if same bit set in val print name */
31237c478bd9Sstevel@tonic-gate 
31247c478bd9Sstevel@tonic-gate 	while (name_val) {
31257c478bd9Sstevel@tonic-gate 		if ((name_val->sv.value & val) == name_val->sv.value) {
31267c478bd9Sstevel@tonic-gate 			if (isfirstval == B_TRUE) {
31277c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%s", name_val->sv.string);
31287c478bd9Sstevel@tonic-gate 				isfirstval = B_FALSE;
31297c478bd9Sstevel@tonic-gate 			} else {
31307c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, ", %s", name_val->sv.string);
31317c478bd9Sstevel@tonic-gate 			}
31327c478bd9Sstevel@tonic-gate 		}
31337c478bd9Sstevel@tonic-gate 		name_val = name_val->next;
31347c478bd9Sstevel@tonic-gate 	}
31357c478bd9Sstevel@tonic-gate }
31367c478bd9Sstevel@tonic-gate 
31377c478bd9Sstevel@tonic-gate 
31387c478bd9Sstevel@tonic-gate /* prints the service name of port, or if unknown the number to fp. */
31397c478bd9Sstevel@tonic-gate static void
31407c478bd9Sstevel@tonic-gate printport(
31417c478bd9Sstevel@tonic-gate FILE *fp,
31427c478bd9Sstevel@tonic-gate uint16_t port)
31437c478bd9Sstevel@tonic-gate {
31447c478bd9Sstevel@tonic-gate 
31457c478bd9Sstevel@tonic-gate 	struct servent *sent;
31467c478bd9Sstevel@tonic-gate 
31477c478bd9Sstevel@tonic-gate 	sent = getservbyport(port, NULL);
31487c478bd9Sstevel@tonic-gate 	if (sent != NULL) {
31497c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s\n", sent->s_name);
31507c478bd9Sstevel@tonic-gate 	} else {
31517c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%u\n", ntohs(port));
31527c478bd9Sstevel@tonic-gate 	}
31537c478bd9Sstevel@tonic-gate }
31547c478bd9Sstevel@tonic-gate 
31557c478bd9Sstevel@tonic-gate /*
31567c478bd9Sstevel@tonic-gate  * prints tp fp the name and value of all user specifiable parameters in the
31577c478bd9Sstevel@tonic-gate  * nvlist.
31587c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
31597c478bd9Sstevel@tonic-gate  */
31607c478bd9Sstevel@tonic-gate static int
31617c478bd9Sstevel@tonic-gate printnvlist(
31627c478bd9Sstevel@tonic-gate FILE *fp,
31637c478bd9Sstevel@tonic-gate char *module,
31647c478bd9Sstevel@tonic-gate nvlist_t *nvl,
31657c478bd9Sstevel@tonic-gate int printall,	/* are we want ip addresses printing if node name */
31667c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt,	/* used to determine if node name set */
31677c478bd9Sstevel@tonic-gate int tab_inserts,
31687c478bd9Sstevel@tonic-gate place_t place)
31697c478bd9Sstevel@tonic-gate {
31707c478bd9Sstevel@tonic-gate 	FILE *tfp;
31717c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
31727c478bd9Sstevel@tonic-gate 	char *name;
31737c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
31747c478bd9Sstevel@tonic-gate 	str_val_nd_t *enum_nvs;
31757c478bd9Sstevel@tonic-gate 	int ret;
31767c478bd9Sstevel@tonic-gate 	char dfltst[IPQOS_VALST_MAXLEN+1];
31777c478bd9Sstevel@tonic-gate 	char *param;
31787c478bd9Sstevel@tonic-gate 	int openerr;
31797c478bd9Sstevel@tonic-gate 	int res;
31807c478bd9Sstevel@tonic-gate 
31817c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In printnvlist\n");
31827c478bd9Sstevel@tonic-gate 
31837c478bd9Sstevel@tonic-gate 
31847c478bd9Sstevel@tonic-gate 	/* open stream to types file */
31857c478bd9Sstevel@tonic-gate 
31867c478bd9Sstevel@tonic-gate 	tfp = validmod(module, &openerr);
31877c478bd9Sstevel@tonic-gate 	if (tfp == NULL) {
31887c478bd9Sstevel@tonic-gate 		if (openerr) {
31897c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "fopen");
31907c478bd9Sstevel@tonic-gate 		}
31917c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
31927c478bd9Sstevel@tonic-gate 	}
31937c478bd9Sstevel@tonic-gate 
31947c478bd9Sstevel@tonic-gate 
31957c478bd9Sstevel@tonic-gate 	/* go through list getting param name and type and printing it */
31967c478bd9Sstevel@tonic-gate 
31977c478bd9Sstevel@tonic-gate 	nvp = nvlist_next_nvpair(nvl, NULL);
31987c478bd9Sstevel@tonic-gate 	while (nvp) {
31997c478bd9Sstevel@tonic-gate 
32007c478bd9Sstevel@tonic-gate 		/* get nvpair name */
32017c478bd9Sstevel@tonic-gate 		name = nvpair_name(nvp);
32027c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(L0, "processing element %s.\n", name);
32037c478bd9Sstevel@tonic-gate 
32047c478bd9Sstevel@tonic-gate 		/* skip ipgpc params that are not explicitly user settable */
32057c478bd9Sstevel@tonic-gate 
32067c478bd9Sstevel@tonic-gate 		if (strcmp(name, IPGPC_FILTER_TYPE) == 0 ||
32077c478bd9Sstevel@tonic-gate 		    strcmp(name, IPGPC_SADDR_MASK) == 0 ||
32087c478bd9Sstevel@tonic-gate 		    strcmp(name, IPGPC_DADDR_MASK) == 0 ||
32097c478bd9Sstevel@tonic-gate 		    strcmp(name, IPGPC_SPORT_MASK) == 0 ||
32107c478bd9Sstevel@tonic-gate 		    strcmp(name, IPGPC_DPORT_MASK) == 0) {
32117c478bd9Sstevel@tonic-gate 			nvp = nvlist_next_nvpair(nvl, nvp);
32127c478bd9Sstevel@tonic-gate 			continue;
32137c478bd9Sstevel@tonic-gate 		}
32147c478bd9Sstevel@tonic-gate 
32157c478bd9Sstevel@tonic-gate 		param = SHORT_NAME(name);
32167c478bd9Sstevel@tonic-gate 
32177c478bd9Sstevel@tonic-gate 		/*
32187c478bd9Sstevel@tonic-gate 		 * get parameter type from types file.
32197c478bd9Sstevel@tonic-gate 		 */
32207c478bd9Sstevel@tonic-gate 		place = PL_ANY;
32217c478bd9Sstevel@tonic-gate 		ret = readtype(tfp, module, param, &type, &enum_nvs, dfltst,
32227c478bd9Sstevel@tonic-gate 		    B_TRUE, &place);
32237c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
32247c478bd9Sstevel@tonic-gate 			return (ret);
32257c478bd9Sstevel@tonic-gate 		}
32267c478bd9Sstevel@tonic-gate 
32277c478bd9Sstevel@tonic-gate 		/*
32287c478bd9Sstevel@tonic-gate 		 * for map entries we don't print the map value, only
32297c478bd9Sstevel@tonic-gate 		 * the index value it was derived from.
32307c478bd9Sstevel@tonic-gate 		 */
32317c478bd9Sstevel@tonic-gate 		if (place == PL_MAP) {
32327c478bd9Sstevel@tonic-gate 			nvp = nvlist_next_nvpair(nvl, nvp);
32337c478bd9Sstevel@tonic-gate 			continue;
32347c478bd9Sstevel@tonic-gate 		}
32357c478bd9Sstevel@tonic-gate 
32367c478bd9Sstevel@tonic-gate 		/*
32377c478bd9Sstevel@tonic-gate 		 * the ifindex is converted to the name and printed out
32387c478bd9Sstevel@tonic-gate 		 * so print the parameter name as ifname.
32397c478bd9Sstevel@tonic-gate 		 */
32407c478bd9Sstevel@tonic-gate 		if (strcmp(name, IPGPC_IF_INDEX) == 0) {
32417c478bd9Sstevel@tonic-gate 			PRINT_TABS(fp, tab_inserts);
32427c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%s ", IPQOS_IFNAME_STR);
32437c478bd9Sstevel@tonic-gate 		/*
32447c478bd9Sstevel@tonic-gate 		 * we may not print the address due to us instead printing
32457c478bd9Sstevel@tonic-gate 		 * the node name in printfilter, therefore we leave the
32467c478bd9Sstevel@tonic-gate 		 * printing of the parameter in the addresses switch case code.
32477c478bd9Sstevel@tonic-gate 		 */
32487c478bd9Sstevel@tonic-gate 		} else if ((strcmp(name, IPGPC_SADDR) != 0 &&
32497c478bd9Sstevel@tonic-gate 		    strcmp(name, IPGPC_DADDR) != 0)) {
32507c478bd9Sstevel@tonic-gate 			PRINT_TABS(fp, tab_inserts);
32517c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%s ", param);
32527c478bd9Sstevel@tonic-gate 		}
32537c478bd9Sstevel@tonic-gate 
32547c478bd9Sstevel@tonic-gate 		switch (type) {
32557c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_IFINDEX: {
32567c478bd9Sstevel@tonic-gate 				uint32_t ifidx;
32577c478bd9Sstevel@tonic-gate 
32587c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint32(nvp, &ifidx);
32597c478bd9Sstevel@tonic-gate 				(void) printifname(fp, ifidx);
32607c478bd9Sstevel@tonic-gate 				break;
32617c478bd9Sstevel@tonic-gate 			}
32627c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_BOOLEAN: {
32637c478bd9Sstevel@tonic-gate 				boolean_t bl;
32647c478bd9Sstevel@tonic-gate 
32657c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint32(nvp,
32667c478bd9Sstevel@tonic-gate 				    (uint32_t *)&bl);
32677c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%s\n",
32687c478bd9Sstevel@tonic-gate 				    bl == B_TRUE ? "true" : "false");
32697c478bd9Sstevel@tonic-gate 				break;
32707c478bd9Sstevel@tonic-gate 			}
32717c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_ACTION: {
32727c478bd9Sstevel@tonic-gate 				char *strval;
32737c478bd9Sstevel@tonic-gate 
32747c478bd9Sstevel@tonic-gate 				(void) nvpair_value_string(nvp, &strval);
32757c478bd9Sstevel@tonic-gate 				print_action_nm(fp, strval);
32767c478bd9Sstevel@tonic-gate 				break;
32777c478bd9Sstevel@tonic-gate 			}
32787c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_STRING: {
32797c478bd9Sstevel@tonic-gate 				char *strval;
32807c478bd9Sstevel@tonic-gate 
32817c478bd9Sstevel@tonic-gate 				(void) nvpair_value_string(nvp, &strval);
32827c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%s\n",
32837c478bd9Sstevel@tonic-gate 				    quote_ws_string(strval));
32847c478bd9Sstevel@tonic-gate 				break;
32857c478bd9Sstevel@tonic-gate 			}
32867c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_ADDRESS: {
32877c478bd9Sstevel@tonic-gate 				uint_t tmp;
32887c478bd9Sstevel@tonic-gate 				in6_addr_t *addr;
32897c478bd9Sstevel@tonic-gate 				char addrstr[INET6_ADDRSTRLEN];
32907c478bd9Sstevel@tonic-gate 				uchar_t ftype;
32917c478bd9Sstevel@tonic-gate 				int af;
32927c478bd9Sstevel@tonic-gate 				in6_addr_t *mask;
32937c478bd9Sstevel@tonic-gate 
32947c478bd9Sstevel@tonic-gate 				/*
32957c478bd9Sstevel@tonic-gate 				 * skip addresses that have node names for
32967c478bd9Sstevel@tonic-gate 				 * non printall listings.
32977c478bd9Sstevel@tonic-gate 				 */
32987c478bd9Sstevel@tonic-gate 				if (printall == 0 &&
32997c478bd9Sstevel@tonic-gate 				    (strcmp(nvpair_name(nvp), IPGPC_SADDR) ==
33007c478bd9Sstevel@tonic-gate 				    0 && flt->src_nd_name ||
33017c478bd9Sstevel@tonic-gate 				    strcmp(nvpair_name(nvp), IPGPC_DADDR) ==
33027c478bd9Sstevel@tonic-gate 				    0 && flt->dst_nd_name)) {
33037c478bd9Sstevel@tonic-gate 					break;
33047c478bd9Sstevel@tonic-gate 				}
33057c478bd9Sstevel@tonic-gate 
33067c478bd9Sstevel@tonic-gate 				/* we skipped this above */
33077c478bd9Sstevel@tonic-gate 
33087c478bd9Sstevel@tonic-gate 				PRINT_TABS(fp, tab_inserts);
33097c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%s ", param);
33107c478bd9Sstevel@tonic-gate 
33117c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint32_array(nvp,
33127c478bd9Sstevel@tonic-gate 				    (uint32_t **)&addr, &tmp);
33137c478bd9Sstevel@tonic-gate 
33147c478bd9Sstevel@tonic-gate 				/* get filter type */
33157c478bd9Sstevel@tonic-gate 
33167c478bd9Sstevel@tonic-gate 				(void) nvlist_lookup_byte(nvl,
33177c478bd9Sstevel@tonic-gate 				    IPGPC_FILTER_TYPE, &ftype);
33187c478bd9Sstevel@tonic-gate 				if (ftype == IPGPC_V4_FLTR) {
33197c478bd9Sstevel@tonic-gate 					af = AF_INET;
33207c478bd9Sstevel@tonic-gate 					addr = (in6_addr_t *)
33217c478bd9Sstevel@tonic-gate 					&V4_PART_OF_V6((*addr));
33227c478bd9Sstevel@tonic-gate 				} else {
33237c478bd9Sstevel@tonic-gate 					af = AF_INET6;
33247c478bd9Sstevel@tonic-gate 				}
33257c478bd9Sstevel@tonic-gate 				/* get mask */
33267c478bd9Sstevel@tonic-gate 
33277c478bd9Sstevel@tonic-gate 				if (strcmp(nvpair_name(nvp), IPGPC_SADDR) ==
33287c478bd9Sstevel@tonic-gate 				    0) {
33297c478bd9Sstevel@tonic-gate 					ret = nvlist_lookup_uint32_array(nvl,
33307c478bd9Sstevel@tonic-gate 					    IPGPC_SADDR_MASK,
33317c478bd9Sstevel@tonic-gate 					    (uint32_t **)&mask, &tmp);
33327c478bd9Sstevel@tonic-gate 				} else {
33337c478bd9Sstevel@tonic-gate 					ret = nvlist_lookup_uint32_array(nvl,
33347c478bd9Sstevel@tonic-gate 					    IPGPC_DADDR_MASK,
33357c478bd9Sstevel@tonic-gate 					    (uint32_t **)&mask, &tmp);
33367c478bd9Sstevel@tonic-gate 				}
33377c478bd9Sstevel@tonic-gate 
33387c478bd9Sstevel@tonic-gate 				/* print address/mask to fp */
33397c478bd9Sstevel@tonic-gate 
33407c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%s/%u\n",
33417c478bd9Sstevel@tonic-gate 				    inet_ntop(af, addr, addrstr,
33427c478bd9Sstevel@tonic-gate 				    INET6_ADDRSTRLEN), masktocidr(af, mask));
33437c478bd9Sstevel@tonic-gate 				break;
33447c478bd9Sstevel@tonic-gate 			}
33457c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_ENUM: {
33467c478bd9Sstevel@tonic-gate 				uint32_t val;
33477c478bd9Sstevel@tonic-gate 
33487c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint32(nvp, &val);
33497c478bd9Sstevel@tonic-gate 
33507c478bd9Sstevel@tonic-gate 				/*
33517c478bd9Sstevel@tonic-gate 				 * print list of tokens resulting in val
33527c478bd9Sstevel@tonic-gate 				 */
33537c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "{ ");
33547c478bd9Sstevel@tonic-gate 				printenum(fp, val, enum_nvs);
33557c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, " }\n");
33567c478bd9Sstevel@tonic-gate 				break;
33577c478bd9Sstevel@tonic-gate 			}
33587c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_PORT: {
33597c478bd9Sstevel@tonic-gate 				uint16_t port;
33607c478bd9Sstevel@tonic-gate 
33617c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint16(nvp, &port);
33627c478bd9Sstevel@tonic-gate 				printport(fp, port);
33637c478bd9Sstevel@tonic-gate 				break;
33647c478bd9Sstevel@tonic-gate 			}
33657c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_PROTO: {
33667c478bd9Sstevel@tonic-gate 				uint8_t proto;
33677c478bd9Sstevel@tonic-gate 
33687c478bd9Sstevel@tonic-gate 				(void) nvpair_value_byte(nvp, &proto);
33697c478bd9Sstevel@tonic-gate 				printproto(fp, proto);
33707c478bd9Sstevel@tonic-gate 				break;
33717c478bd9Sstevel@tonic-gate 			}
33727c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_M_INDEX:
33737c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_UINT8: {
33747c478bd9Sstevel@tonic-gate 				uchar_t u8;
33757c478bd9Sstevel@tonic-gate 
33767c478bd9Sstevel@tonic-gate 				(void) nvpair_value_byte(nvp, &u8);
33777c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%u\n", u8);
33787c478bd9Sstevel@tonic-gate 				break;
33797c478bd9Sstevel@tonic-gate 			}
33807c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_UINT16: {
33817c478bd9Sstevel@tonic-gate 				uint16_t u16;
33827c478bd9Sstevel@tonic-gate 
33837c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint16(nvp, &u16);
33847c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%u\n", u16);
33857c478bd9Sstevel@tonic-gate 				break;
33867c478bd9Sstevel@tonic-gate 			}
33877c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_INT16: {
33887c478bd9Sstevel@tonic-gate 				int16_t i16;
33897c478bd9Sstevel@tonic-gate 
33907c478bd9Sstevel@tonic-gate 				(void) nvpair_value_int16(nvp, &i16);
33917c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%d\n", i16);
33927c478bd9Sstevel@tonic-gate 				break;
33937c478bd9Sstevel@tonic-gate 			}
33947c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_UINT32: {
33957c478bd9Sstevel@tonic-gate 				uint32_t u32;
33967c478bd9Sstevel@tonic-gate 
33977c478bd9Sstevel@tonic-gate 				(void) nvpair_value_uint32(nvp, &u32);
33987c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%u\n", u32);
33997c478bd9Sstevel@tonic-gate 				break;
34007c478bd9Sstevel@tonic-gate 			}
34017c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_INT32: {
34027c478bd9Sstevel@tonic-gate 				int i32;
34037c478bd9Sstevel@tonic-gate 
34047c478bd9Sstevel@tonic-gate 				(void) nvpair_value_int32(nvp, &i32);
34057c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%d\n", i32);
34067c478bd9Sstevel@tonic-gate 				break;
34077c478bd9Sstevel@tonic-gate 			}
34087c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_INT_ARRAY: {
34097c478bd9Sstevel@tonic-gate 				str_val_nd_t *arr_enum_nvs = NULL;
34107c478bd9Sstevel@tonic-gate 				uint32_t size;
34117c478bd9Sstevel@tonic-gate 				int llimit, ulimit;
34127c478bd9Sstevel@tonic-gate 				int *arr;
34137c478bd9Sstevel@tonic-gate 
34147c478bd9Sstevel@tonic-gate 				(void) nvpair_value_int32_array(nvp, &arr,
34157c478bd9Sstevel@tonic-gate 				    &size);
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 				/*
34187c478bd9Sstevel@tonic-gate 				 * read array info from types file.
34197c478bd9Sstevel@tonic-gate 				 */
34207c478bd9Sstevel@tonic-gate 				res = read_int_array_info(dfltst,
34217c478bd9Sstevel@tonic-gate 				    &arr_enum_nvs, &size, &llimit, &ulimit,
34227c478bd9Sstevel@tonic-gate 				    module);
34237c478bd9Sstevel@tonic-gate 
34247c478bd9Sstevel@tonic-gate 				/*
34257c478bd9Sstevel@tonic-gate 				 * print array with numbers, or symbols
34267c478bd9Sstevel@tonic-gate 				 * if enumerated.
34277c478bd9Sstevel@tonic-gate 				 */
34287c478bd9Sstevel@tonic-gate 				if (res == IPQOS_CONF_SUCCESS) {
34297c478bd9Sstevel@tonic-gate 					print_int_array(fp, arr, size,
34307c478bd9Sstevel@tonic-gate 					    llimit, ulimit, arr_enum_nvs,
34317c478bd9Sstevel@tonic-gate 					    tab_inserts);
34327c478bd9Sstevel@tonic-gate 					if (arr_enum_nvs != NULL) {
34337c478bd9Sstevel@tonic-gate 						free_str_val_entrys(
34347c478bd9Sstevel@tonic-gate 						    arr_enum_nvs);
34357c478bd9Sstevel@tonic-gate 					}
34367c478bd9Sstevel@tonic-gate 				}
34377c478bd9Sstevel@tonic-gate 				break;
34387c478bd9Sstevel@tonic-gate 			}
34397c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_USER: {
34407c478bd9Sstevel@tonic-gate 				uid_t uid;
34417c478bd9Sstevel@tonic-gate 
34427c478bd9Sstevel@tonic-gate 				(void) nvpair_value_int32(nvp, (int *)&uid);
34437c478bd9Sstevel@tonic-gate 				printuser(fp, uid);
34447c478bd9Sstevel@tonic-gate 				break;
34457c478bd9Sstevel@tonic-gate 			}
34467c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
34477c478bd9Sstevel@tonic-gate 			default: {
34487c478bd9Sstevel@tonic-gate 				/*
34497c478bd9Sstevel@tonic-gate 				 * we should have catered for all used data
34507c478bd9Sstevel@tonic-gate 				 * types that readtype returns.
34517c478bd9Sstevel@tonic-gate 				 */
34527c478bd9Sstevel@tonic-gate 				assert(1);
34537c478bd9Sstevel@tonic-gate 			}
34547c478bd9Sstevel@tonic-gate #endif
34557c478bd9Sstevel@tonic-gate 		}
34567c478bd9Sstevel@tonic-gate 
34577c478bd9Sstevel@tonic-gate 		nvp = nvlist_next_nvpair(nvl, nvp);
34587c478bd9Sstevel@tonic-gate 	}
34597c478bd9Sstevel@tonic-gate 
34607c478bd9Sstevel@tonic-gate 	(void) fclose(tfp);
34617c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
34627c478bd9Sstevel@tonic-gate }
34637c478bd9Sstevel@tonic-gate 
34647c478bd9Sstevel@tonic-gate /*
34657c478bd9Sstevel@tonic-gate  * print a parameter clause for the parmeters given in params to fp.
34667c478bd9Sstevel@tonic-gate  * If printall is set, then the originator of the parameter object is printed.
34677c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
34687c478bd9Sstevel@tonic-gate  */
34697c478bd9Sstevel@tonic-gate static int
34707c478bd9Sstevel@tonic-gate printparams(
34717c478bd9Sstevel@tonic-gate FILE *fp,
34727c478bd9Sstevel@tonic-gate char *module,
34737c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params,
34747c478bd9Sstevel@tonic-gate int printall,
34757c478bd9Sstevel@tonic-gate int tab_inserts)
34767c478bd9Sstevel@tonic-gate {
34777c478bd9Sstevel@tonic-gate 
34787c478bd9Sstevel@tonic-gate 	int res;
34797c478bd9Sstevel@tonic-gate 
34807c478bd9Sstevel@tonic-gate 	/* print opening clause */
34817c478bd9Sstevel@tonic-gate 
34827c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
34837c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_PARAMS_STR " {\n");
34847c478bd9Sstevel@tonic-gate 
34857c478bd9Sstevel@tonic-gate 	/* print originator name if printall flag set */
34867c478bd9Sstevel@tonic-gate 
34877c478bd9Sstevel@tonic-gate 	if (printall) {
34887c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
34897c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "Originator %s\n",
34907c478bd9Sstevel@tonic-gate 		    quote_ws_string(get_originator_nm(params->originator)));
34917c478bd9Sstevel@tonic-gate 	}
34927c478bd9Sstevel@tonic-gate 
34937c478bd9Sstevel@tonic-gate 	/* print global stats */
34947c478bd9Sstevel@tonic-gate 
34957c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
34967c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_GLOBAL_STATS_STR " %s\n",
34977c478bd9Sstevel@tonic-gate 	    params->stats_enable == B_TRUE ? "true" : "false");
34987c478bd9Sstevel@tonic-gate 
34997c478bd9Sstevel@tonic-gate 	/* print module specific parameters */
35007c478bd9Sstevel@tonic-gate 	res = printnvlist(fp, module, params->nvlist, printall, NULL,
35017c478bd9Sstevel@tonic-gate 	    tab_inserts + 1, PL_PARAMS);
35027c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
35037c478bd9Sstevel@tonic-gate 		return (res);
35047c478bd9Sstevel@tonic-gate 	}
35057c478bd9Sstevel@tonic-gate 
35067c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
35077c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "}\n");
35087c478bd9Sstevel@tonic-gate 
35097c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
35107c478bd9Sstevel@tonic-gate }
35117c478bd9Sstevel@tonic-gate 
35127c478bd9Sstevel@tonic-gate /*
35137c478bd9Sstevel@tonic-gate  * print the interpreted name of the action_nm parameter if it is a special
35147c478bd9Sstevel@tonic-gate  * action, else action_nm verbatim to fp parameter.
35157c478bd9Sstevel@tonic-gate  */
35167c478bd9Sstevel@tonic-gate static void
35177c478bd9Sstevel@tonic-gate print_action_nm(FILE *fp, char *action_nm)
35187c478bd9Sstevel@tonic-gate {
35197c478bd9Sstevel@tonic-gate 
35207c478bd9Sstevel@tonic-gate 	if (strcmp(action_nm, IPP_ANAME_CONT) == 0) {
35217c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, IPQOS_CONF_CONT_STR "\n");
35227c478bd9Sstevel@tonic-gate 	} else if (strcmp(action_nm, IPP_ANAME_DEFER) == 0) {
35237c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, IPQOS_CONF_DEFER_STR "\n");
35247c478bd9Sstevel@tonic-gate 	} else if (strcmp(action_nm, IPP_ANAME_DROP) == 0) {
35257c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, IPQOS_CONF_DROP_STR "\n");
35267c478bd9Sstevel@tonic-gate 	} else {
35277c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s\n", quote_ws_string(action_nm));
35287c478bd9Sstevel@tonic-gate 	}
35297c478bd9Sstevel@tonic-gate }
35307c478bd9Sstevel@tonic-gate 
35317c478bd9Sstevel@tonic-gate /*
35327c478bd9Sstevel@tonic-gate  * print a class clause for class to fp. If printall is set the originator
35337c478bd9Sstevel@tonic-gate  * is printed.
35347c478bd9Sstevel@tonic-gate  */
35357c478bd9Sstevel@tonic-gate static void
35367c478bd9Sstevel@tonic-gate printclass(
35377c478bd9Sstevel@tonic-gate FILE *fp,
35387c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class,
35397c478bd9Sstevel@tonic-gate int printall,
35407c478bd9Sstevel@tonic-gate int tab_inserts)
35417c478bd9Sstevel@tonic-gate {
35427c478bd9Sstevel@tonic-gate 
35437c478bd9Sstevel@tonic-gate 	/* print opening clause */
35447c478bd9Sstevel@tonic-gate 
35457c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
35467c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_CLASS_STR " {\n");
35477c478bd9Sstevel@tonic-gate 
35487c478bd9Sstevel@tonic-gate 
35497c478bd9Sstevel@tonic-gate 	/* if printall flag print originator name */
35507c478bd9Sstevel@tonic-gate 
35517c478bd9Sstevel@tonic-gate 	if (printall) {
35527c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
35537c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "Originator %s\n",
35547c478bd9Sstevel@tonic-gate 		    get_originator_nm(class->originator));
35557c478bd9Sstevel@tonic-gate 	}
35567c478bd9Sstevel@tonic-gate 
35577c478bd9Sstevel@tonic-gate 	/* print name, next action and stats enable */
35587c478bd9Sstevel@tonic-gate 
35597c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
35607c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_NAME_STR " %s\n",
35617c478bd9Sstevel@tonic-gate 	    quote_ws_string(class->name));
35627c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
35637c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_NEXT_ACTION_STR " ");
35647c478bd9Sstevel@tonic-gate 	    print_action_nm(fp, class->alist->name);
35657c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
35667c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_STATS_ENABLE_STR " %s\n",
35677c478bd9Sstevel@tonic-gate 	    class->stats_enable == B_TRUE ? "true" : "false");
35687c478bd9Sstevel@tonic-gate 
35697c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
35707c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "}\n");
35717c478bd9Sstevel@tonic-gate }
35727c478bd9Sstevel@tonic-gate 
35737c478bd9Sstevel@tonic-gate /*
35747c478bd9Sstevel@tonic-gate  * Returns a ptr to the originator name associated with origid. If unknown
35757c478bd9Sstevel@tonic-gate  * id returns ptr to "unknown".
35767c478bd9Sstevel@tonic-gate  * RETURNS: ptr to originator name, or if id not known "unknown".
35777c478bd9Sstevel@tonic-gate  */
35787c478bd9Sstevel@tonic-gate static char *
35797c478bd9Sstevel@tonic-gate get_originator_nm(uint32_t origid)
35807c478bd9Sstevel@tonic-gate {
35817c478bd9Sstevel@tonic-gate 
35827c478bd9Sstevel@tonic-gate 	int x;
35837c478bd9Sstevel@tonic-gate 
35847c478bd9Sstevel@tonic-gate 	/* scan originators table for origid */
35857c478bd9Sstevel@tonic-gate 
35867c478bd9Sstevel@tonic-gate 	for (x = 0; originators[x].value != -1 &&
35877c478bd9Sstevel@tonic-gate 	    originators[x].value != origid; x++) {}
35887c478bd9Sstevel@tonic-gate 
35897c478bd9Sstevel@tonic-gate 	/* if we've reached end of array due to unknown type return "unknown" */
35907c478bd9Sstevel@tonic-gate 
35917c478bd9Sstevel@tonic-gate 	if (originators[x].value == -1) {
35927c478bd9Sstevel@tonic-gate 		return ("unknown");
35937c478bd9Sstevel@tonic-gate 	}
35947c478bd9Sstevel@tonic-gate 
35957c478bd9Sstevel@tonic-gate 	return (originators[x].string);
35967c478bd9Sstevel@tonic-gate }
35977c478bd9Sstevel@tonic-gate 
35987c478bd9Sstevel@tonic-gate /*
35997c478bd9Sstevel@tonic-gate  * print a filter clause for filter pointed to by filter out to fp. If printall
36007c478bd9Sstevel@tonic-gate  * is set then the originator is printed, for filters with node names instance
36017c478bd9Sstevel@tonic-gate  * numbers are printed, and the filter pointer isn't advanced to point at the
36027c478bd9Sstevel@tonic-gate  * last instance of the printed filter.
36037c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
36047c478bd9Sstevel@tonic-gate  */
36057c478bd9Sstevel@tonic-gate static int
36067c478bd9Sstevel@tonic-gate printfilter(
36077c478bd9Sstevel@tonic-gate FILE *fp,
36087c478bd9Sstevel@tonic-gate char *module,
36097c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **filter,
36107c478bd9Sstevel@tonic-gate int printall,
36117c478bd9Sstevel@tonic-gate int tab_inserts)
36127c478bd9Sstevel@tonic-gate {
36137c478bd9Sstevel@tonic-gate 
36147c478bd9Sstevel@tonic-gate 	int res;
36157c478bd9Sstevel@tonic-gate 
36167c478bd9Sstevel@tonic-gate 	/* print opening clause */
36177c478bd9Sstevel@tonic-gate 
36187c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
36197c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_FILTER_STR " {\n");
36207c478bd9Sstevel@tonic-gate 
36217c478bd9Sstevel@tonic-gate 	/* print originator if printall flag set */
36227c478bd9Sstevel@tonic-gate 
36237c478bd9Sstevel@tonic-gate 	if (printall) {
36247c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
36257c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "Originator %s\n",
36267c478bd9Sstevel@tonic-gate 		    quote_ws_string(get_originator_nm((*filter)->originator)));
36277c478bd9Sstevel@tonic-gate 	}
36287c478bd9Sstevel@tonic-gate 
36297c478bd9Sstevel@tonic-gate 	/* print name and class */
36307c478bd9Sstevel@tonic-gate 
36317c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
36327c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_NAME_STR " %s\n",
36337c478bd9Sstevel@tonic-gate 	    quote_ws_string((*filter)->name));
36347c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
36357c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_CLASS_STR " %s\n",
36367c478bd9Sstevel@tonic-gate 	    quote_ws_string((*filter)->class_name));
36377c478bd9Sstevel@tonic-gate 
36387c478bd9Sstevel@tonic-gate 	/* print the instance if printall and potential mhomed addresses */
36397c478bd9Sstevel@tonic-gate 
36407c478bd9Sstevel@tonic-gate 	if (printall && ((*filter)->src_nd_name || (*filter)->dst_nd_name)) {
36417c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
36427c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "Instance %u\n", (*filter)->instance);
36437c478bd9Sstevel@tonic-gate 	}
36447c478bd9Sstevel@tonic-gate 
36457c478bd9Sstevel@tonic-gate 	/* print node names if any */
36467c478bd9Sstevel@tonic-gate 
36477c478bd9Sstevel@tonic-gate 	if ((*filter)->src_nd_name) {
36487c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
36497c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s %s\n", strchr(IPGPC_SADDR, '.') + 1,
36507c478bd9Sstevel@tonic-gate 		    (*filter)->src_nd_name);
36517c478bd9Sstevel@tonic-gate 	}
36527c478bd9Sstevel@tonic-gate 	if ((*filter)->dst_nd_name) {
36537c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
36547c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s %s\n", strchr(IPGPC_DADDR, '.') + 1,
36557c478bd9Sstevel@tonic-gate 		    (*filter)->dst_nd_name);
36567c478bd9Sstevel@tonic-gate 	}
36577c478bd9Sstevel@tonic-gate 
36587c478bd9Sstevel@tonic-gate 	/* print ip_version enumeration if set */
36597c478bd9Sstevel@tonic-gate 
36607c478bd9Sstevel@tonic-gate 	if ((*filter)->ip_versions != 0) {
36617c478bd9Sstevel@tonic-gate 		PRINT_TABS(fp, tab_inserts + 1);
36627c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, IPQOS_CONF_IP_VERSION_STR " {");
36637c478bd9Sstevel@tonic-gate 		if (VERSION_IS_V4(*filter)) {
36647c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, " V4");
36657c478bd9Sstevel@tonic-gate 		}
36667c478bd9Sstevel@tonic-gate 		if (VERSION_IS_V6(*filter)) {
36677c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, " V6");
36687c478bd9Sstevel@tonic-gate 		}
36697c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, " }\n");
36707c478bd9Sstevel@tonic-gate 	}
36717c478bd9Sstevel@tonic-gate 
36727c478bd9Sstevel@tonic-gate 	/* print other module specific parameters parameters */
36737c478bd9Sstevel@tonic-gate 
36747c478bd9Sstevel@tonic-gate 	res = printnvlist(fp, module, (*filter)->nvlist, printall, *filter,
36757c478bd9Sstevel@tonic-gate 	    tab_inserts + 1, PL_FILTER);
36767c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
36777c478bd9Sstevel@tonic-gate 		return (res);
36787c478bd9Sstevel@tonic-gate 	}
36797c478bd9Sstevel@tonic-gate 
36807c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
36817c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "}\n");
36827c478bd9Sstevel@tonic-gate 
36837c478bd9Sstevel@tonic-gate 	/*
36847c478bd9Sstevel@tonic-gate 	 * if not printall advance filter parameter to last instance of this
36857c478bd9Sstevel@tonic-gate 	 * filter.
36867c478bd9Sstevel@tonic-gate 	 */
36877c478bd9Sstevel@tonic-gate 
36887c478bd9Sstevel@tonic-gate 	if (!printall) {
36897c478bd9Sstevel@tonic-gate 		for (;;) {
36907c478bd9Sstevel@tonic-gate 			if ((*filter)->next == NULL ||
36917c478bd9Sstevel@tonic-gate 			    strcmp((*filter)->name, (*filter)->next->name) !=
36927c478bd9Sstevel@tonic-gate 			    0) {
36937c478bd9Sstevel@tonic-gate 				break;
36947c478bd9Sstevel@tonic-gate 			}
36957c478bd9Sstevel@tonic-gate 			*filter = (*filter)->next;
36967c478bd9Sstevel@tonic-gate 		}
36977c478bd9Sstevel@tonic-gate 	}
36987c478bd9Sstevel@tonic-gate 
36997c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
37007c478bd9Sstevel@tonic-gate }
37017c478bd9Sstevel@tonic-gate 
37027c478bd9Sstevel@tonic-gate /*
37037c478bd9Sstevel@tonic-gate  * Returns a pointer to str if no whitespace is present, else it returns
37047c478bd9Sstevel@tonic-gate  * a pointer to a string with the contents of str enclose in double quotes.
37057c478bd9Sstevel@tonic-gate  * This returned strings contents may change in subsequent calls so a copy
37067c478bd9Sstevel@tonic-gate  * should be made of it if the caller wishes to retain it.
37077c478bd9Sstevel@tonic-gate  */
37087c478bd9Sstevel@tonic-gate static char *
37097c478bd9Sstevel@tonic-gate quote_ws_string(const char *str)
37107c478bd9Sstevel@tonic-gate {
37117c478bd9Sstevel@tonic-gate 	static char *buf = NULL;
37127c478bd9Sstevel@tonic-gate 	const char *cp;	/* we don't modify the contents of str so const */
37137c478bd9Sstevel@tonic-gate 
37147c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In quote_ws_string\n");
37157c478bd9Sstevel@tonic-gate 
37167c478bd9Sstevel@tonic-gate 	/*
37177c478bd9Sstevel@tonic-gate 	 * Just return str if no whitespace.
37187c478bd9Sstevel@tonic-gate 	 */
37197c478bd9Sstevel@tonic-gate 	for (cp = str; (*cp != '\0') && !isspace(*cp); cp++)
37207c478bd9Sstevel@tonic-gate 		;
37217c478bd9Sstevel@tonic-gate 	if (*cp == '\0')
37227c478bd9Sstevel@tonic-gate 		return ((char *)str);
37237c478bd9Sstevel@tonic-gate 
37247c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
37257c478bd9Sstevel@tonic-gate 		/*
37267c478bd9Sstevel@tonic-gate 		 * if first run just allocate buffer of
37277c478bd9Sstevel@tonic-gate 		 * strlen(str) + 2 quote characters + NULL terminator.
37287c478bd9Sstevel@tonic-gate 		 */
37297c478bd9Sstevel@tonic-gate 		buf = malloc(strlen(str) + 3);
37307c478bd9Sstevel@tonic-gate 	} else if ((strlen(str) + 2) > strlen(buf)) {
37317c478bd9Sstevel@tonic-gate 		/*
37327c478bd9Sstevel@tonic-gate 		 * Not first run, so check if we have a big enough buffer
37337c478bd9Sstevel@tonic-gate 		 * and if not reallocate the buffer to a sufficient size.
37347c478bd9Sstevel@tonic-gate 		 */
37357c478bd9Sstevel@tonic-gate 		buf = realloc(buf, strlen(str) + 3);
37367c478bd9Sstevel@tonic-gate 	}
37377c478bd9Sstevel@tonic-gate 	if (buf == NULL)
37387c478bd9Sstevel@tonic-gate 		return ("");
37397c478bd9Sstevel@tonic-gate 
37407c478bd9Sstevel@tonic-gate 	/*
37417c478bd9Sstevel@tonic-gate 	 * copy string into buffer with quotes.
37427c478bd9Sstevel@tonic-gate 	 */
37437c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, "\"");
37447c478bd9Sstevel@tonic-gate 	(void) strcat(buf, str);
37457c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "\"");
37467c478bd9Sstevel@tonic-gate 
37477c478bd9Sstevel@tonic-gate 	return (buf);
37487c478bd9Sstevel@tonic-gate }
37497c478bd9Sstevel@tonic-gate 
37507c478bd9Sstevel@tonic-gate /*
37517c478bd9Sstevel@tonic-gate  * print an action clause for action to fp. If the printall flag is set
37527c478bd9Sstevel@tonic-gate  * then all filters and classes (regardless of their originator) and
37537c478bd9Sstevel@tonic-gate  * their originators are displayed.
37547c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
37557c478bd9Sstevel@tonic-gate  */
37567c478bd9Sstevel@tonic-gate static int
37577c478bd9Sstevel@tonic-gate printaction(
37587c478bd9Sstevel@tonic-gate FILE *fp,
37597c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action,
37607c478bd9Sstevel@tonic-gate int printall,
37617c478bd9Sstevel@tonic-gate int tab_inserts)
37627c478bd9Sstevel@tonic-gate {
37637c478bd9Sstevel@tonic-gate 
37647c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
37657c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
37667c478bd9Sstevel@tonic-gate 	int res;
37677c478bd9Sstevel@tonic-gate 
37687c478bd9Sstevel@tonic-gate 	/* print opening clause, module and name */
37697c478bd9Sstevel@tonic-gate 
37707c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
37717c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_ACTION_STR " {\n");
37727c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
37737c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, IPQOS_CONF_MODULE_STR " %s\n",
37747c478bd9Sstevel@tonic-gate 	    quote_ws_string(action->module));
37757c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts + 1);
37767c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "name %s\n", quote_ws_string(action->name));
37777c478bd9Sstevel@tonic-gate 
37787c478bd9Sstevel@tonic-gate 	/* print params clause */
37797c478bd9Sstevel@tonic-gate 
37807c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "\n");
37817c478bd9Sstevel@tonic-gate 	res = printparams(fp, action->module, action->params, printall,
37827c478bd9Sstevel@tonic-gate 	    tab_inserts + 1);
37837c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
37847c478bd9Sstevel@tonic-gate 		return (res);
37857c478bd9Sstevel@tonic-gate 	}
37867c478bd9Sstevel@tonic-gate 
37877c478bd9Sstevel@tonic-gate 	/*
37887c478bd9Sstevel@tonic-gate 	 * print classes clause for each class if printall is set, else
37897c478bd9Sstevel@tonic-gate 	 * just ipqosconf created or permanent classes.
37907c478bd9Sstevel@tonic-gate 	 */
37917c478bd9Sstevel@tonic-gate 	for (cls = action->classes; cls != NULL; cls = cls->next) {
37927c478bd9Sstevel@tonic-gate 		if (printall ||
37937c478bd9Sstevel@tonic-gate 		    cls->originator == IPP_CONFIG_IPQOSCONF ||
37947c478bd9Sstevel@tonic-gate 		    cls->originator == IPP_CONFIG_PERMANENT) {
37957c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
37967c478bd9Sstevel@tonic-gate 			printclass(fp, cls, printall, tab_inserts + 1);
37977c478bd9Sstevel@tonic-gate 		}
37987c478bd9Sstevel@tonic-gate 	}
37997c478bd9Sstevel@tonic-gate 
38007c478bd9Sstevel@tonic-gate 	/*
38017c478bd9Sstevel@tonic-gate 	 * print filter clause for each filter if printall is set, else
38027c478bd9Sstevel@tonic-gate 	 * just ipqosconf created or permanent filters.
38037c478bd9Sstevel@tonic-gate 	 */
38047c478bd9Sstevel@tonic-gate 	for (flt = action->filters; flt != NULL; flt = flt->next) {
38057c478bd9Sstevel@tonic-gate 		if (printall ||
38067c478bd9Sstevel@tonic-gate 		    flt->originator == IPP_CONFIG_IPQOSCONF ||
38077c478bd9Sstevel@tonic-gate 		    flt->originator == IPP_CONFIG_PERMANENT) {
38087c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
38097c478bd9Sstevel@tonic-gate 			res = printfilter(fp, action->module, &flt, printall,
38107c478bd9Sstevel@tonic-gate 			    tab_inserts + 1);
38117c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
38127c478bd9Sstevel@tonic-gate 				return (res);
38137c478bd9Sstevel@tonic-gate 			}
38147c478bd9Sstevel@tonic-gate 		}
38157c478bd9Sstevel@tonic-gate 	}
38167c478bd9Sstevel@tonic-gate 
38177c478bd9Sstevel@tonic-gate 	PRINT_TABS(fp, tab_inserts);
38187c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "}\n");
38197c478bd9Sstevel@tonic-gate 
38207c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
38217c478bd9Sstevel@tonic-gate }
38227c478bd9Sstevel@tonic-gate 
38237c478bd9Sstevel@tonic-gate 
38247c478bd9Sstevel@tonic-gate 
38257c478bd9Sstevel@tonic-gate /* *************************************************************** */
38267c478bd9Sstevel@tonic-gate 
38277c478bd9Sstevel@tonic-gate 
38287c478bd9Sstevel@tonic-gate static void
38297c478bd9Sstevel@tonic-gate list_end(
38307c478bd9Sstevel@tonic-gate ipqos_list_el_t **listp,
38317c478bd9Sstevel@tonic-gate ipqos_list_el_t ***lendpp)
38327c478bd9Sstevel@tonic-gate {
38337c478bd9Sstevel@tonic-gate 	*lendpp = listp;
38347c478bd9Sstevel@tonic-gate 	while (**lendpp != NULL) {
38357c478bd9Sstevel@tonic-gate 		*lendpp = &(**lendpp)->next;
38367c478bd9Sstevel@tonic-gate 	}
38377c478bd9Sstevel@tonic-gate }
38387c478bd9Sstevel@tonic-gate 
38397c478bd9Sstevel@tonic-gate static void
38407c478bd9Sstevel@tonic-gate add_to_list(
38417c478bd9Sstevel@tonic-gate ipqos_list_el_t **listp,
38427c478bd9Sstevel@tonic-gate ipqos_list_el_t *el)
38437c478bd9Sstevel@tonic-gate {
38447c478bd9Sstevel@tonic-gate 	el->next = *listp;
38457c478bd9Sstevel@tonic-gate 	*listp = el;
38467c478bd9Sstevel@tonic-gate }
38477c478bd9Sstevel@tonic-gate 
38487c478bd9Sstevel@tonic-gate /*
38497c478bd9Sstevel@tonic-gate  * given mask calculates the number of bits it spans. The mask must be
38507c478bd9Sstevel@tonic-gate  * continuous.
38517c478bd9Sstevel@tonic-gate  * RETURNS: number of bits spanned.
38527c478bd9Sstevel@tonic-gate  */
38537c478bd9Sstevel@tonic-gate static int
38547c478bd9Sstevel@tonic-gate masktocidr(
38557c478bd9Sstevel@tonic-gate int af,
38567c478bd9Sstevel@tonic-gate in6_addr_t *mask)
38577c478bd9Sstevel@tonic-gate {
38587c478bd9Sstevel@tonic-gate 	int zeros = 0;
38597c478bd9Sstevel@tonic-gate 	int byte;
38607c478bd9Sstevel@tonic-gate 	int cidr;
38617c478bd9Sstevel@tonic-gate 
38627c478bd9Sstevel@tonic-gate 	/*
38637c478bd9Sstevel@tonic-gate 	 * loop through from lowest byte to highest byte counting the
38647c478bd9Sstevel@tonic-gate 	 * number of zero bits till hitting a one bit.
38657c478bd9Sstevel@tonic-gate 	 */
38667c478bd9Sstevel@tonic-gate 	for (byte = 15; byte >= 0; byte--) {
38677c478bd9Sstevel@tonic-gate 		/*
38687c478bd9Sstevel@tonic-gate 		 * zero byte, so add 8 to zeros.
38697c478bd9Sstevel@tonic-gate 		 */
38707c478bd9Sstevel@tonic-gate 		if (mask->s6_addr[byte] == 0) {
38717c478bd9Sstevel@tonic-gate 			zeros += 8;
38727c478bd9Sstevel@tonic-gate 		/*
38737c478bd9Sstevel@tonic-gate 		 * non-zero byte, add zero count to zeros.
38747c478bd9Sstevel@tonic-gate 		 */
38757c478bd9Sstevel@tonic-gate 		} else {
38767c478bd9Sstevel@tonic-gate 			zeros += (ffs((int)mask->s6_addr[byte]) - 1);
38777c478bd9Sstevel@tonic-gate 			break;
38787c478bd9Sstevel@tonic-gate 		}
38797c478bd9Sstevel@tonic-gate 	}
38807c478bd9Sstevel@tonic-gate 	/*
38817c478bd9Sstevel@tonic-gate 	 * translate zero bits to 32 or 128 bit mask based on af.
38827c478bd9Sstevel@tonic-gate 	 */
38837c478bd9Sstevel@tonic-gate 	if (af == AF_INET) {
38847c478bd9Sstevel@tonic-gate 		cidr = 32 - zeros;
38857c478bd9Sstevel@tonic-gate 	} else {
38867c478bd9Sstevel@tonic-gate 		cidr = 128 - zeros;
38877c478bd9Sstevel@tonic-gate 	}
38887c478bd9Sstevel@tonic-gate 
38897c478bd9Sstevel@tonic-gate 	return (cidr);
38907c478bd9Sstevel@tonic-gate }
38917c478bd9Sstevel@tonic-gate 
38927c478bd9Sstevel@tonic-gate /*
38937c478bd9Sstevel@tonic-gate  * Sets the first prefix_len bits in the v4 or v6 address (based upon af)
38947c478bd9Sstevel@tonic-gate  * contained in the v6 address referenced by addr to 1.
38957c478bd9Sstevel@tonic-gate  */
38967c478bd9Sstevel@tonic-gate static void
38977c478bd9Sstevel@tonic-gate setmask(int prefix_len, in6_addr_t *addr, int af)
38987c478bd9Sstevel@tonic-gate {
38997c478bd9Sstevel@tonic-gate 
39007c478bd9Sstevel@tonic-gate 	int i;
39017c478bd9Sstevel@tonic-gate 	int shift;
39027c478bd9Sstevel@tonic-gate 	int maskstartbit = 128 - prefix_len;
39037c478bd9Sstevel@tonic-gate 	int end_u32;
39047c478bd9Sstevel@tonic-gate 
39057c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "In setmask, prefix_len: %u, af: %s\n", prefix_len,
39067c478bd9Sstevel@tonic-gate 	    af == AF_INET ? "AF_INET" : "AF_INET6");
39077c478bd9Sstevel@tonic-gate 
39087c478bd9Sstevel@tonic-gate 	/* zero addr */
39097c478bd9Sstevel@tonic-gate 	bzero(addr, sizeof (in6_addr_t));
39107c478bd9Sstevel@tonic-gate 
39117c478bd9Sstevel@tonic-gate 
39127c478bd9Sstevel@tonic-gate 	/* set which 32bits in *addr are relevant to this af */
39137c478bd9Sstevel@tonic-gate 
39147c478bd9Sstevel@tonic-gate 	if (af == AF_INET) {
39157c478bd9Sstevel@tonic-gate 		end_u32 = 3;
39167c478bd9Sstevel@tonic-gate 		maskstartbit = 32 - prefix_len;
39177c478bd9Sstevel@tonic-gate 	/* AF_INET6 */
39187c478bd9Sstevel@tonic-gate 	} else {
39197c478bd9Sstevel@tonic-gate 		end_u32 = 0;
39207c478bd9Sstevel@tonic-gate 	}
39217c478bd9Sstevel@tonic-gate 	/*
39227c478bd9Sstevel@tonic-gate 	 * go through each of the 32bit quantities in 128 bit in6_addr_t
39237c478bd9Sstevel@tonic-gate 	 * and set appropriate bits according to prefix_len.
39247c478bd9Sstevel@tonic-gate 	 */
39257c478bd9Sstevel@tonic-gate 	for (i = 3; i >= end_u32; i--) {
39267c478bd9Sstevel@tonic-gate 
39277c478bd9Sstevel@tonic-gate 		/* does the prefix apply to this 32bits? */
39287c478bd9Sstevel@tonic-gate 
39297c478bd9Sstevel@tonic-gate 		if (maskstartbit < ((4 - i) * 32)) {
39307c478bd9Sstevel@tonic-gate 
39317c478bd9Sstevel@tonic-gate 			/* is this 32bits fully masked? */
39327c478bd9Sstevel@tonic-gate 
39337c478bd9Sstevel@tonic-gate 			if (maskstartbit <= ((3 - i) * 32)) {
39347c478bd9Sstevel@tonic-gate 				shift = 0;
39357c478bd9Sstevel@tonic-gate 			} else {
39367c478bd9Sstevel@tonic-gate 				shift = maskstartbit % 32;
39377c478bd9Sstevel@tonic-gate 			}
39387c478bd9Sstevel@tonic-gate 			addr->_S6_un._S6_u32[i] = (uint32_t)~0;
39397c478bd9Sstevel@tonic-gate 			addr->_S6_un._S6_u32[i] =
39407c478bd9Sstevel@tonic-gate 			    addr->_S6_un._S6_u32[i] >> shift;
39417c478bd9Sstevel@tonic-gate 			addr->_S6_un._S6_u32[i] =
39427c478bd9Sstevel@tonic-gate 			    addr->_S6_un._S6_u32[i] << shift;
39437c478bd9Sstevel@tonic-gate 		}
39447c478bd9Sstevel@tonic-gate 
39457c478bd9Sstevel@tonic-gate 		/* translate to NBO */
39467c478bd9Sstevel@tonic-gate 		addr->_S6_un._S6_u32[i] = htonl(addr->_S6_un._S6_u32[i]);
39477c478bd9Sstevel@tonic-gate 	}
39487c478bd9Sstevel@tonic-gate }
39497c478bd9Sstevel@tonic-gate 
39507c478bd9Sstevel@tonic-gate /*
39517c478bd9Sstevel@tonic-gate  * search nvlist for an element with the name specified and return a ptr
39527c478bd9Sstevel@tonic-gate  * to it if found.
39537c478bd9Sstevel@tonic-gate  * RETURNS: pointer to nvpair named name if found, else NULL.
39547c478bd9Sstevel@tonic-gate  */
39557c478bd9Sstevel@tonic-gate static nvpair_t *
39567c478bd9Sstevel@tonic-gate find_nvpair(nvlist_t *nvl, char *name)
39577c478bd9Sstevel@tonic-gate {
39587c478bd9Sstevel@tonic-gate 
39597c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
39607c478bd9Sstevel@tonic-gate 	nvpair_t *match = NULL;
39617c478bd9Sstevel@tonic-gate 	char *nvp_name;
39627c478bd9Sstevel@tonic-gate 
39637c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In find_nvpair\n");
39647c478bd9Sstevel@tonic-gate 
39657c478bd9Sstevel@tonic-gate 	nvp = nvlist_next_nvpair(nvl, NULL);
39667c478bd9Sstevel@tonic-gate 	while (nvp) {
39677c478bd9Sstevel@tonic-gate 		nvp_name = nvpair_name(nvp);
39687c478bd9Sstevel@tonic-gate 		if (strcmp(name, nvp_name) == 0) {
39697c478bd9Sstevel@tonic-gate 			match = nvp;
39707c478bd9Sstevel@tonic-gate 		}
39717c478bd9Sstevel@tonic-gate 		nvp = nvlist_next_nvpair(nvl, nvp);
39727c478bd9Sstevel@tonic-gate 	}
39737c478bd9Sstevel@tonic-gate 
39747c478bd9Sstevel@tonic-gate 	return (match);
39757c478bd9Sstevel@tonic-gate }
39767c478bd9Sstevel@tonic-gate 
39777c478bd9Sstevel@tonic-gate /*
39787c478bd9Sstevel@tonic-gate  * returns a string containing module_name '.' name.
39797c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS.
39807c478bd9Sstevel@tonic-gate  */
39817c478bd9Sstevel@tonic-gate static char *
39827c478bd9Sstevel@tonic-gate prepend_module_name(
39837c478bd9Sstevel@tonic-gate char *name,
39847c478bd9Sstevel@tonic-gate char *module)
39857c478bd9Sstevel@tonic-gate {
39867c478bd9Sstevel@tonic-gate 
39877c478bd9Sstevel@tonic-gate 	char *ret;
39887c478bd9Sstevel@tonic-gate 
39897c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L2, "In prepend_module_name\n");
39907c478bd9Sstevel@tonic-gate 
39917c478bd9Sstevel@tonic-gate 	ret = malloc(strlen(module) + strlen(".") + strlen(name) + 1);
39927c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
39937c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
39947c478bd9Sstevel@tonic-gate 		return (NULL);
39957c478bd9Sstevel@tonic-gate 	}
39967c478bd9Sstevel@tonic-gate 
39977c478bd9Sstevel@tonic-gate 	(void) strcpy(ret, module);
39987c478bd9Sstevel@tonic-gate 	(void) strcat(ret, ".");
39997c478bd9Sstevel@tonic-gate 	(void) strcat(ret, name);
40007c478bd9Sstevel@tonic-gate 
40017c478bd9Sstevel@tonic-gate 	return (ret);
40027c478bd9Sstevel@tonic-gate }
40037c478bd9Sstevel@tonic-gate 
40047c478bd9Sstevel@tonic-gate #if 0
40057c478bd9Sstevel@tonic-gate 
40067c478bd9Sstevel@tonic-gate /*
40077c478bd9Sstevel@tonic-gate  * check if element with matching s1 and s2 string is in table table.
40087c478bd9Sstevel@tonic-gate  * RETURNS: 1 if found else 0.
40097c478bd9Sstevel@tonic-gate  */
40107c478bd9Sstevel@tonic-gate static int
40117c478bd9Sstevel@tonic-gate in_str_str_table(
40127c478bd9Sstevel@tonic-gate str_str_t *table,
40137c478bd9Sstevel@tonic-gate char *s1,
40147c478bd9Sstevel@tonic-gate char *s2)
40157c478bd9Sstevel@tonic-gate {
40167c478bd9Sstevel@tonic-gate 
40177c478bd9Sstevel@tonic-gate 	str_str_t *ss = table;
40187c478bd9Sstevel@tonic-gate 
40197c478bd9Sstevel@tonic-gate 	/* loop through table till matched or end */
40207c478bd9Sstevel@tonic-gate 
40217c478bd9Sstevel@tonic-gate 	while (ss->s1[0] != '\0' &&
40227c478bd9Sstevel@tonic-gate 	    (strcmp(ss->s1, s1) != 0 || strcmp(ss->s2, s2) != 0)) {
40237c478bd9Sstevel@tonic-gate 		ss++;
40247c478bd9Sstevel@tonic-gate 	}
40257c478bd9Sstevel@tonic-gate 
40267c478bd9Sstevel@tonic-gate 	if (ss->s1[0] != '\0') {
40277c478bd9Sstevel@tonic-gate 		return (1);
40287c478bd9Sstevel@tonic-gate 	}
40297c478bd9Sstevel@tonic-gate 
40307c478bd9Sstevel@tonic-gate 	return (0);
40317c478bd9Sstevel@tonic-gate }
40327c478bd9Sstevel@tonic-gate #endif	/* 0 */
40337c478bd9Sstevel@tonic-gate 
40347c478bd9Sstevel@tonic-gate /*
40357c478bd9Sstevel@tonic-gate  * check whether name is a valid action/class/filter name.
40367c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if invalid name else IPQOS_CONF_SUCCESS.
40377c478bd9Sstevel@tonic-gate  */
40387c478bd9Sstevel@tonic-gate static int
40397c478bd9Sstevel@tonic-gate valid_name(char *name)
40407c478bd9Sstevel@tonic-gate {
40417c478bd9Sstevel@tonic-gate 
40427c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In valid_name: name: %s\n", name);
40437c478bd9Sstevel@tonic-gate 
40447c478bd9Sstevel@tonic-gate 	/* first char can't be '!' */
40457c478bd9Sstevel@tonic-gate 	if (name[0] == '!') {
40467c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Name not allowed to start with "
40477c478bd9Sstevel@tonic-gate 		    "'!', line %u.\n"), lineno);
40487c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
40497c478bd9Sstevel@tonic-gate 	}
40507c478bd9Sstevel@tonic-gate 
40517c478bd9Sstevel@tonic-gate 	/* can't exceed IPQOS_CONF_NAME_LEN size */
40527c478bd9Sstevel@tonic-gate 	if (strlen(name) >= IPQOS_CONF_NAME_LEN) {
40537c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Name exceeds maximum name length "
40547c478bd9Sstevel@tonic-gate 		    "line %u.\n"), lineno);
40557c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
40567c478bd9Sstevel@tonic-gate 	}
40577c478bd9Sstevel@tonic-gate 
40587c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
40597c478bd9Sstevel@tonic-gate }
40607c478bd9Sstevel@tonic-gate 
40617c478bd9Sstevel@tonic-gate /* ********************* string value manip fns ************************** */
40627c478bd9Sstevel@tonic-gate 
40637c478bd9Sstevel@tonic-gate 
40647c478bd9Sstevel@tonic-gate /*
40657c478bd9Sstevel@tonic-gate  * searches through the str_val_nd_t list of string value pairs finding
40667c478bd9Sstevel@tonic-gate  * the minimum and maximum values for value and places them in the
40677c478bd9Sstevel@tonic-gate  * integers pointed at by min and max.
40687c478bd9Sstevel@tonic-gate  */
40697c478bd9Sstevel@tonic-gate static void
40707c478bd9Sstevel@tonic-gate get_str_val_value_range(
40717c478bd9Sstevel@tonic-gate str_val_nd_t *svnp,
40727c478bd9Sstevel@tonic-gate int *min,
40737c478bd9Sstevel@tonic-gate int *max)
40747c478bd9Sstevel@tonic-gate {
40757c478bd9Sstevel@tonic-gate 	if (svnp != NULL) {
40767c478bd9Sstevel@tonic-gate 		*min = *max = svnp->sv.value;
40777c478bd9Sstevel@tonic-gate 		svnp = svnp->next;
40787c478bd9Sstevel@tonic-gate 	}
40797c478bd9Sstevel@tonic-gate 	while (svnp != NULL) {
40807c478bd9Sstevel@tonic-gate 		if (svnp->sv.value > *max)
40817c478bd9Sstevel@tonic-gate 			*max = svnp->sv.value;
40827c478bd9Sstevel@tonic-gate 		if (svnp->sv.value < *min)
40837c478bd9Sstevel@tonic-gate 			*min = svnp->sv.value;
40847c478bd9Sstevel@tonic-gate 		svnp = svnp->next;
40857c478bd9Sstevel@tonic-gate 	}
40867c478bd9Sstevel@tonic-gate }
40877c478bd9Sstevel@tonic-gate 
40887c478bd9Sstevel@tonic-gate /*
40897c478bd9Sstevel@tonic-gate  * add an entry with string string and value val to sv_entrys.
40907c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
40917c478bd9Sstevel@tonic-gate  */
40927c478bd9Sstevel@tonic-gate static int
40937c478bd9Sstevel@tonic-gate add_str_val_entry(
40947c478bd9Sstevel@tonic-gate str_val_nd_t **sv_entrys,
40957c478bd9Sstevel@tonic-gate char *string,
40967c478bd9Sstevel@tonic-gate uint32_t val)
40977c478bd9Sstevel@tonic-gate {
40987c478bd9Sstevel@tonic-gate 
40997c478bd9Sstevel@tonic-gate 	str_val_nd_t *sv_entry;
41007c478bd9Sstevel@tonic-gate 
41017c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "In add_str_val_entry: string: %s, val: %u\n", string,
41027c478bd9Sstevel@tonic-gate 	    val);
41037c478bd9Sstevel@tonic-gate 
41047c478bd9Sstevel@tonic-gate 	/* alloc new node */
41057c478bd9Sstevel@tonic-gate 
41067c478bd9Sstevel@tonic-gate 	sv_entry = malloc(sizeof (str_val_nd_t));
41077c478bd9Sstevel@tonic-gate 	if (sv_entry == NULL) {
41087c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
41097c478bd9Sstevel@tonic-gate 	}
41107c478bd9Sstevel@tonic-gate 
41117c478bd9Sstevel@tonic-gate 	/* populate node */
41127c478bd9Sstevel@tonic-gate 
41137c478bd9Sstevel@tonic-gate 	sv_entry->sv.string = malloc(strlen(string) + 1);
41147c478bd9Sstevel@tonic-gate 	if (sv_entry->sv.string == NULL) {
41157c478bd9Sstevel@tonic-gate 		free(sv_entry);
41167c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
41177c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
41187c478bd9Sstevel@tonic-gate 	} else {
41197c478bd9Sstevel@tonic-gate 		(void) strcpy(sv_entry->sv.string, string);
41207c478bd9Sstevel@tonic-gate 	}
41217c478bd9Sstevel@tonic-gate 	sv_entry->sv.value = val;
41227c478bd9Sstevel@tonic-gate 
41237c478bd9Sstevel@tonic-gate 	/* place at start of sv_entrys list */
41247c478bd9Sstevel@tonic-gate 
41257c478bd9Sstevel@tonic-gate 	sv_entry->next = *sv_entrys;
41267c478bd9Sstevel@tonic-gate 	*sv_entrys = sv_entry;
41277c478bd9Sstevel@tonic-gate 
41287c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
41297c478bd9Sstevel@tonic-gate }
41307c478bd9Sstevel@tonic-gate 
41317c478bd9Sstevel@tonic-gate 
41327c478bd9Sstevel@tonic-gate /* frees all the elements of sv_entrys. */
41337c478bd9Sstevel@tonic-gate static void
41347c478bd9Sstevel@tonic-gate free_str_val_entrys(
41357c478bd9Sstevel@tonic-gate str_val_nd_t *sv_entrys)
41367c478bd9Sstevel@tonic-gate {
41377c478bd9Sstevel@tonic-gate 
41387c478bd9Sstevel@tonic-gate 	str_val_nd_t *sve = sv_entrys;
41397c478bd9Sstevel@tonic-gate 	str_val_nd_t *tmp;
41407c478bd9Sstevel@tonic-gate 
41417c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In free_str_val_entrys\n");
41427c478bd9Sstevel@tonic-gate 
41437c478bd9Sstevel@tonic-gate 	while (sve) {
41447c478bd9Sstevel@tonic-gate 		free(sve->sv.string);
41457c478bd9Sstevel@tonic-gate 		tmp = sve->next;
41467c478bd9Sstevel@tonic-gate 		free(sve);
41477c478bd9Sstevel@tonic-gate 		sve = tmp;
41487c478bd9Sstevel@tonic-gate 	}
41497c478bd9Sstevel@tonic-gate }
41507c478bd9Sstevel@tonic-gate 
41517c478bd9Sstevel@tonic-gate /*
41527c478bd9Sstevel@tonic-gate  * finds the value associated with string and assigns it to value ref'd by
41537c478bd9Sstevel@tonic-gate  * val.
41547c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if string not found, else IPQOS_CONF_SUCCESS.
41557c478bd9Sstevel@tonic-gate  */
41567c478bd9Sstevel@tonic-gate static int
41577c478bd9Sstevel@tonic-gate str_val_list_lookup(
41587c478bd9Sstevel@tonic-gate str_val_nd_t *svs,
41597c478bd9Sstevel@tonic-gate char *string,
41607c478bd9Sstevel@tonic-gate uint32_t *val)
41617c478bd9Sstevel@tonic-gate {
41627c478bd9Sstevel@tonic-gate 
41637c478bd9Sstevel@tonic-gate 	str_val_nd_t *sv = svs;
41647c478bd9Sstevel@tonic-gate 
41657c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In str_val_list_lookup: %s\n", string);
41667c478bd9Sstevel@tonic-gate 
41677c478bd9Sstevel@tonic-gate 	/* loop through list and exit when found or list end */
41687c478bd9Sstevel@tonic-gate 
41697c478bd9Sstevel@tonic-gate 	while (sv != NULL) {
41707c478bd9Sstevel@tonic-gate 		if (strcmp(sv->sv.string, string) == 0) {
41717c478bd9Sstevel@tonic-gate 			break;
41727c478bd9Sstevel@tonic-gate 		}
41737c478bd9Sstevel@tonic-gate 		sv = sv->next;
41747c478bd9Sstevel@tonic-gate 	}
41757c478bd9Sstevel@tonic-gate 
41767c478bd9Sstevel@tonic-gate 	/* ret error if not found */
41777c478bd9Sstevel@tonic-gate 
41787c478bd9Sstevel@tonic-gate 	if (sv == NULL) {
41797c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
41807c478bd9Sstevel@tonic-gate 	}
41817c478bd9Sstevel@tonic-gate 
41827c478bd9Sstevel@tonic-gate 	*val = sv->sv.value;
41837c478bd9Sstevel@tonic-gate 
41847c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "svll: Value returned is %u\n", *val);
41857c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
41867c478bd9Sstevel@tonic-gate }
41877c478bd9Sstevel@tonic-gate 
41887c478bd9Sstevel@tonic-gate 
41897c478bd9Sstevel@tonic-gate /* ************************ conf file read fns ***************************** */
41907c478bd9Sstevel@tonic-gate 
41917c478bd9Sstevel@tonic-gate /*
41927c478bd9Sstevel@tonic-gate  * Reads a uid or username from string 'str' and assigns either the uid
41937c478bd9Sstevel@tonic-gate  * or associated uid respectively to storage pointed at by 'uid'. The
41947c478bd9Sstevel@tonic-gate  * function determines whether to read a uid by checking whether the first
41957c478bd9Sstevel@tonic-gate  * character of 'str' is numeric, in which case it reads a uid; otherwise it
41967c478bd9Sstevel@tonic-gate  * assumes a username.
41977c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if a NULL string pointer is passed, the read uid
41987c478bd9Sstevel@tonic-gate  * doesn't have an entry on the system, or the read username doesn't have an
41997c478bd9Sstevel@tonic-gate  * entry on the system.
42007c478bd9Sstevel@tonic-gate  */
42017c478bd9Sstevel@tonic-gate static int
42027c478bd9Sstevel@tonic-gate readuser(
42037c478bd9Sstevel@tonic-gate char *str,
42047c478bd9Sstevel@tonic-gate uid_t *uid)
42057c478bd9Sstevel@tonic-gate {
42067c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
42077c478bd9Sstevel@tonic-gate 	char *lo;
42087c478bd9Sstevel@tonic-gate 
42097c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "In readuser, str: %s\n", str);
42107c478bd9Sstevel@tonic-gate 
42117c478bd9Sstevel@tonic-gate 	if (str == NULL)
42127c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
42137c478bd9Sstevel@tonic-gate 	/*
42147c478bd9Sstevel@tonic-gate 	 * Check if this appears to be a uid, and if so check that a
42157c478bd9Sstevel@tonic-gate 	 * corresponding user exists.
42167c478bd9Sstevel@tonic-gate 	 */
42177c478bd9Sstevel@tonic-gate 	if (isdigit((int)str[0])) {
42187c478bd9Sstevel@tonic-gate 		/*
42197c478bd9Sstevel@tonic-gate 		 * Read a 32bit integer and check in doing so that
42207c478bd9Sstevel@tonic-gate 		 * we have consumed the whole string.
42217c478bd9Sstevel@tonic-gate 		 */
42227c478bd9Sstevel@tonic-gate 		if (readint32(str, (int *)uid, &lo) != IPQOS_CONF_SUCCESS ||
42237c478bd9Sstevel@tonic-gate 		    *lo != '\0')
42247c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
42257c478bd9Sstevel@tonic-gate 		if (getpwuid(*uid) == NULL)
42267c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
42277c478bd9Sstevel@tonic-gate 
42287c478bd9Sstevel@tonic-gate 	} else {	/* This must be a username, so lookup the uid. */
42297c478bd9Sstevel@tonic-gate 		pwd = getpwnam(str);
42307c478bd9Sstevel@tonic-gate 		if (pwd == NULL) {
42317c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
42327c478bd9Sstevel@tonic-gate 		} else {
42337c478bd9Sstevel@tonic-gate 			*uid = pwd->pw_uid;
42347c478bd9Sstevel@tonic-gate 		}
42357c478bd9Sstevel@tonic-gate 	}
42367c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
42377c478bd9Sstevel@tonic-gate }
42387c478bd9Sstevel@tonic-gate 
42397c478bd9Sstevel@tonic-gate /*
42407c478bd9Sstevel@tonic-gate  * Reads a range from range_st, either of form 'a-b' or simply 'a'.
42417c478bd9Sstevel@tonic-gate  * In the former case lower and upper have their values set to a
42427c478bd9Sstevel@tonic-gate  * and b respectively; in the later lower and upper have both
42437c478bd9Sstevel@tonic-gate  * their values set to a.
42447c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if there's a parse error, else IPQOS_CONF_SUCCESS.
42457c478bd9Sstevel@tonic-gate  */
42467c478bd9Sstevel@tonic-gate static int
42477c478bd9Sstevel@tonic-gate readrange(
42487c478bd9Sstevel@tonic-gate char *range_st,
42497c478bd9Sstevel@tonic-gate int *lower,
42507c478bd9Sstevel@tonic-gate int *upper)
42517c478bd9Sstevel@tonic-gate {
42527c478bd9Sstevel@tonic-gate 	char *cp;
42537c478bd9Sstevel@tonic-gate 	char *end, *end2;
42547c478bd9Sstevel@tonic-gate 
42557c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "In readrange: string: %s\n", range_st);
42567c478bd9Sstevel@tonic-gate 
42577c478bd9Sstevel@tonic-gate 	/*
42587c478bd9Sstevel@tonic-gate 	 * get range boundarys.
42597c478bd9Sstevel@tonic-gate 	 */
42607c478bd9Sstevel@tonic-gate 	cp = strchr(range_st, '-');
42617c478bd9Sstevel@tonic-gate 
42627c478bd9Sstevel@tonic-gate 	if (cp != NULL) {	/* we have a range */
42637c478bd9Sstevel@tonic-gate 		*cp++ = '\0';
42647c478bd9Sstevel@tonic-gate 		*lower = (int)strtol(range_st, &end, 10);
42657c478bd9Sstevel@tonic-gate 		*upper = (int)strtol(cp, &end2, 10);
42667c478bd9Sstevel@tonic-gate 		SKIPWS(end);
42677c478bd9Sstevel@tonic-gate 		SKIPWS(end2);
42687c478bd9Sstevel@tonic-gate 		if ((range_st == end) || (*end != NULL) ||
42697c478bd9Sstevel@tonic-gate 		    (cp == end) || (*end2 != NULL)) {
42707c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "Failed reading a-b\n");
42717c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
42727c478bd9Sstevel@tonic-gate 		}
42737c478bd9Sstevel@tonic-gate 
42747c478bd9Sstevel@tonic-gate 	} else {		/* single value */
42757c478bd9Sstevel@tonic-gate 
42767c478bd9Sstevel@tonic-gate 		*lower = *upper = (int)strtol(range_st, &end, 10);
42777c478bd9Sstevel@tonic-gate 		SKIPWS(end);
42787c478bd9Sstevel@tonic-gate 		if ((range_st == end) || (*end != NULL)) {
42797c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "Failed reading a\n");
42807c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
42817c478bd9Sstevel@tonic-gate 		}
42827c478bd9Sstevel@tonic-gate 	}
42837c478bd9Sstevel@tonic-gate 
42847c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
42857c478bd9Sstevel@tonic-gate }
42867c478bd9Sstevel@tonic-gate 
42877c478bd9Sstevel@tonic-gate /*
42887c478bd9Sstevel@tonic-gate  * Reads the values of an integer array from fp whose format is:
42897c478bd9Sstevel@tonic-gate  * '{'RANGE[,RANGE[..]]:VALUE[;RANGE:VALUE[..]]'}', creates an array of size
42907c478bd9Sstevel@tonic-gate  * arr_size, applies the values to it and points arrp at this array.
42917c478bd9Sstevel@tonic-gate  * RANGE is one set of array indexes over which this value is to
42927c478bd9Sstevel@tonic-gate  * be applied, and VALUE either an integer within the range
42937c478bd9Sstevel@tonic-gate  * llimit - ulimit, or if enum_nvs isn't NULL, an enumeration value
42947c478bd9Sstevel@tonic-gate  * found in the list enum_nvs. Those values which aren't explicity set
42957c478bd9Sstevel@tonic-gate  * will be set to -1.
42967c478bd9Sstevel@tonic-gate  *
42977c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on resource or parse error, else IPQOS_CONF_SUCCESS.
42987c478bd9Sstevel@tonic-gate  */
42997c478bd9Sstevel@tonic-gate static int
43007c478bd9Sstevel@tonic-gate read_int_array(
43017c478bd9Sstevel@tonic-gate FILE *fp,
43027c478bd9Sstevel@tonic-gate char *first_token,
43037c478bd9Sstevel@tonic-gate int **arrp,
43047c478bd9Sstevel@tonic-gate uint32_t arr_size,
43057c478bd9Sstevel@tonic-gate int llimit,
43067c478bd9Sstevel@tonic-gate int ulimit,
43077c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs)
43087c478bd9Sstevel@tonic-gate {
43097c478bd9Sstevel@tonic-gate 
43107c478bd9Sstevel@tonic-gate 	char buf[5 * IPQOS_CONF_LINEBUF_SZ];
43117c478bd9Sstevel@tonic-gate 	char *token;
43127c478bd9Sstevel@tonic-gate 	char *range;
43137c478bd9Sstevel@tonic-gate 	char *ranges;
43147c478bd9Sstevel@tonic-gate 	char *svalue;
43157c478bd9Sstevel@tonic-gate 	int value;
43167c478bd9Sstevel@tonic-gate 	int res;
43177c478bd9Sstevel@tonic-gate 	char *entry;
43187c478bd9Sstevel@tonic-gate 	char *tmp;
43197c478bd9Sstevel@tonic-gate 	char *end;
43207c478bd9Sstevel@tonic-gate 	int lower, upper;
43217c478bd9Sstevel@tonic-gate 	int x;
43227c478bd9Sstevel@tonic-gate 	uint32_t startln;
43237c478bd9Sstevel@tonic-gate 
43247c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(L0, "In read_int_array: size: %u, lower: %u, upper: %u, "
43257c478bd9Sstevel@tonic-gate 	    "first_token: %s\n", arr_size, llimit, ulimit, first_token);
43267c478bd9Sstevel@tonic-gate 
43277c478bd9Sstevel@tonic-gate 	/*
43287c478bd9Sstevel@tonic-gate 	 * read beginning curl.
43297c478bd9Sstevel@tonic-gate 	 */
43307c478bd9Sstevel@tonic-gate 	if (first_token[0] != CURL_BEGIN) {
43317c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("\'{\' missing at line "
43327c478bd9Sstevel@tonic-gate 		    "%u.\n"), lineno);
43337c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
43347c478bd9Sstevel@tonic-gate 	}
43357c478bd9Sstevel@tonic-gate 
43367c478bd9Sstevel@tonic-gate 	/*
43377c478bd9Sstevel@tonic-gate 	 * allocate and initialise array for holding read values.
43387c478bd9Sstevel@tonic-gate 	 */
43397c478bd9Sstevel@tonic-gate 	*arrp = malloc(arr_size * sizeof (int));
43407c478bd9Sstevel@tonic-gate 	if (*arrp == NULL) {
43417c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
43427c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
43437c478bd9Sstevel@tonic-gate 	}
43447c478bd9Sstevel@tonic-gate 	(void) memset(*arrp, -1, arr_size * sizeof (int));
43457c478bd9Sstevel@tonic-gate 
43467c478bd9Sstevel@tonic-gate 	/*
43477c478bd9Sstevel@tonic-gate 	 * read whole array declaration string into buffer.
43487c478bd9Sstevel@tonic-gate 	 * this is because readtoken doesn't interpret our
43497c478bd9Sstevel@tonic-gate 	 * delimeter values specially and may return them
43507c478bd9Sstevel@tonic-gate 	 * within another string.
43517c478bd9Sstevel@tonic-gate 	 */
43527c478bd9Sstevel@tonic-gate 	startln = lineno;	/* store starting lineno for error reports */
43537c478bd9Sstevel@tonic-gate 	buf[0] = '\0';
43547c478bd9Sstevel@tonic-gate 	res = readtoken(fp, &token);
43557c478bd9Sstevel@tonic-gate 	while ((res != IPQOS_CONF_CURL_END) && (res != IPQOS_CONF_ERR) &&
43567c478bd9Sstevel@tonic-gate 	    (res != IPQOS_CONF_EOF)) {
43577c478bd9Sstevel@tonic-gate 		(void) strlcat(buf, token, sizeof (buf));
43587c478bd9Sstevel@tonic-gate 		free(token);
43597c478bd9Sstevel@tonic-gate 		res = readtoken(fp, &token);
43607c478bd9Sstevel@tonic-gate 	}
43617c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_CURL_END) {
43627c478bd9Sstevel@tonic-gate 		goto array_err;
43637c478bd9Sstevel@tonic-gate 	}
43647c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "array declaration buffer contains: %s\n", buf);
43657c478bd9Sstevel@tonic-gate 
43667c478bd9Sstevel@tonic-gate 	/*
43677c478bd9Sstevel@tonic-gate 	 * loop reading "ranges ':' value;" till end of buffer.
43687c478bd9Sstevel@tonic-gate 	 */
43697c478bd9Sstevel@tonic-gate 	entry = strtok(buf, ";");
43707c478bd9Sstevel@tonic-gate 	while (entry != NULL) {
43717c478bd9Sstevel@tonic-gate 		svalue = strchr(entry, ':');
43727c478bd9Sstevel@tonic-gate 		if (svalue == NULL) {	/* missing value string */
43737c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "Missing value string\n");
43747c478bd9Sstevel@tonic-gate 			goto array_err;
43757c478bd9Sstevel@tonic-gate 		}
43767c478bd9Sstevel@tonic-gate 		*svalue++ = '\0';
43777c478bd9Sstevel@tonic-gate 		ranges = entry;
43787c478bd9Sstevel@tonic-gate 
43797c478bd9Sstevel@tonic-gate 		/*
43807c478bd9Sstevel@tonic-gate 		 * get value of number or enumerated symbol.
43817c478bd9Sstevel@tonic-gate 		 */
43827c478bd9Sstevel@tonic-gate 		if (enum_nvs) {
43837c478bd9Sstevel@tonic-gate 			/*
43847c478bd9Sstevel@tonic-gate 			 * get rid of surrounding whitespace so as not to
43857c478bd9Sstevel@tonic-gate 			 * confuse read_enum_value.
43867c478bd9Sstevel@tonic-gate 			 */
43877c478bd9Sstevel@tonic-gate 			SKIPWS(svalue);
43887c478bd9Sstevel@tonic-gate 			tmp = svalue;
43897c478bd9Sstevel@tonic-gate 			while (*tmp != '\0') {
43907c478bd9Sstevel@tonic-gate 				if (isspace(*tmp)) {
43917c478bd9Sstevel@tonic-gate 					*tmp = '\0';
43927c478bd9Sstevel@tonic-gate 					break;
43937c478bd9Sstevel@tonic-gate 				} else {
43947c478bd9Sstevel@tonic-gate 					tmp++;
43957c478bd9Sstevel@tonic-gate 				}
43967c478bd9Sstevel@tonic-gate 			}
43977c478bd9Sstevel@tonic-gate 
43987c478bd9Sstevel@tonic-gate 			/*
43997c478bd9Sstevel@tonic-gate 			 * read enumeration value.
44007c478bd9Sstevel@tonic-gate 			 */
44017c478bd9Sstevel@tonic-gate 			res = read_enum_value(NULL, svalue, enum_nvs,
44027c478bd9Sstevel@tonic-gate 			    (uint32_t *)&value);
44037c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS)
44047c478bd9Sstevel@tonic-gate 				goto array_err;
44057c478bd9Sstevel@tonic-gate 		} else {
44067c478bd9Sstevel@tonic-gate 			value = (int)strtol(svalue, &end, 10);
44077c478bd9Sstevel@tonic-gate 			SKIPWS(end);
44087c478bd9Sstevel@tonic-gate 			if ((svalue == end) || (*end != NULL)) {
44097c478bd9Sstevel@tonic-gate 				IPQOSCDBG0(L0, "Invalid value\n");
44107c478bd9Sstevel@tonic-gate 				goto array_err;
44117c478bd9Sstevel@tonic-gate 			}
44127c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(L0, "value: %u\n", value);
44137c478bd9Sstevel@tonic-gate 
44147c478bd9Sstevel@tonic-gate 			/*
44157c478bd9Sstevel@tonic-gate 			 * check value within valid range.
44167c478bd9Sstevel@tonic-gate 			 */
44177c478bd9Sstevel@tonic-gate 			if ((value < llimit) || (value > ulimit)) {
44187c478bd9Sstevel@tonic-gate 				IPQOSCDBG0(L0, "value out of range\n");
44197c478bd9Sstevel@tonic-gate 				goto array_err;
44207c478bd9Sstevel@tonic-gate 			}
44217c478bd9Sstevel@tonic-gate 		}
44227c478bd9Sstevel@tonic-gate 
44237c478bd9Sstevel@tonic-gate 		/*
44247c478bd9Sstevel@tonic-gate 		 * loop reading ranges for this value.
44257c478bd9Sstevel@tonic-gate 		 */
44267c478bd9Sstevel@tonic-gate 		range = strtok_r(ranges, ",", &tmp);
44277c478bd9Sstevel@tonic-gate 		while (range != NULL) {
44287c478bd9Sstevel@tonic-gate 			res = readrange(range, &lower, &upper);
44297c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS)
44307c478bd9Sstevel@tonic-gate 				goto array_err;
44317c478bd9Sstevel@tonic-gate 			IPQOSCDBG2(L0, "range: %u - %u\n", lower, upper);
44327c478bd9Sstevel@tonic-gate 
44337c478bd9Sstevel@tonic-gate 
44347c478bd9Sstevel@tonic-gate 			if (upper < lower) {
44357c478bd9Sstevel@tonic-gate 				uint32_t u = lower;
44367c478bd9Sstevel@tonic-gate 				lower = upper;
44377c478bd9Sstevel@tonic-gate 				upper = u;
44387c478bd9Sstevel@tonic-gate 			}
44397c478bd9Sstevel@tonic-gate 
44407c478bd9Sstevel@tonic-gate 			/*
44417c478bd9Sstevel@tonic-gate 			 * check range valid for array size.
44427c478bd9Sstevel@tonic-gate 			 */
44437c478bd9Sstevel@tonic-gate 			if ((lower < 0) || (upper > arr_size)) {
44447c478bd9Sstevel@tonic-gate 				IPQOSCDBG0(L0, "Range out of array "
44457c478bd9Sstevel@tonic-gate 				    "dimensions\n");
44467c478bd9Sstevel@tonic-gate 				goto array_err;
44477c478bd9Sstevel@tonic-gate 			}
44487c478bd9Sstevel@tonic-gate 
44497c478bd9Sstevel@tonic-gate 			/*
44507c478bd9Sstevel@tonic-gate 			 * add this value to array indexes within range.
44517c478bd9Sstevel@tonic-gate 			 */
44527c478bd9Sstevel@tonic-gate 			for (x = lower; x <= upper; x++)
44537c478bd9Sstevel@tonic-gate 				(*arrp)[x] = value;
44547c478bd9Sstevel@tonic-gate 
44557c478bd9Sstevel@tonic-gate 			/*
44567c478bd9Sstevel@tonic-gate 			 * get next range.
44577c478bd9Sstevel@tonic-gate 			 */
44587c478bd9Sstevel@tonic-gate 			range = strtok_r(NULL, ",", &tmp);
44597c478bd9Sstevel@tonic-gate 		}
44607c478bd9Sstevel@tonic-gate 
44617c478bd9Sstevel@tonic-gate 		entry = strtok(NULL, ";");
44627c478bd9Sstevel@tonic-gate 	}
44637c478bd9Sstevel@tonic-gate 
44647c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
44657c478bd9Sstevel@tonic-gate 
44667c478bd9Sstevel@tonic-gate array_err:
44677c478bd9Sstevel@tonic-gate 	ipqos_msg(MT_ERROR,
44687c478bd9Sstevel@tonic-gate 	    gettext("Array declaration line %u is invalid.\n"), startln);
44697c478bd9Sstevel@tonic-gate 	free(*arrp);
44707c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
44717c478bd9Sstevel@tonic-gate }
44727c478bd9Sstevel@tonic-gate 
44737c478bd9Sstevel@tonic-gate static int
44747c478bd9Sstevel@tonic-gate readllong(char *str, long long *llp, char **lo)
44757c478bd9Sstevel@tonic-gate {
44767c478bd9Sstevel@tonic-gate 
44777c478bd9Sstevel@tonic-gate 	*llp = strtoll(str, lo, 0);
44787c478bd9Sstevel@tonic-gate 	if (*lo == str) {
44797c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
44807c478bd9Sstevel@tonic-gate 	}
44817c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
44827c478bd9Sstevel@tonic-gate }
44837c478bd9Sstevel@tonic-gate 
44847c478bd9Sstevel@tonic-gate static int
44857c478bd9Sstevel@tonic-gate readuint8(char *str, uint8_t *ui8, char **lo)
44867c478bd9Sstevel@tonic-gate {
44877c478bd9Sstevel@tonic-gate 
44887c478bd9Sstevel@tonic-gate 	long long tmp;
44897c478bd9Sstevel@tonic-gate 
44907c478bd9Sstevel@tonic-gate 	if (readllong(str, &tmp, lo) != 0) {
44917c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
44927c478bd9Sstevel@tonic-gate 	}
44937c478bd9Sstevel@tonic-gate 	if (tmp > UCHAR_MAX || tmp < 0) {
44947c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
44957c478bd9Sstevel@tonic-gate 	}
44967c478bd9Sstevel@tonic-gate 	*ui8 = (uint8_t)tmp;
44977c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
44987c478bd9Sstevel@tonic-gate }
44997c478bd9Sstevel@tonic-gate 
45007c478bd9Sstevel@tonic-gate static int
45017c478bd9Sstevel@tonic-gate readuint16(char *str, uint16_t *ui16, char **lo)
45027c478bd9Sstevel@tonic-gate {
45037c478bd9Sstevel@tonic-gate 	long long tmp;
45047c478bd9Sstevel@tonic-gate 
45057c478bd9Sstevel@tonic-gate 	if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) {
45067c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45077c478bd9Sstevel@tonic-gate 	}
45087c478bd9Sstevel@tonic-gate 	if (tmp > USHRT_MAX || tmp < 0) {
45097c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45107c478bd9Sstevel@tonic-gate 	}
45117c478bd9Sstevel@tonic-gate 	*ui16 = (uint16_t)tmp;
45127c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
45137c478bd9Sstevel@tonic-gate }
45147c478bd9Sstevel@tonic-gate 
45157c478bd9Sstevel@tonic-gate static int
45167c478bd9Sstevel@tonic-gate readint16(char *str, int16_t *i16, char **lo)
45177c478bd9Sstevel@tonic-gate {
45187c478bd9Sstevel@tonic-gate 	long long tmp;
45197c478bd9Sstevel@tonic-gate 
45207c478bd9Sstevel@tonic-gate 	if (readllong(str, &tmp, lo) != 0) {
45217c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45227c478bd9Sstevel@tonic-gate 	}
45237c478bd9Sstevel@tonic-gate 	if (tmp > SHRT_MAX || tmp < SHRT_MIN) {
45247c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45257c478bd9Sstevel@tonic-gate 	}
45267c478bd9Sstevel@tonic-gate 	*i16 = (int16_t)tmp;
45277c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
45287c478bd9Sstevel@tonic-gate }
45297c478bd9Sstevel@tonic-gate 
45307c478bd9Sstevel@tonic-gate static int
45317c478bd9Sstevel@tonic-gate readint32(char *str, int *i32, char **lo)
45327c478bd9Sstevel@tonic-gate {
45337c478bd9Sstevel@tonic-gate 	long long tmp;
45347c478bd9Sstevel@tonic-gate 
45357c478bd9Sstevel@tonic-gate 	if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) {
45367c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45377c478bd9Sstevel@tonic-gate 	}
45387c478bd9Sstevel@tonic-gate 	if (tmp > INT_MAX || tmp < INT_MIN) {
45397c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45407c478bd9Sstevel@tonic-gate 	}
45417c478bd9Sstevel@tonic-gate 	*i32 = tmp;
45427c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
45437c478bd9Sstevel@tonic-gate }
45447c478bd9Sstevel@tonic-gate 
45457c478bd9Sstevel@tonic-gate static int
45467c478bd9Sstevel@tonic-gate readuint32(char *str, uint32_t *ui32, char **lo)
45477c478bd9Sstevel@tonic-gate {
45487c478bd9Sstevel@tonic-gate 	long long tmp;
45497c478bd9Sstevel@tonic-gate 
45507c478bd9Sstevel@tonic-gate 	if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) {
45517c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45527c478bd9Sstevel@tonic-gate 	}
45537c478bd9Sstevel@tonic-gate 	if (tmp > UINT_MAX || tmp < 0) {
45547c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45557c478bd9Sstevel@tonic-gate 	}
45567c478bd9Sstevel@tonic-gate 	*ui32 = (uint32_t)tmp;
45577c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
45587c478bd9Sstevel@tonic-gate }
45597c478bd9Sstevel@tonic-gate 
45607c478bd9Sstevel@tonic-gate /*
45617c478bd9Sstevel@tonic-gate  * retrieves the index associated with the interface named ifname and assigns
45627c478bd9Sstevel@tonic-gate  * it to the int pointed to by ifindex.
45637c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
45647c478bd9Sstevel@tonic-gate  */
45657c478bd9Sstevel@tonic-gate static int
45667c478bd9Sstevel@tonic-gate readifindex(
45677c478bd9Sstevel@tonic-gate char *ifname,
45687c478bd9Sstevel@tonic-gate int *ifindex)
45697c478bd9Sstevel@tonic-gate {
45707c478bd9Sstevel@tonic-gate 
45717c478bd9Sstevel@tonic-gate 	int s;
45727c478bd9Sstevel@tonic-gate 	struct lifreq lifrq;
45737c478bd9Sstevel@tonic-gate 
45747c478bd9Sstevel@tonic-gate 
45757c478bd9Sstevel@tonic-gate 	/* open socket */
45767c478bd9Sstevel@tonic-gate 
45777c478bd9Sstevel@tonic-gate 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
45787c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, gettext("opening AF_INET socket"));
45797c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45807c478bd9Sstevel@tonic-gate 	}
45817c478bd9Sstevel@tonic-gate 
45827c478bd9Sstevel@tonic-gate 	/* copy ifname into lifreq */
45837c478bd9Sstevel@tonic-gate 
45847c478bd9Sstevel@tonic-gate 	(void) strlcpy(lifrq.lifr_name, ifname, LIFNAMSIZ);
45857c478bd9Sstevel@tonic-gate 
45867c478bd9Sstevel@tonic-gate 	/* do SIOGLIFINDEX ioctl */
45877c478bd9Sstevel@tonic-gate 
45887c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifrq) == -1) {
45897c478bd9Sstevel@tonic-gate 		(void) close(s);
45907c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
45917c478bd9Sstevel@tonic-gate 	}
45927c478bd9Sstevel@tonic-gate 
45937c478bd9Sstevel@tonic-gate 	/* Warn if a virtual interface is specified */
45947c478bd9Sstevel@tonic-gate 	if ((ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrq) != -1) &&
45957c478bd9Sstevel@tonic-gate 	    (lifrq.lifr_flags & IFF_VIRTUAL)) {
45967c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_WARNING, gettext("Invalid interface"));
45977c478bd9Sstevel@tonic-gate 	}
45987c478bd9Sstevel@tonic-gate 	(void) close(s);
45997c478bd9Sstevel@tonic-gate 	*ifindex = lifrq.lifr_index;
46007c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
46017c478bd9Sstevel@tonic-gate }
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate /*
46047c478bd9Sstevel@tonic-gate  * Case insensitively compares the string in str with IPQOS_CONF_TRUE_STR
46057c478bd9Sstevel@tonic-gate  * and IPQOS_CONF_FALSE_STR and sets boolean pointed to by bool accordingly.
46067c478bd9Sstevel@tonic-gate  * RETURNS: if failure to match either IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS.
46077c478bd9Sstevel@tonic-gate  */
46087c478bd9Sstevel@tonic-gate static int
46097c478bd9Sstevel@tonic-gate readbool(char *str, boolean_t *bool)
46107c478bd9Sstevel@tonic-gate {
46117c478bd9Sstevel@tonic-gate 
46127c478bd9Sstevel@tonic-gate 	if (strcasecmp(str, IPQOS_CONF_TRUE_STR) == 0) {
46137c478bd9Sstevel@tonic-gate 		*bool = B_TRUE;
46147c478bd9Sstevel@tonic-gate 	} else if (strcasecmp(str, IPQOS_CONF_FALSE_STR) == 0) {
46157c478bd9Sstevel@tonic-gate 		*bool = B_FALSE;
46167c478bd9Sstevel@tonic-gate 	} else {
46177c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
46187c478bd9Sstevel@tonic-gate 	}
46197c478bd9Sstevel@tonic-gate 
46207c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
46217c478bd9Sstevel@tonic-gate }
46227c478bd9Sstevel@tonic-gate 
46237c478bd9Sstevel@tonic-gate /*
46247c478bd9Sstevel@tonic-gate  * reads a protocol name/number from proto_str and assigns the number
46257c478bd9Sstevel@tonic-gate  * to the uint8 ref'd by proto.
46267c478bd9Sstevel@tonic-gate  * RETURNS: If not a valid name or protocol number IPQOS_CONF_ERR, else
46277c478bd9Sstevel@tonic-gate  * IPQOS_CONF_SUCCESS.
46287c478bd9Sstevel@tonic-gate  */
46297c478bd9Sstevel@tonic-gate static int
46307c478bd9Sstevel@tonic-gate readproto(char *proto_str, uint8_t *proto)
46317c478bd9Sstevel@tonic-gate {
46327c478bd9Sstevel@tonic-gate 
46337c478bd9Sstevel@tonic-gate 	struct protoent *pent;
46347c478bd9Sstevel@tonic-gate 	char *lo;
46357c478bd9Sstevel@tonic-gate 	int res;
46367c478bd9Sstevel@tonic-gate 
46377c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In readproto: string: %s\n", proto_str);
46387c478bd9Sstevel@tonic-gate 
46397c478bd9Sstevel@tonic-gate 	/* try name lookup */
46407c478bd9Sstevel@tonic-gate 
46417c478bd9Sstevel@tonic-gate 	pent = getprotobyname(proto_str);
46427c478bd9Sstevel@tonic-gate 	if (pent) {
46437c478bd9Sstevel@tonic-gate 		*proto = pent->p_proto;
46447c478bd9Sstevel@tonic-gate 
46457c478bd9Sstevel@tonic-gate 	/* check valid protocol number */
46467c478bd9Sstevel@tonic-gate 	} else {
46477c478bd9Sstevel@tonic-gate 		res = readuint8(proto_str, proto, &lo);
46487c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS || proto == 0) {
46497c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
46507c478bd9Sstevel@tonic-gate 		}
46517c478bd9Sstevel@tonic-gate 	}
46527c478bd9Sstevel@tonic-gate 
46537c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
46547c478bd9Sstevel@tonic-gate }
46557c478bd9Sstevel@tonic-gate 
46567c478bd9Sstevel@tonic-gate /*
46577c478bd9Sstevel@tonic-gate  * reads either a port service, or a port number from port_str and assigns
46587c478bd9Sstevel@tonic-gate  * the associated port number to short ref'd by port.
46597c478bd9Sstevel@tonic-gate  * RETURNS: If invalid name and number IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS.
46607c478bd9Sstevel@tonic-gate  */
46617c478bd9Sstevel@tonic-gate static int
46627c478bd9Sstevel@tonic-gate readport(char *port_str, uint16_t *port)
46637c478bd9Sstevel@tonic-gate {
46647c478bd9Sstevel@tonic-gate 
46657c478bd9Sstevel@tonic-gate 	struct servent *sent;
46667c478bd9Sstevel@tonic-gate 	char *tmp;
46677c478bd9Sstevel@tonic-gate 
46687c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In readport: string: %s\n", port_str);
46697c478bd9Sstevel@tonic-gate 
46707c478bd9Sstevel@tonic-gate 	/* try service name lookup */
46717c478bd9Sstevel@tonic-gate 	sent = getservbyname(port_str, NULL);
46727c478bd9Sstevel@tonic-gate 
46737c478bd9Sstevel@tonic-gate 	/* failed name lookup so read port number */
46747c478bd9Sstevel@tonic-gate 	if (sent == NULL) {
46757c478bd9Sstevel@tonic-gate 		if (readuint16(port_str, port, &tmp) != IPQOS_CONF_SUCCESS ||
46767c478bd9Sstevel@tonic-gate 		    *port == 0) {
46777c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
46787c478bd9Sstevel@tonic-gate 		}
46797c478bd9Sstevel@tonic-gate 		*port = htons(*port);
46807c478bd9Sstevel@tonic-gate 	} else {
46817c478bd9Sstevel@tonic-gate 		*port = sent->s_port;
46827c478bd9Sstevel@tonic-gate 	}
46837c478bd9Sstevel@tonic-gate 
46847c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
46857c478bd9Sstevel@tonic-gate }
46867c478bd9Sstevel@tonic-gate 
46877c478bd9Sstevel@tonic-gate 
46887c478bd9Sstevel@tonic-gate /*
46897c478bd9Sstevel@tonic-gate  * Reads a curly brace, a string enclosed in double quotes, or a whitespace/
46907c478bd9Sstevel@tonic-gate  * curly brace delimited string. If a double quote enclosed string the
46917c478bd9Sstevel@tonic-gate  * closing quotes need to be on the same line.
46927c478bd9Sstevel@tonic-gate  * RETURNS:
46937c478bd9Sstevel@tonic-gate  * on reading a CURL_BEGIN token it returns IPQOS_CONF_CURL_BEGIN,
46947c478bd9Sstevel@tonic-gate  * on reading a CURL_END token it returns IPQOS_CONF_CURL_END,
46957c478bd9Sstevel@tonic-gate  * on reading another valid token it returns IPQOS_CONF_SUCCESS.
46967c478bd9Sstevel@tonic-gate  * for each of these token is set to point at the read string.
46977c478bd9Sstevel@tonic-gate  * at EOF it returns IPQOS_CONF_EOF and if errors it returns IPQOS_CONF_ERR.
46987c478bd9Sstevel@tonic-gate  */
46997c478bd9Sstevel@tonic-gate static int
47007c478bd9Sstevel@tonic-gate readtoken(
47017c478bd9Sstevel@tonic-gate FILE *fp,
47027c478bd9Sstevel@tonic-gate char **token)
47037c478bd9Sstevel@tonic-gate {
47047c478bd9Sstevel@tonic-gate 
47057c478bd9Sstevel@tonic-gate 	char *st, *tmp;
47067c478bd9Sstevel@tonic-gate 	int len;
47077c478bd9Sstevel@tonic-gate 	int quoted = 0;
47087c478bd9Sstevel@tonic-gate 	char *cmnt;
47097c478bd9Sstevel@tonic-gate 	char *bpos;
47107c478bd9Sstevel@tonic-gate 	int rembuf;
47117c478bd9Sstevel@tonic-gate 
47127c478bd9Sstevel@tonic-gate 	static char *lo;
47137c478bd9Sstevel@tonic-gate 	static char *buf = NULL;
47147c478bd9Sstevel@tonic-gate 	static int bufsize;
47157c478bd9Sstevel@tonic-gate 
47167c478bd9Sstevel@tonic-gate 	/* if first call initialize line buf to default size */
47177c478bd9Sstevel@tonic-gate 
47187c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
47197c478bd9Sstevel@tonic-gate 		bufsize = IPQOS_CONF_LINEBUF_SZ;
47207c478bd9Sstevel@tonic-gate 		buf = malloc(bufsize);
47217c478bd9Sstevel@tonic-gate 		if (buf == NULL) {
47227c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
47237c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
47247c478bd9Sstevel@tonic-gate 		}
47257c478bd9Sstevel@tonic-gate 	}
47267c478bd9Sstevel@tonic-gate 
47277c478bd9Sstevel@tonic-gate 	/* set buffer postition and size to use whole buffer */
47287c478bd9Sstevel@tonic-gate 
47297c478bd9Sstevel@tonic-gate 	bpos = buf;
47307c478bd9Sstevel@tonic-gate 	rembuf = bufsize;
47317c478bd9Sstevel@tonic-gate 
47327c478bd9Sstevel@tonic-gate 
47337c478bd9Sstevel@tonic-gate 	/*
47347c478bd9Sstevel@tonic-gate 	 * loop reading lines until we've read a line with a non-whitespace
47357c478bd9Sstevel@tonic-gate 	 * char.
47367c478bd9Sstevel@tonic-gate 	 */
47377c478bd9Sstevel@tonic-gate 
47387c478bd9Sstevel@tonic-gate 	do {
47397c478bd9Sstevel@tonic-gate 		/* if no leftover from previous invocation */
47407c478bd9Sstevel@tonic-gate 
47417c478bd9Sstevel@tonic-gate 		if (lo == NULL) {
47427c478bd9Sstevel@tonic-gate 
47437c478bd9Sstevel@tonic-gate 			/*
47447c478bd9Sstevel@tonic-gate 			 * loop reading into buffer doubling if necessary until
47457c478bd9Sstevel@tonic-gate 			 * we have either read a complete line or reached the
47467c478bd9Sstevel@tonic-gate 			 * end of file.
47477c478bd9Sstevel@tonic-gate 			 */
47487c478bd9Sstevel@tonic-gate 			for (;;) {
47497c478bd9Sstevel@tonic-gate 				st = fgets(bpos, rembuf, fp);
47507c478bd9Sstevel@tonic-gate 
47517c478bd9Sstevel@tonic-gate 				if (st == NULL) {
47527c478bd9Sstevel@tonic-gate 
47537c478bd9Sstevel@tonic-gate 					/* if read error */
47547c478bd9Sstevel@tonic-gate 					if (ferror(fp)) {
47557c478bd9Sstevel@tonic-gate 						free(buf);
47567c478bd9Sstevel@tonic-gate 						buf = NULL;
47577c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ENOSTR,
47587c478bd9Sstevel@tonic-gate 						    "fgets");
47597c478bd9Sstevel@tonic-gate 						return (IPQOS_CONF_ERR);
47607c478bd9Sstevel@tonic-gate 
47617c478bd9Sstevel@tonic-gate 					/* end of file */
47627c478bd9Sstevel@tonic-gate 					} else {
47637c478bd9Sstevel@tonic-gate 						free(buf);
47647c478bd9Sstevel@tonic-gate 						buf = NULL;
47657c478bd9Sstevel@tonic-gate 						*token = NULL;
47667c478bd9Sstevel@tonic-gate 						return (IPQOS_CONF_EOF);
47677c478bd9Sstevel@tonic-gate 					}
47687c478bd9Sstevel@tonic-gate 				} else {
47697c478bd9Sstevel@tonic-gate 					/* if read a newline */
47707c478bd9Sstevel@tonic-gate 
47717c478bd9Sstevel@tonic-gate 					if (buf[strlen(buf) - 1] == '\n') {
47727c478bd9Sstevel@tonic-gate 						lineno++;
47737c478bd9Sstevel@tonic-gate 						break;
47747c478bd9Sstevel@tonic-gate 
47757c478bd9Sstevel@tonic-gate 					/* if read the last line */
47767c478bd9Sstevel@tonic-gate 
47777c478bd9Sstevel@tonic-gate 					} else if (feof(fp)) {
47787c478bd9Sstevel@tonic-gate 						break;
47797c478bd9Sstevel@tonic-gate 
47807c478bd9Sstevel@tonic-gate 					/*
47817c478bd9Sstevel@tonic-gate 					 * not read a full line so buffer size
47827c478bd9Sstevel@tonic-gate 					 * is too small, double it and retry.
47837c478bd9Sstevel@tonic-gate 					 */
47847c478bd9Sstevel@tonic-gate 					} else {
47857c478bd9Sstevel@tonic-gate 						bufsize *= 2;
47867c478bd9Sstevel@tonic-gate 						tmp = realloc(buf, bufsize);
47877c478bd9Sstevel@tonic-gate 						if (tmp == NULL) {
47887c478bd9Sstevel@tonic-gate 							ipqos_msg(MT_ENOSTR,
47897c478bd9Sstevel@tonic-gate 							    "realloc");
47907c478bd9Sstevel@tonic-gate 							free(buf);
47917c478bd9Sstevel@tonic-gate 							return (IPQOS_CONF_ERR);
47927c478bd9Sstevel@tonic-gate 						} else {
47937c478bd9Sstevel@tonic-gate 							buf = tmp;
47947c478bd9Sstevel@tonic-gate 						}
47957c478bd9Sstevel@tonic-gate 
47967c478bd9Sstevel@tonic-gate 						/*
47977c478bd9Sstevel@tonic-gate 						 * make parameters to fgets read
47987c478bd9Sstevel@tonic-gate 						 * into centre of doubled buffer
47997c478bd9Sstevel@tonic-gate 						 * so we retain what we've
48007c478bd9Sstevel@tonic-gate 						 * already read.
48017c478bd9Sstevel@tonic-gate 						 */
48027c478bd9Sstevel@tonic-gate 						bpos = &buf[(bufsize / 2) - 1];
48037c478bd9Sstevel@tonic-gate 						rembuf = (bufsize / 2) + 1;
48047c478bd9Sstevel@tonic-gate 					}
48057c478bd9Sstevel@tonic-gate 				}
48067c478bd9Sstevel@tonic-gate 			}
48077c478bd9Sstevel@tonic-gate 
48087c478bd9Sstevel@tonic-gate 			st = buf;
48097c478bd9Sstevel@tonic-gate 
48107c478bd9Sstevel@tonic-gate 		/* previous leftover, assign to st */
48117c478bd9Sstevel@tonic-gate 
48127c478bd9Sstevel@tonic-gate 		} else {
48137c478bd9Sstevel@tonic-gate 			st = lo;
48147c478bd9Sstevel@tonic-gate 			lo = NULL;
48157c478bd9Sstevel@tonic-gate 		}
48167c478bd9Sstevel@tonic-gate 
48177c478bd9Sstevel@tonic-gate 		/* truncate at comment */
48187c478bd9Sstevel@tonic-gate 
48197c478bd9Sstevel@tonic-gate 		cmnt = strchr(st, '#');
48207c478bd9Sstevel@tonic-gate 		if (cmnt) {
48217c478bd9Sstevel@tonic-gate 			*cmnt = '\0';
48227c478bd9Sstevel@tonic-gate 		}
48237c478bd9Sstevel@tonic-gate 
48247c478bd9Sstevel@tonic-gate 		/* Skip any whitespace */
48257c478bd9Sstevel@tonic-gate 
4826f7819bf9SToomas Soome 		while (isspace(*st) && *st != '\0') {
48277c478bd9Sstevel@tonic-gate 			st++;
48287c478bd9Sstevel@tonic-gate 		}
48297c478bd9Sstevel@tonic-gate 
48307c478bd9Sstevel@tonic-gate 	} while (*st == '\0');
48317c478bd9Sstevel@tonic-gate 
48327c478bd9Sstevel@tonic-gate 
48337c478bd9Sstevel@tonic-gate 	/* find end of token */
48347c478bd9Sstevel@tonic-gate 
48357c478bd9Sstevel@tonic-gate 	tmp = st;
48367c478bd9Sstevel@tonic-gate 
48377c478bd9Sstevel@tonic-gate 	/* if curl advance 1 char */
48387c478bd9Sstevel@tonic-gate 
48397c478bd9Sstevel@tonic-gate 	if (*tmp == CURL_BEGIN || *tmp == CURL_END) {
48407c478bd9Sstevel@tonic-gate 		tmp++;
48417c478bd9Sstevel@tonic-gate 
48427c478bd9Sstevel@tonic-gate 
48437c478bd9Sstevel@tonic-gate 	/* if dbl quote read until matching quote */
48447c478bd9Sstevel@tonic-gate 
48457c478bd9Sstevel@tonic-gate 	} else if (*tmp == '"') {
48467c478bd9Sstevel@tonic-gate 		quoted++;
48477c478bd9Sstevel@tonic-gate 		tmp = ++st;
48487c478bd9Sstevel@tonic-gate 
48497c478bd9Sstevel@tonic-gate 		while (*tmp != '"' && *tmp != '\n' && *tmp != '\0') {
48507c478bd9Sstevel@tonic-gate 			tmp++;
48517c478bd9Sstevel@tonic-gate 		}
48527c478bd9Sstevel@tonic-gate 		if (*tmp != '"') {
48537c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Quoted string exceeds "
48547c478bd9Sstevel@tonic-gate 			    "line, line %u.\n"), lineno);
48557c478bd9Sstevel@tonic-gate 			free(buf);
48567c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
48577c478bd9Sstevel@tonic-gate 		}
48587c478bd9Sstevel@tonic-gate 
48597c478bd9Sstevel@tonic-gate 	/* normal token */
48607c478bd9Sstevel@tonic-gate 	} else {
48617c478bd9Sstevel@tonic-gate 		/* find first whitespace, curl, newline or string end */
48627c478bd9Sstevel@tonic-gate 
48637c478bd9Sstevel@tonic-gate 		while (!isspace(*tmp) && *tmp != CURL_BEGIN &&
48647c478bd9Sstevel@tonic-gate 		    *tmp != CURL_END && *tmp != '\n' && *tmp != '\0') {
48657c478bd9Sstevel@tonic-gate 			tmp++;
48667c478bd9Sstevel@tonic-gate 		}
48677c478bd9Sstevel@tonic-gate 	}
48687c478bd9Sstevel@tonic-gate 
48697c478bd9Sstevel@tonic-gate 	/* copy token to return */
48707c478bd9Sstevel@tonic-gate 	len = tmp - st;
48717c478bd9Sstevel@tonic-gate 	*token = malloc(len + 1);
48727c478bd9Sstevel@tonic-gate 	if (!*token) {
48737c478bd9Sstevel@tonic-gate 		free(buf);
48747c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
48757c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
48767c478bd9Sstevel@tonic-gate 	}
48777c478bd9Sstevel@tonic-gate 	bcopy(st, *token, len);
48787c478bd9Sstevel@tonic-gate 	(*token)[len] = '\0';
48797c478bd9Sstevel@tonic-gate 
48807c478bd9Sstevel@tonic-gate 	/* if just read quoted string remove quote from remaining string */
48817c478bd9Sstevel@tonic-gate 
48827c478bd9Sstevel@tonic-gate 	if (quoted) {
48837c478bd9Sstevel@tonic-gate 		tmp++;
48847c478bd9Sstevel@tonic-gate 	}
48857c478bd9Sstevel@tonic-gate 
48867c478bd9Sstevel@tonic-gate 	/* if not end of string, store rest for latter parsing */
48877c478bd9Sstevel@tonic-gate 
48887c478bd9Sstevel@tonic-gate 	if (*tmp != '\0' && *tmp != '\n') {
48897c478bd9Sstevel@tonic-gate 		lo = tmp;
48907c478bd9Sstevel@tonic-gate 	}
48917c478bd9Sstevel@tonic-gate 
48927c478bd9Sstevel@tonic-gate 	/* for curl_end and curl_begin return special ret codes */
48937c478bd9Sstevel@tonic-gate 
48947c478bd9Sstevel@tonic-gate 	if ((*token)[1] == '\0') {
48957c478bd9Sstevel@tonic-gate 		if (**token == CURL_BEGIN) {
48967c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_CURL_BEGIN);
48977c478bd9Sstevel@tonic-gate 		} else if (**token == CURL_END) {
48987c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_CURL_END);
48997c478bd9Sstevel@tonic-gate 		}
49007c478bd9Sstevel@tonic-gate 	}
49017c478bd9Sstevel@tonic-gate 
49027c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
49037c478bd9Sstevel@tonic-gate }
49047c478bd9Sstevel@tonic-gate 
49057c478bd9Sstevel@tonic-gate /*
49067c478bd9Sstevel@tonic-gate  * Reads an enumeration bitmask definition from line. The format is:
49077c478bd9Sstevel@tonic-gate  * { NAME=VAL, NAME2=VAL2 }. The resulting names and values are returned.
49087c478bd9Sstevel@tonic-gate  * RETURNS: NULL on error, else ptr to name/values.
49097c478bd9Sstevel@tonic-gate  */
49107c478bd9Sstevel@tonic-gate static str_val_nd_t *
49117c478bd9Sstevel@tonic-gate read_enum_nvs(char *line, char *module_name)
49127c478bd9Sstevel@tonic-gate {
49137c478bd9Sstevel@tonic-gate 
49147c478bd9Sstevel@tonic-gate 	str_val_nd_t *enum_vals = NULL;
49157c478bd9Sstevel@tonic-gate 	char *cp;
49167c478bd9Sstevel@tonic-gate 	char *start;
49177c478bd9Sstevel@tonic-gate 	char *name = NULL;
49187c478bd9Sstevel@tonic-gate 	int len;
49197c478bd9Sstevel@tonic-gate 	uint32_t val;
49207c478bd9Sstevel@tonic-gate 	int ret;
49217c478bd9Sstevel@tonic-gate 	int readc;
49227c478bd9Sstevel@tonic-gate 
49237c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In read_enum_nvs, line: %s\n", line);
49247c478bd9Sstevel@tonic-gate 
49257c478bd9Sstevel@tonic-gate 	/* read opening brace */
49267c478bd9Sstevel@tonic-gate 
49277c478bd9Sstevel@tonic-gate 	cp = strchr(line, CURL_BEGIN);
49287c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
49297c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L1, "missing curl begin\n");
49307c478bd9Sstevel@tonic-gate 		goto fail;
49317c478bd9Sstevel@tonic-gate 	} else {
49327c478bd9Sstevel@tonic-gate 		start = cp + 1;
49337c478bd9Sstevel@tonic-gate 	}
49347c478bd9Sstevel@tonic-gate 
49357c478bd9Sstevel@tonic-gate 	/*
49367c478bd9Sstevel@tonic-gate 	 * loop reading 'name = value' entrys seperated by comma until
49377c478bd9Sstevel@tonic-gate 	 * reach closing brace.
49387c478bd9Sstevel@tonic-gate 	 */
49397c478bd9Sstevel@tonic-gate 
49407c478bd9Sstevel@tonic-gate 	for (;;) {
49417c478bd9Sstevel@tonic-gate 		SKIPWS(start);
49427c478bd9Sstevel@tonic-gate 		if (*start == '\0') {
49437c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L1, "missing closing bracket\n");
49447c478bd9Sstevel@tonic-gate 			goto fail;
49457c478bd9Sstevel@tonic-gate 		}
49467c478bd9Sstevel@tonic-gate 
49477c478bd9Sstevel@tonic-gate 		/*
49487c478bd9Sstevel@tonic-gate 		 * read name - read until whitespace, '=', closing curl,
49497c478bd9Sstevel@tonic-gate 		 * or string end.
49507c478bd9Sstevel@tonic-gate 		 */
49517c478bd9Sstevel@tonic-gate 
49527c478bd9Sstevel@tonic-gate 		for (cp = start;
49537c478bd9Sstevel@tonic-gate 		    !isspace(*cp) && *cp != '=' && *cp != CURL_END &&
49547c478bd9Sstevel@tonic-gate 		    *cp != '\0'; cp++) {}
49557c478bd9Sstevel@tonic-gate 
49567c478bd9Sstevel@tonic-gate 		if (*cp == '\0') {
49577c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L1, "Unexpected line end in enum def'n\n");
49587c478bd9Sstevel@tonic-gate 			goto fail;
49597c478bd9Sstevel@tonic-gate 
49607c478bd9Sstevel@tonic-gate 		/* finished definition, exit loop */
49617c478bd9Sstevel@tonic-gate 		} else if (*cp == CURL_END) {
49627c478bd9Sstevel@tonic-gate 			break;
49637c478bd9Sstevel@tonic-gate 		}
49647c478bd9Sstevel@tonic-gate 
49657c478bd9Sstevel@tonic-gate 		/* store name */
49667c478bd9Sstevel@tonic-gate 
49677c478bd9Sstevel@tonic-gate 		len = cp - start;
49687c478bd9Sstevel@tonic-gate 		name = malloc(len + 1);
49697c478bd9Sstevel@tonic-gate 		if (name == NULL) {
49707c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
49717c478bd9Sstevel@tonic-gate 			goto fail;
49727c478bd9Sstevel@tonic-gate 		}
49737c478bd9Sstevel@tonic-gate 		bcopy(start, name, len);
49747c478bd9Sstevel@tonic-gate 		name[len] = NULL;
49757c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(L0, "Stored name: %s\n", name);
49767c478bd9Sstevel@tonic-gate 
49777c478bd9Sstevel@tonic-gate 		/* read assignment */
49787c478bd9Sstevel@tonic-gate 
49797c478bd9Sstevel@tonic-gate 		start = strchr(cp, '=');
49807c478bd9Sstevel@tonic-gate 		if (start == NULL) {
49817c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L1, "Missing = in enum def'n\n");
49827c478bd9Sstevel@tonic-gate 			goto fail;
49837c478bd9Sstevel@tonic-gate 		}
49847c478bd9Sstevel@tonic-gate 
49857c478bd9Sstevel@tonic-gate 		/* read value */
49867c478bd9Sstevel@tonic-gate 
49877c478bd9Sstevel@tonic-gate 		ret = sscanf(++start, "%x%n", &val, &readc);
49887c478bd9Sstevel@tonic-gate 		if (ret != 1) {
49897c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(L1, "sscanf of value failed, string: %s\n",
49907c478bd9Sstevel@tonic-gate 			    cp);
49917c478bd9Sstevel@tonic-gate 			goto fail;
49927c478bd9Sstevel@tonic-gate 		}
49937c478bd9Sstevel@tonic-gate 
49947c478bd9Sstevel@tonic-gate 		/* add name value to set */
49957c478bd9Sstevel@tonic-gate 
49967c478bd9Sstevel@tonic-gate 		ret = add_str_val_entry(&enum_vals, name, val);
49977c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
49987c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L1, "Failed to add str_val entry\n");
49997c478bd9Sstevel@tonic-gate 			goto fail;
50007c478bd9Sstevel@tonic-gate 		}
50017c478bd9Sstevel@tonic-gate 		free(name);
50027c478bd9Sstevel@tonic-gate 		name = NULL;
50037c478bd9Sstevel@tonic-gate 
50047c478bd9Sstevel@tonic-gate 		/* try reading comma */
50057c478bd9Sstevel@tonic-gate 		cp = strchr(start, ',');
50067c478bd9Sstevel@tonic-gate 
50077c478bd9Sstevel@tonic-gate 		if (cp != NULL) {
50087c478bd9Sstevel@tonic-gate 			start = cp + 1;
50097c478bd9Sstevel@tonic-gate 
50107c478bd9Sstevel@tonic-gate 		/* no comma, advance to char past value last read */
50117c478bd9Sstevel@tonic-gate 		} else {
50127c478bd9Sstevel@tonic-gate 			start += readc;
50137c478bd9Sstevel@tonic-gate 		}
50147c478bd9Sstevel@tonic-gate 	}
50157c478bd9Sstevel@tonic-gate 
50167c478bd9Sstevel@tonic-gate 	return (enum_vals);
50177c478bd9Sstevel@tonic-gate fail:
50187c478bd9Sstevel@tonic-gate 	free_str_val_entrys(enum_vals);
50197c478bd9Sstevel@tonic-gate 	if (name != NULL)
50207c478bd9Sstevel@tonic-gate 		free(name);
50217c478bd9Sstevel@tonic-gate 
50227c478bd9Sstevel@tonic-gate 	/* if a parse error */
50237c478bd9Sstevel@tonic-gate 
50247c478bd9Sstevel@tonic-gate 	if (errno == 0) {
50257c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Types file for module %s is "
50267c478bd9Sstevel@tonic-gate 		    "corrupt.\n"), module_name);
50277c478bd9Sstevel@tonic-gate 	}
50287c478bd9Sstevel@tonic-gate 
50297c478bd9Sstevel@tonic-gate 	return (NULL);
50307c478bd9Sstevel@tonic-gate }
50317c478bd9Sstevel@tonic-gate 
50327c478bd9Sstevel@tonic-gate /*
50337c478bd9Sstevel@tonic-gate  * Given mapped_list with is a comma seperated list of map names, and value,
50347c478bd9Sstevel@tonic-gate  * which is used to index into these maps, the function creates x new entries
50357c478bd9Sstevel@tonic-gate  * in nvpp, where x is the number of map names specified. Each of these
50367c478bd9Sstevel@tonic-gate  * entries has the value from the map in the position indexed by value and
50377c478bd9Sstevel@tonic-gate  * with name module.${MAP_NAME}. The maps are contained in the modules config
50387c478bd9Sstevel@tonic-gate  * file and have the form:
50397c478bd9Sstevel@tonic-gate  * map map1 uint32 1,23,32,45,3
50407c478bd9Sstevel@tonic-gate  * As you can see the map values are uint32, and along with uint8 are the
50417c478bd9Sstevel@tonic-gate  * only supported types at the moment.
50427c478bd9Sstevel@tonic-gate  *
50437c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if one of the maps specified in mapped_list
50447c478bd9Sstevel@tonic-gate  * doesn't exist, if value is not a valid map position for a map, or if
50457c478bd9Sstevel@tonic-gate  * there's a resource failure. otherwise IPQOS_CONF_SUCCESS is returned.
50467c478bd9Sstevel@tonic-gate  */
50477c478bd9Sstevel@tonic-gate static int
50487c478bd9Sstevel@tonic-gate read_mapped_values(
50497c478bd9Sstevel@tonic-gate FILE *tfp,
50507c478bd9Sstevel@tonic-gate nvlist_t **nvlp,
50517c478bd9Sstevel@tonic-gate char *module,
50527c478bd9Sstevel@tonic-gate char *mapped_list,
50537c478bd9Sstevel@tonic-gate int value)
50547c478bd9Sstevel@tonic-gate {
50557c478bd9Sstevel@tonic-gate 	char *map_name, *lastparam, *tmpname;
50567c478bd9Sstevel@tonic-gate 	int res;
50577c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
50587c478bd9Sstevel@tonic-gate 	char dfltst[IPQOS_VALST_MAXLEN+1] = "";
50597c478bd9Sstevel@tonic-gate 	str_val_nd_t *enum_nvs;
50607c478bd9Sstevel@tonic-gate 	place_t place;
50617c478bd9Sstevel@tonic-gate 
50627c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In read_mapped_values\n");
50637c478bd9Sstevel@tonic-gate 
50647c478bd9Sstevel@tonic-gate 	map_name = (char *)strtok_r(mapped_list, ",", &lastparam);
50657c478bd9Sstevel@tonic-gate 	while (map_name != NULL) {
50667c478bd9Sstevel@tonic-gate 		char *tokval, *lastval;
50677c478bd9Sstevel@tonic-gate 		int index = 0;
50687c478bd9Sstevel@tonic-gate 
50697c478bd9Sstevel@tonic-gate 		/*
50707c478bd9Sstevel@tonic-gate 		 * get map info from types file.
50717c478bd9Sstevel@tonic-gate 		 */
50727c478bd9Sstevel@tonic-gate 		place = PL_MAP;
50737c478bd9Sstevel@tonic-gate 		res = readtype(tfp, module, map_name, &type, &enum_nvs,
50747c478bd9Sstevel@tonic-gate 		    dfltst, B_FALSE, &place);
50757c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
50767c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
50777c478bd9Sstevel@tonic-gate 		}
50787c478bd9Sstevel@tonic-gate 
50797c478bd9Sstevel@tonic-gate 		/*
50807c478bd9Sstevel@tonic-gate 		 * Just keep browsing the list till we get to the element
50817c478bd9Sstevel@tonic-gate 		 * with the index from the value parameter or the end.
50827c478bd9Sstevel@tonic-gate 		 */
50837c478bd9Sstevel@tonic-gate 		tokval = (char *)strtok_r(dfltst, ",", &lastval);
50847c478bd9Sstevel@tonic-gate 		for (;;) {
50857c478bd9Sstevel@tonic-gate 			if (tokval == NULL) {
50867c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
50877c478bd9Sstevel@tonic-gate 				    gettext("Invalid value, %u, line %u.\n"),
50887c478bd9Sstevel@tonic-gate 				    value, lineno);
50897c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
50907c478bd9Sstevel@tonic-gate 			}
50917c478bd9Sstevel@tonic-gate 			if (index++ == value) {
50927c478bd9Sstevel@tonic-gate 				break;
50937c478bd9Sstevel@tonic-gate 			}
50947c478bd9Sstevel@tonic-gate 			tokval = (char *)strtok_r(NULL, ",", &lastval);
50957c478bd9Sstevel@tonic-gate 		}
50967c478bd9Sstevel@tonic-gate 
50977c478bd9Sstevel@tonic-gate 
50987c478bd9Sstevel@tonic-gate 		/*
50997c478bd9Sstevel@tonic-gate 		 * create fully qualified parameter name for map value.
51007c478bd9Sstevel@tonic-gate 		 */
51017c478bd9Sstevel@tonic-gate 		tmpname = prepend_module_name(map_name, module);
51027c478bd9Sstevel@tonic-gate 		if (tmpname == NULL) {
51037c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
51047c478bd9Sstevel@tonic-gate 		}
51057c478bd9Sstevel@tonic-gate 
51067c478bd9Sstevel@tonic-gate 		/*
51077c478bd9Sstevel@tonic-gate 		 * add map value with fqn to parameter nvlist.
51087c478bd9Sstevel@tonic-gate 		 */
51097c478bd9Sstevel@tonic-gate 		IPQOSCDBG2(L0, "Adding map %s, value %u to nvlist\n",
51107c478bd9Sstevel@tonic-gate 		    tmpname, atoi(tokval));
51117c478bd9Sstevel@tonic-gate 		switch (type) {
51127c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_UINT8: {
51137c478bd9Sstevel@tonic-gate 				res = nvlist_add_byte(*nvlp, tmpname,
51147c478bd9Sstevel@tonic-gate 				    (uint8_t)atoi(tokval));
51157c478bd9Sstevel@tonic-gate 				if (res != 0)  {
51167c478bd9Sstevel@tonic-gate 					free(tmpname);
51177c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
51187c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint8");
51197c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
51207c478bd9Sstevel@tonic-gate 				}
51217c478bd9Sstevel@tonic-gate 				break;
51227c478bd9Sstevel@tonic-gate 			}
51237c478bd9Sstevel@tonic-gate 			case IPQOS_DATA_TYPE_UINT32: {
51247c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32(*nvlp, tmpname,
51257c478bd9Sstevel@tonic-gate 				    (uint32_t)atoi(tokval));
51267c478bd9Sstevel@tonic-gate 				if (res != 0)  {
51277c478bd9Sstevel@tonic-gate 					free(tmpname);
51287c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
51297c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32");
51307c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
51317c478bd9Sstevel@tonic-gate 				}
51327c478bd9Sstevel@tonic-gate 				break;
51337c478bd9Sstevel@tonic-gate 			}
51347c478bd9Sstevel@tonic-gate 			default: {
51357c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
51367c478bd9Sstevel@tonic-gate 				    gettext("Types file for module %s is "
51377c478bd9Sstevel@tonic-gate 				    "corrupt.\n"), module);
51387c478bd9Sstevel@tonic-gate 				IPQOSCDBG1(L0, "Unsupported map type for "
51397c478bd9Sstevel@tonic-gate 				    "parameter %s given in types file.\n",
51407c478bd9Sstevel@tonic-gate 				    map_name);
51417c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
51427c478bd9Sstevel@tonic-gate 			}
51437c478bd9Sstevel@tonic-gate 		}
51447c478bd9Sstevel@tonic-gate 		free(tmpname);
51457c478bd9Sstevel@tonic-gate 
51467c478bd9Sstevel@tonic-gate 		map_name = (char *)strtok_r(NULL, ",", &lastparam);
51477c478bd9Sstevel@tonic-gate 	}
51487c478bd9Sstevel@tonic-gate 
51497c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
51507c478bd9Sstevel@tonic-gate }
51517c478bd9Sstevel@tonic-gate 
51527c478bd9Sstevel@tonic-gate /*
51537c478bd9Sstevel@tonic-gate  * Parses the string info_str into it's components. Its format is:
51547c478bd9Sstevel@tonic-gate  * SIZE','[ENUM_DEF | RANGE], where SIZE is the size of the array,
51557c478bd9Sstevel@tonic-gate  * ENUM_DEF is the definition of the enumeration for this array,
51567c478bd9Sstevel@tonic-gate  * and RANGE is the set of values this array can accept. In
51577c478bd9Sstevel@tonic-gate  * the event this array has an enumeration definition enum_nvs is
51587c478bd9Sstevel@tonic-gate  * set to point at a str_val_nd_t structure which stores the names
51597c478bd9Sstevel@tonic-gate  * and values associated with this enumeration. Otherwise, if this
51607c478bd9Sstevel@tonic-gate  * is not an enumerated array, lower and upper are set to the lower
51617c478bd9Sstevel@tonic-gate  * and upper values of RANGE.
51627c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR due to unexpected parse errors, else
51637c478bd9Sstevel@tonic-gate  * IPQOS_CONF_SUCCESS.
51647c478bd9Sstevel@tonic-gate  */
51657c478bd9Sstevel@tonic-gate static int
51667c478bd9Sstevel@tonic-gate read_int_array_info(
51677c478bd9Sstevel@tonic-gate char *info_str,
51687c478bd9Sstevel@tonic-gate str_val_nd_t **enum_nvs,
51697c478bd9Sstevel@tonic-gate uint32_t *size,
51707c478bd9Sstevel@tonic-gate int *lower,
51717c478bd9Sstevel@tonic-gate int *upper,
51727c478bd9Sstevel@tonic-gate char *module)
51737c478bd9Sstevel@tonic-gate {
51747c478bd9Sstevel@tonic-gate 	int res;
51757c478bd9Sstevel@tonic-gate 	char *end;
51767c478bd9Sstevel@tonic-gate 	char *token;
51777c478bd9Sstevel@tonic-gate 	char *tmp;
51787c478bd9Sstevel@tonic-gate 
51797c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "In read_array_info: info_str: %s\n",
51807c478bd9Sstevel@tonic-gate 	    (info_str != NULL) ? info_str : "NULL");
51817c478bd9Sstevel@tonic-gate 
51827c478bd9Sstevel@tonic-gate 	if (info_str == NULL) {
51837c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L0, "Null info string\n");
51847c478bd9Sstevel@tonic-gate 		goto fail;
51857c478bd9Sstevel@tonic-gate 	}
51867c478bd9Sstevel@tonic-gate 
51877c478bd9Sstevel@tonic-gate 	/*
51887c478bd9Sstevel@tonic-gate 	 * read size.
51897c478bd9Sstevel@tonic-gate 	 */
51907c478bd9Sstevel@tonic-gate 	token = strtok(info_str, ",");
51917c478bd9Sstevel@tonic-gate 	*size = (uint32_t)strtol(token, &end, 10);
51927c478bd9Sstevel@tonic-gate 	SKIPWS(end);
51937c478bd9Sstevel@tonic-gate 	if ((end == token) || (*end != NULL)) {
51947c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L0, "Invalid size\n");
51957c478bd9Sstevel@tonic-gate 		goto fail;
51967c478bd9Sstevel@tonic-gate 	}
51977c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "read size: %u\n", *size);
51987c478bd9Sstevel@tonic-gate 
51997c478bd9Sstevel@tonic-gate 	/*
52007c478bd9Sstevel@tonic-gate 	 * check we have another string.
52017c478bd9Sstevel@tonic-gate 	 */
52027c478bd9Sstevel@tonic-gate 	token = strtok(NULL, "\n");
52037c478bd9Sstevel@tonic-gate 	if (token == NULL) {
52047c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L0, "Missing range/enum def\n");
52057c478bd9Sstevel@tonic-gate 		goto fail;
52067c478bd9Sstevel@tonic-gate 	}
52077c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "range/enum def: %s\n", token);
52087c478bd9Sstevel@tonic-gate 
52097c478bd9Sstevel@tonic-gate 	/*
52107c478bd9Sstevel@tonic-gate 	 * check if enumeration set or integer set and read enumeration
52117c478bd9Sstevel@tonic-gate 	 * definition or integer range respectively.
52127c478bd9Sstevel@tonic-gate 	 */
52137c478bd9Sstevel@tonic-gate 	tmp = strchr(token, CURL_BEGIN);
52147c478bd9Sstevel@tonic-gate 	if (tmp == NULL) {	/* a numeric range */
52157c478bd9Sstevel@tonic-gate 		res = readrange(token, lower, upper);
52167c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
52177c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "Failed reading range\n");
52187c478bd9Sstevel@tonic-gate 			goto fail;
52197c478bd9Sstevel@tonic-gate 		}
52207c478bd9Sstevel@tonic-gate 	} else {		/* an enumeration */
52217c478bd9Sstevel@tonic-gate 		*enum_nvs = read_enum_nvs(token, module);
52227c478bd9Sstevel@tonic-gate 		if (*enum_nvs == NULL) {
52237c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "Failed reading enum def\n");
52247c478bd9Sstevel@tonic-gate 			goto fail;
52257c478bd9Sstevel@tonic-gate 		}
52267c478bd9Sstevel@tonic-gate 	}
52277c478bd9Sstevel@tonic-gate 
52287c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
52297c478bd9Sstevel@tonic-gate fail:
52307c478bd9Sstevel@tonic-gate 	ipqos_msg(MT_ERROR,
52317c478bd9Sstevel@tonic-gate 	    gettext("Types file for module %s is corrupt.\n"), module);
52327c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
52337c478bd9Sstevel@tonic-gate }
52347c478bd9Sstevel@tonic-gate 
52357c478bd9Sstevel@tonic-gate /*
52367c478bd9Sstevel@tonic-gate  * reads the value of an enumeration parameter from first_token and fp.
52377c478bd9Sstevel@tonic-gate  * first_token is the first token of the value.
52387c478bd9Sstevel@tonic-gate  * The format expected is NAME | { NAME1 [, NAME2 ] [, NAME3 ]  }.
52397c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
52407c478bd9Sstevel@tonic-gate  */
52417c478bd9Sstevel@tonic-gate static int
52427c478bd9Sstevel@tonic-gate read_enum_value(
52437c478bd9Sstevel@tonic-gate FILE *fp,
52447c478bd9Sstevel@tonic-gate char *first_token,
52457c478bd9Sstevel@tonic-gate str_val_nd_t *enum_vals,
52467c478bd9Sstevel@tonic-gate uint32_t *val)
52477c478bd9Sstevel@tonic-gate {
52487c478bd9Sstevel@tonic-gate 
52497c478bd9Sstevel@tonic-gate 	uint32_t u32;
52507c478bd9Sstevel@tonic-gate 	int ret;
52517c478bd9Sstevel@tonic-gate 	char *tk;
52527c478bd9Sstevel@tonic-gate 	char *lo = NULL;
52537c478bd9Sstevel@tonic-gate 	char *cm;
52547c478bd9Sstevel@tonic-gate 	int name_expected = 0;
52557c478bd9Sstevel@tonic-gate 
52567c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In read_enum_value\n");
52577c478bd9Sstevel@tonic-gate 
52587c478bd9Sstevel@tonic-gate 	/* init param val */
52597c478bd9Sstevel@tonic-gate 	*val = 0;
52607c478bd9Sstevel@tonic-gate 
52617c478bd9Sstevel@tonic-gate 	/* first token not curl_begin, so lookup its value */
52627c478bd9Sstevel@tonic-gate 
52637c478bd9Sstevel@tonic-gate 	if (*first_token != CURL_BEGIN) {
52647c478bd9Sstevel@tonic-gate 		ret = str_val_list_lookup(enum_vals, first_token, val);
52657c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
52667c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
52677c478bd9Sstevel@tonic-gate 			    gettext("Unrecognized value, %s, line %u.\n"),
52687c478bd9Sstevel@tonic-gate 			    first_token, lineno);
52697c478bd9Sstevel@tonic-gate 			return (ret);
52707c478bd9Sstevel@tonic-gate 		}
52717c478bd9Sstevel@tonic-gate 
52727c478bd9Sstevel@tonic-gate 	/* curl_begin, so read values till curl_end, dicing at ',' */
52737c478bd9Sstevel@tonic-gate 	} else {
52747c478bd9Sstevel@tonic-gate 
52757c478bd9Sstevel@tonic-gate 		name_expected++;
52767c478bd9Sstevel@tonic-gate 
52777c478bd9Sstevel@tonic-gate 		for (;;) {
52787c478bd9Sstevel@tonic-gate 
52797c478bd9Sstevel@tonic-gate 			/*
52807c478bd9Sstevel@tonic-gate 			 * no leftover from pervious iteration so read new
52817c478bd9Sstevel@tonic-gate 			 * token. This leftover happens because readtoken
52827c478bd9Sstevel@tonic-gate 			 * doesn't interpret comma's as special characters
52837c478bd9Sstevel@tonic-gate 			 * and thus could return 'val1,val2' as one token.
52847c478bd9Sstevel@tonic-gate 			 * If this happens the val1 will be used in the
52857c478bd9Sstevel@tonic-gate 			 * current iteration and what follows saved in lo
52867c478bd9Sstevel@tonic-gate 			 * for processing by successive iterations.
52877c478bd9Sstevel@tonic-gate 			 */
52887c478bd9Sstevel@tonic-gate 
52897c478bd9Sstevel@tonic-gate 			if (lo == NULL) {
52907c478bd9Sstevel@tonic-gate 				ret = readtoken(fp, &tk);
52917c478bd9Sstevel@tonic-gate 				if (ret == IPQOS_CONF_ERR) {
52927c478bd9Sstevel@tonic-gate 					return (ret);
52937c478bd9Sstevel@tonic-gate 				} else if (ret == IPQOS_CONF_EOF) {
52947c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
52957c478bd9Sstevel@tonic-gate 					    gettext("Unexpected EOF.\n"));
52967c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
52977c478bd9Sstevel@tonic-gate 
52987c478bd9Sstevel@tonic-gate 				}
52997c478bd9Sstevel@tonic-gate 			} else {	/* previous leftover, so use it */
53007c478bd9Sstevel@tonic-gate 
53017c478bd9Sstevel@tonic-gate 				IPQOSCDBG1(L1, "Using leftover %s.\n", lo);
53027c478bd9Sstevel@tonic-gate 				tk = lo;
53037c478bd9Sstevel@tonic-gate 				lo = NULL;
53047c478bd9Sstevel@tonic-gate 			}
53057c478bd9Sstevel@tonic-gate 
53067c478bd9Sstevel@tonic-gate 			if (name_expected) {
53077c478bd9Sstevel@tonic-gate 				if (ret == IPQOS_CONF_CURL_END ||
53087c478bd9Sstevel@tonic-gate 				    tk[0] == ',') {
53097c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
53107c478bd9Sstevel@tonic-gate 					    gettext("Malformed value list "
53117c478bd9Sstevel@tonic-gate 					    "line %u.\n"), lineno);
53127c478bd9Sstevel@tonic-gate 					free(tk);
53137c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
53147c478bd9Sstevel@tonic-gate 				}
53157c478bd9Sstevel@tonic-gate 
53167c478bd9Sstevel@tonic-gate 				/*
53177c478bd9Sstevel@tonic-gate 				 * check if this token contains a ',' and
53187c478bd9Sstevel@tonic-gate 				 * if so store it and what follows for next
53197c478bd9Sstevel@tonic-gate 				 * iteration.
53207c478bd9Sstevel@tonic-gate 				 */
53217c478bd9Sstevel@tonic-gate 				cm = strchr(tk, ',');
53227c478bd9Sstevel@tonic-gate 				if (cm != NULL) {
53237c478bd9Sstevel@tonic-gate 					lo = malloc(strlen(cm) + 1);
53247c478bd9Sstevel@tonic-gate 					if (lo == NULL) {
53257c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ENOSTR, "malloc");
53267c478bd9Sstevel@tonic-gate 						free(tk);
53277c478bd9Sstevel@tonic-gate 						return (IPQOS_CONF_ERR);
53287c478bd9Sstevel@tonic-gate 					}
53297c478bd9Sstevel@tonic-gate 
53307c478bd9Sstevel@tonic-gate 					(void) strcpy(lo, cm);
53317c478bd9Sstevel@tonic-gate 					*cm = '\0';
53327c478bd9Sstevel@tonic-gate 				}
53337c478bd9Sstevel@tonic-gate 
53347c478bd9Sstevel@tonic-gate 
53357c478bd9Sstevel@tonic-gate 				/* get name value and add to total val */
53367c478bd9Sstevel@tonic-gate 
53377c478bd9Sstevel@tonic-gate 				ret = str_val_list_lookup(enum_vals, tk, &u32);
53387c478bd9Sstevel@tonic-gate 				if (ret != IPQOS_CONF_SUCCESS) {
53397c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
53407c478bd9Sstevel@tonic-gate 					    gettext("Unrecognized value, %s, "
53417c478bd9Sstevel@tonic-gate 					    "line %u.\n"), tk, lineno);
53427c478bd9Sstevel@tonic-gate 					free(tk);
53437c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
53447c478bd9Sstevel@tonic-gate 				}
53457c478bd9Sstevel@tonic-gate 
53467c478bd9Sstevel@tonic-gate 				*val = *val | u32;
53477c478bd9Sstevel@tonic-gate 				name_expected--;
53487c478bd9Sstevel@tonic-gate 
53497c478bd9Sstevel@tonic-gate 			/* comma or curl end accepted */
53507c478bd9Sstevel@tonic-gate 			} else {
53517c478bd9Sstevel@tonic-gate 
53527c478bd9Sstevel@tonic-gate 				/* we've reached curl_end so break */
53537c478bd9Sstevel@tonic-gate 
53547c478bd9Sstevel@tonic-gate 				if (ret == IPQOS_CONF_CURL_END) {
53557c478bd9Sstevel@tonic-gate 					free(tk);
53567c478bd9Sstevel@tonic-gate 					break;
53577c478bd9Sstevel@tonic-gate 
53587c478bd9Sstevel@tonic-gate 				/* not curl end and not comma */
53597c478bd9Sstevel@tonic-gate 
53607c478bd9Sstevel@tonic-gate 				} else if (tk[0] != ',') {
53617c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
53627c478bd9Sstevel@tonic-gate 					    gettext("Malformed value list "
53637c478bd9Sstevel@tonic-gate 					    "line %u.\n"), lineno);
53647c478bd9Sstevel@tonic-gate 					free(tk);
53657c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
53667c478bd9Sstevel@tonic-gate 				}
53677c478bd9Sstevel@tonic-gate 
53687c478bd9Sstevel@tonic-gate 				/*
53697c478bd9Sstevel@tonic-gate 				 * store anything after the comma for next
53707c478bd9Sstevel@tonic-gate 				 * iteration.
53717c478bd9Sstevel@tonic-gate 				 */
53727c478bd9Sstevel@tonic-gate 				if (tk[1] != '\0') {
53737c478bd9Sstevel@tonic-gate 					lo = malloc(strlen(&tk[1]) + 1);
53747c478bd9Sstevel@tonic-gate 					if (lo == NULL) {
53757c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ENOSTR, "malloc");
53767c478bd9Sstevel@tonic-gate 						free(tk);
53777c478bd9Sstevel@tonic-gate 						return (IPQOS_CONF_ERR);
53787c478bd9Sstevel@tonic-gate 					}
53797c478bd9Sstevel@tonic-gate 					(void) strcpy(lo, &tk[1]);
53807c478bd9Sstevel@tonic-gate 				}
53817c478bd9Sstevel@tonic-gate 
53827c478bd9Sstevel@tonic-gate 				name_expected++;
53837c478bd9Sstevel@tonic-gate 			}
53847c478bd9Sstevel@tonic-gate 
53857c478bd9Sstevel@tonic-gate 			free(tk);
53867c478bd9Sstevel@tonic-gate 		}
53877c478bd9Sstevel@tonic-gate 	}
53887c478bd9Sstevel@tonic-gate 
53897c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "value returned is: %u\n", *val);
53907c478bd9Sstevel@tonic-gate 
53917c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
53927c478bd9Sstevel@tonic-gate }
53937c478bd9Sstevel@tonic-gate 
53947c478bd9Sstevel@tonic-gate /*
53957c478bd9Sstevel@tonic-gate  * read the set of permanent classes/filter from the types file ref'd by tfp
53967c478bd9Sstevel@tonic-gate  * and store them in a string table pointed to by perm_items,
53977c478bd9Sstevel@tonic-gate  * with *nitems getting set to number of items read. perm_filters is set
53987c478bd9Sstevel@tonic-gate  * to 1 if we're searching for permanent filters, else 0 for classes.
53997c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS.
54007c478bd9Sstevel@tonic-gate  */
54017c478bd9Sstevel@tonic-gate static int
54027c478bd9Sstevel@tonic-gate read_perm_items(
54037c478bd9Sstevel@tonic-gate int perm_filters,
54047c478bd9Sstevel@tonic-gate FILE *tfp,
54057c478bd9Sstevel@tonic-gate char *module_name,
54067c478bd9Sstevel@tonic-gate char ***perm_items,
54077c478bd9Sstevel@tonic-gate int *nitems)
54087c478bd9Sstevel@tonic-gate {
54097c478bd9Sstevel@tonic-gate 
54107c478bd9Sstevel@tonic-gate 	char lbuf[IPQOS_CONF_TYPE_LINE_LEN];
54117c478bd9Sstevel@tonic-gate 	int cnt = 0;
54127c478bd9Sstevel@tonic-gate 	char name[IPQOS_CONF_NAME_LEN+1];
54137c478bd9Sstevel@tonic-gate 	char foo[IPQOS_CONF_NAME_LEN+1];
54147c478bd9Sstevel@tonic-gate 	int res;
54157c478bd9Sstevel@tonic-gate 	char **items = NULL;
54167c478bd9Sstevel@tonic-gate 	char **tmp;
54177c478bd9Sstevel@tonic-gate 	char *marker;
54187c478bd9Sstevel@tonic-gate 
54197c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In read_perm_items\n");
54207c478bd9Sstevel@tonic-gate 
54217c478bd9Sstevel@tonic-gate 
54227c478bd9Sstevel@tonic-gate 	/* seek to start of types file */
54237c478bd9Sstevel@tonic-gate 
54247c478bd9Sstevel@tonic-gate 	if (fseek(tfp, 0, SEEK_SET) != 0) {
54257c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "fseek");
54267c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
54277c478bd9Sstevel@tonic-gate 	}
54287c478bd9Sstevel@tonic-gate 
54297c478bd9Sstevel@tonic-gate 	/* select which marker were looking for */
54307c478bd9Sstevel@tonic-gate 
54317c478bd9Sstevel@tonic-gate 	if (perm_filters) {
54327c478bd9Sstevel@tonic-gate 		marker = IPQOS_CONF_PERM_FILTER_MK;
54337c478bd9Sstevel@tonic-gate 	} else {
54347c478bd9Sstevel@tonic-gate 		marker = IPQOS_CONF_PERM_CLASS_MK;
54357c478bd9Sstevel@tonic-gate 	}
54367c478bd9Sstevel@tonic-gate 
54377c478bd9Sstevel@tonic-gate 	/* scan file line by line till end */
54387c478bd9Sstevel@tonic-gate 
54397c478bd9Sstevel@tonic-gate 	while (fgets(lbuf, IPQOS_CONF_TYPE_LINE_LEN, tfp) != NULL) {
54407c478bd9Sstevel@tonic-gate 
54417c478bd9Sstevel@tonic-gate 		/*
54427c478bd9Sstevel@tonic-gate 		 * if the line is marked as containing a default item name
54437c478bd9Sstevel@tonic-gate 		 * read the name, extend the items string array
54447c478bd9Sstevel@tonic-gate 		 * and store the string off the array.
54457c478bd9Sstevel@tonic-gate 		 */
54467c478bd9Sstevel@tonic-gate 		if (strncmp(lbuf, marker, strlen(marker)) == 0) {
54477c478bd9Sstevel@tonic-gate 
54487c478bd9Sstevel@tonic-gate 			res = sscanf(lbuf,
54497c478bd9Sstevel@tonic-gate 			    "%" VAL2STR(IPQOS_CONF_NAME_LEN) "s"
54507c478bd9Sstevel@tonic-gate 			    "%" VAL2STR(IPQOS_CONF_NAME_LEN) "s",
54517c478bd9Sstevel@tonic-gate 			    foo, name);
54527c478bd9Sstevel@tonic-gate 			if (res < 2) {
54537c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
54547c478bd9Sstevel@tonic-gate 				    gettext("Types file for module %s is "
54557c478bd9Sstevel@tonic-gate 				    "corrupt.\n"), module_name);
54567c478bd9Sstevel@tonic-gate 				IPQOSCDBG1(L0, "Missing name with a %s.\n",
54577c478bd9Sstevel@tonic-gate 				    marker);
54587c478bd9Sstevel@tonic-gate 				goto fail;
54597c478bd9Sstevel@tonic-gate 			}
54607c478bd9Sstevel@tonic-gate 
54617c478bd9Sstevel@tonic-gate 			/* extend items array to accomodate new item */
54627c478bd9Sstevel@tonic-gate 
54637c478bd9Sstevel@tonic-gate 			tmp = realloc(items, (cnt + 1) * sizeof (char *));
54647c478bd9Sstevel@tonic-gate 			if (tmp == NULL) {
54657c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "realloc");
54667c478bd9Sstevel@tonic-gate 				goto fail;
54677c478bd9Sstevel@tonic-gate 			} else {
54687c478bd9Sstevel@tonic-gate 				items = tmp;
54697c478bd9Sstevel@tonic-gate 			}
54707c478bd9Sstevel@tonic-gate 
54717c478bd9Sstevel@tonic-gate 			/* copy and store item name */
54727c478bd9Sstevel@tonic-gate 
54737c478bd9Sstevel@tonic-gate 			items[cnt] = malloc(strlen(name) + 1);
54747c478bd9Sstevel@tonic-gate 			if (items[cnt] == NULL) {
54757c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "malloc");
54767c478bd9Sstevel@tonic-gate 				goto fail;
54777c478bd9Sstevel@tonic-gate 			}
54787c478bd9Sstevel@tonic-gate 
54797c478bd9Sstevel@tonic-gate 			(void) strcpy(items[cnt], name);
54807c478bd9Sstevel@tonic-gate 			cnt++;
54817c478bd9Sstevel@tonic-gate 
54827c478bd9Sstevel@tonic-gate 
54837c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(L1, "stored %s in perm items array\n",
54847c478bd9Sstevel@tonic-gate 			    name);
54857c478bd9Sstevel@tonic-gate 		}
54867c478bd9Sstevel@tonic-gate 	}
54877c478bd9Sstevel@tonic-gate 
54887c478bd9Sstevel@tonic-gate 	*perm_items = items;
54897c478bd9Sstevel@tonic-gate 	*nitems = cnt;
54907c478bd9Sstevel@tonic-gate 
54917c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
54927c478bd9Sstevel@tonic-gate fail:
54937c478bd9Sstevel@tonic-gate 	for (cnt--; cnt >= 0; cnt--)
54947c478bd9Sstevel@tonic-gate 		free(items[cnt]);
54957c478bd9Sstevel@tonic-gate 	free(items);
54967c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
54977c478bd9Sstevel@tonic-gate }
54987c478bd9Sstevel@tonic-gate 
54997c478bd9Sstevel@tonic-gate /*
55007c478bd9Sstevel@tonic-gate  * Searches types file ref'd by tfp for the parameter named name
55017c478bd9Sstevel@tonic-gate  * with the place corresponding with place parameter. The format
55027c478bd9Sstevel@tonic-gate  * of the lines in the file are:
55037c478bd9Sstevel@tonic-gate  * PLACE NAME TYPE [ ENUM_DEF ] [ DEFAULT_STR ]
55047c478bd9Sstevel@tonic-gate  * The ENUM_DEF is an enumeration definition and is only present
55057c478bd9Sstevel@tonic-gate  * for parameters of type enum. DEFAULT_STR is a default value for
55067c478bd9Sstevel@tonic-gate  * this parameter. If present type is set to the appropriate type
55077c478bd9Sstevel@tonic-gate  * enumeration and dfltst filled with DEFAULT_STR if one was set.
55087c478bd9Sstevel@tonic-gate  * Also if the type is enum enum_nvps is made to point at a
55097c478bd9Sstevel@tonic-gate  * set of name value pairs representing ENUM_DEF.
55107c478bd9Sstevel@tonic-gate  *
55117c478bd9Sstevel@tonic-gate  * RETURNS: If any resource errors occur, or a matching parameter
55127c478bd9Sstevel@tonic-gate  * isn't found IPQOS_CONF_ERR is returned, else IPQOS_CONF_SUCCESS.
55137c478bd9Sstevel@tonic-gate  */
55147c478bd9Sstevel@tonic-gate static int
55157c478bd9Sstevel@tonic-gate readtype(
55167c478bd9Sstevel@tonic-gate FILE *tfp,
55177c478bd9Sstevel@tonic-gate char *module_name,
55187c478bd9Sstevel@tonic-gate char *name,
55197c478bd9Sstevel@tonic-gate ipqos_nvtype_t *type,
55207c478bd9Sstevel@tonic-gate str_val_nd_t **enum_nvps,
55217c478bd9Sstevel@tonic-gate char *dfltst,
55227c478bd9Sstevel@tonic-gate boolean_t allow_ipgpc_priv,
55237c478bd9Sstevel@tonic-gate place_t *place)
55247c478bd9Sstevel@tonic-gate {
55257c478bd9Sstevel@tonic-gate 
55267c478bd9Sstevel@tonic-gate 	int ac;
55277c478bd9Sstevel@tonic-gate 	char lbuf[IPQOS_CONF_TYPE_LINE_LEN];
55287c478bd9Sstevel@tonic-gate 	char param[IPQOS_CONF_PNAME_LEN+1];
55297c478bd9Sstevel@tonic-gate 	char typest[IPQOS_CONF_TYPE_LEN+1];
55307c478bd9Sstevel@tonic-gate 	char place_st[IPQOS_CONF_TYPE_LEN+1];
55317c478bd9Sstevel@tonic-gate 	char *cp;
55327c478bd9Sstevel@tonic-gate 	int x;
55337c478bd9Sstevel@tonic-gate 	char *ipgpc_nm;
55347c478bd9Sstevel@tonic-gate 	int found = 0;
55357c478bd9Sstevel@tonic-gate 
55367c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In readtype: param: %s\n", name);
55377c478bd9Sstevel@tonic-gate 
55387c478bd9Sstevel@tonic-gate 
55397c478bd9Sstevel@tonic-gate 	/*
55407c478bd9Sstevel@tonic-gate 	 * if allow_ipgpc_priv is true then we allow ipgpc parameters that are
55417c478bd9Sstevel@tonic-gate 	 * private between ipqosconf and ipgpc. eg. address masks, port masks.
55427c478bd9Sstevel@tonic-gate 	 */
55437c478bd9Sstevel@tonic-gate 	if (allow_ipgpc_priv && strcmp(module_name, IPGPC_NAME) == 0) {
55447c478bd9Sstevel@tonic-gate 		ipgpc_nm = prepend_module_name(name, IPGPC_NAME);
55457c478bd9Sstevel@tonic-gate 		if (ipgpc_nm == NULL) {
55467c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
55477c478bd9Sstevel@tonic-gate 		}
55487c478bd9Sstevel@tonic-gate 
55497c478bd9Sstevel@tonic-gate 		if (strcmp(ipgpc_nm, IPGPC_SADDR_MASK) == 0 ||
55507c478bd9Sstevel@tonic-gate 		    strcmp(ipgpc_nm, IPGPC_DADDR_MASK) == 0) {
55517c478bd9Sstevel@tonic-gate 			*type = IPQOS_DATA_TYPE_ADDRESS_MASK;
55527c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_SUCCESS);
55537c478bd9Sstevel@tonic-gate 		} else if (strcmp(ipgpc_nm, IPGPC_SPORT_MASK) == 0 ||
55547c478bd9Sstevel@tonic-gate 		    strcmp(ipgpc_nm, IPGPC_DPORT_MASK) == 0) {
55557c478bd9Sstevel@tonic-gate 			*type = IPQOS_DATA_TYPE_UINT16;
55567c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_SUCCESS);
55577c478bd9Sstevel@tonic-gate 		} else if (strcmp(ipgpc_nm, IPGPC_FILTER_TYPE) == 0) {
55587c478bd9Sstevel@tonic-gate 			*type = IPQOS_DATA_TYPE_UINT32;
55597c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_SUCCESS);
55607c478bd9Sstevel@tonic-gate 		} else if (strcmp(ipgpc_nm, IPGPC_IF_INDEX) == 0) {
55617c478bd9Sstevel@tonic-gate 			*type = IPQOS_DATA_TYPE_IFINDEX;
55627c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_SUCCESS);
55637c478bd9Sstevel@tonic-gate 		}
55647c478bd9Sstevel@tonic-gate 
55657c478bd9Sstevel@tonic-gate 		free(ipgpc_nm);
55667c478bd9Sstevel@tonic-gate 	}
55677c478bd9Sstevel@tonic-gate 
55687c478bd9Sstevel@tonic-gate 	/*
55697c478bd9Sstevel@tonic-gate 	 * read upto and including module version line.
55707c478bd9Sstevel@tonic-gate 	 */
55717c478bd9Sstevel@tonic-gate 	if (read_tfile_ver(tfp, IPQOS_MOD_STR, module_name) == -1)
55727c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
55737c478bd9Sstevel@tonic-gate 
55747c478bd9Sstevel@tonic-gate 
55757c478bd9Sstevel@tonic-gate 	/*
55767c478bd9Sstevel@tonic-gate 	 * loop reading lines of the types file until named parameter
55777c478bd9Sstevel@tonic-gate 	 * found or EOF.
55787c478bd9Sstevel@tonic-gate 	 */
55797c478bd9Sstevel@tonic-gate 	while (fgets(lbuf, IPQOS_CONF_TYPE_LINE_LEN, tfp) != NULL) {
55807c478bd9Sstevel@tonic-gate 
55817c478bd9Sstevel@tonic-gate 		/*
55827c478bd9Sstevel@tonic-gate 		 * check whether blank or commented line; if so skip
55837c478bd9Sstevel@tonic-gate 		 */
55847c478bd9Sstevel@tonic-gate 		for (cp = lbuf; isspace(*cp) && *cp != '\0'; cp++) {}
55857c478bd9Sstevel@tonic-gate 		if (*cp == '\0' || *cp == '#') {
55867c478bd9Sstevel@tonic-gate 			continue;
55877c478bd9Sstevel@tonic-gate 		}
55887c478bd9Sstevel@tonic-gate 
55897c478bd9Sstevel@tonic-gate 		dfltst[0] = '\0';
55907c478bd9Sstevel@tonic-gate 
55917c478bd9Sstevel@tonic-gate 		/*
55927c478bd9Sstevel@tonic-gate 		 * read place, param, type and if present default str
55937c478bd9Sstevel@tonic-gate 		 * from line.
55947c478bd9Sstevel@tonic-gate 		 */
55957c478bd9Sstevel@tonic-gate 		ac = sscanf(lbuf,
55967c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_CONF_TYPE_LEN) "s "
55977c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_CONF_PNAME_LEN) "s "
55987c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_CONF_TYPE_LEN) "s "
55997c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_VALST_MAXLEN) "s",
56007c478bd9Sstevel@tonic-gate 		    place_st, param, typest, dfltst);
56017c478bd9Sstevel@tonic-gate 		if (ac < 3) {
56027c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
56037c478bd9Sstevel@tonic-gate 			    gettext("Types file for module %s is corrupt.\n"),
56047c478bd9Sstevel@tonic-gate 			    module_name);
56057c478bd9Sstevel@tonic-gate 			IPQOSCDBG0(L0, "sscanf failed to read 3 strings.\n");
56067c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
56077c478bd9Sstevel@tonic-gate 		}
56087c478bd9Sstevel@tonic-gate 
56097c478bd9Sstevel@tonic-gate 		/*
56107c478bd9Sstevel@tonic-gate 		 * if the place and name match no need to look any further.
56117c478bd9Sstevel@tonic-gate 		 */
56127c478bd9Sstevel@tonic-gate 		if ((*place == PL_ANY) ||
56137c478bd9Sstevel@tonic-gate 		    ((*place == PL_PARAMS) &&
56147c478bd9Sstevel@tonic-gate 		    strcmp(place_st, IPQOS_PLACE_PRM_STR) == 0) ||
56157c478bd9Sstevel@tonic-gate 		    ((*place == PL_FILTER) &&
56167c478bd9Sstevel@tonic-gate 		    strcmp(place_st, IPQOS_PLACE_FILTER_STR) == 0) ||
56177c478bd9Sstevel@tonic-gate 		    ((*place == PL_MAP) &&
56187c478bd9Sstevel@tonic-gate 		    strcmp(place_st, IPQOS_PLACE_MAP_STR) == 0)) {
56197c478bd9Sstevel@tonic-gate 			if (strcmp(param, name) == 0) {
56207c478bd9Sstevel@tonic-gate 				found++;
56217c478bd9Sstevel@tonic-gate 				break;
56227c478bd9Sstevel@tonic-gate 			}
56237c478bd9Sstevel@tonic-gate 		}
56247c478bd9Sstevel@tonic-gate 	}
56257c478bd9Sstevel@tonic-gate 	if (found == 0) {
56267c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
56277c478bd9Sstevel@tonic-gate 		    gettext("Invalid parameter, %s, line %u.\n"), name,
56287c478bd9Sstevel@tonic-gate 		    lineno);
56297c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
56307c478bd9Sstevel@tonic-gate 	}
56317c478bd9Sstevel@tonic-gate 
56327c478bd9Sstevel@tonic-gate 	/*
56337c478bd9Sstevel@tonic-gate 	 * set the place parameter to the actual place when the PL_ANY flag
56347c478bd9Sstevel@tonic-gate 	 * was set.
56357c478bd9Sstevel@tonic-gate 	 */
56367c478bd9Sstevel@tonic-gate 	if (*place == PL_ANY) {
56377c478bd9Sstevel@tonic-gate 		if (strcmp(place_st, IPQOS_PLACE_PRM_STR) == 0) {
56387c478bd9Sstevel@tonic-gate 			*place = PL_PARAMS;
56397c478bd9Sstevel@tonic-gate 		} else if (strcmp(place_st, IPQOS_PLACE_FILTER_STR) == 0) {
56407c478bd9Sstevel@tonic-gate 			*place = PL_FILTER;
56417c478bd9Sstevel@tonic-gate 		} else if (strcmp(place_st, IPQOS_PLACE_MAP_STR) == 0) {
56427c478bd9Sstevel@tonic-gate 			*place = PL_MAP;
56437c478bd9Sstevel@tonic-gate 		}
56447c478bd9Sstevel@tonic-gate 	}
56457c478bd9Sstevel@tonic-gate 
56467c478bd9Sstevel@tonic-gate 	/*
56477c478bd9Sstevel@tonic-gate 	 * get type enumeration
56487c478bd9Sstevel@tonic-gate 	 */
56497c478bd9Sstevel@tonic-gate 	for (x = 0; nv_types[x].string[0]; x++) {
56507c478bd9Sstevel@tonic-gate 		if (strcmp(nv_types[x].string, typest) == 0) {
56517c478bd9Sstevel@tonic-gate 			break;
56527c478bd9Sstevel@tonic-gate 		}
56537c478bd9Sstevel@tonic-gate 	}
56547c478bd9Sstevel@tonic-gate 	/*
56557c478bd9Sstevel@tonic-gate 	 * check that we have a type corresponding with the one the types
56567c478bd9Sstevel@tonic-gate 	 * file specifies.
56577c478bd9Sstevel@tonic-gate 	 */
56587c478bd9Sstevel@tonic-gate 	if (nv_types[x].string[0] == '\0') {
56597c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
56607c478bd9Sstevel@tonic-gate 		    gettext("Types file for module %s is corrupt.\n"),
56617c478bd9Sstevel@tonic-gate 		    module_name);
56627c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
56637c478bd9Sstevel@tonic-gate 	}
56647c478bd9Sstevel@tonic-gate 	*type = nv_types[x].value;
56657c478bd9Sstevel@tonic-gate 
56667c478bd9Sstevel@tonic-gate 	/*
56677c478bd9Sstevel@tonic-gate 	 * if enumeration type get set of name/vals and any default value
56687c478bd9Sstevel@tonic-gate 	 */
56697c478bd9Sstevel@tonic-gate 	if (*type == IPQOS_DATA_TYPE_ENUM) {
56707c478bd9Sstevel@tonic-gate 		*enum_nvps = read_enum_nvs(lbuf, module_name);
56717c478bd9Sstevel@tonic-gate 		if (*enum_nvps == NULL) {
56727c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
56737c478bd9Sstevel@tonic-gate 		}
56747c478bd9Sstevel@tonic-gate 
56757c478bd9Sstevel@tonic-gate 		dfltst[0] = '\0';
56767c478bd9Sstevel@tonic-gate 		cp = strchr(lbuf, CURL_END);
56777c478bd9Sstevel@tonic-gate 		(void) sscanf(++cp,
56787c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_VALST_MAXLEN) "s", dfltst);
56797c478bd9Sstevel@tonic-gate 	}
56807c478bd9Sstevel@tonic-gate 
56817c478bd9Sstevel@tonic-gate 
56827c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "read type: %s default: %s\n", nv_types[x].string,
56837c478bd9Sstevel@tonic-gate 	    *dfltst ? dfltst : "None");
56847c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
56857c478bd9Sstevel@tonic-gate }
56867c478bd9Sstevel@tonic-gate 
56877c478bd9Sstevel@tonic-gate 
56887c478bd9Sstevel@tonic-gate /*
56897c478bd9Sstevel@tonic-gate  * Reads a name and a value from file ref'd by cfp into list indirectly
56907c478bd9Sstevel@tonic-gate  * ref'd by nvlp; If this list is NULL it will be created to accomodate
56917c478bd9Sstevel@tonic-gate  * the name/value. The name must be either a special token for
56927c478bd9Sstevel@tonic-gate  * for the place, or be present in the module types file ref'd by tfp.
56937c478bd9Sstevel@tonic-gate  * *type is set to the enumeration of the type of the parameter and
56947c478bd9Sstevel@tonic-gate  * nvp to point at the element with the nvlp ref'd list.
56957c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_CURL_END if read CURL_END as name,
56967c478bd9Sstevel@tonic-gate  * IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS.
56977c478bd9Sstevel@tonic-gate  */
56987c478bd9Sstevel@tonic-gate static int
56997c478bd9Sstevel@tonic-gate readnvpair(
57007c478bd9Sstevel@tonic-gate FILE *cfp,
57017c478bd9Sstevel@tonic-gate FILE *tfp,
57027c478bd9Sstevel@tonic-gate nvlist_t **nvlp,
57037c478bd9Sstevel@tonic-gate nvpair_t **nvp,
57047c478bd9Sstevel@tonic-gate ipqos_nvtype_t *type,
57057c478bd9Sstevel@tonic-gate place_t place,
57067c478bd9Sstevel@tonic-gate char *module_name)
57077c478bd9Sstevel@tonic-gate {
57087c478bd9Sstevel@tonic-gate 
57097c478bd9Sstevel@tonic-gate 	char *name = NULL;
57107c478bd9Sstevel@tonic-gate 	char *valst = NULL;
57117c478bd9Sstevel@tonic-gate 	int res;
57127c478bd9Sstevel@tonic-gate 	char *tmp;
57137c478bd9Sstevel@tonic-gate 	str_val_nd_t *enum_nvs = NULL;
57147c478bd9Sstevel@tonic-gate 	char dfltst[IPQOS_VALST_MAXLEN+1];
57157c478bd9Sstevel@tonic-gate 
57167c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "in readnvpair\n");
57177c478bd9Sstevel@tonic-gate 
57187c478bd9Sstevel@tonic-gate 	/*
57197c478bd9Sstevel@tonic-gate 	 * read nvpair name
57207c478bd9Sstevel@tonic-gate 	 */
57217c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &name);
57227c478bd9Sstevel@tonic-gate 
57237c478bd9Sstevel@tonic-gate 	/*
57247c478bd9Sstevel@tonic-gate 	 * if reached eof, curl end or error encountered return to caller
57257c478bd9Sstevel@tonic-gate 	 */
57267c478bd9Sstevel@tonic-gate 	if (res == IPQOS_CONF_EOF) {
57277c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n"));
57287c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
57297c478bd9Sstevel@tonic-gate 	} else if (res == IPQOS_CONF_ERR) {
57307c478bd9Sstevel@tonic-gate 		return (res);
57317c478bd9Sstevel@tonic-gate 	} else if (res == IPQOS_CONF_CURL_END) {
57327c478bd9Sstevel@tonic-gate 		free(name);
57337c478bd9Sstevel@tonic-gate 		return (res);
57347c478bd9Sstevel@tonic-gate 	}
57357c478bd9Sstevel@tonic-gate 
57367c478bd9Sstevel@tonic-gate 	/*
57377c478bd9Sstevel@tonic-gate 	 * read nvpair value
57387c478bd9Sstevel@tonic-gate 	 */
57397c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &valst);
57407c478bd9Sstevel@tonic-gate 
57417c478bd9Sstevel@tonic-gate 	/*
57427c478bd9Sstevel@tonic-gate 	 * check we've read a valid value
57437c478bd9Sstevel@tonic-gate 	 */
57447c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS && res != IPQOS_CONF_CURL_BEGIN) {
57457c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_EOF) {
57467c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n"));
57477c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
57487c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
57497c478bd9Sstevel@tonic-gate 			    gettext("Missing parameter value line %u.\n"),
57507c478bd9Sstevel@tonic-gate 			    lineno);
57517c478bd9Sstevel@tonic-gate 			free(valst);
57527c478bd9Sstevel@tonic-gate 		}	/* we do nothing special for IPQOS_CONF_ERR */
57537c478bd9Sstevel@tonic-gate 		free(name);
57547c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
57557c478bd9Sstevel@tonic-gate 	}
57567c478bd9Sstevel@tonic-gate 
57577c478bd9Sstevel@tonic-gate 	/*
57587c478bd9Sstevel@tonic-gate 	 * check for generic parameters.
57597c478bd9Sstevel@tonic-gate 	 */
57607c478bd9Sstevel@tonic-gate 
57617c478bd9Sstevel@tonic-gate 	if ((place == PL_CLASS) &&
57627c478bd9Sstevel@tonic-gate 	    strcmp(name, IPQOS_CONF_NEXT_ACTION_STR) == 0) {
57637c478bd9Sstevel@tonic-gate 		*type = IPQOS_DATA_TYPE_ACTION;
57647c478bd9Sstevel@tonic-gate 
57657c478bd9Sstevel@tonic-gate 	} else if (place == PL_PARAMS &&
57667c478bd9Sstevel@tonic-gate 	    strcmp(name, IPQOS_CONF_GLOBAL_STATS_STR) == 0 ||
57677c478bd9Sstevel@tonic-gate 	    place == PL_CLASS &&
57687c478bd9Sstevel@tonic-gate 	    strcmp(name, IPQOS_CONF_STATS_ENABLE_STR) == 0) {
57697c478bd9Sstevel@tonic-gate 		*type = IPQOS_DATA_TYPE_BOOLEAN;
57707c478bd9Sstevel@tonic-gate 
57717c478bd9Sstevel@tonic-gate 	} else if (tfp == NULL ||
57727c478bd9Sstevel@tonic-gate 	    ((place != PL_PARAMS) && strcmp(name, IPQOS_CONF_NAME_STR) == 0) ||
57737c478bd9Sstevel@tonic-gate 	    (place == PL_FILTER) && (strcmp(name, IPQOS_CONF_CLASS_STR) ==
57747c478bd9Sstevel@tonic-gate 	    0) ||
57757c478bd9Sstevel@tonic-gate 	    (place == PL_ACTION) && (strcmp(name, IPQOS_CONF_MODULE_STR) ==
57767c478bd9Sstevel@tonic-gate 	    0)) {
57777c478bd9Sstevel@tonic-gate 		*type = IPQOS_DATA_TYPE_STRING;
57787c478bd9Sstevel@tonic-gate 
57797c478bd9Sstevel@tonic-gate 	} else {	/* if not generic parameter */
57807c478bd9Sstevel@tonic-gate 		/*
57817c478bd9Sstevel@tonic-gate 		 * get type from types file
57827c478bd9Sstevel@tonic-gate 		 */
57837c478bd9Sstevel@tonic-gate 		if (readtype(tfp, module_name, name, type, &enum_nvs, dfltst,
57847c478bd9Sstevel@tonic-gate 		    B_FALSE, &place) != IPQOS_CONF_SUCCESS) {
57857c478bd9Sstevel@tonic-gate 			free(name);
57867c478bd9Sstevel@tonic-gate 			free(valst);
57877c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
57887c478bd9Sstevel@tonic-gate 		}
57897c478bd9Sstevel@tonic-gate 
57907c478bd9Sstevel@tonic-gate 		/*
57917c478bd9Sstevel@tonic-gate 		 * get full module prefix parameter name
57927c478bd9Sstevel@tonic-gate 		 */
57937c478bd9Sstevel@tonic-gate 		tmp = name;
57947c478bd9Sstevel@tonic-gate 		if ((name = prepend_module_name(name, module_name)) == NULL) {
57957c478bd9Sstevel@tonic-gate 			name = tmp;
57967c478bd9Sstevel@tonic-gate 			goto fail;
57977c478bd9Sstevel@tonic-gate 		}
57987c478bd9Sstevel@tonic-gate 		free(tmp);
57997c478bd9Sstevel@tonic-gate 	}
58007c478bd9Sstevel@tonic-gate 
58017c478bd9Sstevel@tonic-gate 	IPQOSCDBG3(L1, "NVP, name: %s, str_value: %s, type: %s\n", name,
58027c478bd9Sstevel@tonic-gate 	    valst, nv_types[*type].string);
58037c478bd9Sstevel@tonic-gate 
58047c478bd9Sstevel@tonic-gate 
58057c478bd9Sstevel@tonic-gate 	/*
58067c478bd9Sstevel@tonic-gate 	 * create nvlist if not present already
58077c478bd9Sstevel@tonic-gate 	 */
58087c478bd9Sstevel@tonic-gate 	if (*nvlp == NULL) {
58097c478bd9Sstevel@tonic-gate 		res = nvlist_alloc(nvlp, NV_UNIQUE_NAME, 0);
58107c478bd9Sstevel@tonic-gate 		if (res != 0) {
58117c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_alloc");
58127c478bd9Sstevel@tonic-gate 			free(name);
58137c478bd9Sstevel@tonic-gate 			free(valst);
58147c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
58157c478bd9Sstevel@tonic-gate 		}
58167c478bd9Sstevel@tonic-gate 	}
58177c478bd9Sstevel@tonic-gate 
58187c478bd9Sstevel@tonic-gate 	/*
58197c478bd9Sstevel@tonic-gate 	 * check we haven't already read this parameter
58207c478bd9Sstevel@tonic-gate 	 */
58217c478bd9Sstevel@tonic-gate 	if (find_nvpair(*nvlp, name)) {
58227c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Duplicate parameter line %u.\n"),
58237c478bd9Sstevel@tonic-gate 		    lineno);
58247c478bd9Sstevel@tonic-gate 		goto fail;
58257c478bd9Sstevel@tonic-gate 	}
58267c478bd9Sstevel@tonic-gate 
58277c478bd9Sstevel@tonic-gate 	/*
58287c478bd9Sstevel@tonic-gate 	 * convert value string to appropriate type and add to nvlist
58297c478bd9Sstevel@tonic-gate 	 */
58307c478bd9Sstevel@tonic-gate 
58317c478bd9Sstevel@tonic-gate 	switch (*type) {
58327c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_IFNAME: {
58337c478bd9Sstevel@tonic-gate 			uint32_t ifidx;
58347c478bd9Sstevel@tonic-gate 
58357c478bd9Sstevel@tonic-gate 			res = readifindex(valst, (int *)&ifidx);
58367c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
58377c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32(*nvlp, IPGPC_IF_INDEX,
58387c478bd9Sstevel@tonic-gate 				    ifidx);
58397c478bd9Sstevel@tonic-gate 				if (res != 0) {
58407c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
58417c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32");
58427c478bd9Sstevel@tonic-gate 					goto fail;
58437c478bd9Sstevel@tonic-gate 				}
58447c478bd9Sstevel@tonic-gate 				(void) nvlist_remove_all(*nvlp, name);
58457c478bd9Sstevel@tonic-gate 				/*
58467c478bd9Sstevel@tonic-gate 				 * change name to point at the name of the
58477c478bd9Sstevel@tonic-gate 				 * new ifindex nvlist entry as name is used
58487c478bd9Sstevel@tonic-gate 				 * later in the function.
58497c478bd9Sstevel@tonic-gate 				 */
58507c478bd9Sstevel@tonic-gate 				free(name);
58517c478bd9Sstevel@tonic-gate 				name = malloc(strlen(IPGPC_IF_INDEX) + 1);
58527c478bd9Sstevel@tonic-gate 				if (name == NULL) {
58537c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR, "malloc");
58547c478bd9Sstevel@tonic-gate 					goto fail;
58557c478bd9Sstevel@tonic-gate 				}
58567c478bd9Sstevel@tonic-gate 				(void) strcpy(name, IPGPC_IF_INDEX);
58577c478bd9Sstevel@tonic-gate 			}
58587c478bd9Sstevel@tonic-gate 			break;
58597c478bd9Sstevel@tonic-gate 		}
58607c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_PROTO: {
58617c478bd9Sstevel@tonic-gate 			uint8_t proto;
58627c478bd9Sstevel@tonic-gate 
58637c478bd9Sstevel@tonic-gate 			res = readproto(valst, &proto);
58647c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
58657c478bd9Sstevel@tonic-gate 				res = nvlist_add_byte(*nvlp, name, proto);
58667c478bd9Sstevel@tonic-gate 				if (res != 0) {
58677c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
58687c478bd9Sstevel@tonic-gate 					goto fail;
58697c478bd9Sstevel@tonic-gate 				}
58707c478bd9Sstevel@tonic-gate 			}
58717c478bd9Sstevel@tonic-gate 			break;
58727c478bd9Sstevel@tonic-gate 		}
58737c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_PORT: {
58747c478bd9Sstevel@tonic-gate 			uint16_t port;
58757c478bd9Sstevel@tonic-gate 
58767c478bd9Sstevel@tonic-gate 			res = readport(valst, &port);
58777c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
58787c478bd9Sstevel@tonic-gate 
58797c478bd9Sstevel@tonic-gate 				/* add port */
58807c478bd9Sstevel@tonic-gate 
58817c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint16(*nvlp, name, port);
58827c478bd9Sstevel@tonic-gate 				if (res != 0) {
58837c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
58847c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint16");
58857c478bd9Sstevel@tonic-gate 					goto fail;
58867c478bd9Sstevel@tonic-gate 				}
58877c478bd9Sstevel@tonic-gate 
58887c478bd9Sstevel@tonic-gate 				/* add appropriate all ones port mask */
58897c478bd9Sstevel@tonic-gate 
58907c478bd9Sstevel@tonic-gate 				if (strcmp(name, IPGPC_DPORT) == 0) {
58917c478bd9Sstevel@tonic-gate 					res = nvlist_add_uint16(*nvlp,
58927c478bd9Sstevel@tonic-gate 					    IPGPC_DPORT_MASK, ~0);
58937c478bd9Sstevel@tonic-gate 
58947c478bd9Sstevel@tonic-gate 				} else if (strcmp(name, IPGPC_SPORT) == 0) {
58957c478bd9Sstevel@tonic-gate 					res = nvlist_add_uint16(*nvlp,
58967c478bd9Sstevel@tonic-gate 					    IPGPC_SPORT_MASK, ~0);
58977c478bd9Sstevel@tonic-gate 				}
58987c478bd9Sstevel@tonic-gate 				if (res != 0) {
58997c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59007c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint16");
59017c478bd9Sstevel@tonic-gate 					goto fail;
59027c478bd9Sstevel@tonic-gate 				}
59037c478bd9Sstevel@tonic-gate 			}
59047c478bd9Sstevel@tonic-gate 			break;
59057c478bd9Sstevel@tonic-gate 		}
59067c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ADDRESS:
59077c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ACTION:
59087c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_STRING:
59097c478bd9Sstevel@tonic-gate 			res = nvlist_add_string(*nvlp, name, valst);
59107c478bd9Sstevel@tonic-gate 			if (res != 0) {
59117c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "nvlist_add_string");
59127c478bd9Sstevel@tonic-gate 				goto fail;
59137c478bd9Sstevel@tonic-gate 			}
59147c478bd9Sstevel@tonic-gate 			break;
59157c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_BOOLEAN: {
59167c478bd9Sstevel@tonic-gate 			boolean_t b;
59177c478bd9Sstevel@tonic-gate 
59187c478bd9Sstevel@tonic-gate 			res = readbool(valst, &b);
59197c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59207c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32(*nvlp, name,
59217c478bd9Sstevel@tonic-gate 				    (uint32_t)b);
59227c478bd9Sstevel@tonic-gate 				if (res != 0) {
59237c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59247c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32");
59257c478bd9Sstevel@tonic-gate 					goto fail;
59267c478bd9Sstevel@tonic-gate 				}
59277c478bd9Sstevel@tonic-gate 			}
59287c478bd9Sstevel@tonic-gate 			break;
59297c478bd9Sstevel@tonic-gate 		}
59307c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT8: {
59317c478bd9Sstevel@tonic-gate 			uint8_t u8;
59327c478bd9Sstevel@tonic-gate 
59337c478bd9Sstevel@tonic-gate 			res = readuint8(valst, &u8, &tmp);
59347c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59357c478bd9Sstevel@tonic-gate 				res = nvlist_add_byte(*nvlp, name, u8);
59367c478bd9Sstevel@tonic-gate 				if (res != 0) {
59377c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
59387c478bd9Sstevel@tonic-gate 					goto fail;
59397c478bd9Sstevel@tonic-gate 				}
59407c478bd9Sstevel@tonic-gate 			}
59417c478bd9Sstevel@tonic-gate 			break;
59427c478bd9Sstevel@tonic-gate 		}
59437c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT16: {
59447c478bd9Sstevel@tonic-gate 			int16_t i16;
59457c478bd9Sstevel@tonic-gate 
59467c478bd9Sstevel@tonic-gate 			res = readint16(valst, &i16, &tmp);
59477c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59487c478bd9Sstevel@tonic-gate 				res = nvlist_add_int16(*nvlp, name, i16);
59497c478bd9Sstevel@tonic-gate 				if (res != 0) {
59507c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59517c478bd9Sstevel@tonic-gate 					    "nvlist_add_int16");
59527c478bd9Sstevel@tonic-gate 					goto fail;
59537c478bd9Sstevel@tonic-gate 				}
59547c478bd9Sstevel@tonic-gate 			}
59557c478bd9Sstevel@tonic-gate 			break;
59567c478bd9Sstevel@tonic-gate 		}
59577c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT16: {
59587c478bd9Sstevel@tonic-gate 			uint16_t u16;
59597c478bd9Sstevel@tonic-gate 
59607c478bd9Sstevel@tonic-gate 			res = readuint16(valst, &u16, &tmp);
59617c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59627c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint16(*nvlp, name, u16);
59637c478bd9Sstevel@tonic-gate 				if (res != 0) {
59647c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59657c478bd9Sstevel@tonic-gate 					    "nvlist_add_int16");
59667c478bd9Sstevel@tonic-gate 					goto fail;
59677c478bd9Sstevel@tonic-gate 				}
59687c478bd9Sstevel@tonic-gate 			}
59697c478bd9Sstevel@tonic-gate 			break;
59707c478bd9Sstevel@tonic-gate 		}
59717c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT32: {
59727c478bd9Sstevel@tonic-gate 			int i32;
59737c478bd9Sstevel@tonic-gate 
59747c478bd9Sstevel@tonic-gate 			res = readint32(valst, &i32, &tmp);
59757c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59767c478bd9Sstevel@tonic-gate 				res = nvlist_add_int32(*nvlp, name, i32);
59777c478bd9Sstevel@tonic-gate 				if (res != 0) {
59787c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59797c478bd9Sstevel@tonic-gate 					    "nvlist_add_int32");
59807c478bd9Sstevel@tonic-gate 					goto fail;
59817c478bd9Sstevel@tonic-gate 				}
59827c478bd9Sstevel@tonic-gate 			}
59837c478bd9Sstevel@tonic-gate 			break;
59847c478bd9Sstevel@tonic-gate 		}
59857c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_UINT32: {
59867c478bd9Sstevel@tonic-gate 			uint32_t u32;
59877c478bd9Sstevel@tonic-gate 
59887c478bd9Sstevel@tonic-gate 			res = readuint32(valst, &u32, &tmp);
59897c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
59907c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32(*nvlp, name, u32);
59917c478bd9Sstevel@tonic-gate 				if (res != 0) {
59927c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
59937c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32");
59947c478bd9Sstevel@tonic-gate 					goto fail;
59957c478bd9Sstevel@tonic-gate 				}
59967c478bd9Sstevel@tonic-gate 			}
59977c478bd9Sstevel@tonic-gate 			break;
59987c478bd9Sstevel@tonic-gate 		}
59997c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_ENUM: {
60007c478bd9Sstevel@tonic-gate 			uint32_t val;
60017c478bd9Sstevel@tonic-gate 
60027c478bd9Sstevel@tonic-gate 			res = read_enum_value(cfp, valst, enum_nvs, &val);
60037c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
60047c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32(*nvlp, name, val);
60057c478bd9Sstevel@tonic-gate 				if (res != 0) {
60067c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
60077c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32");
60087c478bd9Sstevel@tonic-gate 					goto fail;
60097c478bd9Sstevel@tonic-gate 				}
60107c478bd9Sstevel@tonic-gate 			} else {
60117c478bd9Sstevel@tonic-gate 				goto fail;
60127c478bd9Sstevel@tonic-gate 			}
60137c478bd9Sstevel@tonic-gate 			break;
60147c478bd9Sstevel@tonic-gate 		}
60157c478bd9Sstevel@tonic-gate 		/*
60167c478bd9Sstevel@tonic-gate 		 * For now the dfltst contains a comma separated list of the
60177c478bd9Sstevel@tonic-gate 		 * type we need this parameter to be mapped to.
60187c478bd9Sstevel@tonic-gate 		 * read_mapped_values will fill in all the mapped parameters
60197c478bd9Sstevel@tonic-gate 		 * and their values in the nvlist.
60207c478bd9Sstevel@tonic-gate 		 */
60217c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_M_INDEX: {
60227c478bd9Sstevel@tonic-gate 			uint8_t u8;
60237c478bd9Sstevel@tonic-gate 
60247c478bd9Sstevel@tonic-gate 			res = readuint8(valst, &u8, &tmp);
60257c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
60267c478bd9Sstevel@tonic-gate 				res = nvlist_add_byte(*nvlp, name, u8);
60277c478bd9Sstevel@tonic-gate 				if (res != 0) {
60287c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
60297c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint8");
60307c478bd9Sstevel@tonic-gate 					goto fail;
60317c478bd9Sstevel@tonic-gate 				}
60327c478bd9Sstevel@tonic-gate 			} else {
60337c478bd9Sstevel@tonic-gate 				*type = IPQOS_DATA_TYPE_UINT8;
60347c478bd9Sstevel@tonic-gate 				break;
60357c478bd9Sstevel@tonic-gate 			}
60367c478bd9Sstevel@tonic-gate 			res = read_mapped_values(tfp, nvlp, module_name,
60377c478bd9Sstevel@tonic-gate 			    dfltst, u8);
60387c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
60397c478bd9Sstevel@tonic-gate 				goto fail;
60407c478bd9Sstevel@tonic-gate 			}
60417c478bd9Sstevel@tonic-gate 			break;
60427c478bd9Sstevel@tonic-gate 		}
60437c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_INT_ARRAY: {
60447c478bd9Sstevel@tonic-gate 			str_val_nd_t *arr_enum_nvs = NULL;
60457c478bd9Sstevel@tonic-gate 			uint32_t size;
60467c478bd9Sstevel@tonic-gate 			int llimit = 0, ulimit = 0;
60477c478bd9Sstevel@tonic-gate 			int *arr;
60487c478bd9Sstevel@tonic-gate 
60497c478bd9Sstevel@tonic-gate 			/*
60507c478bd9Sstevel@tonic-gate 			 * read array info from types file.
60517c478bd9Sstevel@tonic-gate 			 */
60527c478bd9Sstevel@tonic-gate 			res = read_int_array_info(dfltst, &arr_enum_nvs, &size,
60537c478bd9Sstevel@tonic-gate 			    &llimit, &ulimit, module_name);
60547c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
60557c478bd9Sstevel@tonic-gate 				goto fail;
60567c478bd9Sstevel@tonic-gate 			}
60577c478bd9Sstevel@tonic-gate 
60587c478bd9Sstevel@tonic-gate 			/*
60597c478bd9Sstevel@tonic-gate 			 * read array contents from config file and construct
60607c478bd9Sstevel@tonic-gate 			 * array with them.
60617c478bd9Sstevel@tonic-gate 			 */
60627c478bd9Sstevel@tonic-gate 			res = read_int_array(cfp, valst, &arr, size, llimit,
60637c478bd9Sstevel@tonic-gate 			    ulimit, arr_enum_nvs);
60647c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
60657c478bd9Sstevel@tonic-gate 				goto fail;
60667c478bd9Sstevel@tonic-gate 			}
60677c478bd9Sstevel@tonic-gate 
60687c478bd9Sstevel@tonic-gate 			/*
60697c478bd9Sstevel@tonic-gate 			 * add array to nvlist.
60707c478bd9Sstevel@tonic-gate 			 */
60717c478bd9Sstevel@tonic-gate 			res = nvlist_add_int32_array(*nvlp, name, arr, size);
60727c478bd9Sstevel@tonic-gate 			if (res != 0) {
60737c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "nvlist_add_int32");
60747c478bd9Sstevel@tonic-gate 				goto fail;
60757c478bd9Sstevel@tonic-gate 			}
60767c478bd9Sstevel@tonic-gate 
60777c478bd9Sstevel@tonic-gate 			/*
60787c478bd9Sstevel@tonic-gate 			 * free uneeded resources.
60797c478bd9Sstevel@tonic-gate 			 */
60807c478bd9Sstevel@tonic-gate 			free(arr);
60817c478bd9Sstevel@tonic-gate 			if (arr_enum_nvs)
60827c478bd9Sstevel@tonic-gate 				free_str_val_entrys(arr_enum_nvs);
60837c478bd9Sstevel@tonic-gate 
60847c478bd9Sstevel@tonic-gate 			break;
60857c478bd9Sstevel@tonic-gate 		}
60867c478bd9Sstevel@tonic-gate 		case IPQOS_DATA_TYPE_USER: {
60877c478bd9Sstevel@tonic-gate 			uid_t uid;
60887c478bd9Sstevel@tonic-gate 
60897c478bd9Sstevel@tonic-gate 			res = readuser(valst, &uid);
60907c478bd9Sstevel@tonic-gate 			if (res == IPQOS_CONF_SUCCESS) {
60917c478bd9Sstevel@tonic-gate 				res = nvlist_add_int32(*nvlp, name, (int)uid);
60927c478bd9Sstevel@tonic-gate 				if (res != 0) {
60937c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
60947c478bd9Sstevel@tonic-gate 					    "nvlist_add_int32");
60957c478bd9Sstevel@tonic-gate 					goto fail;
60967c478bd9Sstevel@tonic-gate 				}
60977c478bd9Sstevel@tonic-gate 			}
60987c478bd9Sstevel@tonic-gate 			break;
60997c478bd9Sstevel@tonic-gate 		}
61007c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
61017c478bd9Sstevel@tonic-gate 		default: {
61027c478bd9Sstevel@tonic-gate 			/*
61037c478bd9Sstevel@tonic-gate 			 * we shouldn't have a type that doesn't have a switch
61047c478bd9Sstevel@tonic-gate 			 * entry.
61057c478bd9Sstevel@tonic-gate 			 */
61067c478bd9Sstevel@tonic-gate 			assert(1);
61077c478bd9Sstevel@tonic-gate 		}
61087c478bd9Sstevel@tonic-gate #endif
61097c478bd9Sstevel@tonic-gate 	}
61107c478bd9Sstevel@tonic-gate 	if (res != 0) {
61117c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Invalid %s, line %u.\n"),
61127c478bd9Sstevel@tonic-gate 		    nv_types[*type].string, lineno);
61137c478bd9Sstevel@tonic-gate 		goto fail;
61147c478bd9Sstevel@tonic-gate 	}
61157c478bd9Sstevel@tonic-gate 
61167c478bd9Sstevel@tonic-gate 	/* set the nvp parameter to point at the newly added nvlist entry */
61177c478bd9Sstevel@tonic-gate 
61187c478bd9Sstevel@tonic-gate 	*nvp = find_nvpair(*nvlp, name);
61197c478bd9Sstevel@tonic-gate 
61207c478bd9Sstevel@tonic-gate 	free(name);
61217c478bd9Sstevel@tonic-gate 	free(valst);
61227c478bd9Sstevel@tonic-gate 	if (enum_nvs)
61237c478bd9Sstevel@tonic-gate 		free_str_val_entrys(enum_nvs);
61247c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
61257c478bd9Sstevel@tonic-gate fail:
61267c478bd9Sstevel@tonic-gate 	if (name != NULL)
61277c478bd9Sstevel@tonic-gate 		free(name);
61287c478bd9Sstevel@tonic-gate 	if (valst != NULL)
61297c478bd9Sstevel@tonic-gate 		free(valst);
61307c478bd9Sstevel@tonic-gate 	if (enum_nvs != NULL)
61317c478bd9Sstevel@tonic-gate 		free_str_val_entrys(enum_nvs);
61327c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
61337c478bd9Sstevel@tonic-gate }
61347c478bd9Sstevel@tonic-gate 
61357c478bd9Sstevel@tonic-gate /*
61367c478bd9Sstevel@tonic-gate  * read a parameter clause from cfp into *params.
61377c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
61387c478bd9Sstevel@tonic-gate  */
61397c478bd9Sstevel@tonic-gate static int
61407c478bd9Sstevel@tonic-gate readparams(
61417c478bd9Sstevel@tonic-gate FILE *cfp,
61427c478bd9Sstevel@tonic-gate FILE *tfp,
61437c478bd9Sstevel@tonic-gate char *module_name,
61447c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params)
61457c478bd9Sstevel@tonic-gate {
61467c478bd9Sstevel@tonic-gate 
61477c478bd9Sstevel@tonic-gate 	int res;
61487c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
61497c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
61507c478bd9Sstevel@tonic-gate 	boolean_t bl;
61517c478bd9Sstevel@tonic-gate 	char *nm;
61527c478bd9Sstevel@tonic-gate 	char *action;
61537c478bd9Sstevel@tonic-gate 	char tmp[IPQOS_CONF_PNAME_LEN];
61547c478bd9Sstevel@tonic-gate 	int read_stats = 0;
61557c478bd9Sstevel@tonic-gate 
61567c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in readparams\n");
61577c478bd9Sstevel@tonic-gate 
61587c478bd9Sstevel@tonic-gate 	/* read beginning curl */
61597c478bd9Sstevel@tonic-gate 
61607c478bd9Sstevel@tonic-gate 	res = read_curl_begin(cfp);
61617c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
61627c478bd9Sstevel@tonic-gate 		return (res);
61637c478bd9Sstevel@tonic-gate 	}
61647c478bd9Sstevel@tonic-gate 
61657c478bd9Sstevel@tonic-gate 	/*
61667c478bd9Sstevel@tonic-gate 	 * loop reading nvpairs, adding to params nvlist until encounter
61677c478bd9Sstevel@tonic-gate 	 * CURL_END.
61687c478bd9Sstevel@tonic-gate 	 */
61697c478bd9Sstevel@tonic-gate 	for (;;) {
61707c478bd9Sstevel@tonic-gate 		/* read nvpair */
61717c478bd9Sstevel@tonic-gate 
61727c478bd9Sstevel@tonic-gate 		res = readnvpair(cfp, tfp, &params->nvlist,
61737c478bd9Sstevel@tonic-gate 		    &nvp, &type, PL_PARAMS, module_name);
61747c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
61757c478bd9Sstevel@tonic-gate 			goto fail;
61767c478bd9Sstevel@tonic-gate 
61777c478bd9Sstevel@tonic-gate 		/* we have finished reading params */
61787c478bd9Sstevel@tonic-gate 
61797c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
61807c478bd9Sstevel@tonic-gate 			break;
61817c478bd9Sstevel@tonic-gate 		}
61827c478bd9Sstevel@tonic-gate 
61837c478bd9Sstevel@tonic-gate 		/*
61847c478bd9Sstevel@tonic-gate 		 * read global stats - place into params struct and remove
61857c478bd9Sstevel@tonic-gate 		 * from nvlist.
61867c478bd9Sstevel@tonic-gate 		 */
61877c478bd9Sstevel@tonic-gate 		if (strcmp(nvpair_name(nvp), IPQOS_CONF_GLOBAL_STATS_STR) ==
61887c478bd9Sstevel@tonic-gate 		    0) {
61897c478bd9Sstevel@tonic-gate 			/* check we haven't read stats before */
61907c478bd9Sstevel@tonic-gate 
61917c478bd9Sstevel@tonic-gate 			if (read_stats) {
61927c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
61937c478bd9Sstevel@tonic-gate 				    gettext("Duplicate parameter line %u.\n"),
61947c478bd9Sstevel@tonic-gate 				    lineno);
61957c478bd9Sstevel@tonic-gate 				goto fail;
61967c478bd9Sstevel@tonic-gate 			}
61977c478bd9Sstevel@tonic-gate 			read_stats++;
61987c478bd9Sstevel@tonic-gate 
61997c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, (uint32_t *)&bl);
62007c478bd9Sstevel@tonic-gate 			params->stats_enable = bl;
62017c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all(params->nvlist,
62027c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_GLOBAL_STATS_STR);
62037c478bd9Sstevel@tonic-gate 
62047c478bd9Sstevel@tonic-gate 
62057c478bd9Sstevel@tonic-gate 		/*
62067c478bd9Sstevel@tonic-gate 		 * read action type parameter - add it to list of action refs.
62077c478bd9Sstevel@tonic-gate 		 * also, if it's one of continue or drop virtual actions
62087c478bd9Sstevel@tonic-gate 		 * change the action name to their special ipp names in
62097c478bd9Sstevel@tonic-gate 		 * the action ref list and the nvlist.
62107c478bd9Sstevel@tonic-gate 		 */
62117c478bd9Sstevel@tonic-gate 		} else if (type == IPQOS_DATA_TYPE_ACTION) {
62127c478bd9Sstevel@tonic-gate 
62137c478bd9Sstevel@tonic-gate 			/* get name and value from nvlist */
62147c478bd9Sstevel@tonic-gate 
62157c478bd9Sstevel@tonic-gate 			nm = nvpair_name(nvp);
62167c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &action);
62177c478bd9Sstevel@tonic-gate 
62187c478bd9Sstevel@tonic-gate 			/* if virtual action names change to ipp name */
62197c478bd9Sstevel@tonic-gate 
62207c478bd9Sstevel@tonic-gate 			if ((strcmp(action, IPQOS_CONF_CONT_STR) == 0) ||
62217c478bd9Sstevel@tonic-gate 			    strcmp(action, IPQOS_CONF_DROP_STR) == 0) {
62227c478bd9Sstevel@tonic-gate 				/*
62237c478bd9Sstevel@tonic-gate 				 * we copy nm to a seperate buffer as nv_pair
62247c478bd9Sstevel@tonic-gate 				 * name above gave us a ptr to internal
62257c478bd9Sstevel@tonic-gate 				 * memory which causes strange behaviour
62267c478bd9Sstevel@tonic-gate 				 * when we re-value that nvlist element.
62277c478bd9Sstevel@tonic-gate 				 */
62287c478bd9Sstevel@tonic-gate 				(void) strlcpy(tmp, nm, sizeof (tmp));
62297c478bd9Sstevel@tonic-gate 				nm = tmp;
62307c478bd9Sstevel@tonic-gate 
62317c478bd9Sstevel@tonic-gate 
62327c478bd9Sstevel@tonic-gate 				/* modify nvlist entry and change action */
62337c478bd9Sstevel@tonic-gate 
62347c478bd9Sstevel@tonic-gate 				if (strcmp(action, IPQOS_CONF_CONT_STR) == 0) {
62357c478bd9Sstevel@tonic-gate 					action = IPP_ANAME_CONT;
62367c478bd9Sstevel@tonic-gate 					res = nvlist_add_string(params->nvlist,
62377c478bd9Sstevel@tonic-gate 					    nm, action);
62387c478bd9Sstevel@tonic-gate 				} else {
62397c478bd9Sstevel@tonic-gate 					action = IPP_ANAME_DROP;
62407c478bd9Sstevel@tonic-gate 					res = nvlist_add_string(params->nvlist,
62417c478bd9Sstevel@tonic-gate 					    nm, action);
62427c478bd9Sstevel@tonic-gate 				}
62437c478bd9Sstevel@tonic-gate 				if (res != 0) {
62447c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
62457c478bd9Sstevel@tonic-gate 					    "nvlist_add_string");
62467c478bd9Sstevel@tonic-gate 					goto fail;
62477c478bd9Sstevel@tonic-gate 				}
62487c478bd9Sstevel@tonic-gate 			}
62497c478bd9Sstevel@tonic-gate 
62507c478bd9Sstevel@tonic-gate 			/* add action reference to params */
62517c478bd9Sstevel@tonic-gate 
62527c478bd9Sstevel@tonic-gate 			res = add_aref(&params->actions, nm, action);
62537c478bd9Sstevel@tonic-gate 		}
62547c478bd9Sstevel@tonic-gate 	}
62557c478bd9Sstevel@tonic-gate 
62567c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
62577c478bd9Sstevel@tonic-gate fail:
62587c478bd9Sstevel@tonic-gate 
62597c478bd9Sstevel@tonic-gate 	if (params->nvlist) {
62607c478bd9Sstevel@tonic-gate 		nvlist_free(params->nvlist);
62617c478bd9Sstevel@tonic-gate 		params->nvlist = NULL;
62627c478bd9Sstevel@tonic-gate 	}
62637c478bd9Sstevel@tonic-gate 	if (params->actions) {
62647c478bd9Sstevel@tonic-gate 		free_arefs(params->actions);
62657c478bd9Sstevel@tonic-gate 		params->actions = NULL;
62667c478bd9Sstevel@tonic-gate 	}
62677c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
62687c478bd9Sstevel@tonic-gate }
62697c478bd9Sstevel@tonic-gate 
62707c478bd9Sstevel@tonic-gate /* ************************* class manip fns ****************************** */
62717c478bd9Sstevel@tonic-gate 
62727c478bd9Sstevel@tonic-gate 
62737c478bd9Sstevel@tonic-gate 
62747c478bd9Sstevel@tonic-gate /*
62757c478bd9Sstevel@tonic-gate  * make dst point at a dupicate class struct with duplicate elements to src.
62767c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
62777c478bd9Sstevel@tonic-gate  */
62787c478bd9Sstevel@tonic-gate static int
62797c478bd9Sstevel@tonic-gate dup_class(
62807c478bd9Sstevel@tonic-gate ipqos_conf_class_t *src,
62817c478bd9Sstevel@tonic-gate ipqos_conf_class_t **dst)
62827c478bd9Sstevel@tonic-gate {
62837c478bd9Sstevel@tonic-gate 
62847c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
62857c478bd9Sstevel@tonic-gate 	int res;
62867c478bd9Sstevel@tonic-gate 
62877c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(DIFF, "In dup_class: class: %s\n", src->name);
62887c478bd9Sstevel@tonic-gate 	cls = alloc_class();
62897c478bd9Sstevel@tonic-gate 	if (cls == NULL) {
62907c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
62917c478bd9Sstevel@tonic-gate 	}
62927c478bd9Sstevel@tonic-gate 
62937c478bd9Sstevel@tonic-gate 	/* struct copy */
62947c478bd9Sstevel@tonic-gate 	*cls = *src;
62957c478bd9Sstevel@tonic-gate 
62967c478bd9Sstevel@tonic-gate 	/* we're not interested in the nvlist for a class */
62977c478bd9Sstevel@tonic-gate 	cls->nvlist = NULL;
62987c478bd9Sstevel@tonic-gate 
62997c478bd9Sstevel@tonic-gate 
63007c478bd9Sstevel@tonic-gate 	/* copy first action reference */
63017c478bd9Sstevel@tonic-gate 	cls->alist = NULL;
63027c478bd9Sstevel@tonic-gate 	res = add_aref(&cls->alist, src->alist->field, src->alist->name);
63037c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
63047c478bd9Sstevel@tonic-gate 		free(cls);
63057c478bd9Sstevel@tonic-gate 		return (res);
63067c478bd9Sstevel@tonic-gate 	}
63077c478bd9Sstevel@tonic-gate 
63087c478bd9Sstevel@tonic-gate 	*dst = cls;
63097c478bd9Sstevel@tonic-gate 
63107c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
63117c478bd9Sstevel@tonic-gate }
63127c478bd9Sstevel@tonic-gate 
63137c478bd9Sstevel@tonic-gate /*
63147c478bd9Sstevel@tonic-gate  * create a zero'd class struct and return a ptr to it.
63157c478bd9Sstevel@tonic-gate  * RETURNS: ptr to struct on success, NULL otherwise.
63167c478bd9Sstevel@tonic-gate  */
63177c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *
63187c478bd9Sstevel@tonic-gate alloc_class()
63197c478bd9Sstevel@tonic-gate {
63207c478bd9Sstevel@tonic-gate 
63217c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *class;
63227c478bd9Sstevel@tonic-gate 
63237c478bd9Sstevel@tonic-gate 	class = malloc(sizeof (ipqos_conf_class_t));
63247c478bd9Sstevel@tonic-gate 	if (class) {
63257c478bd9Sstevel@tonic-gate 		bzero(class, sizeof (ipqos_conf_class_t));
63267c478bd9Sstevel@tonic-gate 	} else {
63277c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
63287c478bd9Sstevel@tonic-gate 	}
63297c478bd9Sstevel@tonic-gate 
63307c478bd9Sstevel@tonic-gate 	return (class);
63317c478bd9Sstevel@tonic-gate }
63327c478bd9Sstevel@tonic-gate 
63337c478bd9Sstevel@tonic-gate /* frees up all memory occupied by a filter struct and its contents. */
63347c478bd9Sstevel@tonic-gate static void
63357c478bd9Sstevel@tonic-gate free_class(ipqos_conf_class_t *cls)
63367c478bd9Sstevel@tonic-gate {
63377c478bd9Sstevel@tonic-gate 
63387c478bd9Sstevel@tonic-gate 	if (cls == NULL)
63397c478bd9Sstevel@tonic-gate 		return;
63407c478bd9Sstevel@tonic-gate 
63417c478bd9Sstevel@tonic-gate 	/* free its nvlist if present */
63427c478bd9Sstevel@tonic-gate 
63437c478bd9Sstevel@tonic-gate 	nvlist_free(cls->nvlist);
63447c478bd9Sstevel@tonic-gate 
63457c478bd9Sstevel@tonic-gate 	/* free its action refs if present */
63467c478bd9Sstevel@tonic-gate 
63477c478bd9Sstevel@tonic-gate 	if (cls->alist)
63487c478bd9Sstevel@tonic-gate 		free_arefs(cls->alist);
63497c478bd9Sstevel@tonic-gate 
63507c478bd9Sstevel@tonic-gate 	/* finally free class itself */
63517c478bd9Sstevel@tonic-gate 	free(cls);
63527c478bd9Sstevel@tonic-gate }
63537c478bd9Sstevel@tonic-gate 
63547c478bd9Sstevel@tonic-gate /*
63557c478bd9Sstevel@tonic-gate  * Checks whether there is a class called class_nm  in classes list.
63567c478bd9Sstevel@tonic-gate  * RETURNS: ptr to first matched class, else if not matched NULL.
63577c478bd9Sstevel@tonic-gate  */
63587c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *
63597c478bd9Sstevel@tonic-gate classexist(
63607c478bd9Sstevel@tonic-gate char *class_nm,
63617c478bd9Sstevel@tonic-gate ipqos_conf_class_t *classes)
63627c478bd9Sstevel@tonic-gate {
63637c478bd9Sstevel@tonic-gate 
63647c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
63657c478bd9Sstevel@tonic-gate 
63667c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In classexist: name: %s\n", class_nm);
63677c478bd9Sstevel@tonic-gate 
63687c478bd9Sstevel@tonic-gate 	for (cls = classes; cls; cls = cls->next) {
63697c478bd9Sstevel@tonic-gate 		if (strcmp(class_nm, cls->name) == 0) {
63707c478bd9Sstevel@tonic-gate 			break;
63717c478bd9Sstevel@tonic-gate 		}
63727c478bd9Sstevel@tonic-gate 	}
63737c478bd9Sstevel@tonic-gate 
63747c478bd9Sstevel@tonic-gate 	return (cls);
63757c478bd9Sstevel@tonic-gate }
63767c478bd9Sstevel@tonic-gate 
63777c478bd9Sstevel@tonic-gate 
63787c478bd9Sstevel@tonic-gate 
63797c478bd9Sstevel@tonic-gate /* ************************** filter manip fns **************************** */
63807c478bd9Sstevel@tonic-gate 
63817c478bd9Sstevel@tonic-gate 
63827c478bd9Sstevel@tonic-gate 
63837c478bd9Sstevel@tonic-gate /*
63847c478bd9Sstevel@tonic-gate  * Checks whether there is a filter called filter_nm with instance number
63857c478bd9Sstevel@tonic-gate  * instance in filters list created by us or permanent. Instance value -1
63867c478bd9Sstevel@tonic-gate  * is a wildcard.
63877c478bd9Sstevel@tonic-gate  * RETURNS: ptr to first matched filter, else if not matched NULL.
63887c478bd9Sstevel@tonic-gate  */
63897c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *
63907c478bd9Sstevel@tonic-gate filterexist(
63917c478bd9Sstevel@tonic-gate char *filter_nm,
63927c478bd9Sstevel@tonic-gate int instance,
63937c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filters)
63947c478bd9Sstevel@tonic-gate {
63957c478bd9Sstevel@tonic-gate 
63967c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "In filterexist: name :%s, inst: %d\n", filter_nm,
63977c478bd9Sstevel@tonic-gate 	    instance);
63987c478bd9Sstevel@tonic-gate 
63997c478bd9Sstevel@tonic-gate 	while (filters) {
64007c478bd9Sstevel@tonic-gate 		if (strcmp(filters->name, filter_nm) == 0 &&
64017c478bd9Sstevel@tonic-gate 		    (instance == -1 || filters->instance == instance) &&
64027c478bd9Sstevel@tonic-gate 		    (filters->originator == IPP_CONFIG_IPQOSCONF ||
64037c478bd9Sstevel@tonic-gate 		    filters->originator == IPP_CONFIG_PERMANENT)) {
64047c478bd9Sstevel@tonic-gate 			break;
64057c478bd9Sstevel@tonic-gate 		}
64067c478bd9Sstevel@tonic-gate 		filters = filters->next;
64077c478bd9Sstevel@tonic-gate 	}
64087c478bd9Sstevel@tonic-gate 	return (filters);
64097c478bd9Sstevel@tonic-gate }
64107c478bd9Sstevel@tonic-gate 
64117c478bd9Sstevel@tonic-gate /*
64127c478bd9Sstevel@tonic-gate  * allocate and zero a filter structure.
64137c478bd9Sstevel@tonic-gate  * RETURNS: NULL on error, else ptr to filter struct.
64147c478bd9Sstevel@tonic-gate  */
64157c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *
64167c478bd9Sstevel@tonic-gate alloc_filter()
64177c478bd9Sstevel@tonic-gate {
64187c478bd9Sstevel@tonic-gate 
64197c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
64207c478bd9Sstevel@tonic-gate 
64217c478bd9Sstevel@tonic-gate 	flt = malloc(sizeof (ipqos_conf_filter_t));
64227c478bd9Sstevel@tonic-gate 	if (flt) {
64237c478bd9Sstevel@tonic-gate 		bzero(flt, sizeof (ipqos_conf_filter_t));
64247c478bd9Sstevel@tonic-gate 		flt->instance = -1;
64257c478bd9Sstevel@tonic-gate 	} else {
64267c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
64277c478bd9Sstevel@tonic-gate 	}
64287c478bd9Sstevel@tonic-gate 
64297c478bd9Sstevel@tonic-gate 	return (flt);
64307c478bd9Sstevel@tonic-gate }
64317c478bd9Sstevel@tonic-gate 
64327c478bd9Sstevel@tonic-gate /* free flt and all it's contents. */
64337c478bd9Sstevel@tonic-gate 
64347c478bd9Sstevel@tonic-gate static void
64357c478bd9Sstevel@tonic-gate free_filter(ipqos_conf_filter_t *flt)
64367c478bd9Sstevel@tonic-gate {
64377c478bd9Sstevel@tonic-gate 
64387c478bd9Sstevel@tonic-gate 	IPQOSCDBG2(L1, "In free_filter: filter: %s, inst: %d\n", flt->name,
64397c478bd9Sstevel@tonic-gate 	    flt->instance);
64407c478bd9Sstevel@tonic-gate 
64417c478bd9Sstevel@tonic-gate 	if (flt == NULL)
64427c478bd9Sstevel@tonic-gate 		return;
64437c478bd9Sstevel@tonic-gate 
64447c478bd9Sstevel@tonic-gate 	if (flt->src_nd_name)
64457c478bd9Sstevel@tonic-gate 		free(flt->src_nd_name);
64467c478bd9Sstevel@tonic-gate 	if (flt->dst_nd_name)
64477c478bd9Sstevel@tonic-gate 		free(flt->dst_nd_name);
64487c478bd9Sstevel@tonic-gate 	if (flt->nvlist) {
64497c478bd9Sstevel@tonic-gate 		nvlist_free(flt->nvlist);
64507c478bd9Sstevel@tonic-gate 	}
64517c478bd9Sstevel@tonic-gate 	free(flt);
64527c478bd9Sstevel@tonic-gate }
64537c478bd9Sstevel@tonic-gate 
64547c478bd9Sstevel@tonic-gate /*
64557c478bd9Sstevel@tonic-gate  * makes a copy of ofilter and its contents and points nfilter at it. It
64567c478bd9Sstevel@tonic-gate  * also adds an instance number to the filter and if either saddr or
64577c478bd9Sstevel@tonic-gate  * daddr are non-null that address to the filters nvlist along with
64587c478bd9Sstevel@tonic-gate  * an all 1s address mask and the af.
64597c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
64607c478bd9Sstevel@tonic-gate  */
64617c478bd9Sstevel@tonic-gate static int
64627c478bd9Sstevel@tonic-gate dup_filter(
64637c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *ofilter,
64647c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **nfilter,
64657c478bd9Sstevel@tonic-gate int af,
64667c478bd9Sstevel@tonic-gate int inv6,	/* if saddr or daddr set and v4 filter are they in v6 addr */
64677c478bd9Sstevel@tonic-gate void *saddr,
64687c478bd9Sstevel@tonic-gate void *daddr,
64697c478bd9Sstevel@tonic-gate int inst)
64707c478bd9Sstevel@tonic-gate {
64717c478bd9Sstevel@tonic-gate 
64727c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *nf;
64737c478bd9Sstevel@tonic-gate 	int res;
64747c478bd9Sstevel@tonic-gate 	in6_addr_t v6addr;
64757c478bd9Sstevel@tonic-gate 	in6_addr_t all_1s_v6;
64767c478bd9Sstevel@tonic-gate 
64777c478bd9Sstevel@tonic-gate 	IPQOSCDBG4(MHME, "In dup_filter: name: %s, af: %u, inv6: %u, ins: %d\n",
64787c478bd9Sstevel@tonic-gate 	    ofilter->name, af, inv6, inst);
64797c478bd9Sstevel@tonic-gate 
64807c478bd9Sstevel@tonic-gate /* show src address and dst address if present */
64817c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
64827c478bd9Sstevel@tonic-gate 	if (ipqosconf_dbg_flgs & MHME) {
64837c478bd9Sstevel@tonic-gate 		char st[100];
64847c478bd9Sstevel@tonic-gate 
64857c478bd9Sstevel@tonic-gate 		if (saddr) {
64867c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "saddr: %s\n",
64877c478bd9Sstevel@tonic-gate 			    inet_ntop(inv6 ? AF_INET6 : AF_INET, saddr, st,
64887c478bd9Sstevel@tonic-gate 			    100));
64897c478bd9Sstevel@tonic-gate 		}
64907c478bd9Sstevel@tonic-gate 
64917c478bd9Sstevel@tonic-gate 		if (daddr) {
64927c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "daddr: %s\n",
64937c478bd9Sstevel@tonic-gate 			    inet_ntop(inv6 ? AF_INET6 : AF_INET, daddr, st,
64947c478bd9Sstevel@tonic-gate 			    100));
64957c478bd9Sstevel@tonic-gate 		}
64967c478bd9Sstevel@tonic-gate 	}
64977c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
64987c478bd9Sstevel@tonic-gate 
64997c478bd9Sstevel@tonic-gate 	/* init local v6 address to 0 */
65007c478bd9Sstevel@tonic-gate 	(void) bzero(&v6addr, sizeof (in6_addr_t));
65017c478bd9Sstevel@tonic-gate 
65027c478bd9Sstevel@tonic-gate 	/* create an all 1s address for use as mask */
65037c478bd9Sstevel@tonic-gate 	(void) memset(&all_1s_v6, ~0, sizeof (in6_addr_t));
65047c478bd9Sstevel@tonic-gate 
65057c478bd9Sstevel@tonic-gate 	/* create a new filter */
65067c478bd9Sstevel@tonic-gate 
65077c478bd9Sstevel@tonic-gate 	nf = alloc_filter();
65087c478bd9Sstevel@tonic-gate 	if (nf == NULL) {
65097c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
65107c478bd9Sstevel@tonic-gate 	}
65117c478bd9Sstevel@tonic-gate 
65127c478bd9Sstevel@tonic-gate 	/* struct copy old filter to new */
65137c478bd9Sstevel@tonic-gate 	*nf = *ofilter;
65147c478bd9Sstevel@tonic-gate 
65157c478bd9Sstevel@tonic-gate 	/* copy src filters nvlist if there is one to copy */
65167c478bd9Sstevel@tonic-gate 
65177c478bd9Sstevel@tonic-gate 	if (ofilter->nvlist) {
65187c478bd9Sstevel@tonic-gate 		res = nvlist_dup(ofilter->nvlist, &nf->nvlist, 0);
65197c478bd9Sstevel@tonic-gate 		if (res != 0) {
65207c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_dup");
65217c478bd9Sstevel@tonic-gate 			goto fail;
65227c478bd9Sstevel@tonic-gate 		}
65237c478bd9Sstevel@tonic-gate 	}
65247c478bd9Sstevel@tonic-gate 
65257c478bd9Sstevel@tonic-gate 	/* copy src and dst node names if present */
65267c478bd9Sstevel@tonic-gate 
65277c478bd9Sstevel@tonic-gate 	if (ofilter->src_nd_name) {
65287c478bd9Sstevel@tonic-gate 		nf->src_nd_name = malloc(strlen(ofilter->src_nd_name) + 1);
65297c478bd9Sstevel@tonic-gate 		if (nf->src_nd_name == NULL) {
65307c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
65317c478bd9Sstevel@tonic-gate 			goto fail;
65327c478bd9Sstevel@tonic-gate 		}
65337c478bd9Sstevel@tonic-gate 		(void) strcpy(nf->src_nd_name, ofilter->src_nd_name);
65347c478bd9Sstevel@tonic-gate 	}
65357c478bd9Sstevel@tonic-gate 	if (ofilter->dst_nd_name) {
65367c478bd9Sstevel@tonic-gate 		nf->dst_nd_name = malloc(strlen(ofilter->dst_nd_name) + 1);
65377c478bd9Sstevel@tonic-gate 		if (nf->dst_nd_name == NULL) {
65387c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
65397c478bd9Sstevel@tonic-gate 			goto fail;
65407c478bd9Sstevel@tonic-gate 		}
65417c478bd9Sstevel@tonic-gate 		(void) strcpy(nf->dst_nd_name, ofilter->dst_nd_name);
65427c478bd9Sstevel@tonic-gate 	}
65437c478bd9Sstevel@tonic-gate 
65447c478bd9Sstevel@tonic-gate 	/* add filter addresses type */
65457c478bd9Sstevel@tonic-gate 
65467c478bd9Sstevel@tonic-gate 	res = nvlist_add_byte(nf->nvlist, IPGPC_FILTER_TYPE,
65477c478bd9Sstevel@tonic-gate 	    af == AF_INET ? IPGPC_V4_FLTR : IPGPC_V6_FLTR);
65487c478bd9Sstevel@tonic-gate 	if (res != 0) {
65497c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "nvlist_add_byte");
65507c478bd9Sstevel@tonic-gate 		goto fail;
65517c478bd9Sstevel@tonic-gate 	}
65527c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(MHME, "adding address type %s in dup filter\n",
65537c478bd9Sstevel@tonic-gate 	    af == AF_INET ? "AF_INET" : "AF_INET6");
65547c478bd9Sstevel@tonic-gate 
65557c478bd9Sstevel@tonic-gate 	/* add saddr if present */
65567c478bd9Sstevel@tonic-gate 
65577c478bd9Sstevel@tonic-gate 	if (saddr) {
65587c478bd9Sstevel@tonic-gate 		if (af == AF_INET && !inv6) {
65597c478bd9Sstevel@tonic-gate 			V4_PART_OF_V6(v6addr) = *(uint32_t *)saddr;
65607c478bd9Sstevel@tonic-gate 			saddr = &v6addr;
65617c478bd9Sstevel@tonic-gate 		}
65627c478bd9Sstevel@tonic-gate 
65637c478bd9Sstevel@tonic-gate 		/* add address and all 1's mask */
65647c478bd9Sstevel@tonic-gate 
65657c478bd9Sstevel@tonic-gate 		if (nvlist_add_uint32_array(nf->nvlist, IPGPC_SADDR,
65667c478bd9Sstevel@tonic-gate 		    (uint32_t *)saddr, 4) != 0 ||
65677c478bd9Sstevel@tonic-gate 		    nvlist_add_uint32_array(nf->nvlist, IPGPC_SADDR_MASK,
65687c478bd9Sstevel@tonic-gate 		    (uint32_t *)&all_1s_v6, 4) != 0) {
65697c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_uint32_array");
65707c478bd9Sstevel@tonic-gate 			goto fail;
65717c478bd9Sstevel@tonic-gate 		}
65727c478bd9Sstevel@tonic-gate 
65737c478bd9Sstevel@tonic-gate 	}
65747c478bd9Sstevel@tonic-gate 
65757c478bd9Sstevel@tonic-gate 	/* add daddr if present */
65767c478bd9Sstevel@tonic-gate 
65777c478bd9Sstevel@tonic-gate 	if (daddr) {
65787c478bd9Sstevel@tonic-gate 		if (af == AF_INET && !inv6) {
65797c478bd9Sstevel@tonic-gate 			V4_PART_OF_V6(v6addr) = *(uint32_t *)daddr;
65807c478bd9Sstevel@tonic-gate 			daddr = &v6addr;
65817c478bd9Sstevel@tonic-gate 		}
65827c478bd9Sstevel@tonic-gate 
65837c478bd9Sstevel@tonic-gate 		/* add address and all 1's mask */
65847c478bd9Sstevel@tonic-gate 
65857c478bd9Sstevel@tonic-gate 		if (nvlist_add_uint32_array(nf->nvlist, IPGPC_DADDR,
65867c478bd9Sstevel@tonic-gate 		    (uint32_t *)daddr, 4) != 0 ||
65877c478bd9Sstevel@tonic-gate 		    nvlist_add_uint32_array(nf->nvlist, IPGPC_DADDR_MASK,
65887c478bd9Sstevel@tonic-gate 		    (uint32_t *)&all_1s_v6, 4) != 0) {
65897c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "nvlist_add_uint32_array");
65907c478bd9Sstevel@tonic-gate 			goto fail;
65917c478bd9Sstevel@tonic-gate 		}
65927c478bd9Sstevel@tonic-gate 	}
65937c478bd9Sstevel@tonic-gate 
65947c478bd9Sstevel@tonic-gate 	/* add filter instance */
65957c478bd9Sstevel@tonic-gate 
65967c478bd9Sstevel@tonic-gate 	nf->instance = inst;
65977c478bd9Sstevel@tonic-gate 
65987c478bd9Sstevel@tonic-gate 	*nfilter = nf;
65997c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
66007c478bd9Sstevel@tonic-gate fail:
66017c478bd9Sstevel@tonic-gate 	free_filter(nf);
66027c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
66037c478bd9Sstevel@tonic-gate }
66047c478bd9Sstevel@tonic-gate 
66057c478bd9Sstevel@tonic-gate 
66067c478bd9Sstevel@tonic-gate 
66077c478bd9Sstevel@tonic-gate /* ************************* action manip fns ********************** */
66087c478bd9Sstevel@tonic-gate 
66097c478bd9Sstevel@tonic-gate 
66107c478bd9Sstevel@tonic-gate 
66117c478bd9Sstevel@tonic-gate /*
66127c478bd9Sstevel@tonic-gate  * create and zero action structure and a params structure hung off of it.
66137c478bd9Sstevel@tonic-gate  * RETURNS: ptr to allocated action on success, else NULL.
66147c478bd9Sstevel@tonic-gate  */
66157c478bd9Sstevel@tonic-gate static ipqos_conf_action_t *
66167c478bd9Sstevel@tonic-gate alloc_action()
66177c478bd9Sstevel@tonic-gate {
66187c478bd9Sstevel@tonic-gate 
66197c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *action;
66207c478bd9Sstevel@tonic-gate 
66217c478bd9Sstevel@tonic-gate 	action = (ipqos_conf_action_t *)malloc(sizeof (ipqos_conf_action_t));
66227c478bd9Sstevel@tonic-gate 	if (action == NULL) {
66237c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
66247c478bd9Sstevel@tonic-gate 		return (action);
66257c478bd9Sstevel@tonic-gate 	}
66267c478bd9Sstevel@tonic-gate 	bzero(action, sizeof (ipqos_conf_action_t));
66277c478bd9Sstevel@tonic-gate 
66287c478bd9Sstevel@tonic-gate 	action->params = (ipqos_conf_params_t *)
66297c478bd9Sstevel@tonic-gate 			malloc(sizeof (ipqos_conf_params_t));
66307c478bd9Sstevel@tonic-gate 	if (action->params == NULL) {
66317c478bd9Sstevel@tonic-gate 		free(action);
66327c478bd9Sstevel@tonic-gate 		return (NULL);
66337c478bd9Sstevel@tonic-gate 	}
66347c478bd9Sstevel@tonic-gate 	bzero(action->params, sizeof (ipqos_conf_params_t));
66357c478bd9Sstevel@tonic-gate 	action->params->stats_enable = B_FALSE;
66367c478bd9Sstevel@tonic-gate 
66377c478bd9Sstevel@tonic-gate 	return (action);
66387c478bd9Sstevel@tonic-gate }
66397c478bd9Sstevel@tonic-gate 
66407c478bd9Sstevel@tonic-gate /*
66417c478bd9Sstevel@tonic-gate  * free all the memory used in all the actions in actions list.
66427c478bd9Sstevel@tonic-gate  */
66437c478bd9Sstevel@tonic-gate static void
66447c478bd9Sstevel@tonic-gate free_actions(
66457c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions)
66467c478bd9Sstevel@tonic-gate {
66477c478bd9Sstevel@tonic-gate 
66487c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act = actions;
66497c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *next;
66507c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt, *nf;
66517c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls, *nc;
66527c478bd9Sstevel@tonic-gate 
66537c478bd9Sstevel@tonic-gate 	while (act != NULL) {
66547c478bd9Sstevel@tonic-gate 		/* free parameters */
66557c478bd9Sstevel@tonic-gate 
66567c478bd9Sstevel@tonic-gate 		if (act->params != NULL) {
66577c478bd9Sstevel@tonic-gate 			free_arefs(act->params->actions);
66587c478bd9Sstevel@tonic-gate 			if (act->params->nvlist != NULL) {
66597c478bd9Sstevel@tonic-gate 				nvlist_free(act->params->nvlist);
66607c478bd9Sstevel@tonic-gate 			}
66617c478bd9Sstevel@tonic-gate 			free(act->params);
66627c478bd9Sstevel@tonic-gate 		}
66637c478bd9Sstevel@tonic-gate 
66647c478bd9Sstevel@tonic-gate 		/* free action nvlist */
66657c478bd9Sstevel@tonic-gate 
66667c478bd9Sstevel@tonic-gate 		if (act->nvlist != NULL)
66677c478bd9Sstevel@tonic-gate 			free(act->nvlist);
66687c478bd9Sstevel@tonic-gate 
66697c478bd9Sstevel@tonic-gate 		/* free filters */
66707c478bd9Sstevel@tonic-gate 
66717c478bd9Sstevel@tonic-gate 		flt = act->filters;
66727c478bd9Sstevel@tonic-gate 		while (flt != NULL) {
66737c478bd9Sstevel@tonic-gate 			nf = flt->next;
66747c478bd9Sstevel@tonic-gate 			free_filter(flt);
66757c478bd9Sstevel@tonic-gate 			flt = nf;
66767c478bd9Sstevel@tonic-gate 		}
66777c478bd9Sstevel@tonic-gate 
66787c478bd9Sstevel@tonic-gate 		/* free classes */
66797c478bd9Sstevel@tonic-gate 
66807c478bd9Sstevel@tonic-gate 		cls = act->classes;
66817c478bd9Sstevel@tonic-gate 		while (cls != NULL) {
66827c478bd9Sstevel@tonic-gate 			nc = cls->next;
66837c478bd9Sstevel@tonic-gate 			free_class(cls);
66847c478bd9Sstevel@tonic-gate 			cls = nc;
66857c478bd9Sstevel@tonic-gate 		}
66867c478bd9Sstevel@tonic-gate 
66877c478bd9Sstevel@tonic-gate 		/* free permanent classes table */
66887c478bd9Sstevel@tonic-gate 		cleanup_string_table(act->perm_classes, act->num_perm_classes);
66897c478bd9Sstevel@tonic-gate 
66907c478bd9Sstevel@tonic-gate 		/* free filters to retry */
66917c478bd9Sstevel@tonic-gate 
66927c478bd9Sstevel@tonic-gate 		flt = act->retry_filters;
66937c478bd9Sstevel@tonic-gate 		while (flt != NULL) {
66947c478bd9Sstevel@tonic-gate 			nf = flt->next;
66957c478bd9Sstevel@tonic-gate 			free_filter(flt);
66967c478bd9Sstevel@tonic-gate 			flt = nf;
66977c478bd9Sstevel@tonic-gate 		}
66987c478bd9Sstevel@tonic-gate 
66997c478bd9Sstevel@tonic-gate 		/* free dependency pointers */
67007c478bd9Sstevel@tonic-gate 		free_arefs(act->dependencies);
67017c478bd9Sstevel@tonic-gate 
67027c478bd9Sstevel@tonic-gate 		next = act->next;
67037c478bd9Sstevel@tonic-gate 		free(act);
67047c478bd9Sstevel@tonic-gate 		act = next;
67057c478bd9Sstevel@tonic-gate 	}
67067c478bd9Sstevel@tonic-gate }
67077c478bd9Sstevel@tonic-gate 
67087c478bd9Sstevel@tonic-gate /*
67097c478bd9Sstevel@tonic-gate  * Checks whether there is an action called action_name in actions list.
67107c478bd9Sstevel@tonic-gate  * RETURNS: ptr to first matched action, else if not matched NULL.
67117c478bd9Sstevel@tonic-gate  *
67127c478bd9Sstevel@tonic-gate  */
67137c478bd9Sstevel@tonic-gate static ipqos_conf_action_t *
67147c478bd9Sstevel@tonic-gate actionexist(
67157c478bd9Sstevel@tonic-gate char *action_name,
67167c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions)
67177c478bd9Sstevel@tonic-gate {
67187c478bd9Sstevel@tonic-gate 
67197c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In actionexist: name: %s\n", action_name);
67207c478bd9Sstevel@tonic-gate 
67217c478bd9Sstevel@tonic-gate 	while (actions) {
67227c478bd9Sstevel@tonic-gate 		if (strcmp(action_name, actions->name) == 0) {
67237c478bd9Sstevel@tonic-gate 			break;
67247c478bd9Sstevel@tonic-gate 		}
67257c478bd9Sstevel@tonic-gate 		actions = actions->next;
67267c478bd9Sstevel@tonic-gate 	}
67277c478bd9Sstevel@tonic-gate 
67287c478bd9Sstevel@tonic-gate 	return (actions);
67297c478bd9Sstevel@tonic-gate }
67307c478bd9Sstevel@tonic-gate 
67317c478bd9Sstevel@tonic-gate /* **************************** act ref manip fns ******************** */
67327c478bd9Sstevel@tonic-gate 
67337c478bd9Sstevel@tonic-gate 
67347c478bd9Sstevel@tonic-gate /*
67357c478bd9Sstevel@tonic-gate  * add an action reference element with parameter field and action
67367c478bd9Sstevel@tonic-gate  * action_name to arefs.
67377c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
67387c478bd9Sstevel@tonic-gate  */
67397c478bd9Sstevel@tonic-gate static int
67407c478bd9Sstevel@tonic-gate add_aref(
67417c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t **arefs,
67427c478bd9Sstevel@tonic-gate char *field,
67437c478bd9Sstevel@tonic-gate char *action_name)
67447c478bd9Sstevel@tonic-gate {
67457c478bd9Sstevel@tonic-gate 
67467c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *aref;
67477c478bd9Sstevel@tonic-gate 
67487c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "add_aref: action: %s.\n", action_name);
67497c478bd9Sstevel@tonic-gate 
67507c478bd9Sstevel@tonic-gate 	/* allocate zero'd aref */
67517c478bd9Sstevel@tonic-gate 
67527c478bd9Sstevel@tonic-gate 	aref = malloc(sizeof (ipqos_conf_act_ref_t));
67537c478bd9Sstevel@tonic-gate 	if (aref == NULL) {
67547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
67557c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
67567c478bd9Sstevel@tonic-gate 	}
67577c478bd9Sstevel@tonic-gate 	(void) bzero(aref, sizeof (ipqos_conf_act_ref_t));
67587c478bd9Sstevel@tonic-gate 
67597c478bd9Sstevel@tonic-gate 	/* copy parameter name if present */
67607c478bd9Sstevel@tonic-gate 
67617c478bd9Sstevel@tonic-gate 	if (field)
67627c478bd9Sstevel@tonic-gate 		(void) strlcpy(aref->field, field, IPQOS_CONF_PNAME_LEN);
67637c478bd9Sstevel@tonic-gate 
67647c478bd9Sstevel@tonic-gate 	/* copy action name */
67657c478bd9Sstevel@tonic-gate 	(void) strlcpy(aref->name, action_name, IPQOS_CONF_NAME_LEN);
67667c478bd9Sstevel@tonic-gate 
67677c478bd9Sstevel@tonic-gate 	/* place at head of list */
67687c478bd9Sstevel@tonic-gate 
67697c478bd9Sstevel@tonic-gate 	aref->next = *arefs;
67707c478bd9Sstevel@tonic-gate 	*arefs = aref;
67717c478bd9Sstevel@tonic-gate 
67727c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
67737c478bd9Sstevel@tonic-gate }
67747c478bd9Sstevel@tonic-gate 
67757c478bd9Sstevel@tonic-gate /*
67767c478bd9Sstevel@tonic-gate  * free all the memory used by the action references in arefs.
67777c478bd9Sstevel@tonic-gate  */
67787c478bd9Sstevel@tonic-gate static void
67797c478bd9Sstevel@tonic-gate free_arefs(
67807c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *arefs)
67817c478bd9Sstevel@tonic-gate {
67827c478bd9Sstevel@tonic-gate 
67837c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *aref = arefs;
67847c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *next;
67857c478bd9Sstevel@tonic-gate 
67867c478bd9Sstevel@tonic-gate 	while (aref) {
67877c478bd9Sstevel@tonic-gate 		nvlist_free(aref->nvlist);
67887c478bd9Sstevel@tonic-gate 		next = aref->next;
67897c478bd9Sstevel@tonic-gate 		free(aref);
67907c478bd9Sstevel@tonic-gate 		aref = next;
67917c478bd9Sstevel@tonic-gate 	}
67927c478bd9Sstevel@tonic-gate }
67937c478bd9Sstevel@tonic-gate 
67947c478bd9Sstevel@tonic-gate 
67957c478bd9Sstevel@tonic-gate 
67967c478bd9Sstevel@tonic-gate /* *************************************************************** */
67977c478bd9Sstevel@tonic-gate 
67987c478bd9Sstevel@tonic-gate 
67997c478bd9Sstevel@tonic-gate 
68007c478bd9Sstevel@tonic-gate /*
68017c478bd9Sstevel@tonic-gate  * checks whether aname is a valid action name.
68027c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if invalid, else IPQOS_CONF_SUCCESS.
68037c478bd9Sstevel@tonic-gate  */
68047c478bd9Sstevel@tonic-gate static int
68057c478bd9Sstevel@tonic-gate valid_aname(char *aname)
68067c478bd9Sstevel@tonic-gate {
68077c478bd9Sstevel@tonic-gate 
68087c478bd9Sstevel@tonic-gate 	/*
68097c478bd9Sstevel@tonic-gate 	 * dissallow the use of the name of a virtual action, either
68107c478bd9Sstevel@tonic-gate 	 * the ipqosconf name, or the longer ipp names.
68117c478bd9Sstevel@tonic-gate 	 */
68127c478bd9Sstevel@tonic-gate 	if (strcmp(aname, IPQOS_CONF_CONT_STR) == 0 ||
68137c478bd9Sstevel@tonic-gate 	    strcmp(aname, IPQOS_CONF_DEFER_STR) == 0 ||
68147c478bd9Sstevel@tonic-gate 	    strcmp(aname, IPQOS_CONF_DROP_STR) == 0 ||
68157c478bd9Sstevel@tonic-gate 	    virtual_action(aname)) {
68167c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Invalid action name line %u.\n"),
68177c478bd9Sstevel@tonic-gate 		    lineno);
68187c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
68197c478bd9Sstevel@tonic-gate 	}
68207c478bd9Sstevel@tonic-gate 
68217c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
68227c478bd9Sstevel@tonic-gate }
68237c478bd9Sstevel@tonic-gate 
68247c478bd9Sstevel@tonic-gate /*
68257c478bd9Sstevel@tonic-gate  * Opens a stream to the types file for module module_name (assuming
68267c478bd9Sstevel@tonic-gate  * that the file path is TYPES_FILE_DIR/module_name.types). if
68277c478bd9Sstevel@tonic-gate  * a file open failure occurs, *openerr is set to 1.
68287c478bd9Sstevel@tonic-gate  * RETURNS: NULL on error, else stream ptr to module types file.
68297c478bd9Sstevel@tonic-gate  */
68307c478bd9Sstevel@tonic-gate static FILE *
68317c478bd9Sstevel@tonic-gate validmod(
68327c478bd9Sstevel@tonic-gate char *module_name,
68337c478bd9Sstevel@tonic-gate int *openerr)
68347c478bd9Sstevel@tonic-gate {
68357c478bd9Sstevel@tonic-gate 
68367c478bd9Sstevel@tonic-gate 	FILE *fp;
68377c478bd9Sstevel@tonic-gate 	char *path;
68387c478bd9Sstevel@tonic-gate 
68397c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In validmod: module_name: %s\n", module_name);
68407c478bd9Sstevel@tonic-gate 
68417c478bd9Sstevel@tonic-gate 	*openerr = 0;
68427c478bd9Sstevel@tonic-gate 
68437c478bd9Sstevel@tonic-gate 	/* create modules type file path */
68447c478bd9Sstevel@tonic-gate 
68457c478bd9Sstevel@tonic-gate 	path = malloc(strlen(TYPES_FILE_DIR) + strlen(module_name) +
68467c478bd9Sstevel@tonic-gate 	    strlen(".types") + 1);
68477c478bd9Sstevel@tonic-gate 	if (path == NULL) {
68487c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
68497c478bd9Sstevel@tonic-gate 		return (NULL);
68507c478bd9Sstevel@tonic-gate 	}
68517c478bd9Sstevel@tonic-gate 	(void) strcpy(path, TYPES_FILE_DIR);
68527c478bd9Sstevel@tonic-gate 	(void) strcat(path, module_name);
68537c478bd9Sstevel@tonic-gate 	(void) strcat(path, ".types");
68547c478bd9Sstevel@tonic-gate 
68557c478bd9Sstevel@tonic-gate 
68567c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "opening file %s\n", path);
68577c478bd9Sstevel@tonic-gate 
68587c478bd9Sstevel@tonic-gate 	/* open stream to types file */
68597c478bd9Sstevel@tonic-gate 
68607c478bd9Sstevel@tonic-gate 	fp = fopen(path, "r");
68617c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
68627c478bd9Sstevel@tonic-gate 		(*openerr)++;
68637c478bd9Sstevel@tonic-gate 	}
68647c478bd9Sstevel@tonic-gate 
68657c478bd9Sstevel@tonic-gate 	free(path);
68667c478bd9Sstevel@tonic-gate 	return (fp);
68677c478bd9Sstevel@tonic-gate }
68687c478bd9Sstevel@tonic-gate 
68697c478bd9Sstevel@tonic-gate 
68707c478bd9Sstevel@tonic-gate /*
68717c478bd9Sstevel@tonic-gate  * read a class clause from cfp into a class struct and point class at this.
68727c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
68737c478bd9Sstevel@tonic-gate  */
68747c478bd9Sstevel@tonic-gate static int
68757c478bd9Sstevel@tonic-gate readclass(
68767c478bd9Sstevel@tonic-gate FILE *cfp,
68777c478bd9Sstevel@tonic-gate char *module_name,
68787c478bd9Sstevel@tonic-gate ipqos_conf_class_t **class,
68797c478bd9Sstevel@tonic-gate char **perm_classes,
68807c478bd9Sstevel@tonic-gate int num_perm_classes)
68817c478bd9Sstevel@tonic-gate {
68827c478bd9Sstevel@tonic-gate 
68837c478bd9Sstevel@tonic-gate 	int nm, act;
68847c478bd9Sstevel@tonic-gate 	int res;
68857c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
68867c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
68877c478bd9Sstevel@tonic-gate 	char *name;
68887c478bd9Sstevel@tonic-gate 	char *action;
68897c478bd9Sstevel@tonic-gate 	int stats;
68907c478bd9Sstevel@tonic-gate 
68917c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in readclass\n");
68927c478bd9Sstevel@tonic-gate 
68937c478bd9Sstevel@tonic-gate 	/* create and zero class struct */
68947c478bd9Sstevel@tonic-gate 
68957c478bd9Sstevel@tonic-gate 	*class = alloc_class();
68967c478bd9Sstevel@tonic-gate 	if (!*class) {
68977c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
68987c478bd9Sstevel@tonic-gate 	}
68997c478bd9Sstevel@tonic-gate 	(*class)->originator = IPP_CONFIG_IPQOSCONF;
69007c478bd9Sstevel@tonic-gate 
69017c478bd9Sstevel@tonic-gate 	/* get starting line for error reporting */
69027c478bd9Sstevel@tonic-gate 	(*class)->lineno = lineno;
69037c478bd9Sstevel@tonic-gate 
69047c478bd9Sstevel@tonic-gate 	/* read curl_begin */
69057c478bd9Sstevel@tonic-gate 
69067c478bd9Sstevel@tonic-gate 	res = read_curl_begin(cfp);
69077c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
69087c478bd9Sstevel@tonic-gate 		goto fail;
69097c478bd9Sstevel@tonic-gate 	}
69107c478bd9Sstevel@tonic-gate 
69117c478bd9Sstevel@tonic-gate 	/* loop reading parameters till read curl_end */
69127c478bd9Sstevel@tonic-gate 
69137c478bd9Sstevel@tonic-gate 	stats = nm = act = 0;
69147c478bd9Sstevel@tonic-gate 	for (;;) {
69157c478bd9Sstevel@tonic-gate 		/* read nvpair */
69167c478bd9Sstevel@tonic-gate 		res = readnvpair(cfp, NULL, &(*class)->nvlist,
69177c478bd9Sstevel@tonic-gate 		    &nvp, &type, PL_CLASS, module_name);
69187c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
69197c478bd9Sstevel@tonic-gate 			goto fail;
69207c478bd9Sstevel@tonic-gate 
69217c478bd9Sstevel@tonic-gate 		/* reached end of class clause */
69227c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
69237c478bd9Sstevel@tonic-gate 			break;
69247c478bd9Sstevel@tonic-gate 		}
69257c478bd9Sstevel@tonic-gate 
69267c478bd9Sstevel@tonic-gate 		/*
69277c478bd9Sstevel@tonic-gate 		 * catch name and action nv pairs and stats if present
69287c478bd9Sstevel@tonic-gate 		 * and place values in class structure.
69297c478bd9Sstevel@tonic-gate 		 */
69307c478bd9Sstevel@tonic-gate 
69317c478bd9Sstevel@tonic-gate 		/* name */
69327c478bd9Sstevel@tonic-gate 
69337c478bd9Sstevel@tonic-gate 		if (nm == 0 &&
69347c478bd9Sstevel@tonic-gate 		    strcmp(nvpair_name(nvp), IPQOS_CONF_NAME_STR) == 0) {
69357c478bd9Sstevel@tonic-gate 
69367c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &name);
69377c478bd9Sstevel@tonic-gate 
69387c478bd9Sstevel@tonic-gate 			if (valid_name(name) != IPQOS_CONF_SUCCESS) {
69397c478bd9Sstevel@tonic-gate 				goto fail;
69407c478bd9Sstevel@tonic-gate 			}
69417c478bd9Sstevel@tonic-gate 			(void) strcpy((*class)->name, name);
69427c478bd9Sstevel@tonic-gate 			nm++;
69437c478bd9Sstevel@tonic-gate 
69447c478bd9Sstevel@tonic-gate 		/* next action */
69457c478bd9Sstevel@tonic-gate 
69467c478bd9Sstevel@tonic-gate 		} else if (act == 0 &&
69477c478bd9Sstevel@tonic-gate 		    strcmp(nvpair_name(nvp), IPQOS_CONF_NEXT_ACTION_STR) == 0) {
69487c478bd9Sstevel@tonic-gate 
69497c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &action);
69507c478bd9Sstevel@tonic-gate 
69517c478bd9Sstevel@tonic-gate 			/*
69527c478bd9Sstevel@tonic-gate 			 * if next action string continue string set action to
69537c478bd9Sstevel@tonic-gate 			 * IPP_ANAME_CONT, else if drop string IPP_ANAME_DROP
69547c478bd9Sstevel@tonic-gate 			 */
69557c478bd9Sstevel@tonic-gate 			if (strcmp(action, IPQOS_CONF_CONT_STR) == 0) {
69567c478bd9Sstevel@tonic-gate 				action = IPP_ANAME_CONT;
69577c478bd9Sstevel@tonic-gate 			} else if (strcmp(action, IPQOS_CONF_DROP_STR) == 0) {
69587c478bd9Sstevel@tonic-gate 				action = IPP_ANAME_DROP;
69597c478bd9Sstevel@tonic-gate 			}
69607c478bd9Sstevel@tonic-gate 
69617c478bd9Sstevel@tonic-gate 			/* add an action reference to action list */
69627c478bd9Sstevel@tonic-gate 
69637c478bd9Sstevel@tonic-gate 			res = add_aref(&(*class)->alist,
69647c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NEXT_ACTION_STR, action);
69657c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
69667c478bd9Sstevel@tonic-gate 				goto fail;
69677c478bd9Sstevel@tonic-gate 			}
69687c478bd9Sstevel@tonic-gate 			act++;
69697c478bd9Sstevel@tonic-gate 
69707c478bd9Sstevel@tonic-gate 		/* class stats enable */
69717c478bd9Sstevel@tonic-gate 
69727c478bd9Sstevel@tonic-gate 		} else if (stats == 0 &&
69737c478bd9Sstevel@tonic-gate 		    strcmp(nvpair_name(nvp), IPQOS_CONF_STATS_ENABLE_STR) ==
69747c478bd9Sstevel@tonic-gate 		    0) {
69757c478bd9Sstevel@tonic-gate 			boolean_t bl;
69767c478bd9Sstevel@tonic-gate 
69777c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, (uint32_t *)&bl);
69787c478bd9Sstevel@tonic-gate 			(*class)->stats_enable = bl;
69797c478bd9Sstevel@tonic-gate 
69807c478bd9Sstevel@tonic-gate 			stats++;
69817c478bd9Sstevel@tonic-gate 
69827c478bd9Sstevel@tonic-gate 		/* no other / duplicate parameters allowed */
69837c478bd9Sstevel@tonic-gate 
69847c478bd9Sstevel@tonic-gate 		} else {
69857c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
69867c478bd9Sstevel@tonic-gate 			    gettext("Unexpected parameter line %u.\n"), lineno);
69877c478bd9Sstevel@tonic-gate 			goto fail;
69887c478bd9Sstevel@tonic-gate 		}
69897c478bd9Sstevel@tonic-gate 	}
69907c478bd9Sstevel@tonic-gate 	if (nm == 0 || act == 0) {
69917c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
69927c478bd9Sstevel@tonic-gate 		    gettext("Missing class name/next action before line %u.\n"),
69937c478bd9Sstevel@tonic-gate 		    lineno);
69947c478bd9Sstevel@tonic-gate 		goto fail;
69957c478bd9Sstevel@tonic-gate 	}
69967c478bd9Sstevel@tonic-gate 
69977c478bd9Sstevel@tonic-gate 	/* change class originator field to permanent if permanent class */
69987c478bd9Sstevel@tonic-gate 
69997c478bd9Sstevel@tonic-gate 	if (in_string_table(perm_classes, num_perm_classes, (*class)->name)) {
70007c478bd9Sstevel@tonic-gate 	    IPQOSCDBG1(L0, "Setting class %s as permanent.\n", (*class)->name);
70017c478bd9Sstevel@tonic-gate 		(*class)->originator = IPP_CONFIG_PERMANENT;
70027c478bd9Sstevel@tonic-gate 	}
70037c478bd9Sstevel@tonic-gate 
70047c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
70057c478bd9Sstevel@tonic-gate fail:
70067c478bd9Sstevel@tonic-gate 	if (*class)
70077c478bd9Sstevel@tonic-gate 		free_class(*class);
70087c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
70097c478bd9Sstevel@tonic-gate }
70107c478bd9Sstevel@tonic-gate 
70117c478bd9Sstevel@tonic-gate /*
70127c478bd9Sstevel@tonic-gate  * This function assumes either src_nd_name or dst_node_nm are set in filter.
70137c478bd9Sstevel@tonic-gate  *
70147c478bd9Sstevel@tonic-gate  * Creates one of more copies of filter according to the ip versions
70157c478bd9Sstevel@tonic-gate  * requested (or assumed) and the resolution of the src and dst address
70167c478bd9Sstevel@tonic-gate  * node names if spec'd. If both node names are spec'd then a filter is
70177c478bd9Sstevel@tonic-gate  * created for each pair of addresses (one from each node name) that is
70187c478bd9Sstevel@tonic-gate  * compatible with the chosen address family, otherwise a filter copy is
70197c478bd9Sstevel@tonic-gate  * created for just each address of the single node name that is
70207c478bd9Sstevel@tonic-gate  * compatible.
70217c478bd9Sstevel@tonic-gate  * If filter->ip_versions has been set that is used to determine the
70227c478bd9Sstevel@tonic-gate  * af's we will create filters for, else if a numeric address was
70237c478bd9Sstevel@tonic-gate  * added the family of that will be used, otherwise we fall back
70247c478bd9Sstevel@tonic-gate  * to both v4 and v6 addresses.
70257c478bd9Sstevel@tonic-gate  *
70267c478bd9Sstevel@tonic-gate  * Any name lookup failures that occur are checked to see whether the failure
70277c478bd9Sstevel@tonic-gate  * was a soft or hard failure and the nlerr field of filter set accordingly
70287c478bd9Sstevel@tonic-gate  * before the error is returned.
70297c478bd9Sstevel@tonic-gate  *
70307c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on any error, else IPQOS_CONF_SUCCESS.
70317c478bd9Sstevel@tonic-gate  */
70327c478bd9Sstevel@tonic-gate 
70337c478bd9Sstevel@tonic-gate static int
70347c478bd9Sstevel@tonic-gate domultihome(
70357c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter,
70367c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **flist,
70377c478bd9Sstevel@tonic-gate boolean_t last_retry)
70387c478bd9Sstevel@tonic-gate {
70397c478bd9Sstevel@tonic-gate 
70407c478bd9Sstevel@tonic-gate 	uint32_t ftype;
70417c478bd9Sstevel@tonic-gate 	int v4 = 1, v6 = 1;	/* default lookup family is v4 and v6 */
70427c478bd9Sstevel@tonic-gate 	int saf, daf;
70437c478bd9Sstevel@tonic-gate 	struct hostent *shp = NULL;
70447c478bd9Sstevel@tonic-gate 	struct hostent *dhp = NULL;
70457c478bd9Sstevel@tonic-gate 	in6_addr_t daddr, saddr;
70467c478bd9Sstevel@tonic-gate 	int idx = 0;
70477c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *nfilter;
70487c478bd9Sstevel@tonic-gate 	int res;
70497c478bd9Sstevel@tonic-gate 	int ernum;
70507c478bd9Sstevel@tonic-gate 	int in32b = 0;
70517c478bd9Sstevel@tonic-gate 	char **sp, **dp;
70527c478bd9Sstevel@tonic-gate 
70537c478bd9Sstevel@tonic-gate 	IPQOSCDBG3(MHME, "In domultihome: filter: %s, src_node: %s, "
70547c478bd9Sstevel@tonic-gate 	    "dst_node: %s\n", filter->name,
70557c478bd9Sstevel@tonic-gate 	    (filter->src_nd_name ? filter->src_nd_name : "NULL"),
70567c478bd9Sstevel@tonic-gate 	    (filter->dst_nd_name ? filter->dst_nd_name : "NULL"));
70577c478bd9Sstevel@tonic-gate 
70587c478bd9Sstevel@tonic-gate 	/* check if we've read an ip_version request to get the versions */
70597c478bd9Sstevel@tonic-gate 
70607c478bd9Sstevel@tonic-gate 	if (filter->ip_versions != 0) {
70617c478bd9Sstevel@tonic-gate 		v4 = VERSION_IS_V4(filter);
70627c478bd9Sstevel@tonic-gate 		v6 = VERSION_IS_V6(filter);
70637c478bd9Sstevel@tonic-gate 
70647c478bd9Sstevel@tonic-gate 	/* otherwise check if we've read a numeric address and get versions */
70657c478bd9Sstevel@tonic-gate 
70667c478bd9Sstevel@tonic-gate 	} else if (nvlist_lookup_uint32(filter->nvlist, IPGPC_FILTER_TYPE,
70677c478bd9Sstevel@tonic-gate 	    &ftype) == 0) {
70687c478bd9Sstevel@tonic-gate 		if (ftype == IPGPC_V4_FLTR) {
70697c478bd9Sstevel@tonic-gate 			v6--;
70707c478bd9Sstevel@tonic-gate 		} else {
70717c478bd9Sstevel@tonic-gate 			v4--;
70727c478bd9Sstevel@tonic-gate 		}
70737c478bd9Sstevel@tonic-gate 	}
70747c478bd9Sstevel@tonic-gate 
70757c478bd9Sstevel@tonic-gate 	/* read saddrs if src node name */
70767c478bd9Sstevel@tonic-gate 
70777c478bd9Sstevel@tonic-gate 	if (filter->src_nd_name) {
70787c478bd9Sstevel@tonic-gate 
70797c478bd9Sstevel@tonic-gate 		/* v4 only address */
70807c478bd9Sstevel@tonic-gate 
70817c478bd9Sstevel@tonic-gate 		if (v4 && !v6) {
70827c478bd9Sstevel@tonic-gate 			in32b++;
70837c478bd9Sstevel@tonic-gate 			shp = getipnodebyname(filter->src_nd_name, AF_INET,
70847c478bd9Sstevel@tonic-gate 			    AI_ADDRCONFIG, &ernum);
70857c478bd9Sstevel@tonic-gate 
70867c478bd9Sstevel@tonic-gate 		/* v6 only  */
70877c478bd9Sstevel@tonic-gate 
70887c478bd9Sstevel@tonic-gate 		} else if (v6 && !v4) {
70897c478bd9Sstevel@tonic-gate 			shp = getipnodebyname(filter->src_nd_name, AF_INET6,
70907c478bd9Sstevel@tonic-gate 			    AI_DEFAULT, &ernum);
70917c478bd9Sstevel@tonic-gate 
70927c478bd9Sstevel@tonic-gate 		/* v4 and v6 */
70937c478bd9Sstevel@tonic-gate 
70947c478bd9Sstevel@tonic-gate 		} else if (v6 && v4) {
70957c478bd9Sstevel@tonic-gate 			shp = getipnodebyname(filter->src_nd_name, AF_INET6,
70967c478bd9Sstevel@tonic-gate 			    AI_DEFAULT|AI_ALL, &ernum);
70977c478bd9Sstevel@tonic-gate 		}
70987c478bd9Sstevel@tonic-gate 
70997c478bd9Sstevel@tonic-gate #ifdef	TESTING_RETRY
71007c478bd9Sstevel@tonic-gate if (!last_retry) {
71017c478bd9Sstevel@tonic-gate 	filter->nlerr = IPQOS_LOOKUP_RETRY;
71027c478bd9Sstevel@tonic-gate 	goto fail;
71037c478bd9Sstevel@tonic-gate }
71047c478bd9Sstevel@tonic-gate #endif
71057c478bd9Sstevel@tonic-gate 
71067c478bd9Sstevel@tonic-gate 		/*
71077c478bd9Sstevel@tonic-gate 		 * if lookup error determine whether it was a soft or hard
71087c478bd9Sstevel@tonic-gate 		 * failure and mark as such in filter.
71097c478bd9Sstevel@tonic-gate 		 */
71107c478bd9Sstevel@tonic-gate 		if (shp == NULL) {
71117c478bd9Sstevel@tonic-gate 			if (ernum != TRY_AGAIN) {
71127c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR, gettext("Failed to "
71137c478bd9Sstevel@tonic-gate 				    "resolve src host name for filter at "
71147c478bd9Sstevel@tonic-gate 				    "line %u, ignoring filter.\n"),
71157c478bd9Sstevel@tonic-gate 				    filter->lineno);
71167c478bd9Sstevel@tonic-gate 				filter->nlerr = IPQOS_LOOKUP_FAIL;
71177c478bd9Sstevel@tonic-gate 			} else {
71187c478bd9Sstevel@tonic-gate 				if (last_retry) {
71197c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR, gettext("Failed "
71207c478bd9Sstevel@tonic-gate 					    "to resolve src host name for "
71217c478bd9Sstevel@tonic-gate 					    "filter at line %u, ignoring "
71227c478bd9Sstevel@tonic-gate 					    "filter.\n"), filter->lineno);
71237c478bd9Sstevel@tonic-gate 				}
71247c478bd9Sstevel@tonic-gate 				filter->nlerr = IPQOS_LOOKUP_RETRY;
71257c478bd9Sstevel@tonic-gate 			}
71267c478bd9Sstevel@tonic-gate 			goto fail;
71277c478bd9Sstevel@tonic-gate 		}
71287c478bd9Sstevel@tonic-gate 	}
71297c478bd9Sstevel@tonic-gate 
71307c478bd9Sstevel@tonic-gate 	/* read daddrs if dst node name */
71317c478bd9Sstevel@tonic-gate 	if (filter->dst_nd_name) {
71327c478bd9Sstevel@tonic-gate 
71337c478bd9Sstevel@tonic-gate 		/* v4 only address */
71347c478bd9Sstevel@tonic-gate 
71357c478bd9Sstevel@tonic-gate 		if (v4 && !v6) {
71367c478bd9Sstevel@tonic-gate 			in32b++;
71377c478bd9Sstevel@tonic-gate 			dhp = getipnodebyname(filter->dst_nd_name, AF_INET,
71387c478bd9Sstevel@tonic-gate 			    AI_ADDRCONFIG, &ernum);
71397c478bd9Sstevel@tonic-gate 
71407c478bd9Sstevel@tonic-gate 		/* v6 only */
71417c478bd9Sstevel@tonic-gate 
71427c478bd9Sstevel@tonic-gate 		} else if (v6 && !v4) {
71437c478bd9Sstevel@tonic-gate 			dhp = getipnodebyname(filter->dst_nd_name, AF_INET6,
71447c478bd9Sstevel@tonic-gate 			    AI_DEFAULT, &ernum);
71457c478bd9Sstevel@tonic-gate 
71467c478bd9Sstevel@tonic-gate 		/*  v6 and v4 addresses */
71477c478bd9Sstevel@tonic-gate 
71487c478bd9Sstevel@tonic-gate 		} else {
71497c478bd9Sstevel@tonic-gate 			dhp = getipnodebyname(filter->dst_nd_name, AF_INET6,
71507c478bd9Sstevel@tonic-gate 			    AI_DEFAULT|AI_ALL, &ernum);
71517c478bd9Sstevel@tonic-gate 		}
71527c478bd9Sstevel@tonic-gate 
71537c478bd9Sstevel@tonic-gate 		if (dhp == NULL) {
71547c478bd9Sstevel@tonic-gate 			if (ernum != TRY_AGAIN) {
71557c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR, gettext("Failed to "
71567c478bd9Sstevel@tonic-gate 				    "resolve dst host name for filter at "
71577c478bd9Sstevel@tonic-gate 				    "line %u, ignoring filter.\n"),
71587c478bd9Sstevel@tonic-gate 				    filter->lineno);
71597c478bd9Sstevel@tonic-gate 				filter->nlerr = IPQOS_LOOKUP_FAIL;
71607c478bd9Sstevel@tonic-gate 			} else {
71617c478bd9Sstevel@tonic-gate 				if (last_retry) {
71627c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR, gettext("Failed "
71637c478bd9Sstevel@tonic-gate 					    "to resolve dst host name for "
71647c478bd9Sstevel@tonic-gate 					    "filter at line %u, ignoring "
71657c478bd9Sstevel@tonic-gate 					    "filter.\n"), filter->lineno);
71667c478bd9Sstevel@tonic-gate 				}
71677c478bd9Sstevel@tonic-gate 				filter->nlerr = IPQOS_LOOKUP_RETRY;
71687c478bd9Sstevel@tonic-gate 			}
71697c478bd9Sstevel@tonic-gate 			goto fail;
71707c478bd9Sstevel@tonic-gate 		}
71717c478bd9Sstevel@tonic-gate 	}
71727c478bd9Sstevel@tonic-gate 
71737c478bd9Sstevel@tonic-gate 	/*
71747c478bd9Sstevel@tonic-gate 	 * if src and dst node name, create set of filters; one for each
71757c478bd9Sstevel@tonic-gate 	 * src and dst address of matching types.
71767c478bd9Sstevel@tonic-gate 	 */
71777c478bd9Sstevel@tonic-gate 	if (filter->src_nd_name && filter->dst_nd_name) {
71787c478bd9Sstevel@tonic-gate 
71797c478bd9Sstevel@tonic-gate 		for (sp = shp->h_addr_list; *sp != NULL; sp++) {
71807c478bd9Sstevel@tonic-gate 			(void) bcopy(*sp, &saddr, shp->h_length);
71817c478bd9Sstevel@tonic-gate 
71827c478bd9Sstevel@tonic-gate 			/* get saddr family */
71837c478bd9Sstevel@tonic-gate 
71847c478bd9Sstevel@tonic-gate 			if (in32b || IN6_IS_ADDR_V4MAPPED(&saddr)) {
71857c478bd9Sstevel@tonic-gate 				saf = AF_INET;
71867c478bd9Sstevel@tonic-gate 			} else {
71877c478bd9Sstevel@tonic-gate 				saf = AF_INET6;
71887c478bd9Sstevel@tonic-gate 			}
71897c478bd9Sstevel@tonic-gate 
71907c478bd9Sstevel@tonic-gate 			for (dp = dhp->h_addr_list; *dp != NULL; dp++) {
71917c478bd9Sstevel@tonic-gate 				(void) bcopy(*dp, &daddr, dhp->h_length);
71927c478bd9Sstevel@tonic-gate 
71937c478bd9Sstevel@tonic-gate 				/* get daddr family */
71947c478bd9Sstevel@tonic-gate 
71957c478bd9Sstevel@tonic-gate 				if (in32b || IN6_IS_ADDR_V4MAPPED(&daddr)) {
71967c478bd9Sstevel@tonic-gate 					daf = AF_INET;
71977c478bd9Sstevel@tonic-gate 				} else {
71987c478bd9Sstevel@tonic-gate 					daf = AF_INET6;
71997c478bd9Sstevel@tonic-gate 				}
72007c478bd9Sstevel@tonic-gate 
72017c478bd9Sstevel@tonic-gate 				/*
72027c478bd9Sstevel@tonic-gate 				 * if saddr and daddr same af duplicate
72037c478bd9Sstevel@tonic-gate 				 * filter adding addresses and new instance
72047c478bd9Sstevel@tonic-gate 				 * number and add to flist filter list.
72057c478bd9Sstevel@tonic-gate 				 */
72067c478bd9Sstevel@tonic-gate 
72077c478bd9Sstevel@tonic-gate 				if (daf == saf) {
72087c478bd9Sstevel@tonic-gate 
72097c478bd9Sstevel@tonic-gate 					res = dup_filter(filter, &nfilter, saf,
72107c478bd9Sstevel@tonic-gate 					    !in32b, &saddr, &daddr, ++idx);
72117c478bd9Sstevel@tonic-gate 					if (res != IPQOS_CONF_SUCCESS) {
72127c478bd9Sstevel@tonic-gate 						goto fail;
72137c478bd9Sstevel@tonic-gate 					}
72147c478bd9Sstevel@tonic-gate 					ADD_TO_LIST(flist, nfilter);
72157c478bd9Sstevel@tonic-gate 				}
72167c478bd9Sstevel@tonic-gate 			}
72177c478bd9Sstevel@tonic-gate 		}
72187c478bd9Sstevel@tonic-gate 
72197c478bd9Sstevel@tonic-gate 	/* if src name only create set of filters, one for each node address */
72207c478bd9Sstevel@tonic-gate 
72217c478bd9Sstevel@tonic-gate 	} else if (filter->src_nd_name) {
72227c478bd9Sstevel@tonic-gate 
72237c478bd9Sstevel@tonic-gate 		for (sp = shp->h_addr_list; *sp != NULL; sp++) {
72247c478bd9Sstevel@tonic-gate 			(void) bcopy(*sp, &saddr, shp->h_length);
72257c478bd9Sstevel@tonic-gate 
72267c478bd9Sstevel@tonic-gate 			/* get af */
72277c478bd9Sstevel@tonic-gate 
72287c478bd9Sstevel@tonic-gate 			if (in32b || IN6_IS_ADDR_V4MAPPED(&saddr)) {
72297c478bd9Sstevel@tonic-gate 				saf = AF_INET;
72307c478bd9Sstevel@tonic-gate 			} else {
72317c478bd9Sstevel@tonic-gate 				saf = AF_INET6;
72327c478bd9Sstevel@tonic-gate 			}
72337c478bd9Sstevel@tonic-gate 
72347c478bd9Sstevel@tonic-gate 
72357c478bd9Sstevel@tonic-gate 			/*
72367c478bd9Sstevel@tonic-gate 			 * dup filter adding saddr and new instance num and
72377c478bd9Sstevel@tonic-gate 			 * add to flist filter list.
72387c478bd9Sstevel@tonic-gate 			 */
72397c478bd9Sstevel@tonic-gate 			res = dup_filter(filter, &nfilter, saf, !in32b, &saddr,
72407c478bd9Sstevel@tonic-gate 			    NULL, ++idx);
72417c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
72427c478bd9Sstevel@tonic-gate 				goto fail;
72437c478bd9Sstevel@tonic-gate 			}
72447c478bd9Sstevel@tonic-gate 
72457c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(flist, nfilter);
72467c478bd9Sstevel@tonic-gate 
72477c478bd9Sstevel@tonic-gate 		}
72487c478bd9Sstevel@tonic-gate 
72497c478bd9Sstevel@tonic-gate 	/* if dname only create set of filters, one for each node address */
72507c478bd9Sstevel@tonic-gate 
72517c478bd9Sstevel@tonic-gate 	} else {
72527c478bd9Sstevel@tonic-gate 		for (dp = dhp->h_addr_list; *dp != NULL; dp++) {
72537c478bd9Sstevel@tonic-gate 			(void) bcopy(*dp, &daddr, dhp->h_length);
72547c478bd9Sstevel@tonic-gate 
72557c478bd9Sstevel@tonic-gate 			/* get af */
72567c478bd9Sstevel@tonic-gate 
72577c478bd9Sstevel@tonic-gate 			if (in32b || IN6_IS_ADDR_V4MAPPED(&daddr)) {
72587c478bd9Sstevel@tonic-gate 				daf = AF_INET;
72597c478bd9Sstevel@tonic-gate 			} else {
72607c478bd9Sstevel@tonic-gate 				daf = AF_INET6;
72617c478bd9Sstevel@tonic-gate 			}
72627c478bd9Sstevel@tonic-gate 
72637c478bd9Sstevel@tonic-gate 			/*
72647c478bd9Sstevel@tonic-gate 			 * dup filter adding daddr and new instance num and
72657c478bd9Sstevel@tonic-gate 			 * add to flist filter list.
72667c478bd9Sstevel@tonic-gate 			 */
72677c478bd9Sstevel@tonic-gate 			res = dup_filter(filter, &nfilter, daf, !in32b, NULL,
72687c478bd9Sstevel@tonic-gate 			    &daddr, ++idx);
72697c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
72707c478bd9Sstevel@tonic-gate 				goto fail;
72717c478bd9Sstevel@tonic-gate 			}
72727c478bd9Sstevel@tonic-gate 
72737c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(flist, nfilter);
72747c478bd9Sstevel@tonic-gate 		}
72757c478bd9Sstevel@tonic-gate 	}
72767c478bd9Sstevel@tonic-gate 
72777c478bd9Sstevel@tonic-gate 	if (shp)
72787c478bd9Sstevel@tonic-gate 		freehostent(shp);
72797c478bd9Sstevel@tonic-gate 	if (dhp)
72807c478bd9Sstevel@tonic-gate 		freehostent(dhp);
72817c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
72827c478bd9Sstevel@tonic-gate fail:
72837c478bd9Sstevel@tonic-gate 	/*
72847c478bd9Sstevel@tonic-gate 	 * should really clean up any filters that we have created,
72857c478bd9Sstevel@tonic-gate 	 * however, free_actions called from readaction will cleam them up.
72867c478bd9Sstevel@tonic-gate 	 */
72877c478bd9Sstevel@tonic-gate 	if (shp)
72887c478bd9Sstevel@tonic-gate 		freehostent(shp);
72897c478bd9Sstevel@tonic-gate 	if (dhp)
72907c478bd9Sstevel@tonic-gate 		freehostent(dhp);
72917c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
72927c478bd9Sstevel@tonic-gate }
72937c478bd9Sstevel@tonic-gate 
72947c478bd9Sstevel@tonic-gate 
72957c478bd9Sstevel@tonic-gate /*
72967c478bd9Sstevel@tonic-gate  * read a filter clause from cfp into a filter struct and point filter
72977c478bd9Sstevel@tonic-gate  * at this.
72987c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
72997c478bd9Sstevel@tonic-gate  */
73007c478bd9Sstevel@tonic-gate static int
73017c478bd9Sstevel@tonic-gate readfilter(
73027c478bd9Sstevel@tonic-gate FILE *cfp,
73037c478bd9Sstevel@tonic-gate FILE *tfp,
73047c478bd9Sstevel@tonic-gate char *module_name,
73057c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **filter,
73067c478bd9Sstevel@tonic-gate char **perm_filters,
73077c478bd9Sstevel@tonic-gate int num_perm_filters)
73087c478bd9Sstevel@tonic-gate {
73097c478bd9Sstevel@tonic-gate 
73107c478bd9Sstevel@tonic-gate 	int res;
73117c478bd9Sstevel@tonic-gate 	int nm, cls, ipv;
73127c478bd9Sstevel@tonic-gate 	in6_addr_t mask;
73137c478bd9Sstevel@tonic-gate 	char *addr_str;
73147c478bd9Sstevel@tonic-gate 	char *sl = NULL;
73157c478bd9Sstevel@tonic-gate 	in6_addr_t addr;
73167c478bd9Sstevel@tonic-gate 	int sa;
73177c478bd9Sstevel@tonic-gate 	struct hostent *hp;
73187c478bd9Sstevel@tonic-gate 	int err_num;
73197c478bd9Sstevel@tonic-gate 	int v4 = 0, v6 = 0;
73207c478bd9Sstevel@tonic-gate 	uchar_t mlen;
73217c478bd9Sstevel@tonic-gate 	char *tmp;
73227c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
73237c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
73247c478bd9Sstevel@tonic-gate 	char *name;
73257c478bd9Sstevel@tonic-gate 	char *class;
73267c478bd9Sstevel@tonic-gate 	uchar_t b;
73277c478bd9Sstevel@tonic-gate 	in6_addr_t v6addr;
73287c478bd9Sstevel@tonic-gate 
73297c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in readfilter\n");
73307c478bd9Sstevel@tonic-gate 
73317c478bd9Sstevel@tonic-gate 
73327c478bd9Sstevel@tonic-gate 	/* create and zero filter struct */
73337c478bd9Sstevel@tonic-gate 
73347c478bd9Sstevel@tonic-gate 	*filter = alloc_filter();
73357c478bd9Sstevel@tonic-gate 	if (*filter == NULL) {
73367c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
73377c478bd9Sstevel@tonic-gate 	}
73387c478bd9Sstevel@tonic-gate 	(*filter)->originator = IPP_CONFIG_IPQOSCONF;
73397c478bd9Sstevel@tonic-gate 
73407c478bd9Sstevel@tonic-gate 	/* get starting line for error reporting */
73417c478bd9Sstevel@tonic-gate 	(*filter)->lineno = lineno;
73427c478bd9Sstevel@tonic-gate 
73437c478bd9Sstevel@tonic-gate 	/* read beginning curl */
73447c478bd9Sstevel@tonic-gate 
73457c478bd9Sstevel@tonic-gate 	res = read_curl_begin(cfp);
73467c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
73477c478bd9Sstevel@tonic-gate 		goto fail;
73487c478bd9Sstevel@tonic-gate 	}
73497c478bd9Sstevel@tonic-gate 
73507c478bd9Sstevel@tonic-gate 
73517c478bd9Sstevel@tonic-gate 	/*
73527c478bd9Sstevel@tonic-gate 	 * loop reading nvpairs onto nvlist until encounter CURL_END
73537c478bd9Sstevel@tonic-gate 	 */
73547c478bd9Sstevel@tonic-gate 	ipv = nm = cls = 0;
73557c478bd9Sstevel@tonic-gate 	for (;;) {
73567c478bd9Sstevel@tonic-gate 		/* read nvpair */
73577c478bd9Sstevel@tonic-gate 
73587c478bd9Sstevel@tonic-gate 		res = readnvpair(cfp, tfp, &(*filter)->nvlist,
73597c478bd9Sstevel@tonic-gate 		    &nvp, &type, PL_FILTER, module_name);
73607c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
73617c478bd9Sstevel@tonic-gate 			goto fail;
73627c478bd9Sstevel@tonic-gate 
73637c478bd9Sstevel@tonic-gate 		/* reached the end of filter definition */
73647c478bd9Sstevel@tonic-gate 
73657c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
73667c478bd9Sstevel@tonic-gate 			break;
73677c478bd9Sstevel@tonic-gate 		}
73687c478bd9Sstevel@tonic-gate 
73697c478bd9Sstevel@tonic-gate 		/*
73707c478bd9Sstevel@tonic-gate 		 * catch name and class and place value into filter
73717c478bd9Sstevel@tonic-gate 		 * structure.
73727c478bd9Sstevel@tonic-gate 		 */
73737c478bd9Sstevel@tonic-gate 
73747c478bd9Sstevel@tonic-gate 		/* read filter name */
73757c478bd9Sstevel@tonic-gate 
73767c478bd9Sstevel@tonic-gate 		if (strcmp(nvpair_name(nvp), IPQOS_CONF_NAME_STR) == 0) {
73777c478bd9Sstevel@tonic-gate 			if (nm != 0) {
73787c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
73797c478bd9Sstevel@tonic-gate 				    gettext("Duplicate parameter line %u.\n"),
73807c478bd9Sstevel@tonic-gate 				    lineno);
73817c478bd9Sstevel@tonic-gate 				goto fail;
73827c478bd9Sstevel@tonic-gate 			}
73837c478bd9Sstevel@tonic-gate 
73847c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &name);
73857c478bd9Sstevel@tonic-gate 			if (valid_name(name) != IPQOS_CONF_SUCCESS) {
73867c478bd9Sstevel@tonic-gate 				goto fail;
73877c478bd9Sstevel@tonic-gate 			}
73887c478bd9Sstevel@tonic-gate 
73897c478bd9Sstevel@tonic-gate 			(void) strcpy((*filter)->name, name);
73907c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all((*filter)->nvlist,
73917c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NAME_STR);
73927c478bd9Sstevel@tonic-gate 			nm++;
73937c478bd9Sstevel@tonic-gate 
73947c478bd9Sstevel@tonic-gate 		/* read class name */
73957c478bd9Sstevel@tonic-gate 
73967c478bd9Sstevel@tonic-gate 		} else if (strcmp(nvpair_name(nvp), IPQOS_CONF_CLASS_STR) ==
73977c478bd9Sstevel@tonic-gate 		    0) {
73987c478bd9Sstevel@tonic-gate 			if (cls != 0) {
73997c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
74007c478bd9Sstevel@tonic-gate 				    gettext("Duplicate parameter line %u.\n"),
74017c478bd9Sstevel@tonic-gate 				    lineno);
74027c478bd9Sstevel@tonic-gate 				goto fail;
74037c478bd9Sstevel@tonic-gate 			}
74047c478bd9Sstevel@tonic-gate 
74057c478bd9Sstevel@tonic-gate 			if (nvpair_value_string(nvp, &class) != 0) {
74067c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "nvpair_value_string");
74077c478bd9Sstevel@tonic-gate 				break;
74087c478bd9Sstevel@tonic-gate 			}
74097c478bd9Sstevel@tonic-gate 			if (valid_name(class) != IPQOS_CONF_SUCCESS) {
74107c478bd9Sstevel@tonic-gate 				goto fail;
74117c478bd9Sstevel@tonic-gate 			}
74127c478bd9Sstevel@tonic-gate 			(void) strcpy((*filter)->class_name, class);
74137c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all((*filter)->nvlist,
74147c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_CLASS_STR);
74157c478bd9Sstevel@tonic-gate 			cls++;
74167c478bd9Sstevel@tonic-gate 
74177c478bd9Sstevel@tonic-gate 		/*
74187c478bd9Sstevel@tonic-gate 		 * if a src or dst ip node name/address. For those that
74197c478bd9Sstevel@tonic-gate 		 * are determined to be addresses we convert them from
74207c478bd9Sstevel@tonic-gate 		 * strings here and add to the filter nvlist; for node names
74217c478bd9Sstevel@tonic-gate 		 * we add the name to the filter struct for readaction to
74227c478bd9Sstevel@tonic-gate 		 * process.
74237c478bd9Sstevel@tonic-gate 		 */
74247c478bd9Sstevel@tonic-gate 		} else if (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 0 ||
74257c478bd9Sstevel@tonic-gate 		    strcmp(nvpair_name(nvp), IPGPC_DADDR) == 0) {
74267c478bd9Sstevel@tonic-gate 
74277c478bd9Sstevel@tonic-gate 			sa = 0;
74287c478bd9Sstevel@tonic-gate 
74297c478bd9Sstevel@tonic-gate 			if (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 0) {
74307c478bd9Sstevel@tonic-gate 				sa++;
74317c478bd9Sstevel@tonic-gate 			}
74327c478bd9Sstevel@tonic-gate 
74337c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &addr_str);
74347c478bd9Sstevel@tonic-gate 
74357c478bd9Sstevel@tonic-gate 			/*
74367c478bd9Sstevel@tonic-gate 			 * get the address mask if present.
74377c478bd9Sstevel@tonic-gate 			 * make a copy so that the nvlist element that
74387c478bd9Sstevel@tonic-gate 			 * it is part of doesn't dissapear and causes probs.
74397c478bd9Sstevel@tonic-gate 			 */
74407c478bd9Sstevel@tonic-gate 			sl = strchr(addr_str, '/');
74417c478bd9Sstevel@tonic-gate 			if (sl) {
74427c478bd9Sstevel@tonic-gate 				*sl = '\0';
74437c478bd9Sstevel@tonic-gate 				tmp = malloc(strlen(++sl) + 1);
74447c478bd9Sstevel@tonic-gate 				if (tmp == NULL) {
74457c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR, "malloc");
74467c478bd9Sstevel@tonic-gate 					goto fail;
74477c478bd9Sstevel@tonic-gate 				}
74487c478bd9Sstevel@tonic-gate 				(void) strcpy(tmp, sl);
74497c478bd9Sstevel@tonic-gate 				sl = tmp;
74507c478bd9Sstevel@tonic-gate 			}
74517c478bd9Sstevel@tonic-gate 
74527c478bd9Sstevel@tonic-gate 
74537c478bd9Sstevel@tonic-gate 			/* if a numeric address */
74547c478bd9Sstevel@tonic-gate 
74557c478bd9Sstevel@tonic-gate 			if (inet_pton(AF_INET, addr_str, &addr) == 1 ||
74567c478bd9Sstevel@tonic-gate 			    inet_pton(AF_INET6, addr_str, &addr) == 1) {
74577c478bd9Sstevel@tonic-gate 
74587c478bd9Sstevel@tonic-gate 				/* get address */
74597c478bd9Sstevel@tonic-gate 
74607c478bd9Sstevel@tonic-gate 				hp = getipnodebyname(addr_str, AF_INET6,
74617c478bd9Sstevel@tonic-gate 				    AI_DEFAULT, &err_num);
74627c478bd9Sstevel@tonic-gate 				if (hp == NULL) {
74637c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
74647c478bd9Sstevel@tonic-gate 					    "getipnodebyname");
74657c478bd9Sstevel@tonic-gate 					goto fail;
74667c478bd9Sstevel@tonic-gate 				}
74677c478bd9Sstevel@tonic-gate 
74687c478bd9Sstevel@tonic-gate 				(void) bcopy(hp->h_addr_list[0], &v6addr,
74697c478bd9Sstevel@tonic-gate 				    hp->h_length);
74707c478bd9Sstevel@tonic-gate 				freehostent(hp);
74717c478bd9Sstevel@tonic-gate 
74727c478bd9Sstevel@tonic-gate 				/* determine address type */
74737c478bd9Sstevel@tonic-gate 
74747c478bd9Sstevel@tonic-gate 				v4 = IN6_IS_ADDR_V4MAPPED(&v6addr);
74757c478bd9Sstevel@tonic-gate 				if (!v4) {
74767c478bd9Sstevel@tonic-gate 					v6++;
74777c478bd9Sstevel@tonic-gate 				}
74787c478bd9Sstevel@tonic-gate 
74797c478bd9Sstevel@tonic-gate 				/*
74807c478bd9Sstevel@tonic-gate 				 * check any previous addresses have same
74817c478bd9Sstevel@tonic-gate 				 * version.
74827c478bd9Sstevel@tonic-gate 				 */
74837c478bd9Sstevel@tonic-gate 				if (nvlist_lookup_byte((*filter)->nvlist,
74847c478bd9Sstevel@tonic-gate 				    IPGPC_FILTER_TYPE, &b) == 0) {
74857c478bd9Sstevel@tonic-gate 					if (v4 && b != IPGPC_V4_FLTR ||
74867c478bd9Sstevel@tonic-gate 					    v6 && b != IPGPC_V6_FLTR) {
74877c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ERROR,
74887c478bd9Sstevel@tonic-gate 						    gettext("Incompatible "
74897c478bd9Sstevel@tonic-gate 						    "address version line "
74907c478bd9Sstevel@tonic-gate 						    "%u.\n"), lineno);
74917c478bd9Sstevel@tonic-gate 						goto fail;
74927c478bd9Sstevel@tonic-gate 					}
74937c478bd9Sstevel@tonic-gate 				}
74947c478bd9Sstevel@tonic-gate 
74957c478bd9Sstevel@tonic-gate 				/*
74967c478bd9Sstevel@tonic-gate 				 * check that if ip_version spec'd it
74977c478bd9Sstevel@tonic-gate 				 * corresponds.
74987c478bd9Sstevel@tonic-gate 				 */
74997c478bd9Sstevel@tonic-gate 				if ((*filter)->ip_versions != 0) {
75007c478bd9Sstevel@tonic-gate 					if (v4 && !VERSION_IS_V4(*filter) ||
75017c478bd9Sstevel@tonic-gate 					    v6 && !VERSION_IS_V6(*filter)) {
75027c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ERROR,
75037c478bd9Sstevel@tonic-gate 						    gettext("Incompatible "
75047c478bd9Sstevel@tonic-gate 						    "address version line %u"
75057c478bd9Sstevel@tonic-gate 						    ".\n"), lineno);
75067c478bd9Sstevel@tonic-gate 						goto fail;
75077c478bd9Sstevel@tonic-gate 					}
75087c478bd9Sstevel@tonic-gate 				}
75097c478bd9Sstevel@tonic-gate 
75107c478bd9Sstevel@tonic-gate 				/* add the address type */
75117c478bd9Sstevel@tonic-gate 
75127c478bd9Sstevel@tonic-gate 				res = nvlist_add_byte(
75137c478bd9Sstevel@tonic-gate 				(*filter)->nvlist, IPGPC_FILTER_TYPE,
75147c478bd9Sstevel@tonic-gate 				    v4 ? IPGPC_V4_FLTR : IPGPC_V6_FLTR);
75157c478bd9Sstevel@tonic-gate 				if (res != 0) {
75167c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
75177c478bd9Sstevel@tonic-gate 					    "nvlist_add_byte");
75187c478bd9Sstevel@tonic-gate 					goto fail;
75197c478bd9Sstevel@tonic-gate 				}
75207c478bd9Sstevel@tonic-gate 
75217c478bd9Sstevel@tonic-gate 				/* add address to list */
75227c478bd9Sstevel@tonic-gate 
75237c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32_array((*filter)->nvlist,
75247c478bd9Sstevel@tonic-gate 				    sa ? IPGPC_SADDR : IPGPC_DADDR,
75257c478bd9Sstevel@tonic-gate 				    (uint32_t *)&v6addr, 4);
75267c478bd9Sstevel@tonic-gate 				if (res != 0) {
75277c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
75287c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32_array");
75297c478bd9Sstevel@tonic-gate 					goto fail;
75307c478bd9Sstevel@tonic-gate 				}
75317c478bd9Sstevel@tonic-gate 
75327c478bd9Sstevel@tonic-gate 
75337c478bd9Sstevel@tonic-gate 				/*
75347c478bd9Sstevel@tonic-gate 				 * add mask entry in list.
75357c478bd9Sstevel@tonic-gate 				 */
75367c478bd9Sstevel@tonic-gate 
75377c478bd9Sstevel@tonic-gate 				if (sl) {	/* have CIDR mask */
75387c478bd9Sstevel@tonic-gate 					char *lo;
75397c478bd9Sstevel@tonic-gate 					res = readuint8(sl, &mlen, &lo);
75407c478bd9Sstevel@tonic-gate 					if (res != IPQOS_CONF_SUCCESS ||
75417c478bd9Sstevel@tonic-gate 					    v4 && mlen > 32 ||
75427c478bd9Sstevel@tonic-gate 					    !v4 && mlen > 128 ||
75437c478bd9Sstevel@tonic-gate 					    mlen == 0) {
75447c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ERROR,
75457c478bd9Sstevel@tonic-gate 						    gettext("Invalid CIDR "
75467c478bd9Sstevel@tonic-gate 						    "mask line %u.\n"), lineno);
75477c478bd9Sstevel@tonic-gate 						goto fail;
75487c478bd9Sstevel@tonic-gate 					}
75497c478bd9Sstevel@tonic-gate 					setmask(mlen, &mask,
75507c478bd9Sstevel@tonic-gate 					    v4 ? AF_INET : AF_INET6);
75517c478bd9Sstevel@tonic-gate 					free(sl);
75527c478bd9Sstevel@tonic-gate 				} else {
75537c478bd9Sstevel@tonic-gate 					/* no CIDR mask spec'd - use all 1s */
75547c478bd9Sstevel@tonic-gate 
75557c478bd9Sstevel@tonic-gate 					(void) memset(&mask, ~0,
75567c478bd9Sstevel@tonic-gate 					    sizeof (in6_addr_t));
75577c478bd9Sstevel@tonic-gate 				}
75587c478bd9Sstevel@tonic-gate 				res = nvlist_add_uint32_array((*filter)->nvlist,
75597c478bd9Sstevel@tonic-gate 				    sa ? IPGPC_SADDR_MASK : IPGPC_DADDR_MASK,
75607c478bd9Sstevel@tonic-gate 				    (uint32_t *)&mask, 4);
75617c478bd9Sstevel@tonic-gate 				if (res != 0) {
75627c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
75637c478bd9Sstevel@tonic-gate 					    "nvlist_add_uint32_arr");
75647c478bd9Sstevel@tonic-gate 					goto fail;
75657c478bd9Sstevel@tonic-gate 				}
75667c478bd9Sstevel@tonic-gate 
75677c478bd9Sstevel@tonic-gate 			/* inet_pton returns fail - we assume a node name */
75687c478bd9Sstevel@tonic-gate 
75697c478bd9Sstevel@tonic-gate 			} else {
75707c478bd9Sstevel@tonic-gate 				/*
75717c478bd9Sstevel@tonic-gate 				 * doesn't make sense to have a mask
75727c478bd9Sstevel@tonic-gate 				 * with a node name.
75737c478bd9Sstevel@tonic-gate 				 */
75747c478bd9Sstevel@tonic-gate 				if (sl) {
75757c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
75767c478bd9Sstevel@tonic-gate 					    gettext("Address masks aren't "
75777c478bd9Sstevel@tonic-gate 					    "allowed for host names line "
75787c478bd9Sstevel@tonic-gate 					    "%u.\n"), lineno);
75797c478bd9Sstevel@tonic-gate 					goto fail;
75807c478bd9Sstevel@tonic-gate 				}
75817c478bd9Sstevel@tonic-gate 
75827c478bd9Sstevel@tonic-gate 				/*
75837c478bd9Sstevel@tonic-gate 				 * store node name in filter struct for
75847c478bd9Sstevel@tonic-gate 				 * later resolution.
75857c478bd9Sstevel@tonic-gate 				 */
75867c478bd9Sstevel@tonic-gate 				if (sa) {
75877c478bd9Sstevel@tonic-gate 					(*filter)->src_nd_name =
75887c478bd9Sstevel@tonic-gate 					    malloc(strlen(addr_str) + 1);
75897c478bd9Sstevel@tonic-gate 					(void) strcpy((*filter)->src_nd_name,
75907c478bd9Sstevel@tonic-gate 					    addr_str);
75917c478bd9Sstevel@tonic-gate 				} else {
75927c478bd9Sstevel@tonic-gate 					(*filter)->dst_nd_name =
75937c478bd9Sstevel@tonic-gate 					    malloc(strlen(addr_str) + 1);
75947c478bd9Sstevel@tonic-gate 					(void) strcpy((*filter)->dst_nd_name,
75957c478bd9Sstevel@tonic-gate 					    addr_str);
75967c478bd9Sstevel@tonic-gate 				}
75977c478bd9Sstevel@tonic-gate 			}
75987c478bd9Sstevel@tonic-gate 
75997c478bd9Sstevel@tonic-gate 		/* ip_version enumeration */
76007c478bd9Sstevel@tonic-gate 
76017c478bd9Sstevel@tonic-gate 		} else if (strcmp(nvpair_name(nvp), IPQOS_CONF_IP_VERSION) ==
76027c478bd9Sstevel@tonic-gate 		    0) {
76037c478bd9Sstevel@tonic-gate 			/* check we haven't read ip_version before */
76047c478bd9Sstevel@tonic-gate 			if (ipv) {
76057c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
76067c478bd9Sstevel@tonic-gate 				    gettext("Duplicate parameter line %u.\n"),
76077c478bd9Sstevel@tonic-gate 				    lineno);
76087c478bd9Sstevel@tonic-gate 				goto fail;
76097c478bd9Sstevel@tonic-gate 			}
76107c478bd9Sstevel@tonic-gate 			ipv++;
76117c478bd9Sstevel@tonic-gate 
76127c478bd9Sstevel@tonic-gate 			/* get bitmask value */
76137c478bd9Sstevel@tonic-gate 
76147c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp,
76157c478bd9Sstevel@tonic-gate 			    &(*filter)->ip_versions);
76167c478bd9Sstevel@tonic-gate 
76177c478bd9Sstevel@tonic-gate 			/*
76187c478bd9Sstevel@tonic-gate 			 * check that if either ip address is spec'd it
76197c478bd9Sstevel@tonic-gate 			 * corresponds.
76207c478bd9Sstevel@tonic-gate 			 */
76217c478bd9Sstevel@tonic-gate 			if (v4 && !VERSION_IS_V4(*filter) ||
76227c478bd9Sstevel@tonic-gate 			    v6 && !VERSION_IS_V6(*filter)) {
76237c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR, gettext("Incompatible "
76247c478bd9Sstevel@tonic-gate 				    "address version line %u.\n"), lineno);
76257c478bd9Sstevel@tonic-gate 				goto fail;
76267c478bd9Sstevel@tonic-gate 			}
76277c478bd9Sstevel@tonic-gate 
76287c478bd9Sstevel@tonic-gate 			/* remove ip_version from nvlist */
76297c478bd9Sstevel@tonic-gate 
76307c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all((*filter)->nvlist,
76317c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_IP_VERSION);
76327c478bd9Sstevel@tonic-gate 		}
76337c478bd9Sstevel@tonic-gate 	}
76347c478bd9Sstevel@tonic-gate 	if (nm == 0 || cls == 0) {
76357c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Missing filter/class name "
76367c478bd9Sstevel@tonic-gate 		    "before line %u.\n"), lineno);
76377c478bd9Sstevel@tonic-gate 		goto fail;
76387c478bd9Sstevel@tonic-gate 	}
76397c478bd9Sstevel@tonic-gate 
76407c478bd9Sstevel@tonic-gate 	if (in_string_table(perm_filters, num_perm_filters, (*filter)->name)) {
76417c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(L0, "Setting filter %s as permanent.\n",
76427c478bd9Sstevel@tonic-gate 		    (*filter)->name);
76437c478bd9Sstevel@tonic-gate 
76447c478bd9Sstevel@tonic-gate 		(*filter)->originator = IPP_CONFIG_PERMANENT;
76457c478bd9Sstevel@tonic-gate 	}
76467c478bd9Sstevel@tonic-gate 
76477c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
76487c478bd9Sstevel@tonic-gate fail:
76497c478bd9Sstevel@tonic-gate 	if (*filter)
76507c478bd9Sstevel@tonic-gate 		free_filter(*filter);
76517c478bd9Sstevel@tonic-gate 	if (hp)
76527c478bd9Sstevel@tonic-gate 		freehostent(hp);
76537c478bd9Sstevel@tonic-gate 	if (sl)
76547c478bd9Sstevel@tonic-gate 		free(sl);
76557c478bd9Sstevel@tonic-gate 
76567c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
76577c478bd9Sstevel@tonic-gate }
76587c478bd9Sstevel@tonic-gate 
76597c478bd9Sstevel@tonic-gate /*
76607c478bd9Sstevel@tonic-gate  * reads the curl begin token from cfp stream.
76617c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if not read successfully, else IPQOS_CONF_SUCCES.
76627c478bd9Sstevel@tonic-gate  */
76637c478bd9Sstevel@tonic-gate static int
76647c478bd9Sstevel@tonic-gate read_curl_begin(FILE *cfp)
76657c478bd9Sstevel@tonic-gate {
76667c478bd9Sstevel@tonic-gate 
76677c478bd9Sstevel@tonic-gate 	int res;
76687c478bd9Sstevel@tonic-gate 	char *st;
76697c478bd9Sstevel@tonic-gate 
76707c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &st);
76717c478bd9Sstevel@tonic-gate 
76727c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_CURL_BEGIN) {
76737c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_EOF) {
76747c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n"));
76757c478bd9Sstevel@tonic-gate 
76767c478bd9Sstevel@tonic-gate 		/* if CURL_END or something else */
76777c478bd9Sstevel@tonic-gate 		} else if (res != IPQOS_CONF_ERR) {
76787c478bd9Sstevel@tonic-gate 			free(st);
76797c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("\'{\' missing at line "
76807c478bd9Sstevel@tonic-gate 			    "%u.\n"), lineno);
76817c478bd9Sstevel@tonic-gate 		}
76827c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
76837c478bd9Sstevel@tonic-gate 	}
76847c478bd9Sstevel@tonic-gate 
76857c478bd9Sstevel@tonic-gate 	free(st);
76867c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
76877c478bd9Sstevel@tonic-gate }
76887c478bd9Sstevel@tonic-gate 
76897c478bd9Sstevel@tonic-gate /*
76907c478bd9Sstevel@tonic-gate  * This function parses the parameter string version into a version of the
76917c478bd9Sstevel@tonic-gate  * form "%u.%u" (as a sscanf format string). It then encodes this into an
76927c478bd9Sstevel@tonic-gate  * int and returns this encoding.
76937c478bd9Sstevel@tonic-gate  * RETURNS: -1 if an invalid string, else the integer encoding.
76947c478bd9Sstevel@tonic-gate  */
76957c478bd9Sstevel@tonic-gate static int
76967c478bd9Sstevel@tonic-gate ver_str_to_int(
76977c478bd9Sstevel@tonic-gate char *version)
76987c478bd9Sstevel@tonic-gate {
76997c478bd9Sstevel@tonic-gate 	uint32_t major, minor;
77007c478bd9Sstevel@tonic-gate 	int ver;
77017c478bd9Sstevel@tonic-gate 
77027c478bd9Sstevel@tonic-gate 	if (sscanf(version, "%u.%u", &major, &minor) != 2) {
77037c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L0, "Failed to process version number string\n");
77047c478bd9Sstevel@tonic-gate 		return (-1);
77057c478bd9Sstevel@tonic-gate 	}
77067c478bd9Sstevel@tonic-gate 
77077c478bd9Sstevel@tonic-gate 	ver = (int)((major * 10000) + minor);
77087c478bd9Sstevel@tonic-gate 	return (ver);
77097c478bd9Sstevel@tonic-gate }
77107c478bd9Sstevel@tonic-gate 
77117c478bd9Sstevel@tonic-gate /*
77127c478bd9Sstevel@tonic-gate  * This function scans through the stream fp line by line looking for
77137c478bd9Sstevel@tonic-gate  * a line beginning with version_tag and returns a integer encoding of
77147c478bd9Sstevel@tonic-gate  * the version following it.
77157c478bd9Sstevel@tonic-gate  *
77167c478bd9Sstevel@tonic-gate  * RETURNS: If the version definition isn't found or the version is not
77177c478bd9Sstevel@tonic-gate  * a valid version (%u.%u) then -1 is returned, else an integer encoding
77187c478bd9Sstevel@tonic-gate  * of the read version.
77197c478bd9Sstevel@tonic-gate  */
77207c478bd9Sstevel@tonic-gate static int
77217c478bd9Sstevel@tonic-gate read_tfile_ver(
77227c478bd9Sstevel@tonic-gate FILE *fp,
77237c478bd9Sstevel@tonic-gate char *version_tag,
77247c478bd9Sstevel@tonic-gate char *module_name)
77257c478bd9Sstevel@tonic-gate {
77267c478bd9Sstevel@tonic-gate 	char lbuf[IPQOS_CONF_LINEBUF_SZ];
77277c478bd9Sstevel@tonic-gate 	char buf[IPQOS_CONF_LINEBUF_SZ+1];
77287c478bd9Sstevel@tonic-gate 	char buf2[IPQOS_CONF_LINEBUF_SZ+1];
77297c478bd9Sstevel@tonic-gate 	int found = 0;
77307c478bd9Sstevel@tonic-gate 	int version;
77317c478bd9Sstevel@tonic-gate 
77327c478bd9Sstevel@tonic-gate 	/*
77337c478bd9Sstevel@tonic-gate 	 * reset to file start
77347c478bd9Sstevel@tonic-gate 	 */
77357c478bd9Sstevel@tonic-gate 	if (fseek(fp, 0, SEEK_SET) != 0) {
77367c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "fseek");
77377c478bd9Sstevel@tonic-gate 		return (-1);
77387c478bd9Sstevel@tonic-gate 	}
77397c478bd9Sstevel@tonic-gate 
77407c478bd9Sstevel@tonic-gate 	/*
77417c478bd9Sstevel@tonic-gate 	 * loop reading lines till found the one beginning with version_tag.
77427c478bd9Sstevel@tonic-gate 	 */
77437c478bd9Sstevel@tonic-gate 	while (fgets(lbuf, IPQOS_CONF_LINEBUF_SZ, fp) != NULL) {
77447c478bd9Sstevel@tonic-gate 		if ((sscanf(lbuf,
77457c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_CONF_LINEBUF_SZ) "s"
77467c478bd9Sstevel@tonic-gate 		    "%" VAL2STR(IPQOS_CONF_LINEBUF_SZ) "s",
77477c478bd9Sstevel@tonic-gate 		    buf, buf2) == 2) &&
77487c478bd9Sstevel@tonic-gate 		    (strcmp(buf, version_tag) == 0)) {
77497c478bd9Sstevel@tonic-gate 			found++;
77507c478bd9Sstevel@tonic-gate 			break;
77517c478bd9Sstevel@tonic-gate 		}
77527c478bd9Sstevel@tonic-gate 	}
77537c478bd9Sstevel@tonic-gate 	if (found == 0) {
77547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Types file for module %s is "
77557c478bd9Sstevel@tonic-gate 		    "corrupt.\n"), module_name);
77567c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(L1, "Couldn't find %s in types file\n",
77577c478bd9Sstevel@tonic-gate 		    version_tag);
77587c478bd9Sstevel@tonic-gate 		return (-1);
77597c478bd9Sstevel@tonic-gate 	}
77607c478bd9Sstevel@tonic-gate 
77617c478bd9Sstevel@tonic-gate 	/*
77627c478bd9Sstevel@tonic-gate 	 * convert version string into int.
77637c478bd9Sstevel@tonic-gate 	 */
77647c478bd9Sstevel@tonic-gate 	if ((version = ver_str_to_int(buf2)) == -1) {
77657c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Types file for module %s is "
77667c478bd9Sstevel@tonic-gate 		    "corrupt.\n"), module_name);
77677c478bd9Sstevel@tonic-gate 		return (-1);
77687c478bd9Sstevel@tonic-gate 	}
77697c478bd9Sstevel@tonic-gate 
77707c478bd9Sstevel@tonic-gate 	return (version);
77717c478bd9Sstevel@tonic-gate }
77727c478bd9Sstevel@tonic-gate 
77737c478bd9Sstevel@tonic-gate /*
77747c478bd9Sstevel@tonic-gate  * read action clause and params/classes/filters clauses within and
77757c478bd9Sstevel@tonic-gate  * store in and hang off an action structure, and point action at it.
77767c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
77777c478bd9Sstevel@tonic-gate  */
77787c478bd9Sstevel@tonic-gate static int
77797c478bd9Sstevel@tonic-gate readaction(
77807c478bd9Sstevel@tonic-gate FILE *cfp,
77817c478bd9Sstevel@tonic-gate ipqos_conf_action_t **action)
77827c478bd9Sstevel@tonic-gate {
77837c478bd9Sstevel@tonic-gate 
77847c478bd9Sstevel@tonic-gate 	char *st;
77857c478bd9Sstevel@tonic-gate 	FILE *tfp = NULL;
77867c478bd9Sstevel@tonic-gate 	int nm, md;
77877c478bd9Sstevel@tonic-gate 	int readprms = 0;
77887c478bd9Sstevel@tonic-gate 	int res;
77897c478bd9Sstevel@tonic-gate 	char *strval;
77907c478bd9Sstevel@tonic-gate 	char *name;
77917c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
77927c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
77937c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *filter;
77947c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *class;
77957c478bd9Sstevel@tonic-gate 	int oe;
77967c478bd9Sstevel@tonic-gate 	char **perm_filters;
77977c478bd9Sstevel@tonic-gate 	int num_perm_filters;
77987c478bd9Sstevel@tonic-gate 	int tf_fmt_ver;
77997c478bd9Sstevel@tonic-gate 
78007c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in readaction\n");
78017c478bd9Sstevel@tonic-gate 
78027c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &st);
78037c478bd9Sstevel@tonic-gate 	if (res == IPQOS_CONF_ERR || res == IPQOS_CONF_EOF) {
78047c478bd9Sstevel@tonic-gate 		return (res);
78057c478bd9Sstevel@tonic-gate 	} else if (strcmp(st, IPQOS_CONF_ACTION_STR) != 0) {
78067c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Missing %s token line "
78077c478bd9Sstevel@tonic-gate 			    "%u.\n"), IPQOS_CONF_ACTION_STR, lineno);
78087c478bd9Sstevel@tonic-gate 			free(st);
78097c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
78107c478bd9Sstevel@tonic-gate 	}
78117c478bd9Sstevel@tonic-gate 	free(st);
78127c478bd9Sstevel@tonic-gate 
78137c478bd9Sstevel@tonic-gate 	/* create action structure */
78147c478bd9Sstevel@tonic-gate 
78157c478bd9Sstevel@tonic-gate 	*action = alloc_action();
78167c478bd9Sstevel@tonic-gate 	if (*action == NULL) {
78177c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
78187c478bd9Sstevel@tonic-gate 	}
78197c478bd9Sstevel@tonic-gate 	(*action)->params->originator = IPP_CONFIG_IPQOSCONF;
78207c478bd9Sstevel@tonic-gate 
78217c478bd9Sstevel@tonic-gate 
78227c478bd9Sstevel@tonic-gate 	/* get starting line for error reporting */
78237c478bd9Sstevel@tonic-gate 	(*action)->lineno = lineno;
78247c478bd9Sstevel@tonic-gate 
78257c478bd9Sstevel@tonic-gate 	/* read beginning curl */
78267c478bd9Sstevel@tonic-gate 
78277c478bd9Sstevel@tonic-gate 	res = read_curl_begin(cfp);
78287c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
78297c478bd9Sstevel@tonic-gate 		goto fail;
78307c478bd9Sstevel@tonic-gate 	}
78317c478bd9Sstevel@tonic-gate 
78327c478bd9Sstevel@tonic-gate 	/* loop till read both action name and module */
78337c478bd9Sstevel@tonic-gate 
78347c478bd9Sstevel@tonic-gate 	nm = md = 0;
78357c478bd9Sstevel@tonic-gate 	do {
78367c478bd9Sstevel@tonic-gate 		/* read nvpair */
78377c478bd9Sstevel@tonic-gate 
78387c478bd9Sstevel@tonic-gate 		res = readnvpair(cfp, NULL, &(*action)->nvlist, &nvp, &type,
78397c478bd9Sstevel@tonic-gate 		    PL_ACTION, NULL);
78407c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
78417c478bd9Sstevel@tonic-gate 			goto fail;
78427c478bd9Sstevel@tonic-gate 
78437c478bd9Sstevel@tonic-gate 		/* read curl_end */
78447c478bd9Sstevel@tonic-gate 
78457c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
78467c478bd9Sstevel@tonic-gate 			if (nm == 0 || md == 0) {
78477c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
78487c478bd9Sstevel@tonic-gate 				    gettext("Missing action name/ module "
78497c478bd9Sstevel@tonic-gate 				    "before line %u.\n"), lineno);
78507c478bd9Sstevel@tonic-gate 				goto fail;
78517c478bd9Sstevel@tonic-gate 			}
78527c478bd9Sstevel@tonic-gate 		}
78537c478bd9Sstevel@tonic-gate 
78547c478bd9Sstevel@tonic-gate 
78557c478bd9Sstevel@tonic-gate 		/* store name and module in action structure */
78567c478bd9Sstevel@tonic-gate 
78577c478bd9Sstevel@tonic-gate 		name = nvpair_name(nvp);
78587c478bd9Sstevel@tonic-gate 
78597c478bd9Sstevel@tonic-gate 		/* read action name */
78607c478bd9Sstevel@tonic-gate 
78617c478bd9Sstevel@tonic-gate 		if (nm == 0 && strcmp(name, IPQOS_CONF_NAME_STR) == 0) {
78627c478bd9Sstevel@tonic-gate 
78637c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &strval);
78647c478bd9Sstevel@tonic-gate 
78657c478bd9Sstevel@tonic-gate 			/* check name is valid */
78667c478bd9Sstevel@tonic-gate 
78677c478bd9Sstevel@tonic-gate 			if (valid_name(strval) != IPQOS_CONF_SUCCESS ||
78687c478bd9Sstevel@tonic-gate 			    valid_aname(strval) != IPQOS_CONF_SUCCESS) {
78697c478bd9Sstevel@tonic-gate 				goto fail;
78707c478bd9Sstevel@tonic-gate 			}
78717c478bd9Sstevel@tonic-gate 
78727c478bd9Sstevel@tonic-gate 			/* store and remove from list */
78737c478bd9Sstevel@tonic-gate 
78747c478bd9Sstevel@tonic-gate 			(void) strcpy((*action)->name, strval);
78757c478bd9Sstevel@tonic-gate 			/* remove name from nvlist */
78767c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all((*action)->nvlist,
78777c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NAME_STR);
78787c478bd9Sstevel@tonic-gate 
78797c478bd9Sstevel@tonic-gate 			nm++;
78807c478bd9Sstevel@tonic-gate 
78817c478bd9Sstevel@tonic-gate 		/* read module name */
78827c478bd9Sstevel@tonic-gate 
78837c478bd9Sstevel@tonic-gate 		} else if (md == 0 &&
78847c478bd9Sstevel@tonic-gate 		    strcmp(name, IPQOS_CONF_MODULE_STR) == 0) {
78857c478bd9Sstevel@tonic-gate 			/*
78867c478bd9Sstevel@tonic-gate 			 * check that module has a type file and get
78877c478bd9Sstevel@tonic-gate 			 * open stream to it.
78887c478bd9Sstevel@tonic-gate 			 */
78897c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &strval);
78907c478bd9Sstevel@tonic-gate 			if ((tfp = validmod(strval, &oe)) == NULL) {
78917c478bd9Sstevel@tonic-gate 				if (oe) {
78927c478bd9Sstevel@tonic-gate 					if (errno == ENOENT) {
78937c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ERROR,
78947c478bd9Sstevel@tonic-gate 						    gettext("Invalid "
78957c478bd9Sstevel@tonic-gate 						    "module name line %u.\n"),
78967c478bd9Sstevel@tonic-gate 						    lineno);
78977c478bd9Sstevel@tonic-gate 					} else {
78987c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ENOSTR, "fopen");
78997c478bd9Sstevel@tonic-gate 					}
79007c478bd9Sstevel@tonic-gate 				}
79017c478bd9Sstevel@tonic-gate 				goto fail;
79027c478bd9Sstevel@tonic-gate 			}
79037c478bd9Sstevel@tonic-gate 
79047c478bd9Sstevel@tonic-gate 			/*
79057c478bd9Sstevel@tonic-gate 			 * move module name to action struct
79067c478bd9Sstevel@tonic-gate 			 */
79077c478bd9Sstevel@tonic-gate 			(void) strlcpy((*action)->module, strval,
79087c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NAME_LEN);
79097c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all((*action)->nvlist,
79107c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_MODULE_STR);
79117c478bd9Sstevel@tonic-gate 			md++;
79127c478bd9Sstevel@tonic-gate 
79137c478bd9Sstevel@tonic-gate 		/* duplicate/other parameter */
79147c478bd9Sstevel@tonic-gate 
79157c478bd9Sstevel@tonic-gate 		} else {
79167c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
79177c478bd9Sstevel@tonic-gate 			    gettext("Unexpected parameter line %u.\n"),
79187c478bd9Sstevel@tonic-gate 			    lineno);
79197c478bd9Sstevel@tonic-gate 			goto fail;
79207c478bd9Sstevel@tonic-gate 		}
79217c478bd9Sstevel@tonic-gate 
79227c478bd9Sstevel@tonic-gate 	} while (nm == 0 || md == 0);
79237c478bd9Sstevel@tonic-gate 
79247c478bd9Sstevel@tonic-gate 	/*
79257c478bd9Sstevel@tonic-gate 	 * check that if the ipgpc action it is named correctly
79267c478bd9Sstevel@tonic-gate 	 */
79277c478bd9Sstevel@tonic-gate 	if ((strcmp((*action)->module, IPGPC_NAME) == 0) &&
79287c478bd9Sstevel@tonic-gate 	    (strcmp((*action)->name, IPGPC_CLASSIFY) != 0)) {
79297c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
79307c478bd9Sstevel@tonic-gate 		    gettext("%s action has incorrect name line %u.\n"),
79317c478bd9Sstevel@tonic-gate 		    IPGPC_NAME, (*action)->lineno);
79327c478bd9Sstevel@tonic-gate 		goto fail;
79337c478bd9Sstevel@tonic-gate 	}
79347c478bd9Sstevel@tonic-gate 
79357c478bd9Sstevel@tonic-gate 	/* get list of permanent classes */
79367c478bd9Sstevel@tonic-gate 
79377c478bd9Sstevel@tonic-gate 	res = read_perm_items(0, tfp, (*action)->module,
79387c478bd9Sstevel@tonic-gate 	    &(*action)->perm_classes, &(*action)->num_perm_classes);
79397c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
79407c478bd9Sstevel@tonic-gate 		goto fail;
79417c478bd9Sstevel@tonic-gate 	}
79427c478bd9Sstevel@tonic-gate 
79437c478bd9Sstevel@tonic-gate 	/* get list of permanent filters */
79447c478bd9Sstevel@tonic-gate 
79457c478bd9Sstevel@tonic-gate 	res = read_perm_items(1, tfp, (*action)->module,
79467c478bd9Sstevel@tonic-gate 	    &perm_filters, &num_perm_filters);
79477c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
79487c478bd9Sstevel@tonic-gate 		goto fail;
79497c478bd9Sstevel@tonic-gate 	}
79507c478bd9Sstevel@tonic-gate 
79517c478bd9Sstevel@tonic-gate 	/*
79527c478bd9Sstevel@tonic-gate 	 * get types file format version and check its supported.
79537c478bd9Sstevel@tonic-gate 	 */
79547c478bd9Sstevel@tonic-gate 	if ((tf_fmt_ver = read_tfile_ver(tfp, IPQOS_FMT_STR,
79557c478bd9Sstevel@tonic-gate 	    (*action)->module)) == -1)
79567c478bd9Sstevel@tonic-gate 		goto fail;
79577c478bd9Sstevel@tonic-gate 	if (IPP_MAJOR_MODULE_VER(tf_fmt_ver) > 1 ||
79587c478bd9Sstevel@tonic-gate 	    IPP_MINOR_MODULE_VER(tf_fmt_ver) > 0) {
79597c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Types file for module %s is "
79607c478bd9Sstevel@tonic-gate 		    "incompatible.\n"), (*action)->module);
79617c478bd9Sstevel@tonic-gate 		IPQOSCDBG0(L1, "Unsupported fmt major/minor version\n");
79627c478bd9Sstevel@tonic-gate 		goto fail;
79637c478bd9Sstevel@tonic-gate 	}
79647c478bd9Sstevel@tonic-gate 
79657c478bd9Sstevel@tonic-gate 	/*
79667c478bd9Sstevel@tonic-gate 	 * get module version
79677c478bd9Sstevel@tonic-gate 	 */
79687c478bd9Sstevel@tonic-gate 	if (((*action)->module_version = read_tfile_ver(tfp, IPQOS_MOD_STR,
79697c478bd9Sstevel@tonic-gate 	    (*action)->module)) == -1)
79707c478bd9Sstevel@tonic-gate 		goto fail;
79717c478bd9Sstevel@tonic-gate 
79727c478bd9Sstevel@tonic-gate 	/* read filter/class/params blocks until CURL_END */
79737c478bd9Sstevel@tonic-gate 
79747c478bd9Sstevel@tonic-gate 	for (;;) {
79757c478bd9Sstevel@tonic-gate 		/* read token */
79767c478bd9Sstevel@tonic-gate 		res = readtoken(cfp, &st);
79777c478bd9Sstevel@tonic-gate 
79787c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
79797c478bd9Sstevel@tonic-gate 			goto fail;
79807c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_EOF) {
79817c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n"));
79827c478bd9Sstevel@tonic-gate 			goto fail;
79837c478bd9Sstevel@tonic-gate 
79847c478bd9Sstevel@tonic-gate 		/* read CURL_END - end of action definition */
79857c478bd9Sstevel@tonic-gate 
79867c478bd9Sstevel@tonic-gate 		} else if (res == IPQOS_CONF_CURL_END) {
79877c478bd9Sstevel@tonic-gate 			free(st);
79887c478bd9Sstevel@tonic-gate 			break;
79897c478bd9Sstevel@tonic-gate 		}
79907c478bd9Sstevel@tonic-gate 
79917c478bd9Sstevel@tonic-gate 
79927c478bd9Sstevel@tonic-gate 		/*
79937c478bd9Sstevel@tonic-gate 		 * read in either a filter/class or parameter block.
79947c478bd9Sstevel@tonic-gate 		 */
79957c478bd9Sstevel@tonic-gate 
79967c478bd9Sstevel@tonic-gate 		/* read filter */
79977c478bd9Sstevel@tonic-gate 
79987c478bd9Sstevel@tonic-gate 		if (strcmp(st, IPQOS_CONF_FILTER_STR) == 0) {
79997c478bd9Sstevel@tonic-gate 			free(st);
80007c478bd9Sstevel@tonic-gate 
80017c478bd9Sstevel@tonic-gate 			res = readfilter(cfp, tfp, (*action)->module, &filter,
80027c478bd9Sstevel@tonic-gate 			    perm_filters, num_perm_filters);
80037c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
80047c478bd9Sstevel@tonic-gate 				goto fail;
80057c478bd9Sstevel@tonic-gate 			}
80067c478bd9Sstevel@tonic-gate 
80077c478bd9Sstevel@tonic-gate 			/*
80087c478bd9Sstevel@tonic-gate 			 * if we read a host name for either src or dst addr
80097c478bd9Sstevel@tonic-gate 			 * resolve the hostnames and create the appropriate
80107c478bd9Sstevel@tonic-gate 			 * number of filters.
80117c478bd9Sstevel@tonic-gate 			 */
80127c478bd9Sstevel@tonic-gate 
80137c478bd9Sstevel@tonic-gate 			if (filter->src_nd_name || filter->dst_nd_name) {
80147c478bd9Sstevel@tonic-gate 
80157c478bd9Sstevel@tonic-gate 				res = domultihome(filter, &(*action)->filters,
80167c478bd9Sstevel@tonic-gate 				    B_FALSE);
80177c478bd9Sstevel@tonic-gate 				/*
80187c478bd9Sstevel@tonic-gate 				 * if a lookup fails and the filters
80197c478bd9Sstevel@tonic-gate 				 * marked as retry we add it to a list
80207c478bd9Sstevel@tonic-gate 				 * for another attempt later, otherwise
80217c478bd9Sstevel@tonic-gate 				 * it is thrown away.
80227c478bd9Sstevel@tonic-gate 				 */
80237c478bd9Sstevel@tonic-gate 				if (res != IPQOS_CONF_SUCCESS) {
80247c478bd9Sstevel@tonic-gate 
80257c478bd9Sstevel@tonic-gate 					/* if not name lookup problem */
80267c478bd9Sstevel@tonic-gate 
80277c478bd9Sstevel@tonic-gate 					if (filter->nlerr == 0) {
80287c478bd9Sstevel@tonic-gate 						free_filter(filter);
80297c478bd9Sstevel@tonic-gate 						goto fail;
80307c478bd9Sstevel@tonic-gate 
80317c478bd9Sstevel@tonic-gate 					/* name lookup problem */
80327c478bd9Sstevel@tonic-gate 
80337c478bd9Sstevel@tonic-gate 					/*
80347c478bd9Sstevel@tonic-gate 					 * if intermitent lookup failure
80357c478bd9Sstevel@tonic-gate 					 * add to list of filters to
80367c478bd9Sstevel@tonic-gate 					 * retry later.
80377c478bd9Sstevel@tonic-gate 					 */
80387c478bd9Sstevel@tonic-gate 					} else if (filter->nlerr ==
80397c478bd9Sstevel@tonic-gate 					    IPQOS_LOOKUP_RETRY) {
80407c478bd9Sstevel@tonic-gate 						filter->nlerr = 0;
80417c478bd9Sstevel@tonic-gate 						ADD_TO_LIST(
80427c478bd9Sstevel@tonic-gate 						    &(*action)->retry_filters,
80437c478bd9Sstevel@tonic-gate 						    filter);
80447c478bd9Sstevel@tonic-gate 					/*
80457c478bd9Sstevel@tonic-gate 					 * for non-existing names
80467c478bd9Sstevel@tonic-gate 					 * ignore the filter.
80477c478bd9Sstevel@tonic-gate 					 */
80487c478bd9Sstevel@tonic-gate 					} else {
80497c478bd9Sstevel@tonic-gate 						free_filter(filter);
80507c478bd9Sstevel@tonic-gate 					}
80517c478bd9Sstevel@tonic-gate 
80527c478bd9Sstevel@tonic-gate 				/* creation of new filters successful */
80537c478bd9Sstevel@tonic-gate 
80547c478bd9Sstevel@tonic-gate 				} else {
80557c478bd9Sstevel@tonic-gate 					free_filter(filter);
80567c478bd9Sstevel@tonic-gate 				}
80577c478bd9Sstevel@tonic-gate 
80587c478bd9Sstevel@tonic-gate 			/* non-node name filter */
80597c478bd9Sstevel@tonic-gate 
80607c478bd9Sstevel@tonic-gate 			} else {
80617c478bd9Sstevel@tonic-gate 				ADD_TO_LIST(&(*action)->filters, filter);
80627c478bd9Sstevel@tonic-gate 			}
80637c478bd9Sstevel@tonic-gate 
80647c478bd9Sstevel@tonic-gate 		/* read class */
80657c478bd9Sstevel@tonic-gate 
80667c478bd9Sstevel@tonic-gate 		} else if (strcmp(st, IPQOS_CONF_CLASS_STR) == 0) {
80677c478bd9Sstevel@tonic-gate 			free(st);
80687c478bd9Sstevel@tonic-gate 			res = readclass(cfp, (*action)->module, &class,
80697c478bd9Sstevel@tonic-gate 			    (*action)->perm_classes,
80707c478bd9Sstevel@tonic-gate 			    (*action)->num_perm_classes);
80717c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
80727c478bd9Sstevel@tonic-gate 				goto fail;
80737c478bd9Sstevel@tonic-gate 			}
80747c478bd9Sstevel@tonic-gate 
80757c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(&(*action)->classes, class);
80767c478bd9Sstevel@tonic-gate 
80777c478bd9Sstevel@tonic-gate 		/* read params */
80787c478bd9Sstevel@tonic-gate 
80797c478bd9Sstevel@tonic-gate 		} else if (strcmp(st, IPQOS_CONF_PARAMS_STR) == 0) {
80807c478bd9Sstevel@tonic-gate 			free(st);
80817c478bd9Sstevel@tonic-gate 			if (readprms) {
80827c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
80837c478bd9Sstevel@tonic-gate 				    gettext("Second parameter clause not "
80847c478bd9Sstevel@tonic-gate 				    "supported line %u.\n"), lineno);
80857c478bd9Sstevel@tonic-gate 				goto fail;
80867c478bd9Sstevel@tonic-gate 			}
80877c478bd9Sstevel@tonic-gate 			res = readparams(cfp, tfp, (*action)->module,
80887c478bd9Sstevel@tonic-gate 			    (*action)->params);
80897c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
80907c478bd9Sstevel@tonic-gate 				goto fail;
80917c478bd9Sstevel@tonic-gate 			}
80927c478bd9Sstevel@tonic-gate 			readprms++;
80937c478bd9Sstevel@tonic-gate 
80947c478bd9Sstevel@tonic-gate 		/* something unexpected */
80957c478bd9Sstevel@tonic-gate 		} else {
80967c478bd9Sstevel@tonic-gate 			free(st);
80977c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
80987c478bd9Sstevel@tonic-gate 			    gettext("Params/filter/class clause expected "
80997c478bd9Sstevel@tonic-gate 			    "line %u.\n"), lineno);
81007c478bd9Sstevel@tonic-gate 			goto fail;
81017c478bd9Sstevel@tonic-gate 		}
81027c478bd9Sstevel@tonic-gate 	}
81037c478bd9Sstevel@tonic-gate 
81047c478bd9Sstevel@tonic-gate 	(void) fclose(tfp);
81057c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
81067c478bd9Sstevel@tonic-gate 
81077c478bd9Sstevel@tonic-gate fail:
81087c478bd9Sstevel@tonic-gate 	if (tfp)
81097c478bd9Sstevel@tonic-gate 		(void) fclose(tfp);
81107c478bd9Sstevel@tonic-gate 	if (*action) {
81117c478bd9Sstevel@tonic-gate 		free_actions(*action);
81127c478bd9Sstevel@tonic-gate 		*action = NULL;
81137c478bd9Sstevel@tonic-gate 	}
81147c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
81157c478bd9Sstevel@tonic-gate }
81167c478bd9Sstevel@tonic-gate 
81177c478bd9Sstevel@tonic-gate /*
81187c478bd9Sstevel@tonic-gate  * check that each of the actions in actions is uniquely named. If one isn't
81197c478bd9Sstevel@tonic-gate  * set *name to point at the name of the duplicate action.
81207c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if a non-unique action, else IPQOS_CONF_SUCCESS.
81217c478bd9Sstevel@tonic-gate  */
81227c478bd9Sstevel@tonic-gate static int
81237c478bd9Sstevel@tonic-gate actions_unique(ipqos_conf_action_t *actions, char **name)
81247c478bd9Sstevel@tonic-gate {
81257c478bd9Sstevel@tonic-gate 
81267c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In actions_unique.\n");
81277c478bd9Sstevel@tonic-gate 
81287c478bd9Sstevel@tonic-gate 	while (actions) {
81297c478bd9Sstevel@tonic-gate 		if (actionexist(actions->name, actions->next)) {
81307c478bd9Sstevel@tonic-gate 			*name = actions->name;
81317c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
81327c478bd9Sstevel@tonic-gate 		}
81337c478bd9Sstevel@tonic-gate 		actions = actions->next;
81347c478bd9Sstevel@tonic-gate 	}
81357c478bd9Sstevel@tonic-gate 
81367c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
81377c478bd9Sstevel@tonic-gate }
81387c478bd9Sstevel@tonic-gate 
81397c478bd9Sstevel@tonic-gate /*
81407c478bd9Sstevel@tonic-gate  * checks whether the action parameter is involved in an action cycle.
81417c478bd9Sstevel@tonic-gate  * RETURNS: 1 if involved in a cycle, 0 otherwise.
81427c478bd9Sstevel@tonic-gate  */
81437c478bd9Sstevel@tonic-gate static int
81447c478bd9Sstevel@tonic-gate in_cycle(
81457c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action)
81467c478bd9Sstevel@tonic-gate {
81477c478bd9Sstevel@tonic-gate 
81487c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *aref;
81497c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *c;
81507c478bd9Sstevel@tonic-gate 
81517c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L0, "in_cycle: visiting action %s\n", action->name);
81527c478bd9Sstevel@tonic-gate 
81537c478bd9Sstevel@tonic-gate 
81547c478bd9Sstevel@tonic-gate 	/* have we visited this action before? */
81557c478bd9Sstevel@tonic-gate 
81567c478bd9Sstevel@tonic-gate 	if (action->visited == INCYCLE_VISITED) {
81577c478bd9Sstevel@tonic-gate 		action->visited = 0;
81587c478bd9Sstevel@tonic-gate 		return (1);
81597c478bd9Sstevel@tonic-gate 	}
81607c478bd9Sstevel@tonic-gate 	action->visited = INCYCLE_VISITED;
81617c478bd9Sstevel@tonic-gate 
81627c478bd9Sstevel@tonic-gate 	/*
81637c478bd9Sstevel@tonic-gate 	 * recurse down the child actions of this action through the
81647c478bd9Sstevel@tonic-gate 	 * classes next action and parameter actions.
81657c478bd9Sstevel@tonic-gate 	 */
81667c478bd9Sstevel@tonic-gate 
81677c478bd9Sstevel@tonic-gate 	for (aref = action->params->actions; aref != NULL; aref = aref->next) {
81687c478bd9Sstevel@tonic-gate 
81697c478bd9Sstevel@tonic-gate 		/* skip virtual actions - they can't be in a cycle */
81707c478bd9Sstevel@tonic-gate 
81717c478bd9Sstevel@tonic-gate 		if (virtual_action(aref->name)) {
81727c478bd9Sstevel@tonic-gate 			continue;
81737c478bd9Sstevel@tonic-gate 		}
81747c478bd9Sstevel@tonic-gate 
81757c478bd9Sstevel@tonic-gate 		if (in_cycle(aref->action)) {
81767c478bd9Sstevel@tonic-gate 			action->visited = 0;
81777c478bd9Sstevel@tonic-gate 			return (1);
81787c478bd9Sstevel@tonic-gate 		}
81797c478bd9Sstevel@tonic-gate 	}
81807c478bd9Sstevel@tonic-gate 
81817c478bd9Sstevel@tonic-gate 	for (c = action->classes; c != NULL; c = c->next) {
81827c478bd9Sstevel@tonic-gate 		aref = c->alist;
81837c478bd9Sstevel@tonic-gate 
81847c478bd9Sstevel@tonic-gate 		if (virtual_action(aref->name)) {
81857c478bd9Sstevel@tonic-gate 			continue;
81867c478bd9Sstevel@tonic-gate 		}
81877c478bd9Sstevel@tonic-gate 
81887c478bd9Sstevel@tonic-gate 		if (in_cycle(aref->action)) {
81897c478bd9Sstevel@tonic-gate 			action->visited = 0;
81907c478bd9Sstevel@tonic-gate 			return (1);
81917c478bd9Sstevel@tonic-gate 		}
81927c478bd9Sstevel@tonic-gate 	}
81937c478bd9Sstevel@tonic-gate 
81947c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in_cycle: return\n");
81957c478bd9Sstevel@tonic-gate 	action->visited = 0;
81967c478bd9Sstevel@tonic-gate 	return (0);
81977c478bd9Sstevel@tonic-gate }
81987c478bd9Sstevel@tonic-gate 
81997c478bd9Sstevel@tonic-gate /*
82007c478bd9Sstevel@tonic-gate  * checks that the configuration in actions is a valid whole, that
82017c478bd9Sstevel@tonic-gate  * all actions are unique, all filters and classes are unique within
82027c478bd9Sstevel@tonic-gate  * their action, that classes referenced by filters exist and actions
82037c478bd9Sstevel@tonic-gate  * referenced by classes and params exist. Also checks that there are no root
82047c478bd9Sstevel@tonic-gate  * actions but ipgpc and that no actions are involved in cycles. As
82057c478bd9Sstevel@tonic-gate  * a consequence of checking that the actions exist two way pointers
82067c478bd9Sstevel@tonic-gate  * are created between the dependee and dependant actions.
82077c478bd9Sstevel@tonic-gate  *
82087c478bd9Sstevel@tonic-gate  * In the case the the userconf flag is zero only this link creation is
82097c478bd9Sstevel@tonic-gate  * set as we trust the kernel to return a valid configuration.
82107c478bd9Sstevel@tonic-gate  *
82117c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if config isn't valid, else IPQOS_CONF_SUCCESS.
82127c478bd9Sstevel@tonic-gate  *
82137c478bd9Sstevel@tonic-gate  */
82147c478bd9Sstevel@tonic-gate 
82157c478bd9Sstevel@tonic-gate static int
82167c478bd9Sstevel@tonic-gate validconf(
82177c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions,
82187c478bd9Sstevel@tonic-gate int userconf)			/* are we checking a conf file ? */
82197c478bd9Sstevel@tonic-gate {
82207c478bd9Sstevel@tonic-gate 	char *name;
82217c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
82227c478bd9Sstevel@tonic-gate 	int res;
82237c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *dact;
82247c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
82257c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *cls;
82267c478bd9Sstevel@tonic-gate 	ipqos_conf_params_t *params;
82277c478bd9Sstevel@tonic-gate 	ipqos_conf_act_ref_t *aref;
82287c478bd9Sstevel@tonic-gate 
82297c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In validconf\n");
82307c478bd9Sstevel@tonic-gate 
82317c478bd9Sstevel@tonic-gate 	/* check actions are unique */
82327c478bd9Sstevel@tonic-gate 
82337c478bd9Sstevel@tonic-gate 	if (userconf && actions_unique(actions, &name) != IPQOS_CONF_SUCCESS) {
82347c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Duplicate named action %s.\n"),
82357c478bd9Sstevel@tonic-gate 		    name);
82367c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
82377c478bd9Sstevel@tonic-gate 	}
82387c478bd9Sstevel@tonic-gate 
82397c478bd9Sstevel@tonic-gate 	for (act = actions; act; act = act->next) {
82407c478bd9Sstevel@tonic-gate 
82417c478bd9Sstevel@tonic-gate 		/*
82427c478bd9Sstevel@tonic-gate 		 * check filters (for user land configs only).
82437c478bd9Sstevel@tonic-gate 		 * check they are unique in this action and their class exists.
82447c478bd9Sstevel@tonic-gate 		 */
82457c478bd9Sstevel@tonic-gate 		if (userconf) {
82467c478bd9Sstevel@tonic-gate 			for (flt = act->filters; flt; flt = flt->next) {
82477c478bd9Sstevel@tonic-gate 
82487c478bd9Sstevel@tonic-gate 				/* check unique name */
82497c478bd9Sstevel@tonic-gate 
82507c478bd9Sstevel@tonic-gate 				if (filterexist(flt->name, flt->instance,
82517c478bd9Sstevel@tonic-gate 				    flt->next)) {
82527c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
82537c478bd9Sstevel@tonic-gate 					    gettext("Duplicate named filter "
82547c478bd9Sstevel@tonic-gate 					    "%s in action %s.\n"), flt->name,
82557c478bd9Sstevel@tonic-gate 					    act->name);
82567c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
82577c478bd9Sstevel@tonic-gate 				}
82587c478bd9Sstevel@tonic-gate 
82597c478bd9Sstevel@tonic-gate 				/*
82607c478bd9Sstevel@tonic-gate 				 * check existence of class and error if
82617c478bd9Sstevel@tonic-gate 				 * class doesn't exist and not a perm class
82627c478bd9Sstevel@tonic-gate 				 */
82637c478bd9Sstevel@tonic-gate 
82647c478bd9Sstevel@tonic-gate 				if (!classexist(flt->class_name,
82657c478bd9Sstevel@tonic-gate 				    act->classes)) {
82667c478bd9Sstevel@tonic-gate 					if (!in_string_table(act->perm_classes,
82677c478bd9Sstevel@tonic-gate 					    act->num_perm_classes,
82687c478bd9Sstevel@tonic-gate 					    flt->class_name)) {
82697c478bd9Sstevel@tonic-gate 						ipqos_msg(MT_ERROR,
82707c478bd9Sstevel@tonic-gate 						    gettext("Undefined "
82717c478bd9Sstevel@tonic-gate 						    "class in filter %s, "
82727c478bd9Sstevel@tonic-gate 						    "action %s.\n"), flt->name,
82737c478bd9Sstevel@tonic-gate 						    act->name);
82747c478bd9Sstevel@tonic-gate 						return (IPQOS_CONF_ERR);
82757c478bd9Sstevel@tonic-gate 					}
82767c478bd9Sstevel@tonic-gate 				}
82777c478bd9Sstevel@tonic-gate 			}
82787c478bd9Sstevel@tonic-gate 		}
82797c478bd9Sstevel@tonic-gate 
82807c478bd9Sstevel@tonic-gate 		/* check classes */
82817c478bd9Sstevel@tonic-gate 
82827c478bd9Sstevel@tonic-gate 		for (cls = act->classes; cls; cls = cls->next) {
82837c478bd9Sstevel@tonic-gate 
82847c478bd9Sstevel@tonic-gate 			/* check if class name unique (userland only) */
82857c478bd9Sstevel@tonic-gate 
82867c478bd9Sstevel@tonic-gate 			if (userconf && classexist(cls->name, cls->next)) {
82877c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
82887c478bd9Sstevel@tonic-gate 				    gettext("Duplicate named class %s in "
82897c478bd9Sstevel@tonic-gate 				    "action %s.\n"), cls->name, act->name);
82907c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
82917c478bd9Sstevel@tonic-gate 			}
82927c478bd9Sstevel@tonic-gate 
82937c478bd9Sstevel@tonic-gate 			/*
82947c478bd9Sstevel@tonic-gate 			 * virtual actions always exist so don't check for next
82957c478bd9Sstevel@tonic-gate 			 * action.
82967c478bd9Sstevel@tonic-gate 			 */
82977c478bd9Sstevel@tonic-gate 			if (virtual_action(cls->alist->name)) {
82987c478bd9Sstevel@tonic-gate 				continue;
82997c478bd9Sstevel@tonic-gate 			}
83007c478bd9Sstevel@tonic-gate 
83017c478bd9Sstevel@tonic-gate 			/*
83027c478bd9Sstevel@tonic-gate 			 * check existance of next action and create link to
83037c478bd9Sstevel@tonic-gate 			 * it.
83047c478bd9Sstevel@tonic-gate 			 */
83057c478bd9Sstevel@tonic-gate 			if ((cls->alist->action =
83067c478bd9Sstevel@tonic-gate 			    actionexist(cls->alist->name, actions)) == NULL) {
83077c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
83087c478bd9Sstevel@tonic-gate 				    gettext("Undefined action in class %s, "
83097c478bd9Sstevel@tonic-gate 				    "action %s.\n"), cls->name, act->name);
83107c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
83117c478bd9Sstevel@tonic-gate 			}
83127c478bd9Sstevel@tonic-gate 
83137c478bd9Sstevel@tonic-gate 			/* create backwards link - used for deletions */
83147c478bd9Sstevel@tonic-gate 
83157c478bd9Sstevel@tonic-gate 			dact = cls->alist->action;
83167c478bd9Sstevel@tonic-gate 			res = add_aref(&dact->dependencies, NULL, act->name);
83177c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
83187c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
83197c478bd9Sstevel@tonic-gate 			}
83207c478bd9Sstevel@tonic-gate 			dact->dependencies->action = act;
83217c478bd9Sstevel@tonic-gate 		}
83227c478bd9Sstevel@tonic-gate 
83237c478bd9Sstevel@tonic-gate 
83247c478bd9Sstevel@tonic-gate 		/* check actions exist for action type parameters */
83257c478bd9Sstevel@tonic-gate 
83267c478bd9Sstevel@tonic-gate 		params = act->params;
83277c478bd9Sstevel@tonic-gate 		for (aref = params->actions; aref; aref = aref->next) {
83287c478bd9Sstevel@tonic-gate 
83297c478bd9Sstevel@tonic-gate 			/* skip virtuals */
83307c478bd9Sstevel@tonic-gate 
83317c478bd9Sstevel@tonic-gate 			if (virtual_action(aref->name)) {
83327c478bd9Sstevel@tonic-gate 				continue;
83337c478bd9Sstevel@tonic-gate 			}
83347c478bd9Sstevel@tonic-gate 
83357c478bd9Sstevel@tonic-gate 			/*
83367c478bd9Sstevel@tonic-gate 			 * check existance of action in this ref
83377c478bd9Sstevel@tonic-gate 			 * and if present create a ptr to it.
83387c478bd9Sstevel@tonic-gate 			 */
83397c478bd9Sstevel@tonic-gate 			aref->action = actionexist(aref->name, actions);
83407c478bd9Sstevel@tonic-gate 			if (aref->action == NULL) {
83417c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
83427c478bd9Sstevel@tonic-gate 				    gettext("Undefined action in parameter "
83437c478bd9Sstevel@tonic-gate 				    "%s, action %s.\n"),
83447c478bd9Sstevel@tonic-gate 				    SHORT_NAME(aref->field), act->name);
83457c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
83467c478bd9Sstevel@tonic-gate 			}
83477c478bd9Sstevel@tonic-gate 
83487c478bd9Sstevel@tonic-gate 			/* create backwards link */
83497c478bd9Sstevel@tonic-gate 
83507c478bd9Sstevel@tonic-gate 			dact = aref->action;
83517c478bd9Sstevel@tonic-gate 			res = add_aref(&dact->dependencies, NULL,
83527c478bd9Sstevel@tonic-gate 			    act->name);
83537c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
83547c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
83557c478bd9Sstevel@tonic-gate 			}
83567c478bd9Sstevel@tonic-gate 			dact->dependencies->action = act;
83577c478bd9Sstevel@tonic-gate 		}
83587c478bd9Sstevel@tonic-gate 	}
83597c478bd9Sstevel@tonic-gate 
83607c478bd9Sstevel@tonic-gate 	/* for kernel retrieved configs we don't do the following checks. */
83617c478bd9Sstevel@tonic-gate 	if (!userconf) {
83627c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
83637c478bd9Sstevel@tonic-gate 	}
83647c478bd9Sstevel@tonic-gate 
83657c478bd9Sstevel@tonic-gate 	/* check for cycles in config and orphaned actions other than ipgpc */
83667c478bd9Sstevel@tonic-gate 
83677c478bd9Sstevel@tonic-gate 	for (act = actions; act; act = act->next) {
83687c478bd9Sstevel@tonic-gate 
83697c478bd9Sstevel@tonic-gate 		/* check if involved in cycle */
83707c478bd9Sstevel@tonic-gate 
83717c478bd9Sstevel@tonic-gate 		if (in_cycle(act)) {
83727c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
83737c478bd9Sstevel@tonic-gate 			    gettext("Action %s involved in cycle.\n"),
83747c478bd9Sstevel@tonic-gate 			    act->name);
83757c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
83767c478bd9Sstevel@tonic-gate 		}
83777c478bd9Sstevel@tonic-gate 
83787c478bd9Sstevel@tonic-gate 		/* check that this action has a parent (except ipgpc) */
83797c478bd9Sstevel@tonic-gate 
83807c478bd9Sstevel@tonic-gate 		if (act->dependencies == NULL &&
83817c478bd9Sstevel@tonic-gate 		    strcmp(act->name, IPGPC_CLASSIFY) != 0) {
83827c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Action %s isn't "
83837c478bd9Sstevel@tonic-gate 			    "referenced by any other actions.\n"), act->name);
83847c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
83857c478bd9Sstevel@tonic-gate 		}
83867c478bd9Sstevel@tonic-gate 	}
83877c478bd9Sstevel@tonic-gate 
83887c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
83897c478bd9Sstevel@tonic-gate }
83907c478bd9Sstevel@tonic-gate 
83917c478bd9Sstevel@tonic-gate /*
83927c478bd9Sstevel@tonic-gate  * Read the version from the config file with stream cfp with
83937c478bd9Sstevel@tonic-gate  * the tag version_tag. The tag-value pair should be the first tokens
83947c478bd9Sstevel@tonic-gate  * encountered.
83957c478bd9Sstevel@tonic-gate  *
83967c478bd9Sstevel@tonic-gate  * RETURNS: -1 if a missing or invalid version or a read error,
83977c478bd9Sstevel@tonic-gate  * else an integer encoding of the version.
83987c478bd9Sstevel@tonic-gate  */
83997c478bd9Sstevel@tonic-gate static int
84007c478bd9Sstevel@tonic-gate read_cfile_ver(
84017c478bd9Sstevel@tonic-gate FILE *cfp,
84027c478bd9Sstevel@tonic-gate char *version_tag)
84037c478bd9Sstevel@tonic-gate {
84047c478bd9Sstevel@tonic-gate 	char *sp = NULL;
84057c478bd9Sstevel@tonic-gate 	int res;
84067c478bd9Sstevel@tonic-gate 	int version;
84077c478bd9Sstevel@tonic-gate 
84087c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L1, "In read_cfile_ver:\n");
84097c478bd9Sstevel@tonic-gate 
84107c478bd9Sstevel@tonic-gate 	/*
84117c478bd9Sstevel@tonic-gate 	 * read version tag string.
84127c478bd9Sstevel@tonic-gate 	 */
84137c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &sp);
84147c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
84157c478bd9Sstevel@tonic-gate 		goto fail;
84167c478bd9Sstevel@tonic-gate 	} else if (strcasecmp(sp, version_tag) != 0) {
84177c478bd9Sstevel@tonic-gate 		goto fail;
84187c478bd9Sstevel@tonic-gate 	}
84197c478bd9Sstevel@tonic-gate 	free(sp);
84207c478bd9Sstevel@tonic-gate 	sp = NULL;
84217c478bd9Sstevel@tonic-gate 
84227c478bd9Sstevel@tonic-gate 	/*
84237c478bd9Sstevel@tonic-gate 	 * read version number string.
84247c478bd9Sstevel@tonic-gate 	 */
84257c478bd9Sstevel@tonic-gate 	res = readtoken(cfp, &sp);
84267c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
84277c478bd9Sstevel@tonic-gate 		goto fail;
84287c478bd9Sstevel@tonic-gate 	}
84297c478bd9Sstevel@tonic-gate 
84307c478bd9Sstevel@tonic-gate 	/*
84317c478bd9Sstevel@tonic-gate 	 * encode version into int.
84327c478bd9Sstevel@tonic-gate 	 */
84337c478bd9Sstevel@tonic-gate 	if ((version = ver_str_to_int(sp)) == -1) {
84347c478bd9Sstevel@tonic-gate 		goto fail;
84357c478bd9Sstevel@tonic-gate 	}
84367c478bd9Sstevel@tonic-gate 	free(sp);
84377c478bd9Sstevel@tonic-gate 
84387c478bd9Sstevel@tonic-gate 	return (version);
84397c478bd9Sstevel@tonic-gate fail:
84407c478bd9Sstevel@tonic-gate 	ipqos_msg(MT_ERROR,
84417c478bd9Sstevel@tonic-gate 	    gettext("Missing/Invalid config file %s.\n"), version_tag);
84427c478bd9Sstevel@tonic-gate 	if (sp != NULL)
84437c478bd9Sstevel@tonic-gate 		free(sp);
84447c478bd9Sstevel@tonic-gate 	return (-1);
84457c478bd9Sstevel@tonic-gate }
84467c478bd9Sstevel@tonic-gate 
84477c478bd9Sstevel@tonic-gate /*
84487c478bd9Sstevel@tonic-gate  * read the set of actions definitions from the stream cfp and store
84497c478bd9Sstevel@tonic-gate  * them in a list pointed to by conf.
84507c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS.
84517c478bd9Sstevel@tonic-gate  */
84527c478bd9Sstevel@tonic-gate static int
84537c478bd9Sstevel@tonic-gate readconf(
84547c478bd9Sstevel@tonic-gate FILE *cfp,
84557c478bd9Sstevel@tonic-gate ipqos_conf_action_t **conf)
84567c478bd9Sstevel@tonic-gate {
84577c478bd9Sstevel@tonic-gate 
84587c478bd9Sstevel@tonic-gate 	int res;
84597c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *action;
84607c478bd9Sstevel@tonic-gate 	boolean_t ipgpc_action = B_FALSE;
84617c478bd9Sstevel@tonic-gate 	int fmt_ver;
84627c478bd9Sstevel@tonic-gate 
84637c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In readconf\n");
84647c478bd9Sstevel@tonic-gate 
84657c478bd9Sstevel@tonic-gate 	*conf = NULL;
84667c478bd9Sstevel@tonic-gate 
84677c478bd9Sstevel@tonic-gate 	/*
84687c478bd9Sstevel@tonic-gate 	 * get config file format version.
84697c478bd9Sstevel@tonic-gate 	 */
84707c478bd9Sstevel@tonic-gate 	fmt_ver = read_cfile_ver(cfp, IPQOS_FMT_VERSION_STR);
84717c478bd9Sstevel@tonic-gate 	if (fmt_ver == -1) {
84727c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
84737c478bd9Sstevel@tonic-gate 	} else {
84747c478bd9Sstevel@tonic-gate 		/*
84757c478bd9Sstevel@tonic-gate 		 * check version is valid
84767c478bd9Sstevel@tonic-gate 		 */
84777c478bd9Sstevel@tonic-gate 		if ((IPP_MAJOR_MODULE_VER(fmt_ver) > 1) ||
84787c478bd9Sstevel@tonic-gate 		    (IPP_MINOR_MODULE_VER(fmt_ver) > 0)) {
84797c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Unsupported config file "
84807c478bd9Sstevel@tonic-gate 			    "format version.\n"));
84817c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
84827c478bd9Sstevel@tonic-gate 		}
84837c478bd9Sstevel@tonic-gate 	}
84847c478bd9Sstevel@tonic-gate 
84857c478bd9Sstevel@tonic-gate 	/* loop reading actions adding to conf till EOF */
84867c478bd9Sstevel@tonic-gate 
84877c478bd9Sstevel@tonic-gate 	for (;;) {
84887c478bd9Sstevel@tonic-gate 		action = NULL;
84897c478bd9Sstevel@tonic-gate 
84907c478bd9Sstevel@tonic-gate 		/* readaction */
84917c478bd9Sstevel@tonic-gate 
84927c478bd9Sstevel@tonic-gate 		res = readaction(cfp, &action);
84937c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_ERR) {
84947c478bd9Sstevel@tonic-gate 			goto fail;
84957c478bd9Sstevel@tonic-gate 		}
84967c478bd9Sstevel@tonic-gate 
84977c478bd9Sstevel@tonic-gate 		/* reached eof, finish */
84987c478bd9Sstevel@tonic-gate 
84997c478bd9Sstevel@tonic-gate 		if (res == IPQOS_CONF_EOF) {
85007c478bd9Sstevel@tonic-gate 			break;
85017c478bd9Sstevel@tonic-gate 		}
85027c478bd9Sstevel@tonic-gate 
85037c478bd9Sstevel@tonic-gate 		ADD_TO_LIST(conf, action);
85047c478bd9Sstevel@tonic-gate 
85057c478bd9Sstevel@tonic-gate 		/* check if we just read an ipgpc action */
85067c478bd9Sstevel@tonic-gate 
85077c478bd9Sstevel@tonic-gate 		if (strcmp(action->name, IPGPC_CLASSIFY) == 0)
85087c478bd9Sstevel@tonic-gate 			ipgpc_action = B_TRUE;
85097c478bd9Sstevel@tonic-gate 	}
85107c478bd9Sstevel@tonic-gate 
85117c478bd9Sstevel@tonic-gate 	/* check that there is one or more actions and that one is ipgpc */
85127c478bd9Sstevel@tonic-gate 
85137c478bd9Sstevel@tonic-gate 	if (ipgpc_action == B_FALSE) {
85147c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("No %s action defined.\n"),
85157c478bd9Sstevel@tonic-gate 		    IPGPC_NAME);
85167c478bd9Sstevel@tonic-gate 		goto fail;
85177c478bd9Sstevel@tonic-gate 	}
85187c478bd9Sstevel@tonic-gate 
85197c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
85207c478bd9Sstevel@tonic-gate fail:
85217c478bd9Sstevel@tonic-gate 	free_actions(*conf);
85227c478bd9Sstevel@tonic-gate 	*conf = NULL;
85237c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
85247c478bd9Sstevel@tonic-gate }
85257c478bd9Sstevel@tonic-gate 
85267c478bd9Sstevel@tonic-gate /* ************************ kernel config retrieval ************************ */
85277c478bd9Sstevel@tonic-gate 
85287c478bd9Sstevel@tonic-gate 
85297c478bd9Sstevel@tonic-gate /*
85307c478bd9Sstevel@tonic-gate  * read the current configuration from the kernel and make *conf a ptr to it.
85317c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
85327c478bd9Sstevel@tonic-gate  */
85337c478bd9Sstevel@tonic-gate static int
85347c478bd9Sstevel@tonic-gate readkconf(ipqos_conf_action_t **conf)
85357c478bd9Sstevel@tonic-gate {
85367c478bd9Sstevel@tonic-gate 
85377c478bd9Sstevel@tonic-gate 	int res;
85387c478bd9Sstevel@tonic-gate 	char **modnames = NULL;
85397c478bd9Sstevel@tonic-gate 	int nmods;
85407c478bd9Sstevel@tonic-gate 	char **actnames = NULL;
85417c478bd9Sstevel@tonic-gate 	int nacts;
85427c478bd9Sstevel@tonic-gate 	int x, y;
85437c478bd9Sstevel@tonic-gate 	FILE *tfp;
85447c478bd9Sstevel@tonic-gate 	int openerr;
85457c478bd9Sstevel@tonic-gate 	ipqos_actinfo_prm_t ai_prm;
85467c478bd9Sstevel@tonic-gate 
85477c478bd9Sstevel@tonic-gate 
85487c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In readkconf\n");
85497c478bd9Sstevel@tonic-gate 
85507c478bd9Sstevel@tonic-gate 	/* initialise conf to NULL */
85517c478bd9Sstevel@tonic-gate 	*conf = NULL;
85527c478bd9Sstevel@tonic-gate 
85537c478bd9Sstevel@tonic-gate 	/* get list of modules currently loaded */
85547c478bd9Sstevel@tonic-gate 
85557c478bd9Sstevel@tonic-gate 	res = ipp_list_mods(&modnames, &nmods);
85567c478bd9Sstevel@tonic-gate 	if (res != 0) {
85577c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "ipp_list_mods");
85587c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
85597c478bd9Sstevel@tonic-gate 	}
85607c478bd9Sstevel@tonic-gate 
85617c478bd9Sstevel@tonic-gate 	/*
85627c478bd9Sstevel@tonic-gate 	 * iterate through all loaded modules retrieving their list of actions
85637c478bd9Sstevel@tonic-gate 	 * and then retrieving the configuration of each of these
85647c478bd9Sstevel@tonic-gate 	 * and attatching it to conf.
85657c478bd9Sstevel@tonic-gate 	 */
85667c478bd9Sstevel@tonic-gate 	for (x = 0; x < nmods; x++) {
85677c478bd9Sstevel@tonic-gate 
85687c478bd9Sstevel@tonic-gate 		/* skip actions of modules that we can't open types file of */
85697c478bd9Sstevel@tonic-gate 
85707c478bd9Sstevel@tonic-gate 		if ((tfp = validmod(modnames[x], &openerr)) == NULL) {
85717c478bd9Sstevel@tonic-gate 
85727c478bd9Sstevel@tonic-gate 			/* mem error */
85737c478bd9Sstevel@tonic-gate 
85747c478bd9Sstevel@tonic-gate 			if (!openerr) {
85757c478bd9Sstevel@tonic-gate 				goto fail;
85767c478bd9Sstevel@tonic-gate 
85777c478bd9Sstevel@tonic-gate 			/*
85787c478bd9Sstevel@tonic-gate 			 * fopen fail - if we failed because the file didn't
85797c478bd9Sstevel@tonic-gate 			 * exist we assume this is an unknown module and
85807c478bd9Sstevel@tonic-gate 			 * ignore this module, otherwise error.
85817c478bd9Sstevel@tonic-gate 			 */
85827c478bd9Sstevel@tonic-gate 			} else {
85837c478bd9Sstevel@tonic-gate 				if (errno == ENOENT) {
85847c478bd9Sstevel@tonic-gate 					continue;
85857c478bd9Sstevel@tonic-gate 				} else {
85867c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR, "fopen");
85877c478bd9Sstevel@tonic-gate 					goto fail;
85887c478bd9Sstevel@tonic-gate 				}
85897c478bd9Sstevel@tonic-gate 			}
85907c478bd9Sstevel@tonic-gate 		}
85917c478bd9Sstevel@tonic-gate 		(void) fclose(tfp);
85927c478bd9Sstevel@tonic-gate 
85937c478bd9Sstevel@tonic-gate 		/* get action list for this module */
85947c478bd9Sstevel@tonic-gate 
85957c478bd9Sstevel@tonic-gate 		res = ipp_mod_list_actions(modnames[x], &actnames, &nacts);
85967c478bd9Sstevel@tonic-gate 		if (res != 0) {
85977c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "ipp_mod_list_actions");
85987c478bd9Sstevel@tonic-gate 			goto fail;
85997c478bd9Sstevel@tonic-gate 		}
86007c478bd9Sstevel@tonic-gate 
86017c478bd9Sstevel@tonic-gate 		/* read config of each action of this module */
86027c478bd9Sstevel@tonic-gate 
86037c478bd9Sstevel@tonic-gate 		for (y = 0; y < nacts; y++) {
86047c478bd9Sstevel@tonic-gate 			ai_prm.action = alloc_action();
86057c478bd9Sstevel@tonic-gate 			if (ai_prm.action == NULL) {
86067c478bd9Sstevel@tonic-gate 				goto fail;
86077c478bd9Sstevel@tonic-gate 			}
86087c478bd9Sstevel@tonic-gate 
86097c478bd9Sstevel@tonic-gate 			/* copy action name into action struct */
86107c478bd9Sstevel@tonic-gate 
86117c478bd9Sstevel@tonic-gate 			(void) strlcpy(ai_prm.action->name, actnames[y],
86127c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NAME_LEN);
86137c478bd9Sstevel@tonic-gate 
86147c478bd9Sstevel@tonic-gate 			/* copy module name into action struct */
86157c478bd9Sstevel@tonic-gate 
86167c478bd9Sstevel@tonic-gate 			(void) strlcpy(ai_prm.action->module, modnames[x],
86177c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_NAME_LEN);
86187c478bd9Sstevel@tonic-gate 
86197c478bd9Sstevel@tonic-gate 			/* get action info */
86207c478bd9Sstevel@tonic-gate 
86217c478bd9Sstevel@tonic-gate 			res = ipp_action_info(actnames[y],
86227c478bd9Sstevel@tonic-gate 			    (int (*)(nvlist_t *, void *))parse_kaction,
86237c478bd9Sstevel@tonic-gate 			    (void *)&ai_prm, 0);
86247c478bd9Sstevel@tonic-gate 			if (res != 0) {
86257c478bd9Sstevel@tonic-gate 				/* was this an ipp error */
86267c478bd9Sstevel@tonic-gate 				if (ai_prm.intl_ret == IPQOS_CONF_SUCCESS) {
86277c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ENOSTR,
86287c478bd9Sstevel@tonic-gate 					    "ipp_action_info");
86297c478bd9Sstevel@tonic-gate 				}
86307c478bd9Sstevel@tonic-gate 				goto fail;
86317c478bd9Sstevel@tonic-gate 			}
86327c478bd9Sstevel@tonic-gate 
86337c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(conf, ai_prm.action);
86347c478bd9Sstevel@tonic-gate 		}
86357c478bd9Sstevel@tonic-gate 
86367c478bd9Sstevel@tonic-gate 		cleanup_string_table(actnames, nacts);
86377c478bd9Sstevel@tonic-gate 	}
86387c478bd9Sstevel@tonic-gate 
86397c478bd9Sstevel@tonic-gate 	cleanup_string_table(modnames, nmods);
86407c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
86417c478bd9Sstevel@tonic-gate fail:
86427c478bd9Sstevel@tonic-gate 	free_actions(*conf);
86437c478bd9Sstevel@tonic-gate 	*conf = NULL;
86447c478bd9Sstevel@tonic-gate 	cleanup_string_table(modnames, nmods);
86457c478bd9Sstevel@tonic-gate 	cleanup_string_table(actnames, nacts);
86467c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
86477c478bd9Sstevel@tonic-gate }
86487c478bd9Sstevel@tonic-gate 
86497c478bd9Sstevel@tonic-gate /*
86507c478bd9Sstevel@tonic-gate  * This is passed as a parameter to ipp_action_info() in readkaction and
86517c478bd9Sstevel@tonic-gate  * is called back one for each configuration element within the action
86527c478bd9Sstevel@tonic-gate  * specified. This results in filters and classes being created and chained
86537c478bd9Sstevel@tonic-gate  * off of action, and action having its params set.
86547c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS.
86557c478bd9Sstevel@tonic-gate  */
86567c478bd9Sstevel@tonic-gate static int
86577c478bd9Sstevel@tonic-gate parse_kaction(
86587c478bd9Sstevel@tonic-gate nvlist_t *nvl,
86597c478bd9Sstevel@tonic-gate ipqos_actinfo_prm_t *ai_prm)
86607c478bd9Sstevel@tonic-gate {
86617c478bd9Sstevel@tonic-gate 
86627c478bd9Sstevel@tonic-gate 	int ret;
86637c478bd9Sstevel@tonic-gate 	uint8_t cfgtype;
86647c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *filter = NULL;
86657c478bd9Sstevel@tonic-gate 	ipqos_conf_class_t *class = NULL;
86667c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *action = ai_prm->action;
86677c478bd9Sstevel@tonic-gate 
86687c478bd9Sstevel@tonic-gate 
86697c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(KRET, "In parse_kaction: action_name: %s\n", action->name);
86707c478bd9Sstevel@tonic-gate 
86717c478bd9Sstevel@tonic-gate 	/* get config type */
86727c478bd9Sstevel@tonic-gate 
86737c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_byte(nvl, IPP_CONFIG_TYPE, &cfgtype);
86747c478bd9Sstevel@tonic-gate 	(void) nvlist_remove_all(nvl, IPP_CONFIG_TYPE);
86757c478bd9Sstevel@tonic-gate 
86767c478bd9Sstevel@tonic-gate 	switch (cfgtype) {
86777c478bd9Sstevel@tonic-gate 		case CLASSIFIER_ADD_FILTER: {
86787c478bd9Sstevel@tonic-gate 			/*
86797c478bd9Sstevel@tonic-gate 			 * parse the passed filter nvlist
86807c478bd9Sstevel@tonic-gate 			 * and add result to action's filter list.
86817c478bd9Sstevel@tonic-gate 			 */
86827c478bd9Sstevel@tonic-gate 			filter = alloc_filter();
86837c478bd9Sstevel@tonic-gate 			if (filter == NULL) {
86847c478bd9Sstevel@tonic-gate 				ai_prm->intl_ret = IPQOS_CONF_ERR;
86857c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
86867c478bd9Sstevel@tonic-gate 			}
86877c478bd9Sstevel@tonic-gate 
86887c478bd9Sstevel@tonic-gate 			ret = parse_kfilter(filter, nvl);
86897c478bd9Sstevel@tonic-gate 			if (ret != IPQOS_CONF_SUCCESS) {
86907c478bd9Sstevel@tonic-gate 				free_filter(filter);
86917c478bd9Sstevel@tonic-gate 				ai_prm->intl_ret = IPQOS_CONF_ERR;
86927c478bd9Sstevel@tonic-gate 				return (ret);
86937c478bd9Sstevel@tonic-gate 			}
86947c478bd9Sstevel@tonic-gate 
86957c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(&action->filters, filter);
86967c478bd9Sstevel@tonic-gate 			break;
86977c478bd9Sstevel@tonic-gate 		}
86987c478bd9Sstevel@tonic-gate 		case CLASSIFIER_ADD_CLASS:
86997c478bd9Sstevel@tonic-gate 		case CLASSIFIER_MODIFY_CLASS: {
87007c478bd9Sstevel@tonic-gate 			/*
87017c478bd9Sstevel@tonic-gate 			 * parse the passed class nvlist
87027c478bd9Sstevel@tonic-gate 			 * and add result to action's class list.
87037c478bd9Sstevel@tonic-gate 			 */
87047c478bd9Sstevel@tonic-gate 			class = alloc_class();
87057c478bd9Sstevel@tonic-gate 			if (class == NULL) {
87067c478bd9Sstevel@tonic-gate 				ai_prm->intl_ret = IPQOS_CONF_ERR;
87077c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
87087c478bd9Sstevel@tonic-gate 			}
87097c478bd9Sstevel@tonic-gate 
87107c478bd9Sstevel@tonic-gate 			ret = parse_kclass(class, nvl);
87117c478bd9Sstevel@tonic-gate 			if (ret != IPQOS_CONF_SUCCESS) {
87127c478bd9Sstevel@tonic-gate 				free_class(class);
87137c478bd9Sstevel@tonic-gate 				ai_prm->intl_ret = IPQOS_CONF_ERR;
87147c478bd9Sstevel@tonic-gate 				return (ret);
87157c478bd9Sstevel@tonic-gate 			}
87167c478bd9Sstevel@tonic-gate 
87177c478bd9Sstevel@tonic-gate 			ADD_TO_LIST(&action->classes, class);
87187c478bd9Sstevel@tonic-gate 			break;
87197c478bd9Sstevel@tonic-gate 		}
87207c478bd9Sstevel@tonic-gate 		case IPP_SET: {
87217c478bd9Sstevel@tonic-gate 			/*
87227c478bd9Sstevel@tonic-gate 			 * we don't alloc a params struct as it is created
87237c478bd9Sstevel@tonic-gate 			 * as part of an action.
87247c478bd9Sstevel@tonic-gate 			 */
87257c478bd9Sstevel@tonic-gate 
87267c478bd9Sstevel@tonic-gate 			/* parse the passed params nvlist */
87277c478bd9Sstevel@tonic-gate 
87287c478bd9Sstevel@tonic-gate 			ret = parse_kparams(action->module, action->params,
87297c478bd9Sstevel@tonic-gate 			    nvl);
87307c478bd9Sstevel@tonic-gate 			if (ret != IPQOS_CONF_SUCCESS) {
87317c478bd9Sstevel@tonic-gate 				ai_prm->intl_ret = IPQOS_CONF_ERR;
87327c478bd9Sstevel@tonic-gate 				return (ret);
87337c478bd9Sstevel@tonic-gate 			}
87347c478bd9Sstevel@tonic-gate 		}
87357c478bd9Sstevel@tonic-gate 	}
87367c478bd9Sstevel@tonic-gate 
87377c478bd9Sstevel@tonic-gate 	ai_prm->intl_ret = IPQOS_CONF_SUCCESS;
87387c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
87397c478bd9Sstevel@tonic-gate }
87407c478bd9Sstevel@tonic-gate 
87417c478bd9Sstevel@tonic-gate /*
87427c478bd9Sstevel@tonic-gate  * parses a params nvlist returned from the kernel.
87437c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
87447c478bd9Sstevel@tonic-gate  */
87457c478bd9Sstevel@tonic-gate int
87467c478bd9Sstevel@tonic-gate parse_kparams(
87477c478bd9Sstevel@tonic-gate char *module,
87487c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params,
87497c478bd9Sstevel@tonic-gate nvlist_t *nvl) {
87507c478bd9Sstevel@tonic-gate 
87517c478bd9Sstevel@tonic-gate 	int ret;
87527c478bd9Sstevel@tonic-gate 	ipqos_nvtype_t type;
87537c478bd9Sstevel@tonic-gate 	str_val_nd_t *tmp;
87547c478bd9Sstevel@tonic-gate 	char *act;
87557c478bd9Sstevel@tonic-gate 	uint32_t u32;
87567c478bd9Sstevel@tonic-gate 	nvpair_t *nvp;
87577c478bd9Sstevel@tonic-gate 	FILE *tfp;
87587c478bd9Sstevel@tonic-gate 	char dfltst[IPQOS_VALST_MAXLEN];
87597c478bd9Sstevel@tonic-gate 	char *param;
87607c478bd9Sstevel@tonic-gate 	nvlist_t *nvlcp;
87617c478bd9Sstevel@tonic-gate 	int openerr;
87627c478bd9Sstevel@tonic-gate 	place_t place;
87637c478bd9Sstevel@tonic-gate 
87647c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(KRET, "In parse_kparams:\n");
87657c478bd9Sstevel@tonic-gate 
87667c478bd9Sstevel@tonic-gate 	/* get stream to module types file */
87677c478bd9Sstevel@tonic-gate 
87687c478bd9Sstevel@tonic-gate 	tfp = validmod(module, &openerr);
87697c478bd9Sstevel@tonic-gate 	if (tfp == NULL) {
87707c478bd9Sstevel@tonic-gate 		if (openerr) {
87717c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "fopen");
87727c478bd9Sstevel@tonic-gate 		}
87737c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
87747c478bd9Sstevel@tonic-gate 	}
87757c478bd9Sstevel@tonic-gate 
87767c478bd9Sstevel@tonic-gate 	/* make copy of passed in nvlist as it is freed by the caller */
87777c478bd9Sstevel@tonic-gate 
87787c478bd9Sstevel@tonic-gate 	ret = nvlist_dup(nvl, &nvlcp, 0);
87797c478bd9Sstevel@tonic-gate 	if (ret != 0) {
87807c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
87817c478bd9Sstevel@tonic-gate 	}
87827c478bd9Sstevel@tonic-gate 
87837c478bd9Sstevel@tonic-gate 	/*
87847c478bd9Sstevel@tonic-gate 	 * get config originator and remove from nvlist. If no owner we
87857c478bd9Sstevel@tonic-gate 	 * assume ownership.
87867c478bd9Sstevel@tonic-gate 	 */
87877c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_uint32(nvlcp, IPP_CONFIG_ORIGINATOR, &u32);
87887c478bd9Sstevel@tonic-gate 	if (ret == 0) {
87897c478bd9Sstevel@tonic-gate 		params->originator = u32;
87907c478bd9Sstevel@tonic-gate 		(void) nvlist_remove_all(nvlcp, IPP_CONFIG_ORIGINATOR);
87917c478bd9Sstevel@tonic-gate 	} else {
87927c478bd9Sstevel@tonic-gate 		params->originator = IPP_CONFIG_IPQOSCONF;
87937c478bd9Sstevel@tonic-gate 	}
87947c478bd9Sstevel@tonic-gate 
87957c478bd9Sstevel@tonic-gate 	/* get action stats and remove from nvlist */
87967c478bd9Sstevel@tonic-gate 
87977c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_uint32(nvlcp, IPP_ACTION_STATS_ENABLE, &u32);
87987c478bd9Sstevel@tonic-gate 	if (ret == 0) {
87997c478bd9Sstevel@tonic-gate 		params->stats_enable = *(boolean_t *)&u32;
88007c478bd9Sstevel@tonic-gate 		(void) nvlist_remove_all(nvlcp, IPP_ACTION_STATS_ENABLE);
88017c478bd9Sstevel@tonic-gate 	}
88027c478bd9Sstevel@tonic-gate 
88037c478bd9Sstevel@tonic-gate 	/*
88047c478bd9Sstevel@tonic-gate 	 * loop throught nvlist elements and for those that are actions create
88057c478bd9Sstevel@tonic-gate 	 * action ref entrys for them.
88067c478bd9Sstevel@tonic-gate 	 */
88077c478bd9Sstevel@tonic-gate 	nvp = nvlist_next_nvpair(nvlcp, NULL);
88087c478bd9Sstevel@tonic-gate 	while (nvp != NULL) {
88097c478bd9Sstevel@tonic-gate 		param = SHORT_NAME(nvpair_name(nvp));
88107c478bd9Sstevel@tonic-gate 		place = PL_ANY;
88117c478bd9Sstevel@tonic-gate 		ret = readtype(tfp, module, param, &type, &tmp, dfltst,
88127c478bd9Sstevel@tonic-gate 		    B_FALSE, &place);
88137c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
88147c478bd9Sstevel@tonic-gate 			goto fail;
88157c478bd9Sstevel@tonic-gate 		}
88167c478bd9Sstevel@tonic-gate 
88177c478bd9Sstevel@tonic-gate 		if ((place == PL_PARAMS) &&	/* avoid map entries */
88187c478bd9Sstevel@tonic-gate 		    (type == IPQOS_DATA_TYPE_ACTION)) {
88197c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &act);
88207c478bd9Sstevel@tonic-gate 			ret = add_aref(&params->actions, nvpair_name(nvp), act);
88217c478bd9Sstevel@tonic-gate 			if (ret != IPQOS_CONF_SUCCESS) {
88227c478bd9Sstevel@tonic-gate 				goto fail;
88237c478bd9Sstevel@tonic-gate 			}
88247c478bd9Sstevel@tonic-gate 		}
88257c478bd9Sstevel@tonic-gate 
88267c478bd9Sstevel@tonic-gate 		nvp = nvlist_next_nvpair(nvlcp, nvp);
88277c478bd9Sstevel@tonic-gate 	}
88287c478bd9Sstevel@tonic-gate 
88297c478bd9Sstevel@tonic-gate 	/* assign copied nvlist to params struct */
88307c478bd9Sstevel@tonic-gate 
88317c478bd9Sstevel@tonic-gate 	params->nvlist = nvlcp;
88327c478bd9Sstevel@tonic-gate 
88337c478bd9Sstevel@tonic-gate 	(void) fclose(tfp);
88347c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
88357c478bd9Sstevel@tonic-gate fail:
88367c478bd9Sstevel@tonic-gate 	(void) fclose(tfp);
88377c478bd9Sstevel@tonic-gate 	free_arefs(params->actions);
88387c478bd9Sstevel@tonic-gate 	params->actions = NULL;
88397c478bd9Sstevel@tonic-gate 	nvlist_free(nvlcp);
88407c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_ERR);
88417c478bd9Sstevel@tonic-gate }
88427c478bd9Sstevel@tonic-gate 
88437c478bd9Sstevel@tonic-gate /*
88447c478bd9Sstevel@tonic-gate  * parses a classes nvlist returned from the kernel.
88457c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
88467c478bd9Sstevel@tonic-gate  */
88477c478bd9Sstevel@tonic-gate static int
88487c478bd9Sstevel@tonic-gate parse_kclass(
88497c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class,
88507c478bd9Sstevel@tonic-gate nvlist_t *nvl)
88517c478bd9Sstevel@tonic-gate {
88527c478bd9Sstevel@tonic-gate 
88537c478bd9Sstevel@tonic-gate 	int ret;
88547c478bd9Sstevel@tonic-gate 	uint32_t u32;
88557c478bd9Sstevel@tonic-gate 	char *str;
88567c478bd9Sstevel@tonic-gate 
88577c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(KRET, "In parse_kclass:\n");
88587c478bd9Sstevel@tonic-gate 
88597c478bd9Sstevel@tonic-gate 	/* lookup object originator */
88607c478bd9Sstevel@tonic-gate 
88617c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_uint32(nvl, IPP_CONFIG_ORIGINATOR, &u32);
88627c478bd9Sstevel@tonic-gate 	if (ret == 0) {
88637c478bd9Sstevel@tonic-gate 		class->originator = u32;
88647c478bd9Sstevel@tonic-gate 	} else {
88657c478bd9Sstevel@tonic-gate 		class->originator = IPP_CONFIG_IPQOSCONF;
88667c478bd9Sstevel@tonic-gate 	}
88677c478bd9Sstevel@tonic-gate 
88687c478bd9Sstevel@tonic-gate 	/* lookup name */
88697c478bd9Sstevel@tonic-gate 
88707c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(nvl, CLASSIFIER_CLASS_NAME, &str);
88717c478bd9Sstevel@tonic-gate 	(void) strlcpy(class->name, str, IPQOS_CONF_NAME_LEN);
88727c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(KRET, "reading class %s\n", class->name);
88737c478bd9Sstevel@tonic-gate 
88747c478bd9Sstevel@tonic-gate 	/* lookup next action */
88757c478bd9Sstevel@tonic-gate 
88767c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(nvl, CLASSIFIER_NEXT_ACTION, &str);
88777c478bd9Sstevel@tonic-gate 	ret = add_aref(&class->alist, NULL, str);
88787c478bd9Sstevel@tonic-gate 	if (ret != IPQOS_CONF_SUCCESS) {
88797c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
88807c478bd9Sstevel@tonic-gate 	}
88817c478bd9Sstevel@tonic-gate 
88827c478bd9Sstevel@tonic-gate 	/* lookup stats enable */
88837c478bd9Sstevel@tonic-gate 
88847c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE, &u32);
88857c478bd9Sstevel@tonic-gate 	if (ret == 0) {
88867c478bd9Sstevel@tonic-gate 		class->stats_enable = *(boolean_t *)&u32;
88877c478bd9Sstevel@tonic-gate 	}
88887c478bd9Sstevel@tonic-gate 
88897c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
88907c478bd9Sstevel@tonic-gate }
88917c478bd9Sstevel@tonic-gate 
88927c478bd9Sstevel@tonic-gate /*
88937c478bd9Sstevel@tonic-gate  * parses a filters nvlist returned from the kernel.
88947c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
88957c478bd9Sstevel@tonic-gate  */
88967c478bd9Sstevel@tonic-gate static int
88977c478bd9Sstevel@tonic-gate parse_kfilter(
88987c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter,
88997c478bd9Sstevel@tonic-gate nvlist_t *nvl)
89007c478bd9Sstevel@tonic-gate {
89017c478bd9Sstevel@tonic-gate 
89027c478bd9Sstevel@tonic-gate 	int ret;
89037c478bd9Sstevel@tonic-gate 	char *str;
89047c478bd9Sstevel@tonic-gate 	uint32_t u32;
89057c478bd9Sstevel@tonic-gate 	nvlist_t *nvlcp;
89067c478bd9Sstevel@tonic-gate 	char *end;
89077c478bd9Sstevel@tonic-gate 
89087c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(KRET, "In parse_kfilter:\n");
89097c478bd9Sstevel@tonic-gate 
89107c478bd9Sstevel@tonic-gate 	/* make copy of passed in nvlist as it is freed by the caller */
89117c478bd9Sstevel@tonic-gate 
89127c478bd9Sstevel@tonic-gate 	ret = nvlist_dup(nvl, &nvlcp, 0);
89137c478bd9Sstevel@tonic-gate 	if (ret != 0) {
89147c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
89157c478bd9Sstevel@tonic-gate 	}
89167c478bd9Sstevel@tonic-gate 
89177c478bd9Sstevel@tonic-gate 	/* lookup originator */
89187c478bd9Sstevel@tonic-gate 
89197c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_uint32(nvlcp, IPP_CONFIG_ORIGINATOR, &u32);
89207c478bd9Sstevel@tonic-gate 	if (ret == 0) {
89217c478bd9Sstevel@tonic-gate 		filter->originator = u32;
89227c478bd9Sstevel@tonic-gate 		(void) nvlist_remove_all(nvlcp, IPP_CONFIG_ORIGINATOR);
89237c478bd9Sstevel@tonic-gate 	} else {
89247c478bd9Sstevel@tonic-gate 		filter->originator = IPP_CONFIG_IPQOSCONF;
89257c478bd9Sstevel@tonic-gate 	}
89267c478bd9Sstevel@tonic-gate 
89277c478bd9Sstevel@tonic-gate 	/* lookup filter name */
89287c478bd9Sstevel@tonic-gate 
89297c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(nvlcp, CLASSIFIER_FILTER_NAME, &str);
89307c478bd9Sstevel@tonic-gate 	(void) strlcpy(filter->name, str, IPQOS_CONF_NAME_LEN);
89317c478bd9Sstevel@tonic-gate 	(void) nvlist_remove_all(nvlcp, CLASSIFIER_FILTER_NAME);
89327c478bd9Sstevel@tonic-gate 
89337c478bd9Sstevel@tonic-gate 	/* lookup class name */
89347c478bd9Sstevel@tonic-gate 
89357c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(nvlcp, CLASSIFIER_CLASS_NAME, &str);
89367c478bd9Sstevel@tonic-gate 	(void) strlcpy(filter->class_name, str, IPQOS_CONF_NAME_LEN);
89377c478bd9Sstevel@tonic-gate 	(void) nvlist_remove_all(nvlcp, CLASSIFIER_CLASS_NAME);
89387c478bd9Sstevel@tonic-gate 
89397c478bd9Sstevel@tonic-gate 	/* lookup src and dst host names if present */
89407c478bd9Sstevel@tonic-gate 
89417c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlcp, IPGPC_SADDR_HOSTNAME, &str) == 0) {
89427c478bd9Sstevel@tonic-gate 		filter->src_nd_name = malloc(strlen(str) + 1);
89437c478bd9Sstevel@tonic-gate 		if (filter->src_nd_name) {
89447c478bd9Sstevel@tonic-gate 			(void) strcpy(filter->src_nd_name, str);
89457c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all(nvlcp, IPGPC_SADDR_HOSTNAME);
89467c478bd9Sstevel@tonic-gate 		} else {
89477c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
89487c478bd9Sstevel@tonic-gate 			nvlist_free(nvlcp);
89497c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
89507c478bd9Sstevel@tonic-gate 		}
89517c478bd9Sstevel@tonic-gate 	}
89527c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlcp, IPGPC_DADDR_HOSTNAME, &str) == 0) {
89537c478bd9Sstevel@tonic-gate 		filter->dst_nd_name = malloc(strlen(str) + 1);
89547c478bd9Sstevel@tonic-gate 		if (filter->dst_nd_name) {
89557c478bd9Sstevel@tonic-gate 			(void) strcpy(filter->dst_nd_name, str);
89567c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all(nvlcp, IPGPC_DADDR_HOSTNAME);
89577c478bd9Sstevel@tonic-gate 		} else {
89587c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
89597c478bd9Sstevel@tonic-gate 			nvlist_free(nvlcp);
89607c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
89617c478bd9Sstevel@tonic-gate 		}
89627c478bd9Sstevel@tonic-gate 	}
89637c478bd9Sstevel@tonic-gate 
89647c478bd9Sstevel@tonic-gate 	/* lookup ip_version if present */
89657c478bd9Sstevel@tonic-gate 
89667c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlcp, IPGPC_FILTER_PRIVATE, &str) == 0) {
89677c478bd9Sstevel@tonic-gate 		filter->ip_versions = (uint32_t)strtol(str, &end, 0);
89687c478bd9Sstevel@tonic-gate 		if (end != str) {
89697c478bd9Sstevel@tonic-gate 			(void) nvlist_remove_all(nvlcp, IPGPC_FILTER_PRIVATE);
89707c478bd9Sstevel@tonic-gate 		} else {
89717c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
89727c478bd9Sstevel@tonic-gate 			    gettext("Corrupted ip_version returned from "
89737c478bd9Sstevel@tonic-gate 			    "kernel.\n"));
89747c478bd9Sstevel@tonic-gate 			nvlist_free(nvlcp);
89757c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
89767c478bd9Sstevel@tonic-gate 		}
89777c478bd9Sstevel@tonic-gate 	}
89787c478bd9Sstevel@tonic-gate 
89797c478bd9Sstevel@tonic-gate 	/* lookup filter instance if present */
89807c478bd9Sstevel@tonic-gate 
89817c478bd9Sstevel@tonic-gate 	ret = nvlist_lookup_int32(nvlcp, IPGPC_FILTER_INSTANCE,
89827c478bd9Sstevel@tonic-gate 	    &filter->instance);
89837c478bd9Sstevel@tonic-gate 	if (ret != 0) {
89847c478bd9Sstevel@tonic-gate 		filter->instance = -1;
89857c478bd9Sstevel@tonic-gate 	} else {
89867c478bd9Sstevel@tonic-gate 		(void) nvlist_remove_all(nvlcp, IPGPC_FILTER_INSTANCE);
89877c478bd9Sstevel@tonic-gate 	}
89887c478bd9Sstevel@tonic-gate 
89897c478bd9Sstevel@tonic-gate 	/* attach new trimmed nvlist to filter */
89907c478bd9Sstevel@tonic-gate 	filter->nvlist = nvlcp;
89917c478bd9Sstevel@tonic-gate 
89927c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
89937c478bd9Sstevel@tonic-gate }
89947c478bd9Sstevel@tonic-gate 
89957c478bd9Sstevel@tonic-gate 
89967c478bd9Sstevel@tonic-gate /*
89977c478bd9Sstevel@tonic-gate  * determines whether action_name is a virtual action name.
89987c478bd9Sstevel@tonic-gate  * RETURNS: if virtual action 1, else 0.
89997c478bd9Sstevel@tonic-gate  */
90007c478bd9Sstevel@tonic-gate static int
90017c478bd9Sstevel@tonic-gate virtual_action(char *action_name)
90027c478bd9Sstevel@tonic-gate {
90037c478bd9Sstevel@tonic-gate 
90047c478bd9Sstevel@tonic-gate 	if (strcmp(action_name, IPP_ANAME_CONT) == 0 ||
90057c478bd9Sstevel@tonic-gate 	    strcmp(action_name, IPP_ANAME_DEFER) == 0 ||
90067c478bd9Sstevel@tonic-gate 	    strcmp(action_name, IPP_ANAME_DROP) == 0) {
90077c478bd9Sstevel@tonic-gate 		return (1);
90087c478bd9Sstevel@tonic-gate 	}
90097c478bd9Sstevel@tonic-gate 
90107c478bd9Sstevel@tonic-gate 	return (0);
90117c478bd9Sstevel@tonic-gate }
90127c478bd9Sstevel@tonic-gate 
90137c478bd9Sstevel@tonic-gate /*
90147c478bd9Sstevel@tonic-gate  * remove all the actions within the kernel. If there is a failure
90157c478bd9Sstevel@tonic-gate  * modified is set to represent whether the attempt to flush modified
90167c478bd9Sstevel@tonic-gate  * the configuration in any way.
90177c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if the ipp_* functions return any errors,
90187c478bd9Sstevel@tonic-gate  * else IPQOS_CONF_SUCCESS.
90197c478bd9Sstevel@tonic-gate  */
90207c478bd9Sstevel@tonic-gate static int
90217c478bd9Sstevel@tonic-gate flush(
90227c478bd9Sstevel@tonic-gate boolean_t *modified)
90237c478bd9Sstevel@tonic-gate {
90247c478bd9Sstevel@tonic-gate 
90257c478bd9Sstevel@tonic-gate 	int res;
90267c478bd9Sstevel@tonic-gate 	char **modnames = NULL;
90277c478bd9Sstevel@tonic-gate 	int nmods;
90287c478bd9Sstevel@tonic-gate 	char **actnames = NULL;
90297c478bd9Sstevel@tonic-gate 	int nacts;
90307c478bd9Sstevel@tonic-gate 	int x, y;
90317c478bd9Sstevel@tonic-gate 
90327c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In flush\n");
90337c478bd9Sstevel@tonic-gate 
90347c478bd9Sstevel@tonic-gate 	*modified = B_FALSE;
90357c478bd9Sstevel@tonic-gate 
90367c478bd9Sstevel@tonic-gate 	/*
90377c478bd9Sstevel@tonic-gate 	 * get list of modules currently loaded.
90387c478bd9Sstevel@tonic-gate 	 */
90397c478bd9Sstevel@tonic-gate 	res = ipp_list_mods(&modnames, &nmods);
90407c478bd9Sstevel@tonic-gate 	if (res != 0) {
90417c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "ipp_list_mods");
90427c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
90437c478bd9Sstevel@tonic-gate 	}
90447c478bd9Sstevel@tonic-gate 
90457c478bd9Sstevel@tonic-gate 	/*
90467c478bd9Sstevel@tonic-gate 	 * iterate through all the modules listing their actions and
90477c478bd9Sstevel@tonic-gate 	 * deleting all of them.
90487c478bd9Sstevel@tonic-gate 	 */
90497c478bd9Sstevel@tonic-gate 	for (x = 0; x < nmods; x++) {
90507c478bd9Sstevel@tonic-gate 		IPQOSCDBG1(APPLY, "Getting actions of module %s.\n",
90517c478bd9Sstevel@tonic-gate 		    modnames[x]);
90527c478bd9Sstevel@tonic-gate 		res = ipp_mod_list_actions(modnames[x], &actnames, &nacts);
90537c478bd9Sstevel@tonic-gate 		if (res != 0) {
90547c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "ipp_mod_list_actions");
90557c478bd9Sstevel@tonic-gate 			cleanup_string_table(modnames, nmods);
90567c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
90577c478bd9Sstevel@tonic-gate 		}
90587c478bd9Sstevel@tonic-gate 
90597c478bd9Sstevel@tonic-gate 		for (y = 0; y < nacts; y++) {
90607c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(APPLY, "deleting action %s\n", actnames[y]);
90617c478bd9Sstevel@tonic-gate 			res = ipp_action_destroy(actnames[y], IPP_DESTROY_REF);
90627c478bd9Sstevel@tonic-gate 			/*
90637c478bd9Sstevel@tonic-gate 			 * if fails for reason other than action doesn't
90647c478bd9Sstevel@tonic-gate 			 * exist or action has dependency.
90657c478bd9Sstevel@tonic-gate 			 */
90667c478bd9Sstevel@tonic-gate 			if (res != 0 && errno != ENOENT && errno != EBUSY) {
90677c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ENOSTR, "ipp_action_destroy");
90687c478bd9Sstevel@tonic-gate 				cleanup_string_table(modnames, nmods);
90697c478bd9Sstevel@tonic-gate 				cleanup_string_table(actnames, nacts);
90707c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
90717c478bd9Sstevel@tonic-gate 			}
90727c478bd9Sstevel@tonic-gate 
90737c478bd9Sstevel@tonic-gate 			if (res == 0)
90747c478bd9Sstevel@tonic-gate 				*modified = B_TRUE;
90757c478bd9Sstevel@tonic-gate 		}
90767c478bd9Sstevel@tonic-gate 		cleanup_string_table(actnames, nacts);
90777c478bd9Sstevel@tonic-gate 	}
90787c478bd9Sstevel@tonic-gate 	cleanup_string_table(modnames, nmods);
90797c478bd9Sstevel@tonic-gate 
90807c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
90817c478bd9Sstevel@tonic-gate }
90827c478bd9Sstevel@tonic-gate 
90837c478bd9Sstevel@tonic-gate /*
90847c478bd9Sstevel@tonic-gate  * Trys to flush the configuration. If it fails and nothing has been modified
90857c478bd9Sstevel@tonic-gate  * and force_flush is false just return an error, otherwise persist trying to
90867c478bd9Sstevel@tonic-gate  * completion.
90877c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if flush attempt failed without modifying anything
90887c478bd9Sstevel@tonic-gate  * and force_flush was set to false, otherwise IPQOS_CONF_SUCCESS.
90897c478bd9Sstevel@tonic-gate  */
90907c478bd9Sstevel@tonic-gate static int
90917c478bd9Sstevel@tonic-gate atomic_flush(
90927c478bd9Sstevel@tonic-gate boolean_t force_flush)
90937c478bd9Sstevel@tonic-gate {
90947c478bd9Sstevel@tonic-gate 	int x = 0;
90957c478bd9Sstevel@tonic-gate 	int res;
90967c478bd9Sstevel@tonic-gate 	boolean_t modified = B_FALSE;
90977c478bd9Sstevel@tonic-gate 
90987c478bd9Sstevel@tonic-gate 	/*
90997c478bd9Sstevel@tonic-gate 	 * attempt first flush of config.
91007c478bd9Sstevel@tonic-gate 	 */
91017c478bd9Sstevel@tonic-gate 	res = flush(&modified);
91027c478bd9Sstevel@tonic-gate 	if ((force_flush == B_FALSE) && (res != IPQOS_CONF_SUCCESS) &&
91037c478bd9Sstevel@tonic-gate 	    (modified == B_FALSE)) {
91047c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
91057c478bd9Sstevel@tonic-gate 	} else if (res == IPQOS_CONF_SUCCESS) {
91067c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_SUCCESS);
91077c478bd9Sstevel@tonic-gate 	}
91087c478bd9Sstevel@tonic-gate 
91097c478bd9Sstevel@tonic-gate 	/*
91107c478bd9Sstevel@tonic-gate 	 * failed flush that modified config, or force flush set; loop till
91117c478bd9Sstevel@tonic-gate 	 * successful flush.
91127c478bd9Sstevel@tonic-gate 	 */
91137c478bd9Sstevel@tonic-gate 	while (res != IPQOS_CONF_SUCCESS) {
91147c478bd9Sstevel@tonic-gate 		if (x == 5) {	/* 10 secs since start/last message. */
91157c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
91167c478bd9Sstevel@tonic-gate 			    gettext("Retrying configuration flush.\n"));
91177c478bd9Sstevel@tonic-gate 			x = 0;
91187c478bd9Sstevel@tonic-gate 		}
91197c478bd9Sstevel@tonic-gate 		(void) sleep(2);
91207c478bd9Sstevel@tonic-gate 		x++;
91217c478bd9Sstevel@tonic-gate 		res = flush(&modified);
91227c478bd9Sstevel@tonic-gate 	}
91237c478bd9Sstevel@tonic-gate 
91247c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
91257c478bd9Sstevel@tonic-gate }
91267c478bd9Sstevel@tonic-gate 
91277c478bd9Sstevel@tonic-gate /*
91287c478bd9Sstevel@tonic-gate  * Performs a flush of the configuration within a signal blocking region
91297c478bd9Sstevel@tonic-gate  * so that there's minimal chance of it being killed and the flush only
91307c478bd9Sstevel@tonic-gate  * partially completing.
91317c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_SUCCESS (for symmetry with the other main functions).
91327c478bd9Sstevel@tonic-gate  */
91337c478bd9Sstevel@tonic-gate static int
91347c478bd9Sstevel@tonic-gate flushconf()
91357c478bd9Sstevel@tonic-gate {
91367c478bd9Sstevel@tonic-gate 	int res;
91377c478bd9Sstevel@tonic-gate 
91387c478bd9Sstevel@tonic-gate 	/*
91397c478bd9Sstevel@tonic-gate 	 * make sure that flush is as atomic as possible.
91407c478bd9Sstevel@tonic-gate 	 */
91417c478bd9Sstevel@tonic-gate 	if ((res = block_all_signals()) == -1)
91427c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
91437c478bd9Sstevel@tonic-gate 
91447c478bd9Sstevel@tonic-gate 	res = atomic_flush(B_FALSE);
91457c478bd9Sstevel@tonic-gate 
91467c478bd9Sstevel@tonic-gate 	/*
91477c478bd9Sstevel@tonic-gate 	 * restore signals.
91487c478bd9Sstevel@tonic-gate 	 */
91497c478bd9Sstevel@tonic-gate 	(void) restore_all_signals();
91507c478bd9Sstevel@tonic-gate 
91517c478bd9Sstevel@tonic-gate 	if (res == IPQOS_CONF_SUCCESS) {
91527c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_LOG, gettext("Configuration flushed.\n"));
91537c478bd9Sstevel@tonic-gate 	} else {
91547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "atomic_flush");
91557c478bd9Sstevel@tonic-gate 	}
91567c478bd9Sstevel@tonic-gate 
91577c478bd9Sstevel@tonic-gate 	return (res);
91587c478bd9Sstevel@tonic-gate }
91597c478bd9Sstevel@tonic-gate 
91607c478bd9Sstevel@tonic-gate static int
91617c478bd9Sstevel@tonic-gate in_string_table(char *stable[], int size, char *string)
91627c478bd9Sstevel@tonic-gate {
91637c478bd9Sstevel@tonic-gate 
91647c478bd9Sstevel@tonic-gate 	IPQOSCDBG1(L1, "In in_string_table: search string %s\n", string);
91657c478bd9Sstevel@tonic-gate 
91667c478bd9Sstevel@tonic-gate 	for (--size; size >= 0; size--) {
91677c478bd9Sstevel@tonic-gate 		if (strcmp(stable[size], string) == 0) {
91687c478bd9Sstevel@tonic-gate 			IPQOSCDBG1(L1, "Found %s in string table\n", string);
91697c478bd9Sstevel@tonic-gate 			return (1);
91707c478bd9Sstevel@tonic-gate 		}
91717c478bd9Sstevel@tonic-gate 	}
91727c478bd9Sstevel@tonic-gate 
91737c478bd9Sstevel@tonic-gate 	return (0);
91747c478bd9Sstevel@tonic-gate }
91757c478bd9Sstevel@tonic-gate 
91767c478bd9Sstevel@tonic-gate /* free the memory occupied by the string table ctable and its contents. */
91777c478bd9Sstevel@tonic-gate static void
91787c478bd9Sstevel@tonic-gate cleanup_string_table(char *ctable[], int size)
91797c478bd9Sstevel@tonic-gate {
91807c478bd9Sstevel@tonic-gate 
91817c478bd9Sstevel@tonic-gate 	int x;
91827c478bd9Sstevel@tonic-gate 
91837c478bd9Sstevel@tonic-gate 	if (ctable) {
91847c478bd9Sstevel@tonic-gate 		for (x = 0; x < size; x++) {
91857c478bd9Sstevel@tonic-gate 			free(ctable[x]);
91867c478bd9Sstevel@tonic-gate 		}
91877c478bd9Sstevel@tonic-gate 		free(ctable);
91887c478bd9Sstevel@tonic-gate 	}
91897c478bd9Sstevel@tonic-gate }
91907c478bd9Sstevel@tonic-gate 
91917c478bd9Sstevel@tonic-gate #if 0
91927c478bd9Sstevel@tonic-gate 
91937c478bd9Sstevel@tonic-gate /*
91947c478bd9Sstevel@tonic-gate  * makes a copy of a string table and returns a ptr to it.
91957c478bd9Sstevel@tonic-gate  * RETURNS: NULL on error or if size was 0, else ptr to copied table.
91967c478bd9Sstevel@tonic-gate  */
91977c478bd9Sstevel@tonic-gate static char **
91987c478bd9Sstevel@tonic-gate copy_string_table(char *stable1[], int size)
91997c478bd9Sstevel@tonic-gate {
92007c478bd9Sstevel@tonic-gate 
92017c478bd9Sstevel@tonic-gate 	char **st = NULL;
92027c478bd9Sstevel@tonic-gate 	int pos;
92037c478bd9Sstevel@tonic-gate 
92047c478bd9Sstevel@tonic-gate 	/* create char ptr array */
92057c478bd9Sstevel@tonic-gate 
92067c478bd9Sstevel@tonic-gate 	st = malloc(size * sizeof (char *));
92077c478bd9Sstevel@tonic-gate 	if (st == NULL) {
92087c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "malloc");
92097c478bd9Sstevel@tonic-gate 		return (st);
92107c478bd9Sstevel@tonic-gate 	}
92117c478bd9Sstevel@tonic-gate 
92127c478bd9Sstevel@tonic-gate 	/* create copy of each string from stable1 in array */
92137c478bd9Sstevel@tonic-gate 
92147c478bd9Sstevel@tonic-gate 	for (pos = size - 1; pos >= 0; pos--) {
92157c478bd9Sstevel@tonic-gate 		st[pos] = malloc(strlen(stable1[pos] + 1));
92167c478bd9Sstevel@tonic-gate 		if (st[pos] == NULL) {
92177c478bd9Sstevel@tonic-gate 			for (pos++; pos < size; pos++)
92187c478bd9Sstevel@tonic-gate 				free(st[pos]);
92197c478bd9Sstevel@tonic-gate 			free(st);
92207c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
92217c478bd9Sstevel@tonic-gate 			return (NULL);
92227c478bd9Sstevel@tonic-gate 		}
92237c478bd9Sstevel@tonic-gate 
92247c478bd9Sstevel@tonic-gate 		(void) strcpy(st[pos], stable1[pos]);
92257c478bd9Sstevel@tonic-gate 	}
92267c478bd9Sstevel@tonic-gate 
92277c478bd9Sstevel@tonic-gate 	return (st);
92287c478bd9Sstevel@tonic-gate }
92297c478bd9Sstevel@tonic-gate #endif	/* 0 */
92307c478bd9Sstevel@tonic-gate 
92317c478bd9Sstevel@tonic-gate /*
92327c478bd9Sstevel@tonic-gate  * retry lookups on filters that soft failed a previous lookup and
92337c478bd9Sstevel@tonic-gate  * were put on the retry list.
92347c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on any errors, else IPQOS_CONF_SUCCESS.
92357c478bd9Sstevel@tonic-gate  */
92367c478bd9Sstevel@tonic-gate static int
92377c478bd9Sstevel@tonic-gate retry_name_lookups(
92387c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions)
92397c478bd9Sstevel@tonic-gate {
92407c478bd9Sstevel@tonic-gate 
92417c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
92427c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t **new_filters;
92437c478bd9Sstevel@tonic-gate 	ipqos_conf_filter_t *flt;
92447c478bd9Sstevel@tonic-gate 
92457c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(APPLY, "In retry_name_lookups:\n");
92467c478bd9Sstevel@tonic-gate 
92477c478bd9Sstevel@tonic-gate 	for (act = actions; act != NULL; act = act->next) {
92487c478bd9Sstevel@tonic-gate 
92497c478bd9Sstevel@tonic-gate 		/* store start of new resolved filters */
9250*85280f08SToomas Soome 		GET_LIST_END(&act->filters, &new_filters);
92517c478bd9Sstevel@tonic-gate 
92527c478bd9Sstevel@tonic-gate 		/*
92537c478bd9Sstevel@tonic-gate 		 * do name resolution on retry list adding resolved filters
92547c478bd9Sstevel@tonic-gate 		 * to end of actions filters.
92557c478bd9Sstevel@tonic-gate 		 */
92567c478bd9Sstevel@tonic-gate 		for (flt = act->retry_filters; flt != NULL; flt = flt->next) {
92577c478bd9Sstevel@tonic-gate 
92587c478bd9Sstevel@tonic-gate 			if (domultihome(flt, new_filters, B_TRUE) !=
92597c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_SUCCESS) {
92607c478bd9Sstevel@tonic-gate 
92617c478bd9Sstevel@tonic-gate 				/* if resource failure */
92627c478bd9Sstevel@tonic-gate 
92637c478bd9Sstevel@tonic-gate 				if (flt->nlerr == 0) {
92647c478bd9Sstevel@tonic-gate 					return (IPQOS_CONF_ERR);
92657c478bd9Sstevel@tonic-gate 				}
92667c478bd9Sstevel@tonic-gate 			}
92677c478bd9Sstevel@tonic-gate 		}
92687c478bd9Sstevel@tonic-gate 
92697c478bd9Sstevel@tonic-gate 		/* add the newly resolved filters to the kernel action */
92707c478bd9Sstevel@tonic-gate 
92717c478bd9Sstevel@tonic-gate 		for (flt = *new_filters; flt != NULL; flt = flt->next) {
92727c478bd9Sstevel@tonic-gate 			if (add_filter(act->name, flt, act->module_version) !=
92737c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_SUCCESS) {
92747c478bd9Sstevel@tonic-gate 				return (IPQOS_CONF_ERR);
92757c478bd9Sstevel@tonic-gate 			}
92767c478bd9Sstevel@tonic-gate 		}
92777c478bd9Sstevel@tonic-gate 	}
92787c478bd9Sstevel@tonic-gate 
92797c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
92807c478bd9Sstevel@tonic-gate }
92817c478bd9Sstevel@tonic-gate 
92827c478bd9Sstevel@tonic-gate /*
92837c478bd9Sstevel@tonic-gate  * write the configuration in conf to the file given in dstpath. This
92847c478bd9Sstevel@tonic-gate  * is done by writing first to a temporary file and then renaming that
92857c478bd9Sstevel@tonic-gate  * file to dstpath. This assures an atomic write.
92867c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on any errors, else IPQOS_CONF_SUCCESS.
92877c478bd9Sstevel@tonic-gate  */
92887c478bd9Sstevel@tonic-gate static int
92897c478bd9Sstevel@tonic-gate writeconf(
92907c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf,
92917c478bd9Sstevel@tonic-gate char *dstpath)
92927c478bd9Sstevel@tonic-gate {
92937c478bd9Sstevel@tonic-gate 
92947c478bd9Sstevel@tonic-gate 	FILE *tmpfp;
92957c478bd9Sstevel@tonic-gate 	char *tmppath;
92967c478bd9Sstevel@tonic-gate 	char *pathend;
92977c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
92987c478bd9Sstevel@tonic-gate 	int res;
92997c478bd9Sstevel@tonic-gate 
93007c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "in writeconf\n");
93017c478bd9Sstevel@tonic-gate 
93027c478bd9Sstevel@tonic-gate 	/* construct tmp file path so we can use rename() */
93037c478bd9Sstevel@tonic-gate 
93047c478bd9Sstevel@tonic-gate 	pathend = strrchr(dstpath, '/');
93057c478bd9Sstevel@tonic-gate 
93067c478bd9Sstevel@tonic-gate 	/* dstpath in current dir */
93077c478bd9Sstevel@tonic-gate 
93087c478bd9Sstevel@tonic-gate 	if (pathend == NULL) {
93097c478bd9Sstevel@tonic-gate 		tmppath = malloc(strlen("ipqosconf.tmp") + 1);
93107c478bd9Sstevel@tonic-gate 		if (tmppath == NULL) {
93117c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
93127c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
93137c478bd9Sstevel@tonic-gate 		}
93147c478bd9Sstevel@tonic-gate 		(void) strcpy(tmppath, "ipqosconf.tmp");
93157c478bd9Sstevel@tonic-gate 
93167c478bd9Sstevel@tonic-gate 	/* dstpath in root dir */
93177c478bd9Sstevel@tonic-gate 
93187c478bd9Sstevel@tonic-gate 	} else if (pathend == dstpath) {
93197c478bd9Sstevel@tonic-gate 		tmppath = malloc(strlen("/ipqosconf.tmp") + 1);
93207c478bd9Sstevel@tonic-gate 		if (tmppath == NULL) {
93217c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
93227c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
93237c478bd9Sstevel@tonic-gate 		}
93247c478bd9Sstevel@tonic-gate 		(void) strcpy(tmppath, "/ipqosconf.tmp");
93257c478bd9Sstevel@tonic-gate 
93267c478bd9Sstevel@tonic-gate 	/* not pwd or root */
93277c478bd9Sstevel@tonic-gate 
93287c478bd9Sstevel@tonic-gate 	} else {
93297c478bd9Sstevel@tonic-gate 		*pathend = NULL;
93307c478bd9Sstevel@tonic-gate 		tmppath = malloc(strlen(dstpath) + strlen("/ipqosconf.tmp") +
93317c478bd9Sstevel@tonic-gate 		    1);
93327c478bd9Sstevel@tonic-gate 		if (tmppath == NULL) {
93337c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR, "malloc");
93347c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
93357c478bd9Sstevel@tonic-gate 		}
93367c478bd9Sstevel@tonic-gate 		(void) strcpy(tmppath, dstpath);
93377c478bd9Sstevel@tonic-gate 		(void) strcat(tmppath, "/ipqosconf.tmp");
93387c478bd9Sstevel@tonic-gate 		*pathend = '/';
93397c478bd9Sstevel@tonic-gate 	}
93407c478bd9Sstevel@tonic-gate 
93417c478bd9Sstevel@tonic-gate 
93427c478bd9Sstevel@tonic-gate 	/* open tmp file */
93437c478bd9Sstevel@tonic-gate 
93447c478bd9Sstevel@tonic-gate 	tmpfp = fopen(tmppath, "w");
93457c478bd9Sstevel@tonic-gate 	if (tmpfp == NULL) {
93467c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "fopen");
93477c478bd9Sstevel@tonic-gate 		free(tmppath);
93487c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
93497c478bd9Sstevel@tonic-gate 	}
93507c478bd9Sstevel@tonic-gate 
93517c478bd9Sstevel@tonic-gate 	/* write out format version */
93527c478bd9Sstevel@tonic-gate 
93537c478bd9Sstevel@tonic-gate 	(void) fprintf(tmpfp, "%s %d.%d\n\n", IPQOS_FMT_VERSION_STR,
93547c478bd9Sstevel@tonic-gate 	    IPQOS_CUR_FMT_MAJOR_VER, IPQOS_CUR_FMT_MINOR_VER);
93557c478bd9Sstevel@tonic-gate 
93567c478bd9Sstevel@tonic-gate 	/*
93577c478bd9Sstevel@tonic-gate 	 * loop through actions in list writing ipqosconf originated
93587c478bd9Sstevel@tonic-gate 	 * ones out to the tmp file.
93597c478bd9Sstevel@tonic-gate 	 */
93607c478bd9Sstevel@tonic-gate 	for (act = conf; act != NULL; act = act->next) {
93617c478bd9Sstevel@tonic-gate 		if (act->params->originator == IPP_CONFIG_IPQOSCONF) {
93627c478bd9Sstevel@tonic-gate 			res = printaction(tmpfp, act, 0, 0);
93637c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
93647c478bd9Sstevel@tonic-gate 				free(tmppath);
93657c478bd9Sstevel@tonic-gate 				(void) fclose(tmpfp);
93667c478bd9Sstevel@tonic-gate 				return (res);
93677c478bd9Sstevel@tonic-gate 			}
93687c478bd9Sstevel@tonic-gate 		}
93697c478bd9Sstevel@tonic-gate 	}
93707c478bd9Sstevel@tonic-gate 	(void) fclose(tmpfp);
93717c478bd9Sstevel@tonic-gate 
93727c478bd9Sstevel@tonic-gate 	/* rename tmp file to dst file */
93737c478bd9Sstevel@tonic-gate 
93747c478bd9Sstevel@tonic-gate 	if (rename(tmppath, dstpath) != 0) {
93757c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "rename");
93767c478bd9Sstevel@tonic-gate 		free(tmppath);
93777c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
93787c478bd9Sstevel@tonic-gate 	}
93797c478bd9Sstevel@tonic-gate 	free(tmppath);
93807c478bd9Sstevel@tonic-gate 
93817c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
93827c478bd9Sstevel@tonic-gate }
93837c478bd9Sstevel@tonic-gate 
93847c478bd9Sstevel@tonic-gate /*
93857c478bd9Sstevel@tonic-gate  * read the configuration back from the kernel and then write each of the
93867c478bd9Sstevel@tonic-gate  * actions read to IPQOS_CONF_INIT_PATH.
93877c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS.
93887c478bd9Sstevel@tonic-gate  */
93897c478bd9Sstevel@tonic-gate static int
93907c478bd9Sstevel@tonic-gate commitconf()
93917c478bd9Sstevel@tonic-gate {
93927c478bd9Sstevel@tonic-gate 
93937c478bd9Sstevel@tonic-gate 	int ret;
93947c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *conf;
93957c478bd9Sstevel@tonic-gate 
93967c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In commitconf\n");
93977c478bd9Sstevel@tonic-gate 
93987c478bd9Sstevel@tonic-gate 	/* read the configuration from the kernel */
93997c478bd9Sstevel@tonic-gate 
94007c478bd9Sstevel@tonic-gate 	ret = readkconf(&conf);
94017c478bd9Sstevel@tonic-gate 	if (ret != IPQOS_CONF_SUCCESS) {
94027c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
94037c478bd9Sstevel@tonic-gate 	}
94047c478bd9Sstevel@tonic-gate 
94057c478bd9Sstevel@tonic-gate 	/* dissallow a null config to be stored (we can't read one in) */
94067c478bd9Sstevel@tonic-gate 
94077c478bd9Sstevel@tonic-gate 	if (conf == NULL) {
94087c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR,
94097c478bd9Sstevel@tonic-gate 		    gettext("Can't commit a null configuration.\n"));
94107c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
94117c478bd9Sstevel@tonic-gate 	}
94127c478bd9Sstevel@tonic-gate 
94137c478bd9Sstevel@tonic-gate 	/* make sure if we create file that perms are 644 */
94147c478bd9Sstevel@tonic-gate 
94157c478bd9Sstevel@tonic-gate 	(void) umask(S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH);
94167c478bd9Sstevel@tonic-gate 
94177c478bd9Sstevel@tonic-gate 	/* write the configuration to the init file */
94187c478bd9Sstevel@tonic-gate 
94197c478bd9Sstevel@tonic-gate 	ret = writeconf(conf, IPQOS_CONF_INIT_PATH);
94207c478bd9Sstevel@tonic-gate 	if (ret != IPQOS_CONF_SUCCESS) {
94217c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
94227c478bd9Sstevel@tonic-gate 	}
94237c478bd9Sstevel@tonic-gate 
94247c478bd9Sstevel@tonic-gate 	ipqos_msg(MT_LOG,
94257c478bd9Sstevel@tonic-gate 	    gettext("Current configuration saved to init file.\n"));
94267c478bd9Sstevel@tonic-gate 
94277c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
94287c478bd9Sstevel@tonic-gate }
94297c478bd9Sstevel@tonic-gate 
94307c478bd9Sstevel@tonic-gate /*
94317c478bd9Sstevel@tonic-gate  * Called in the event of a failed rollback. It first flushes the
94327c478bd9Sstevel@tonic-gate  * current configuration, then attempts to apply the oconf (the old
94337c478bd9Sstevel@tonic-gate  * one), and if that fails flushes again.
94347c478bd9Sstevel@tonic-gate  *
94357c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR if the application of old config fails,
94367c478bd9Sstevel@tonic-gate  * else IPQOS_CONF_SUCCESS.
94377c478bd9Sstevel@tonic-gate  */
94387c478bd9Sstevel@tonic-gate static int
94397c478bd9Sstevel@tonic-gate rollback_recover(
94407c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oconf)
94417c478bd9Sstevel@tonic-gate {
94427c478bd9Sstevel@tonic-gate 	int res;
94437c478bd9Sstevel@tonic-gate 
94447c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(RBK, "In rollback_recover\n");
94457c478bd9Sstevel@tonic-gate 
94467c478bd9Sstevel@tonic-gate 	/*
94477c478bd9Sstevel@tonic-gate 	 * flush configuration.
94487c478bd9Sstevel@tonic-gate 	 */
94497c478bd9Sstevel@tonic-gate 	(void) atomic_flush(B_TRUE);
94507c478bd9Sstevel@tonic-gate 
94517c478bd9Sstevel@tonic-gate 	/*
94527c478bd9Sstevel@tonic-gate 	 * mark all elements of old config for application.
94537c478bd9Sstevel@tonic-gate 	 */
94547c478bd9Sstevel@tonic-gate 	mark_config_new(oconf);
94557c478bd9Sstevel@tonic-gate 
94567c478bd9Sstevel@tonic-gate 	/*
94577c478bd9Sstevel@tonic-gate 	 * attempt to apply old config.
94587c478bd9Sstevel@tonic-gate 	 */
94597c478bd9Sstevel@tonic-gate 	res = applydiff(oconf, NULL);
94607c478bd9Sstevel@tonic-gate 	/*
94617c478bd9Sstevel@tonic-gate 	 * if failed force flush of config.
94627c478bd9Sstevel@tonic-gate 	 */
94637c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
94647c478bd9Sstevel@tonic-gate 		(void) atomic_flush(B_TRUE);
94657c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
94667c478bd9Sstevel@tonic-gate 	}
94677c478bd9Sstevel@tonic-gate 
94687c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
94697c478bd9Sstevel@tonic-gate }
94707c478bd9Sstevel@tonic-gate 
94717c478bd9Sstevel@tonic-gate /*
94727c478bd9Sstevel@tonic-gate  * read and apply the configuration contained if file ifile to the kernel.
94737c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
94747c478bd9Sstevel@tonic-gate  */
94757c478bd9Sstevel@tonic-gate static int
94767c478bd9Sstevel@tonic-gate applyconf(char *ifile)
94777c478bd9Sstevel@tonic-gate {
94787c478bd9Sstevel@tonic-gate 
94797c478bd9Sstevel@tonic-gate 	FILE *ifp;
94807c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *conf = NULL;
94817c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *oconf = NULL;
94827c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act, *oact;
94837c478bd9Sstevel@tonic-gate 	int res;
94847c478bd9Sstevel@tonic-gate 
94857c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In applyconf:\n");
94867c478bd9Sstevel@tonic-gate 
94877c478bd9Sstevel@tonic-gate 
94887c478bd9Sstevel@tonic-gate 	/* if filename '-' read from stdin */
94897c478bd9Sstevel@tonic-gate 
94907c478bd9Sstevel@tonic-gate 	if (strcmp(ifile, "-") == 0) {
94917c478bd9Sstevel@tonic-gate 		ifp = stdin;
94927c478bd9Sstevel@tonic-gate 	} else {
94937c478bd9Sstevel@tonic-gate 		ifp = fopen(ifile, "r");
94947c478bd9Sstevel@tonic-gate 		if (ifp == NULL) {
94957c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
94967c478bd9Sstevel@tonic-gate 			    gettext("Opening file %s for read: %s.\n"),
94977c478bd9Sstevel@tonic-gate 			    ifile, strerror(errno));
94987c478bd9Sstevel@tonic-gate 			return (IPQOS_CONF_ERR);
94997c478bd9Sstevel@tonic-gate 		}
95007c478bd9Sstevel@tonic-gate 	}
95017c478bd9Sstevel@tonic-gate 
95027c478bd9Sstevel@tonic-gate 	/* read in new configuration */
95037c478bd9Sstevel@tonic-gate 
95047c478bd9Sstevel@tonic-gate 	res = readconf(ifp, &conf);
95057c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95067c478bd9Sstevel@tonic-gate 		goto fail;
95077c478bd9Sstevel@tonic-gate 	}
95087c478bd9Sstevel@tonic-gate 
95097c478bd9Sstevel@tonic-gate 	/* check configuration is valid */
95107c478bd9Sstevel@tonic-gate 
95117c478bd9Sstevel@tonic-gate 	res = validconf(conf, 1);
95127c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95137c478bd9Sstevel@tonic-gate 		goto fail;
95147c478bd9Sstevel@tonic-gate 	}
95157c478bd9Sstevel@tonic-gate 
95167c478bd9Sstevel@tonic-gate 	/* read in kernel configuration */
95177c478bd9Sstevel@tonic-gate 
95187c478bd9Sstevel@tonic-gate 	res = readkconf(&oconf);
95197c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95207c478bd9Sstevel@tonic-gate 		goto fail;
95217c478bd9Sstevel@tonic-gate 	}
95227c478bd9Sstevel@tonic-gate 
95237c478bd9Sstevel@tonic-gate 	/*
95247c478bd9Sstevel@tonic-gate 	 * check there are no same named actions in both config file and the
95257c478bd9Sstevel@tonic-gate 	 * the kernel that are for a different module. The application
95267c478bd9Sstevel@tonic-gate 	 * system can't handle these as we would try to add the new
95277c478bd9Sstevel@tonic-gate 	 * action before we deleted the old one and because actions
95287c478bd9Sstevel@tonic-gate 	 * in the kernel are indexed solely on their name (their module
95297c478bd9Sstevel@tonic-gate 	 * isn't included) the kernel would return an error. We want
95307c478bd9Sstevel@tonic-gate 	 * to avoid this error and the resulting rollback.
95317c478bd9Sstevel@tonic-gate 	 */
95327c478bd9Sstevel@tonic-gate 	for (act = conf; act != NULL; act = act->next) {
95337c478bd9Sstevel@tonic-gate 		for (oact = oconf; oact != NULL; oact = oact->next) {
95347c478bd9Sstevel@tonic-gate 			/* found action */
95357c478bd9Sstevel@tonic-gate 			if (strcmp(act->name, oact->name) == 0) {
95367c478bd9Sstevel@tonic-gate 				/* different module */
95377c478bd9Sstevel@tonic-gate 				if (strcmp(act->module, oact->module) != 0) {
95387c478bd9Sstevel@tonic-gate 					ipqos_msg(MT_ERROR,
95397c478bd9Sstevel@tonic-gate 					    gettext("Action at line %u has "
95407c478bd9Sstevel@tonic-gate 					    "same name as currently "
95417c478bd9Sstevel@tonic-gate 					    "installed action, but is for a "
95427c478bd9Sstevel@tonic-gate 					    "different module.\n"),
95437c478bd9Sstevel@tonic-gate 					    act->lineno);
95447c478bd9Sstevel@tonic-gate 					goto fail;
95457c478bd9Sstevel@tonic-gate 				/* same module - stop search */
95467c478bd9Sstevel@tonic-gate 				} else {
95477c478bd9Sstevel@tonic-gate 					break;
95487c478bd9Sstevel@tonic-gate 				}
95497c478bd9Sstevel@tonic-gate 			}
95507c478bd9Sstevel@tonic-gate 		}
95517c478bd9Sstevel@tonic-gate 	}
95527c478bd9Sstevel@tonic-gate 
95537c478bd9Sstevel@tonic-gate 
95547c478bd9Sstevel@tonic-gate 	/* create links between actions for use with deletions etc.. */
95557c478bd9Sstevel@tonic-gate 
95567c478bd9Sstevel@tonic-gate 	res = validconf(oconf, 0);
95577c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95587c478bd9Sstevel@tonic-gate 		goto fail;
95597c478bd9Sstevel@tonic-gate 	}
95607c478bd9Sstevel@tonic-gate 
95617c478bd9Sstevel@tonic-gate 	/* diff conf file against kernel */
95627c478bd9Sstevel@tonic-gate 
95637c478bd9Sstevel@tonic-gate 	res = diffconf(oconf, conf);
95647c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95657c478bd9Sstevel@tonic-gate 		goto fail;
95667c478bd9Sstevel@tonic-gate 	}
95677c478bd9Sstevel@tonic-gate 
95687c478bd9Sstevel@tonic-gate 	/* make kernel mods as atomic as possible */
95697c478bd9Sstevel@tonic-gate 
95707c478bd9Sstevel@tonic-gate 	if ((res = block_all_signals()) == -1) {
95717c478bd9Sstevel@tonic-gate 		res = IPQOS_CONF_ERR;
95727c478bd9Sstevel@tonic-gate 		goto fail;
95737c478bd9Sstevel@tonic-gate 	}
95747c478bd9Sstevel@tonic-gate 
95757c478bd9Sstevel@tonic-gate 	/* apply difference to kernel */
95767c478bd9Sstevel@tonic-gate 
95777c478bd9Sstevel@tonic-gate 	res = applydiff(conf, oconf);
95787c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
95797c478bd9Sstevel@tonic-gate 	if (force_rback || res != IPQOS_CONF_SUCCESS) {
95807c478bd9Sstevel@tonic-gate #else
95817c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
95827c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
95837c478bd9Sstevel@tonic-gate 
95847c478bd9Sstevel@tonic-gate 		res = rollback(conf, oconf);
95857c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
95867c478bd9Sstevel@tonic-gate 			res = rollback_recover(oconf);
95877c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
95887c478bd9Sstevel@tonic-gate 				/* system left flushed */
95897c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
95907c478bd9Sstevel@tonic-gate 				    gettext("Failed to rollback from failed "
95917c478bd9Sstevel@tonic-gate 				    "configuration, configuration flushed.\n"));
95927c478bd9Sstevel@tonic-gate 				res = IPQOS_CONF_RECOVER_ERR;
95937c478bd9Sstevel@tonic-gate 			} else {	/* old config re-applied */
95947c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
95957c478bd9Sstevel@tonic-gate 				    gettext("Configuration failed, system "
95967c478bd9Sstevel@tonic-gate 				    "state unchanged.\n"));
95977c478bd9Sstevel@tonic-gate 				res = IPQOS_CONF_ERR;
95987c478bd9Sstevel@tonic-gate 			}
95997c478bd9Sstevel@tonic-gate 		} else {
96007c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
96017c478bd9Sstevel@tonic-gate 			    gettext("Configuration failed, system "
96027c478bd9Sstevel@tonic-gate 			    "state unchanged.\n"));
96037c478bd9Sstevel@tonic-gate 			res = IPQOS_CONF_ERR;
96047c478bd9Sstevel@tonic-gate 		}
96057c478bd9Sstevel@tonic-gate 		goto fail;
96067c478bd9Sstevel@tonic-gate 	}
96077c478bd9Sstevel@tonic-gate 
96087c478bd9Sstevel@tonic-gate 	/* retry any soft name lookup failures */
96097c478bd9Sstevel@tonic-gate 
96107c478bd9Sstevel@tonic-gate 	res = retry_name_lookups(conf);
96117c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
96127c478bd9Sstevel@tonic-gate 		res = rollback(conf, oconf);
96137c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
96147c478bd9Sstevel@tonic-gate 			res = rollback_recover(oconf);
96157c478bd9Sstevel@tonic-gate 			if (res != IPQOS_CONF_SUCCESS) {
96167c478bd9Sstevel@tonic-gate 			/* system left flushed */
96177c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
96187c478bd9Sstevel@tonic-gate 				    gettext("Failed to rollback from failed "
96197c478bd9Sstevel@tonic-gate 				    "configuration, configuration flushed.\n"));
96207c478bd9Sstevel@tonic-gate 				res = IPQOS_CONF_RECOVER_ERR;
96217c478bd9Sstevel@tonic-gate 			} else {	/* old config re-applied */
96227c478bd9Sstevel@tonic-gate 				ipqos_msg(MT_ERROR,
96237c478bd9Sstevel@tonic-gate 				    gettext("Configuration failed, system "
96247c478bd9Sstevel@tonic-gate 				    "state unchanged.\n"));
96257c478bd9Sstevel@tonic-gate 				res = IPQOS_CONF_ERR;
96267c478bd9Sstevel@tonic-gate 			}
96277c478bd9Sstevel@tonic-gate 		} else {
96287c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR,
96297c478bd9Sstevel@tonic-gate 			    gettext("Configuration failed, system "
96307c478bd9Sstevel@tonic-gate 			    "state unchanged.\n"));
96317c478bd9Sstevel@tonic-gate 			res = IPQOS_CONF_ERR;
96327c478bd9Sstevel@tonic-gate 		}
96337c478bd9Sstevel@tonic-gate 		goto fail;
96347c478bd9Sstevel@tonic-gate 
96357c478bd9Sstevel@tonic-gate 	}
96367c478bd9Sstevel@tonic-gate 
96377c478bd9Sstevel@tonic-gate 	ipqos_msg(MT_LOG, gettext("IPQoS configuration applied.\n"));
96387c478bd9Sstevel@tonic-gate 
96397c478bd9Sstevel@tonic-gate 	/* re-enable signals */
96407c478bd9Sstevel@tonic-gate 	(void) restore_all_signals();
96417c478bd9Sstevel@tonic-gate 
96427c478bd9Sstevel@tonic-gate 	(void) fclose(ifp);
96437c478bd9Sstevel@tonic-gate 	free_actions(conf);
96447c478bd9Sstevel@tonic-gate 	free_actions(oconf);
96457c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
96467c478bd9Sstevel@tonic-gate fail:
96477c478bd9Sstevel@tonic-gate 	(void) fclose(ifp);
96487c478bd9Sstevel@tonic-gate 	(void) restore_all_signals();
96497c478bd9Sstevel@tonic-gate 	if (conf)
96507c478bd9Sstevel@tonic-gate 		free_actions(conf);
96517c478bd9Sstevel@tonic-gate 	if (oconf)
96527c478bd9Sstevel@tonic-gate 		free_actions(oconf);
96537c478bd9Sstevel@tonic-gate 	if (res == IPQOS_CONF_RECOVER_ERR)
96547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_LOG, gettext("Configuration flushed.\n"));
96557c478bd9Sstevel@tonic-gate 	return (res);
96567c478bd9Sstevel@tonic-gate }
96577c478bd9Sstevel@tonic-gate 
96587c478bd9Sstevel@tonic-gate static sigset_t set, oset;
96597c478bd9Sstevel@tonic-gate 
96607c478bd9Sstevel@tonic-gate static int
96617c478bd9Sstevel@tonic-gate block_all_signals()
96627c478bd9Sstevel@tonic-gate {
96637c478bd9Sstevel@tonic-gate 	if (sigfillset(&set) == -1) {
96647c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "sigfillset");
96657c478bd9Sstevel@tonic-gate 		return (-1);
96667c478bd9Sstevel@tonic-gate 	}
96677c478bd9Sstevel@tonic-gate 	if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) {
96687c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "sigprocmask");
96697c478bd9Sstevel@tonic-gate 		return (-1);
96707c478bd9Sstevel@tonic-gate 	}
96717c478bd9Sstevel@tonic-gate 	return (0);
96727c478bd9Sstevel@tonic-gate }
96737c478bd9Sstevel@tonic-gate 
96747c478bd9Sstevel@tonic-gate static int
96757c478bd9Sstevel@tonic-gate restore_all_signals()
96767c478bd9Sstevel@tonic-gate {
96777c478bd9Sstevel@tonic-gate 	if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) {
96787c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "sigprocmask");
96797c478bd9Sstevel@tonic-gate 		return (-1);
96807c478bd9Sstevel@tonic-gate 	}
96817c478bd9Sstevel@tonic-gate 	return (0);
96827c478bd9Sstevel@tonic-gate }
96837c478bd9Sstevel@tonic-gate 
96847c478bd9Sstevel@tonic-gate static int
96857c478bd9Sstevel@tonic-gate unlock(int fd)
96867c478bd9Sstevel@tonic-gate {
96877c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_ULOCK, 0) == -1) {
96887c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "lockf");
96897c478bd9Sstevel@tonic-gate 		return (-1);
96907c478bd9Sstevel@tonic-gate 	}
96917c478bd9Sstevel@tonic-gate 	return (0);
96927c478bd9Sstevel@tonic-gate }
96937c478bd9Sstevel@tonic-gate 
96947c478bd9Sstevel@tonic-gate static int
96957c478bd9Sstevel@tonic-gate lock()
96967c478bd9Sstevel@tonic-gate {
96977c478bd9Sstevel@tonic-gate 	int fd;
96987c478bd9Sstevel@tonic-gate 	struct stat sbuf1;
96997c478bd9Sstevel@tonic-gate 	struct stat sbuf2;
97007c478bd9Sstevel@tonic-gate 
97017c478bd9Sstevel@tonic-gate 	/*
97027c478bd9Sstevel@tonic-gate 	 * Open the file with O_CREAT|O_EXCL. If it exists already, it
97037c478bd9Sstevel@tonic-gate 	 * will fail. If it already exists, check whether it looks like
97047c478bd9Sstevel@tonic-gate 	 * the one we created.
97057c478bd9Sstevel@tonic-gate 	 */
97067c478bd9Sstevel@tonic-gate 	(void) umask(0077);
97077c478bd9Sstevel@tonic-gate 	if ((fd = open(IPQOS_CONF_LOCK_FILE, O_EXCL|O_CREAT|O_RDWR,
97087c478bd9Sstevel@tonic-gate 	    S_IRUSR|S_IWUSR)) == -1) {
97097c478bd9Sstevel@tonic-gate 		if (errno != EEXIST) {
97107c478bd9Sstevel@tonic-gate 			/* Some other problem. */
97117c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR,
97127c478bd9Sstevel@tonic-gate 			    gettext("Cannot open lock file %s"),
97137c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97147c478bd9Sstevel@tonic-gate 			return (-1);
97157c478bd9Sstevel@tonic-gate 		}
97167c478bd9Sstevel@tonic-gate 
97177c478bd9Sstevel@tonic-gate 		/*
97187c478bd9Sstevel@tonic-gate 		 * open() returned an EEXIST error. We don't fail yet
97197c478bd9Sstevel@tonic-gate 		 * as it could be a residual from a previous
97207c478bd9Sstevel@tonic-gate 		 * execution. However, we need to clear errno here.
97217c478bd9Sstevel@tonic-gate 		 * If we don't and print_cmd_buf() is later invoked
97227c478bd9Sstevel@tonic-gate 		 * as the result of a parsing error, it
97237c478bd9Sstevel@tonic-gate 		 * will assume that the current error is EEXIST and
97247c478bd9Sstevel@tonic-gate 		 * that a corresponding error message has already been
97257c478bd9Sstevel@tonic-gate 		 * printed, which results in an incomplete error
97267c478bd9Sstevel@tonic-gate 		 * message. If errno is zero, print_cmd_buf() will
97277c478bd9Sstevel@tonic-gate 		 * assume that it is called as a result of a
97287c478bd9Sstevel@tonic-gate 		 * parsing error and will print the appropriate
97297c478bd9Sstevel@tonic-gate 		 * error message.
97307c478bd9Sstevel@tonic-gate 		 */
97317c478bd9Sstevel@tonic-gate 		errno = 0;
97327c478bd9Sstevel@tonic-gate 
97337c478bd9Sstevel@tonic-gate 		/*
97347c478bd9Sstevel@tonic-gate 		 * File exists. make sure it is OK. We need to lstat()
97357c478bd9Sstevel@tonic-gate 		 * as fstat() stats the file pointed to by the symbolic
97367c478bd9Sstevel@tonic-gate 		 * link.
97377c478bd9Sstevel@tonic-gate 		 */
97387c478bd9Sstevel@tonic-gate 		if (lstat(IPQOS_CONF_LOCK_FILE, &sbuf1) == -1) {
97397c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR,
97407c478bd9Sstevel@tonic-gate 			    gettext("Cannot lstat lock file %s\n"),
97417c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97427c478bd9Sstevel@tonic-gate 			return (-1);
97437c478bd9Sstevel@tonic-gate 		}
97447c478bd9Sstevel@tonic-gate 		/*
97457c478bd9Sstevel@tonic-gate 		 * Check whether it is a regular file and not a symbolic
97467c478bd9Sstevel@tonic-gate 		 * link. Its link count should be 1. The owner should be
97477c478bd9Sstevel@tonic-gate 		 * root and the file should be empty.
97487c478bd9Sstevel@tonic-gate 		 */
97494bc0a2efScasper 		if (!S_ISREG(sbuf1.st_mode) ||
97507c478bd9Sstevel@tonic-gate 		    sbuf1.st_nlink != 1 ||
97517c478bd9Sstevel@tonic-gate 		    sbuf1.st_uid != 0 ||
97527c478bd9Sstevel@tonic-gate 		    sbuf1.st_size != 0) {
97537c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Bad lock file %s.\n"),
97547c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97557c478bd9Sstevel@tonic-gate 			return (-1);
97567c478bd9Sstevel@tonic-gate 		}
97577c478bd9Sstevel@tonic-gate 		if ((fd = open(IPQOS_CONF_LOCK_FILE, O_CREAT|O_RDWR,
97587c478bd9Sstevel@tonic-gate 		    S_IRUSR|S_IWUSR)) == -1) {
97597c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR,
97607c478bd9Sstevel@tonic-gate 			    gettext("Cannot open lock file %s"),
97617c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97627c478bd9Sstevel@tonic-gate 			return (-1);
97637c478bd9Sstevel@tonic-gate 		}
97647c478bd9Sstevel@tonic-gate 
97657c478bd9Sstevel@tonic-gate 		/* Check whether we opened the file that we lstat()ed. */
97667c478bd9Sstevel@tonic-gate 		if (fstat(fd, &sbuf2) == -1) {
97677c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ENOSTR,
97687c478bd9Sstevel@tonic-gate 			    gettext("Cannot fstat lock file %s\n"),
97697c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97707c478bd9Sstevel@tonic-gate 			return (-1);
97717c478bd9Sstevel@tonic-gate 		}
97727c478bd9Sstevel@tonic-gate 		if (sbuf1.st_dev != sbuf2.st_dev ||
97737c478bd9Sstevel@tonic-gate 		    sbuf1.st_ino != sbuf2.st_ino) {
97747c478bd9Sstevel@tonic-gate 			/* File changed after we did the lstat() above */
97757c478bd9Sstevel@tonic-gate 			ipqos_msg(MT_ERROR, gettext("Bad lock file %s.\n"),
97767c478bd9Sstevel@tonic-gate 			    IPQOS_CONF_LOCK_FILE);
97777c478bd9Sstevel@tonic-gate 			return (-1);
97787c478bd9Sstevel@tonic-gate 		}
97797c478bd9Sstevel@tonic-gate 	}
97807c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_LOCK, 0) == -1) {
97817c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ENOSTR, "lockf");
97827c478bd9Sstevel@tonic-gate 		return (-1);
97837c478bd9Sstevel@tonic-gate 	}
97847c478bd9Sstevel@tonic-gate 	return (fd);
97857c478bd9Sstevel@tonic-gate }
97867c478bd9Sstevel@tonic-gate 
97877c478bd9Sstevel@tonic-gate /*
97887c478bd9Sstevel@tonic-gate  * print the current kernel configuration out to stdout. If viewall
97897c478bd9Sstevel@tonic-gate  * is set this causes more verbose configuration listing including
97907c478bd9Sstevel@tonic-gate  * showing objects we didn't create, each instance of a mhome filter,
97917c478bd9Sstevel@tonic-gate  * etc.. see printaction().
97927c478bd9Sstevel@tonic-gate  * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES.
97937c478bd9Sstevel@tonic-gate  */
97947c478bd9Sstevel@tonic-gate 
97957c478bd9Sstevel@tonic-gate static int
97967c478bd9Sstevel@tonic-gate viewconf(int viewall)
97977c478bd9Sstevel@tonic-gate {
97987c478bd9Sstevel@tonic-gate 
97997c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *conf = NULL;
98007c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
98017c478bd9Sstevel@tonic-gate 	int ret;
98027c478bd9Sstevel@tonic-gate 
98037c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In viewconf\n");
98047c478bd9Sstevel@tonic-gate 
98057c478bd9Sstevel@tonic-gate 	/* get kernel configuration */
98067c478bd9Sstevel@tonic-gate 
98077c478bd9Sstevel@tonic-gate 	ret = readkconf(&conf);
98087c478bd9Sstevel@tonic-gate 	if (ret != IPQOS_CONF_SUCCESS) {
98097c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
98107c478bd9Sstevel@tonic-gate 	}
98117c478bd9Sstevel@tonic-gate 
98127c478bd9Sstevel@tonic-gate 	/* write out format version */
98137c478bd9Sstevel@tonic-gate 
98147c478bd9Sstevel@tonic-gate 	if (conf != NULL) {
98157c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "%s %d.%d\n\n", IPQOS_FMT_VERSION_STR,
98167c478bd9Sstevel@tonic-gate 		    IPQOS_CUR_FMT_MAJOR_VER, IPQOS_CUR_FMT_MINOR_VER);
98177c478bd9Sstevel@tonic-gate 	}
98187c478bd9Sstevel@tonic-gate 
98197c478bd9Sstevel@tonic-gate 	/* print each of the actions in the kernel config to stdout */
98207c478bd9Sstevel@tonic-gate 
98217c478bd9Sstevel@tonic-gate 	for (act = conf; act != NULL; act = act->next) {
98227c478bd9Sstevel@tonic-gate 		ret = printaction(stdout, act, viewall, 0);
98237c478bd9Sstevel@tonic-gate 		if (ret != IPQOS_CONF_SUCCESS) {
98247c478bd9Sstevel@tonic-gate 			free_actions(conf);
98257c478bd9Sstevel@tonic-gate 			return (ret);
98267c478bd9Sstevel@tonic-gate 		}
98277c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "\n");
98287c478bd9Sstevel@tonic-gate 	}
98297c478bd9Sstevel@tonic-gate 
98307c478bd9Sstevel@tonic-gate 	free_actions(conf);
98317c478bd9Sstevel@tonic-gate 
98327c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
98337c478bd9Sstevel@tonic-gate }
98347c478bd9Sstevel@tonic-gate 
98357c478bd9Sstevel@tonic-gate 
98367c478bd9Sstevel@tonic-gate /*
98377c478bd9Sstevel@tonic-gate  * debug function that reads the config file and prints it out after
98387c478bd9Sstevel@tonic-gate  * interpreting to stdout.
98397c478bd9Sstevel@tonic-gate  */
98407c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
98417c478bd9Sstevel@tonic-gate static int
98427c478bd9Sstevel@tonic-gate viewcfile(char *cfile)
98437c478bd9Sstevel@tonic-gate {
98447c478bd9Sstevel@tonic-gate 
98457c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *conf;
98467c478bd9Sstevel@tonic-gate 	ipqos_conf_action_t *act;
98477c478bd9Sstevel@tonic-gate 	int res;
98487c478bd9Sstevel@tonic-gate 	FILE *ifp;
98497c478bd9Sstevel@tonic-gate 	int viewall = 1;
98507c478bd9Sstevel@tonic-gate 
98517c478bd9Sstevel@tonic-gate 	IPQOSCDBG0(L0, "In viewcfile\n");
98527c478bd9Sstevel@tonic-gate 	ifp = fopen(cfile, "r");
98537c478bd9Sstevel@tonic-gate 	if (ifp == NULL) {
98547c478bd9Sstevel@tonic-gate 		ipqos_msg(MT_ERROR, gettext("Opening file %s for read: %s.\n"),
98557c478bd9Sstevel@tonic-gate 		    cfile, strerror(errno));
98567c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
98577c478bd9Sstevel@tonic-gate 	}
98587c478bd9Sstevel@tonic-gate 
98597c478bd9Sstevel@tonic-gate 	res = readconf(ifp, &conf);
98607c478bd9Sstevel@tonic-gate 	if (res != IPQOS_CONF_SUCCESS) {
98617c478bd9Sstevel@tonic-gate 		free(ifp);
98627c478bd9Sstevel@tonic-gate 		return (IPQOS_CONF_ERR);
98637c478bd9Sstevel@tonic-gate 	}
98647c478bd9Sstevel@tonic-gate 
98657c478bd9Sstevel@tonic-gate 	/* print each of the actions in the kernel config to stdout */
98667c478bd9Sstevel@tonic-gate 	for (act = conf; act != NULL; act = act->next) {
98677c478bd9Sstevel@tonic-gate 		res = printaction(stdout, act, viewall, 0);
98687c478bd9Sstevel@tonic-gate 		if (res != IPQOS_CONF_SUCCESS) {
98697c478bd9Sstevel@tonic-gate 			free(ifp);
98707c478bd9Sstevel@tonic-gate 			return (res);
98717c478bd9Sstevel@tonic-gate 		}
98727c478bd9Sstevel@tonic-gate 
98737c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "\n");
98747c478bd9Sstevel@tonic-gate 	}
98757c478bd9Sstevel@tonic-gate 
98767c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
98777c478bd9Sstevel@tonic-gate 
98787c478bd9Sstevel@tonic-gate 
98797c478bd9Sstevel@tonic-gate 	return (IPQOS_CONF_SUCCESS);
98807c478bd9Sstevel@tonic-gate }
98817c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
98827c478bd9Sstevel@tonic-gate 
98837c478bd9Sstevel@tonic-gate static void
98847c478bd9Sstevel@tonic-gate usage(void)
98857c478bd9Sstevel@tonic-gate {
98867c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("usage:\n"
98877c478bd9Sstevel@tonic-gate 	    "\tipqosconf [-sv] -a file|-\n"
98887c478bd9Sstevel@tonic-gate 	    "\tipqosconf -c\n"
98897c478bd9Sstevel@tonic-gate 	    "\tipqosconf -l\n"
98907c478bd9Sstevel@tonic-gate 	    "\tipqosconf -L\n"
98917c478bd9Sstevel@tonic-gate 	    "\tipqosconf -f\n"));
98927c478bd9Sstevel@tonic-gate }
98937c478bd9Sstevel@tonic-gate 
98947c478bd9Sstevel@tonic-gate int
98957c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
98967c478bd9Sstevel@tonic-gate {
98977c478bd9Sstevel@tonic-gate 
98987c478bd9Sstevel@tonic-gate 	int c;
98997c478bd9Sstevel@tonic-gate 	char *ifile = NULL;
99007c478bd9Sstevel@tonic-gate 	int args;
99017c478bd9Sstevel@tonic-gate 	int ret;
99027c478bd9Sstevel@tonic-gate 	int cmd;
99037c478bd9Sstevel@tonic-gate 	int viewall = 0;
99047c478bd9Sstevel@tonic-gate 	int lfp;
99057c478bd9Sstevel@tonic-gate 
99067c478bd9Sstevel@tonic-gate 	/* init global flags */
99077c478bd9Sstevel@tonic-gate 	use_syslog = verbose = 0;
99087c478bd9Sstevel@tonic-gate 
99097c478bd9Sstevel@tonic-gate 	/* init current line number */
99107c478bd9Sstevel@tonic-gate 	lineno = 0;
99117c478bd9Sstevel@tonic-gate 
99127c478bd9Sstevel@tonic-gate 	/* setup internationalisation */
99137c478bd9Sstevel@tonic-gate 
99147c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
99157c478bd9Sstevel@tonic-gate #if	!defined(TEXT_DOMAIN)
99167c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
99177c478bd9Sstevel@tonic-gate #endif
99187c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
99197c478bd9Sstevel@tonic-gate 
99207c478bd9Sstevel@tonic-gate 	/* setup syslog parameters */
99217c478bd9Sstevel@tonic-gate 	openlog("ipqosconf", 0, LOG_USER);
99227c478bd9Sstevel@tonic-gate 
99237c478bd9Sstevel@tonic-gate 	args = 0;
99247c478bd9Sstevel@tonic-gate 
99257c478bd9Sstevel@tonic-gate /* enable debug options */
99267c478bd9Sstevel@tonic-gate 
99277c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
99287c478bd9Sstevel@tonic-gate #define	DBGOPTS	"rz:"
99297c478bd9Sstevel@tonic-gate #else
99307c478bd9Sstevel@tonic-gate #define	DBGOPTS
99317c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
99327c478bd9Sstevel@tonic-gate 
99337c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "sca:vflL" DBGOPTS)) != EOF) {
99347c478bd9Sstevel@tonic-gate 		switch (c) {
99357c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
99367c478bd9Sstevel@tonic-gate 			case 'z':
99377c478bd9Sstevel@tonic-gate 				cmd = -1;
99387c478bd9Sstevel@tonic-gate 				ifile = optarg;
99397c478bd9Sstevel@tonic-gate 				if (*ifile == '\0') {
99407c478bd9Sstevel@tonic-gate 					usage();
99417c478bd9Sstevel@tonic-gate 					exit(1);
99427c478bd9Sstevel@tonic-gate 				}
99437c478bd9Sstevel@tonic-gate 				args++;
99447c478bd9Sstevel@tonic-gate 				break;
99457c478bd9Sstevel@tonic-gate 			case 'r':
99467c478bd9Sstevel@tonic-gate 				force_rback++;
99477c478bd9Sstevel@tonic-gate 				break;
99487c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
99497c478bd9Sstevel@tonic-gate 			case 'c':
99507c478bd9Sstevel@tonic-gate 				cmd = IPQOS_CONF_COMMIT;
99517c478bd9Sstevel@tonic-gate 				args++;
99527c478bd9Sstevel@tonic-gate 				break;
99537c478bd9Sstevel@tonic-gate 			case 'a':
99547c478bd9Sstevel@tonic-gate 				cmd = IPQOS_CONF_APPLY;
99557c478bd9Sstevel@tonic-gate 				ifile = optarg;
99567c478bd9Sstevel@tonic-gate 				if (*ifile == '\0') {
99577c478bd9Sstevel@tonic-gate 					usage();
99587c478bd9Sstevel@tonic-gate 					exit(1);
99597c478bd9Sstevel@tonic-gate 				}
99607c478bd9Sstevel@tonic-gate 				args++;
99617c478bd9Sstevel@tonic-gate 				break;
99627c478bd9Sstevel@tonic-gate 			case 'f':
99637c478bd9Sstevel@tonic-gate 				cmd = IPQOS_CONF_FLUSH;
99647c478bd9Sstevel@tonic-gate 				args++;
99657c478bd9Sstevel@tonic-gate 				break;
99667c478bd9Sstevel@tonic-gate 			case 'l':
99677c478bd9Sstevel@tonic-gate 				cmd = IPQOS_CONF_VIEW;
99687c478bd9Sstevel@tonic-gate 				args++;
99697c478bd9Sstevel@tonic-gate 				break;
99707c478bd9Sstevel@tonic-gate 			case 'L':
99717c478bd9Sstevel@tonic-gate 				cmd = IPQOS_CONF_VIEW;
99727c478bd9Sstevel@tonic-gate 				viewall++;
99737c478bd9Sstevel@tonic-gate 				args++;
99747c478bd9Sstevel@tonic-gate 				break;
99757c478bd9Sstevel@tonic-gate 			case 'v':
99767c478bd9Sstevel@tonic-gate 				verbose++;
99777c478bd9Sstevel@tonic-gate 				break;
99787c478bd9Sstevel@tonic-gate 			case 's':
99797c478bd9Sstevel@tonic-gate 				use_syslog++;
99807c478bd9Sstevel@tonic-gate 				break;
99817c478bd9Sstevel@tonic-gate 			case '?':
99827c478bd9Sstevel@tonic-gate 				usage();
99837c478bd9Sstevel@tonic-gate 				return (1);
99847c478bd9Sstevel@tonic-gate 		}
99857c478bd9Sstevel@tonic-gate 	}
99867c478bd9Sstevel@tonic-gate 
99877c478bd9Sstevel@tonic-gate 	/*
99887c478bd9Sstevel@tonic-gate 	 * dissallow non-option args, > 1 cmd args and syslog/verbose flags set
99897c478bd9Sstevel@tonic-gate 	 * for anything but apply.
99907c478bd9Sstevel@tonic-gate 	 */
99917c478bd9Sstevel@tonic-gate 	if (optind != argc || args > 1 ||
99927c478bd9Sstevel@tonic-gate 	    use_syslog && cmd != IPQOS_CONF_APPLY ||
99937c478bd9Sstevel@tonic-gate 	    verbose && cmd != IPQOS_CONF_APPLY) {
99947c478bd9Sstevel@tonic-gate 		usage();
99957c478bd9Sstevel@tonic-gate 		exit(1);
99967c478bd9Sstevel@tonic-gate 	}
99977c478bd9Sstevel@tonic-gate 
99987c478bd9Sstevel@tonic-gate 	/* if no cmd option then show config */
99997c478bd9Sstevel@tonic-gate 
100007c478bd9Sstevel@tonic-gate 	if (args == 0) {
100017c478bd9Sstevel@tonic-gate 		cmd = IPQOS_CONF_VIEW;
100027c478bd9Sstevel@tonic-gate 	}
100037c478bd9Sstevel@tonic-gate 
100047c478bd9Sstevel@tonic-gate 	/* stop concurrent ipqosconf invocations */
100057c478bd9Sstevel@tonic-gate 	lfp = lock();
100067c478bd9Sstevel@tonic-gate 	if (lfp == -1) {
100077c478bd9Sstevel@tonic-gate 		exit(1);
100087c478bd9Sstevel@tonic-gate 	}
100097c478bd9Sstevel@tonic-gate 
100107c478bd9Sstevel@tonic-gate 	switch (cmd) {
100117c478bd9Sstevel@tonic-gate #ifdef	_IPQOS_CONF_DEBUG
100127c478bd9Sstevel@tonic-gate 		case -1:
100137c478bd9Sstevel@tonic-gate 			ret = viewcfile(ifile);
100147c478bd9Sstevel@tonic-gate 			break;
100157c478bd9Sstevel@tonic-gate #endif	/* _IPQOS_CONF_DEBUG */
100167c478bd9Sstevel@tonic-gate 		case IPQOS_CONF_APPLY:
100177c478bd9Sstevel@tonic-gate 			ret = applyconf(ifile);
100187c478bd9Sstevel@tonic-gate 			break;
100197c478bd9Sstevel@tonic-gate 		case IPQOS_CONF_COMMIT:
100207c478bd9Sstevel@tonic-gate 			ret = commitconf();
100217c478bd9Sstevel@tonic-gate 			break;
100227c478bd9Sstevel@tonic-gate 		case IPQOS_CONF_VIEW:
100237c478bd9Sstevel@tonic-gate 			ret = viewconf(viewall);
100247c478bd9Sstevel@tonic-gate 			break;
100257c478bd9Sstevel@tonic-gate 		case IPQOS_CONF_FLUSH:
100267c478bd9Sstevel@tonic-gate 			ret = flushconf();
100277c478bd9Sstevel@tonic-gate 			break;
100287c478bd9Sstevel@tonic-gate 	}
100297c478bd9Sstevel@tonic-gate 
100307c478bd9Sstevel@tonic-gate 	(void) unlock(lfp);
100317c478bd9Sstevel@tonic-gate 
100327c478bd9Sstevel@tonic-gate 	return (ret);
100337c478bd9Sstevel@tonic-gate 
100347c478bd9Sstevel@tonic-gate }
10035