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 /*
23*4bc0a2efScasper * 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 */
2527c478bd9Sstevel@tonic-gate #define 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
ipqos_msg(enum msg_type msgt,char * format,...)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
modify_params(char * action_name,nvlist_t ** nvl,int module_version,boolean_t stats_enable)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
add_class(char * action_name,char * class_name,int module_version,boolean_t stats_enable,char * first_action)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
modify_class(char * action_name,char * class_name,int module_version,boolean_t stats_enable,char * first_action,enum ipp_flags flags)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
remove_class(char * action_name,char * class_name,int module_version,enum ipp_flags flags)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
add_filter(char * action_name,ipqos_conf_filter_t * flt,int module_version)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
modify_filter(char * action_name,ipqos_conf_filter_t * flt,int module_version)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
remove_filter(char * action_name,char * filter_name,int instance,int module_version)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
add_orig_ipqosconf(nvlist_t * nvl)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
arrays_equal(int array1[],int array2[],uint32_t size)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
diffclass(ipqos_conf_class_t * old,ipqos_conf_class_t * new)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
diffparams(ipqos_conf_params_t * old,ipqos_conf_params_t * new,char * module_name)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
difffilter(ipqos_conf_filter_t * old,ipqos_conf_filter_t * new,char * module_name)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
mark_classes_filters_del(ipqos_conf_action_t * action)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
mark_classes_filters_new(ipqos_conf_action_t * action)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
mark_config_new(ipqos_conf_action_t * conf)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
diffconf(ipqos_conf_action_t * old,ipqos_conf_action_t * new)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
diffaction(ipqos_conf_action_t * old,ipqos_conf_action_t * new)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
diffclasses(ipqos_conf_action_t * old,ipqos_conf_action_t * new)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
difffilters(ipqos_conf_action_t * old,ipqos_conf_action_t * new)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
diffnvlists(nvlist_t * old,nvlist_t * new,char * module_name,int * pdiff,place_t place)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
applydiff(ipqos_conf_action_t * actions,ipqos_conf_action_t * old_actions)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
add_items(ipqos_conf_action_t * actions,boolean_t rem_undo)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
add_item(ipqos_conf_action_t * actions,boolean_t rem_undo)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
add_action(ipqos_conf_action_t * act)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
add_filters(ipqos_conf_filter_t * filters,char * action,int module_version,boolean_t rem_undo)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
add_classes(ipqos_conf_class_t * classes,char * action,int module_version,boolean_t rem_undo)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
remove_items(ipqos_conf_action_t * actions,boolean_t add_undo)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
remove_item(ipqos_conf_action_t * act,boolean_t add_undo)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
modify_items(ipqos_conf_action_t * actions)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
undo_modifys(ipqos_conf_action_t * oactions,ipqos_conf_action_t * nactions)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
rollback(ipqos_conf_action_t * actions,ipqos_conf_action_t * old_actions)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
printuser(FILE * fp,uid_t uid)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
printrange(FILE * fp,uint32_t start,uint32_t end)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
print_int_array(FILE * fp,int arr[],uint32_t size,int llimit,int ulimit,str_val_nd_t * enum_nvs,int tab_inserts)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
printproto(FILE * fp,uint8_t proto)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
printifname(FILE * fp,int ifindex)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
printenum(FILE * fp,uint32_t val,str_val_nd_t * enum_nvs)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
printport(FILE * fp,uint16_t port)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
printnvlist(FILE * fp,char * module,nvlist_t * nvl,int printall,ipqos_conf_filter_t * flt,int tab_inserts,place_t place)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
printparams(FILE * fp,char * module,ipqos_conf_params_t * params,int printall,int tab_inserts)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
print_action_nm(FILE * fp,char * action_nm)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
printclass(FILE * fp,ipqos_conf_class_t * class,int printall,int tab_inserts)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 *
get_originator_nm(uint32_t origid)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
printfilter(FILE * fp,char * module,ipqos_conf_filter_t ** filter,int printall,int tab_inserts)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 *
quote_ws_string(const char * str)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
printaction(FILE * fp,ipqos_conf_action_t * action,int printall,int tab_inserts)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
list_end(ipqos_list_el_t ** listp,ipqos_list_el_t *** lendpp)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
add_to_list(ipqos_list_el_t ** listp,ipqos_list_el_t * el)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
masktocidr(int af,in6_addr_t * mask)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
setmask(int prefix_len,in6_addr_t * addr,int af)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 *
find_nvpair(nvlist_t * nvl,char * name)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 *
prepend_module_name(char * name,char * module)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
valid_name(char * name)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
get_str_val_value_range(str_val_nd_t * svnp,int * min,int * max)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
add_str_val_entry(str_val_nd_t ** sv_entrys,char * string,uint32_t val)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
free_str_val_entrys(str_val_nd_t * sv_entrys)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
str_val_list_lookup(str_val_nd_t * svs,char * string,uint32_t * val)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
readuser(char * str,uid_t * uid)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
readrange(char * range_st,int * lower,int * upper)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
read_int_array(FILE * fp,char * first_token,int ** arrp,uint32_t arr_size,int llimit,int ulimit,str_val_nd_t * enum_nvs)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
readllong(char * str,long long * llp,char ** lo)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
readuint8(char * str,uint8_t * ui8,char ** lo)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
readuint16(char * str,uint16_t * ui16,char ** lo)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
readint16(char * str,int16_t * i16,char ** lo)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
readint32(char * str,int * i32,char ** lo)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
readuint32(char * str,uint32_t * ui32,char ** lo)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
readifindex(char * ifname,int * ifindex)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
readbool(char * str,boolean_t * bool)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
readproto(char * proto_str,uint8_t * proto)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
readport(char * port_str,uint16_t * port)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
readtoken(FILE * fp,char ** token)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
48267c478bd9Sstevel@tonic-gate 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 *
read_enum_nvs(char * line,char * module_name)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
read_mapped_values(FILE * tfp,nvlist_t ** nvlp,char * module,char * mapped_list,int value)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
read_int_array_info(char * info_str,str_val_nd_t ** enum_nvs,uint32_t * size,int * lower,int * upper,char * module)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
read_enum_value(FILE * fp,char * first_token,str_val_nd_t * enum_vals,uint32_t * val)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
read_perm_items(int perm_filters,FILE * tfp,char * module_name,char *** perm_items,int * nitems)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
readtype(FILE * tfp,char * module_name,char * name,ipqos_nvtype_t * type,str_val_nd_t ** enum_nvps,char * dfltst,boolean_t allow_ipgpc_priv,place_t * place)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
readnvpair(FILE * cfp,FILE * tfp,nvlist_t ** nvlp,nvpair_t ** nvp,ipqos_nvtype_t * type,place_t place,char * module_name)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
readparams(FILE * cfp,FILE * tfp,char * module_name,ipqos_conf_params_t * params)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, ¶ms->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(¶ms->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
dup_class(ipqos_conf_class_t * src,ipqos_conf_class_t ** dst)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 *
alloc_class()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
free_class(ipqos_conf_class_t * cls)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 *
classexist(char * class_nm,ipqos_conf_class_t * classes)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 *
filterexist(char * filter_nm,int instance,ipqos_conf_filter_t * filters)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 *
alloc_filter()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
free_filter(ipqos_conf_filter_t * flt)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
dup_filter(ipqos_conf_filter_t * ofilter,ipqos_conf_filter_t ** nfilter,int af,int inv6,void * saddr,void * daddr,int inst)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 *
alloc_action()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
free_actions(ipqos_conf_action_t * actions)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 *
actionexist(char * action_name,ipqos_conf_action_t * actions)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
add_aref(ipqos_conf_act_ref_t ** arefs,char * field,char * action_name)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
free_arefs(ipqos_conf_act_ref_t * arefs)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
valid_aname(char * aname)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 *
validmod(char * module_name,int * openerr)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
readclass(FILE * cfp,char * module_name,ipqos_conf_class_t ** class,char ** perm_classes,int num_perm_classes)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
domultihome(ipqos_conf_filter_t * filter,ipqos_conf_filter_t ** flist,boolean_t last_retry)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
readfilter(FILE * cfp,FILE * tfp,char * module_name,ipqos_conf_filter_t ** filter,char ** perm_filters,int num_perm_filters)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
read_curl_begin(FILE * cfp)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
ver_str_to_int(char * version)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
read_tfile_ver(FILE * fp,char * version_tag,char * module_name)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
readaction(FILE * cfp,ipqos_conf_action_t ** action)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
actions_unique(ipqos_conf_action_t * actions,char ** name)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
in_cycle(ipqos_conf_action_t * action)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
validconf(ipqos_conf_action_t * actions,int userconf)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
read_cfile_ver(FILE * cfp,char * version_tag)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
readconf(FILE * cfp,ipqos_conf_action_t ** conf)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
readkconf(ipqos_conf_action_t ** conf)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
parse_kaction(nvlist_t * nvl,ipqos_actinfo_prm_t * ai_prm)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
parse_kparams(char * module,ipqos_conf_params_t * params,nvlist_t * nvl)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(¶ms->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
parse_kclass(ipqos_conf_class_t * class,nvlist_t * nvl)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
parse_kfilter(ipqos_conf_filter_t * filter,nvlist_t * nvl)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
virtual_action(char * action_name)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
flush(boolean_t * modified)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
atomic_flush(boolean_t force_flush)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
flushconf()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
in_string_table(char * stable[],int size,char * string)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
cleanup_string_table(char * ctable[],int size)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
retry_name_lookups(ipqos_conf_action_t * actions)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 */
92507c478bd9Sstevel@tonic-gate 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
writeconf(ipqos_conf_action_t * conf,char * dstpath)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
commitconf()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
rollback_recover(ipqos_conf_action_t * oconf)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
applyconf(char * ifile)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 */
9749*4bc0a2efScasper 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