17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 234bc0a2efScasper * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* enable debug output and some debug asserts */ 287c478bd9Sstevel@tonic-gate #undef _IPQOS_CONF_DEBUG 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <libintl.h> 337c478bd9Sstevel@tonic-gate #include <signal.h> 347c478bd9Sstevel@tonic-gate #include <strings.h> 357c478bd9Sstevel@tonic-gate #include <sys/nvpair.h> 367c478bd9Sstevel@tonic-gate #include <stdio.h> 377c478bd9Sstevel@tonic-gate #include <netinet/in.h> 387c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <sys/socket.h> 417c478bd9Sstevel@tonic-gate #include <limits.h> 427c478bd9Sstevel@tonic-gate #include <netdb.h> 437c478bd9Sstevel@tonic-gate #include <fcntl.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include <sys/stat.h> 467c478bd9Sstevel@tonic-gate #include <errno.h> 477c478bd9Sstevel@tonic-gate #include <libipp.h> 487c478bd9Sstevel@tonic-gate #include <ipp/ipp_config.h> 497c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/ipgpc.h> 507c478bd9Sstevel@tonic-gate #include <ipp/ipp.h> 517c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 527c478bd9Sstevel@tonic-gate #include <assert.h> 537c478bd9Sstevel@tonic-gate #endif 547c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 557c478bd9Sstevel@tonic-gate #include <syslog.h> 567c478bd9Sstevel@tonic-gate #include <stdarg.h> 577c478bd9Sstevel@tonic-gate #include <libintl.h> 587c478bd9Sstevel@tonic-gate #include <locale.h> 597c478bd9Sstevel@tonic-gate #include <pwd.h> 607c478bd9Sstevel@tonic-gate #include "ipqosconf.h" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #if defined(_IPQOS_CONF_DEBUG) 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* debug level */ 657c478bd9Sstevel@tonic-gate static int ipqosconf_dbg_flgs = 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate RBK | 697c478bd9Sstevel@tonic-gate MHME | 707c478bd9Sstevel@tonic-gate KRET | 717c478bd9Sstevel@tonic-gate DIFF | 727c478bd9Sstevel@tonic-gate APPLY | 737c478bd9Sstevel@tonic-gate L2 | 747c478bd9Sstevel@tonic-gate L1 | 757c478bd9Sstevel@tonic-gate L0 | 767c478bd9Sstevel@tonic-gate 0; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define IPQOSCDBG0(lvl, x)\ 817c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x) 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #define IPQOSCDBG1(lvl, x, y)\ 857c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x, y) 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #define IPQOSCDBG2(lvl, x, y, z)\ 897c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x, y, z) 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate #define IPQOSCDBG3(lvl, x, y, z, a)\ 937c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x, y, z, a) 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #define IPQOSCDBG4(lvl, x, y, z, a, b)\ 977c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x, y, z, a, b) 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #define IPQOSCDBG5(lvl, x, y, z, a, b, c)\ 1017c478bd9Sstevel@tonic-gate if (lvl & ipqosconf_dbg_flgs)\ 1027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, x, y, z, a, b, c) 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate #else /* defined(_IPQOS_CONF_DEBUG) && !defined(lint) */ 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #define IPQOSCDBG0(lvl, x) 1077c478bd9Sstevel@tonic-gate #define IPQOSCDBG1(lvl, x, y) 1087c478bd9Sstevel@tonic-gate #define IPQOSCDBG2(lvl, x, y, z) 1097c478bd9Sstevel@tonic-gate #define IPQOSCDBG3(lvl, x, y, z, a) 1107c478bd9Sstevel@tonic-gate #define IPQOSCDBG4(lvl, x, y, z, a, b) 1117c478bd9Sstevel@tonic-gate #define IPQOSCDBG5(lvl, x, y, z, a, b, c) 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate #endif /* defined(_IPQOS_CONF_DEBUG) */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* function prototypes */ 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate static int modify_params(char *, nvlist_t **, int, boolean_t); 1207c478bd9Sstevel@tonic-gate static int add_class(char *, char *, int, boolean_t, char *); 1217c478bd9Sstevel@tonic-gate static int modify_class(char *, char *, int, boolean_t, char *, 1227c478bd9Sstevel@tonic-gate enum ipp_flags); 1237c478bd9Sstevel@tonic-gate static int remove_class(char *, char *, int, enum ipp_flags); 1247c478bd9Sstevel@tonic-gate static int add_filter(char *, ipqos_conf_filter_t *, int); 1257c478bd9Sstevel@tonic-gate static int modify_filter(char *, ipqos_conf_filter_t *, int); 1267c478bd9Sstevel@tonic-gate static int remove_filter(char *, char *, int, int); 1277c478bd9Sstevel@tonic-gate static boolean_t arrays_equal(int *, int *, uint32_t); 1287c478bd9Sstevel@tonic-gate static int diffclass(ipqos_conf_class_t *, ipqos_conf_class_t *); 1297c478bd9Sstevel@tonic-gate static int diffparams(ipqos_conf_params_t *, ipqos_conf_params_t *, char *); 1307c478bd9Sstevel@tonic-gate static int difffilter(ipqos_conf_filter_t *, ipqos_conf_filter_t *, char *); 1317c478bd9Sstevel@tonic-gate static int add_filters(ipqos_conf_filter_t *, char *, int, boolean_t); 1327c478bd9Sstevel@tonic-gate static int add_classes(ipqos_conf_class_t *, char *, int, boolean_t); 1337c478bd9Sstevel@tonic-gate static int modify_items(ipqos_conf_action_t *); 1347c478bd9Sstevel@tonic-gate static int add_items(ipqos_conf_action_t *, boolean_t); 1357c478bd9Sstevel@tonic-gate static int add_item(ipqos_conf_action_t *, boolean_t); 1367c478bd9Sstevel@tonic-gate static int remove_items(ipqos_conf_action_t *, boolean_t); 1377c478bd9Sstevel@tonic-gate static int remove_item(ipqos_conf_action_t *, boolean_t); 1387c478bd9Sstevel@tonic-gate static int undo_modifys(ipqos_conf_action_t *, ipqos_conf_action_t *); 1397c478bd9Sstevel@tonic-gate static int applydiff(ipqos_conf_action_t *, ipqos_conf_action_t *); 1407c478bd9Sstevel@tonic-gate static int rollback(ipqos_conf_action_t *, ipqos_conf_action_t *); 1417c478bd9Sstevel@tonic-gate static int rollback_recover(ipqos_conf_action_t *); 1427c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *classexist(char *, ipqos_conf_class_t *); 1437c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *filterexist(char *, int, ipqos_conf_filter_t *); 1447c478bd9Sstevel@tonic-gate static ipqos_conf_action_t *actionexist(char *, ipqos_conf_action_t *); 1457c478bd9Sstevel@tonic-gate static int diffnvlists(nvlist_t *, nvlist_t *, char *, int *, place_t); 1467c478bd9Sstevel@tonic-gate static int diffaction(ipqos_conf_action_t *, ipqos_conf_action_t *); 1477c478bd9Sstevel@tonic-gate static int diffconf(ipqos_conf_action_t *, ipqos_conf_action_t *); 1487c478bd9Sstevel@tonic-gate static int readllong(char *, long long *, char **); 1497c478bd9Sstevel@tonic-gate static int readuint8(char *, uint8_t *, char **); 1507c478bd9Sstevel@tonic-gate static int readuint16(char *, uint16_t *, char **); 1517c478bd9Sstevel@tonic-gate static int readint16(char *, int16_t *, char **); 1527c478bd9Sstevel@tonic-gate static int readint32(char *, int *, char **); 1537c478bd9Sstevel@tonic-gate static int readuint32(char *, uint32_t *, char **); 1547c478bd9Sstevel@tonic-gate static int readbool(char *, boolean_t *); 1557c478bd9Sstevel@tonic-gate static void setmask(int, in6_addr_t *, int); 1567c478bd9Sstevel@tonic-gate static int readtoken(FILE *, char **); 1577c478bd9Sstevel@tonic-gate static nvpair_t *find_nvpair(nvlist_t *, char *); 1587c478bd9Sstevel@tonic-gate static char *prepend_module_name(char *, char *); 1597c478bd9Sstevel@tonic-gate static int readnvpair(FILE *, FILE *, nvlist_t **, nvpair_t **, 1607c478bd9Sstevel@tonic-gate ipqos_nvtype_t *, place_t, char *); 1617c478bd9Sstevel@tonic-gate static int add_aref(ipqos_conf_act_ref_t **, char *, char *); 1627c478bd9Sstevel@tonic-gate static int readparams(FILE *, FILE *, char *, ipqos_conf_params_t *); 1637c478bd9Sstevel@tonic-gate static int readclass(FILE *, char *, ipqos_conf_class_t **, char **, int); 1647c478bd9Sstevel@tonic-gate static int readfilter(FILE *, FILE *, char *, ipqos_conf_filter_t **, char **, 1657c478bd9Sstevel@tonic-gate int); 1667c478bd9Sstevel@tonic-gate static FILE *validmod(char *, int *); 1677c478bd9Sstevel@tonic-gate static int readaction(FILE *, ipqos_conf_action_t **); 1687c478bd9Sstevel@tonic-gate static int actions_unique(ipqos_conf_action_t *, char **); 1697c478bd9Sstevel@tonic-gate static int validconf(ipqos_conf_action_t *, int); 1707c478bd9Sstevel@tonic-gate static int readconf(FILE *, ipqos_conf_action_t **); 1717c478bd9Sstevel@tonic-gate static int flush(boolean_t *); 1727c478bd9Sstevel@tonic-gate static int atomic_flush(boolean_t); 1737c478bd9Sstevel@tonic-gate static int flushconf(); 1747c478bd9Sstevel@tonic-gate static int writeconf(ipqos_conf_action_t *, char *); 1757c478bd9Sstevel@tonic-gate static int commitconf(); 1767c478bd9Sstevel@tonic-gate static int applyconf(char *ifile); 1777c478bd9Sstevel@tonic-gate static int block_all_signals(); 1787c478bd9Sstevel@tonic-gate static int restore_all_signals(); 1797c478bd9Sstevel@tonic-gate static int unlock(int fd); 1807c478bd9Sstevel@tonic-gate static int lock(); 1817c478bd9Sstevel@tonic-gate static int viewconf(int); 1827c478bd9Sstevel@tonic-gate static void usage(); 1837c478bd9Sstevel@tonic-gate static int valid_name(char *); 1847c478bd9Sstevel@tonic-gate static int in_cycle(ipqos_conf_action_t *); 1857c478bd9Sstevel@tonic-gate static int readtype(FILE *, char *, char *, ipqos_nvtype_t *, str_val_nd_t **, 1867c478bd9Sstevel@tonic-gate char *, boolean_t, place_t *); 1877c478bd9Sstevel@tonic-gate static int read_int_array_info(char *, str_val_nd_t **, uint32_t *, int *, 1887c478bd9Sstevel@tonic-gate int *, char *); 1897c478bd9Sstevel@tonic-gate static str_val_nd_t *read_enum_nvs(char *, char *); 1907c478bd9Sstevel@tonic-gate static int add_str_val_entry(str_val_nd_t **, char *, uint32_t); 1917c478bd9Sstevel@tonic-gate static void free_str_val_entrys(str_val_nd_t *); 1927c478bd9Sstevel@tonic-gate static void get_str_val_value_range(str_val_nd_t *, int *, int *); 1937c478bd9Sstevel@tonic-gate static int read_enum_value(FILE *, char *, str_val_nd_t *, uint32_t *); 1947c478bd9Sstevel@tonic-gate static int read_mapped_values(FILE *, nvlist_t **, char *, char *, 1957c478bd9Sstevel@tonic-gate int); 1967c478bd9Sstevel@tonic-gate static int read_int_array(FILE *, char *, int **, uint32_t, int, int, 1977c478bd9Sstevel@tonic-gate str_val_nd_t *); 1987c478bd9Sstevel@tonic-gate static int str_val_list_lookup(str_val_nd_t *, char *, uint32_t *); 1997c478bd9Sstevel@tonic-gate static int parse_kparams(char *, ipqos_conf_params_t *, nvlist_t *); 2007c478bd9Sstevel@tonic-gate static int parse_kclass(ipqos_conf_class_t *, nvlist_t *); 2017c478bd9Sstevel@tonic-gate static int parse_kfilter(ipqos_conf_filter_t *, nvlist_t *); 2027c478bd9Sstevel@tonic-gate static int parse_kaction(nvlist_t *, ipqos_actinfo_prm_t *); 2037c478bd9Sstevel@tonic-gate static int readkconf(ipqos_conf_action_t **); 2047c478bd9Sstevel@tonic-gate static void print_int_array(FILE *, int *, uint32_t, int, int, str_val_nd_t *, 2057c478bd9Sstevel@tonic-gate int); 2067c478bd9Sstevel@tonic-gate static void printrange(FILE *fp, uint32_t, uint32_t); 2077c478bd9Sstevel@tonic-gate static void printenum(FILE *, uint32_t, str_val_nd_t *); 2087c478bd9Sstevel@tonic-gate static void printproto(FILE *, uint8_t); 2097c478bd9Sstevel@tonic-gate static void printport(FILE *, uint16_t); 2107c478bd9Sstevel@tonic-gate static int printnvlist(FILE *, char *, nvlist_t *, int, ipqos_conf_filter_t *, 2117c478bd9Sstevel@tonic-gate int, place_t); 2127c478bd9Sstevel@tonic-gate static int virtual_action(char *); 2137c478bd9Sstevel@tonic-gate static void free_arefs(ipqos_conf_act_ref_t *); 2147c478bd9Sstevel@tonic-gate static void print_action_nm(FILE *, char *); 2157c478bd9Sstevel@tonic-gate static int add_orig_ipqosconf(nvlist_t *); 2167c478bd9Sstevel@tonic-gate static char *get_originator_nm(uint32_t); 2177c478bd9Sstevel@tonic-gate static void mark_classes_filters_new(ipqos_conf_action_t *); 2187c478bd9Sstevel@tonic-gate static void mark_classes_filters_del(ipqos_conf_action_t *); 2197c478bd9Sstevel@tonic-gate static void mark_config_new(ipqos_conf_action_t *); 2207c478bd9Sstevel@tonic-gate static int printifname(FILE *, int); 2217c478bd9Sstevel@tonic-gate static int readifindex(char *, int *); 2227c478bd9Sstevel@tonic-gate static void cleanup_string_table(char **, int); 2237c478bd9Sstevel@tonic-gate static int domultihome(ipqos_conf_filter_t *, ipqos_conf_filter_t **, 2247c478bd9Sstevel@tonic-gate boolean_t); 2257c478bd9Sstevel@tonic-gate static int dup_filter(ipqos_conf_filter_t *, ipqos_conf_filter_t **, int, int, 2267c478bd9Sstevel@tonic-gate void *, void *, int); 2277c478bd9Sstevel@tonic-gate static void free_actions(ipqos_conf_action_t *); 2287c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t *alloc_filter(); 2297c478bd9Sstevel@tonic-gate static void free_filter(ipqos_conf_filter_t *); 2307c478bd9Sstevel@tonic-gate static int read_curl_begin(FILE *); 2317c478bd9Sstevel@tonic-gate static ipqos_conf_class_t *alloc_class(void); 2327c478bd9Sstevel@tonic-gate static int diffclasses(ipqos_conf_action_t *old, ipqos_conf_action_t *new); 2337c478bd9Sstevel@tonic-gate static int difffilters(ipqos_conf_action_t *old, ipqos_conf_action_t *new); 2347c478bd9Sstevel@tonic-gate static int dup_class(ipqos_conf_class_t *src, ipqos_conf_class_t **dst); 2357c478bd9Sstevel@tonic-gate static int add_action(ipqos_conf_action_t *act); 2367c478bd9Sstevel@tonic-gate static int masktocidr(int af, in6_addr_t *mask); 2377c478bd9Sstevel@tonic-gate static int read_perm_items(int, FILE *, char *, char ***, int *); 2387c478bd9Sstevel@tonic-gate static int in_string_table(char *stable[], int size, char *string); 2397c478bd9Sstevel@tonic-gate static void list_end(ipqos_list_el_t **listp, ipqos_list_el_t ***lendpp); 2407c478bd9Sstevel@tonic-gate static void add_to_list(ipqos_list_el_t **listp, ipqos_list_el_t *el); 2417c478bd9Sstevel@tonic-gate static int read_cfile_ver(FILE *, char *); 2427c478bd9Sstevel@tonic-gate static char *quote_ws_string(const char *); 2437c478bd9Sstevel@tonic-gate static int read_tfile_ver(FILE *, char *, char *); 2447c478bd9Sstevel@tonic-gate static int ver_str_to_int(char *); 2457c478bd9Sstevel@tonic-gate static void printuser(FILE *fp, uid_t uid); 2467c478bd9Sstevel@tonic-gate static int readuser(char *str, uid_t *uid); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * macros to call list functions with the more complex list element type 2507c478bd9Sstevel@tonic-gate * cast to the skeletal type iqpos_list_el_t. 2517c478bd9Sstevel@tonic-gate */ 252*85280f08SToomas Soome #define GET_LIST_END(list, end)\ 2537c478bd9Sstevel@tonic-gate list_end((ipqos_list_el_t **)list, (ipqos_list_el_t ***)end) 2547c478bd9Sstevel@tonic-gate #define ADD_TO_LIST(list, el)\ 2557c478bd9Sstevel@tonic-gate add_to_list((ipqos_list_el_t **)list, (ipqos_list_el_t *)el) 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 2597c478bd9Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 2607c478bd9Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 2617c478bd9Sstevel@tonic-gate * strings for scanf-family functions below. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate #define QUOTE(x) #x 2647c478bd9Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* globals */ 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* table of supported parameter types and enum value */ 2707c478bd9Sstevel@tonic-gate static str_val_t nv_types[] = { 2717c478bd9Sstevel@tonic-gate {"uint8", IPQOS_DATA_TYPE_UINT8}, 2727c478bd9Sstevel@tonic-gate {"int16", IPQOS_DATA_TYPE_INT16}, 2737c478bd9Sstevel@tonic-gate {"uint16", IPQOS_DATA_TYPE_UINT16}, 2747c478bd9Sstevel@tonic-gate {"int32", IPQOS_DATA_TYPE_INT32}, 2757c478bd9Sstevel@tonic-gate {"uint32", IPQOS_DATA_TYPE_UINT32}, 2767c478bd9Sstevel@tonic-gate {"boolean", IPQOS_DATA_TYPE_BOOLEAN}, 2777c478bd9Sstevel@tonic-gate {"string", IPQOS_DATA_TYPE_STRING}, 2787c478bd9Sstevel@tonic-gate {"action", IPQOS_DATA_TYPE_ACTION}, 2797c478bd9Sstevel@tonic-gate {"address", IPQOS_DATA_TYPE_ADDRESS}, 2807c478bd9Sstevel@tonic-gate {"port", IPQOS_DATA_TYPE_PORT}, 2817c478bd9Sstevel@tonic-gate {"protocol", IPQOS_DATA_TYPE_PROTO}, 2827c478bd9Sstevel@tonic-gate {"enum", IPQOS_DATA_TYPE_ENUM}, 2837c478bd9Sstevel@tonic-gate {"ifname", IPQOS_DATA_TYPE_IFNAME}, 2847c478bd9Sstevel@tonic-gate {"mindex", IPQOS_DATA_TYPE_M_INDEX}, 2857c478bd9Sstevel@tonic-gate {"int_array", IPQOS_DATA_TYPE_INT_ARRAY}, 2867c478bd9Sstevel@tonic-gate {"user", IPQOS_DATA_TYPE_USER}, 2877c478bd9Sstevel@tonic-gate {"", 0} 2887c478bd9Sstevel@tonic-gate }; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* table of name to id mappings for originator field */ 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate static str_val_t originators[] = { 2937c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_PERMANENT, IPP_CONFIG_PERMANENT}, 2947c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_IPQOSCONF, IPP_CONFIG_IPQOSCONF}, 2957c478bd9Sstevel@tonic-gate {IPP_CONFIG_NAME_FTPCL, IPP_CONFIG_FTPCL}, 2967c478bd9Sstevel@tonic-gate {"", -1} 2977c478bd9Sstevel@tonic-gate }; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* current parse line */ 3007c478bd9Sstevel@tonic-gate static int lineno; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* verbose output flag */ 3037c478bd9Sstevel@tonic-gate static int verbose; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* use syslog for msg reporting flag */ 3067c478bd9Sstevel@tonic-gate static int use_syslog; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * flag used to indicate that a rollback should be carried out regardless. 3117c478bd9Sstevel@tonic-gate * Only settable during debug. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate static int force_rback = 0; 3147c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * delivers messages to either syslog or stderr, dependant upon the 3187c478bd9Sstevel@tonic-gate * the state of the flags use_syslog and verbose. The type 3197c478bd9Sstevel@tonic-gate * of the msg as given in msg_type is indicated in the output msg. 3207c478bd9Sstevel@tonic-gate * 3217c478bd9Sstevel@tonic-gate * valid message types are: 3227c478bd9Sstevel@tonic-gate * o MT_ERROR (standard error message) 3237c478bd9Sstevel@tonic-gate * o MT_ENOSTR (error message with system error string appended) 3247c478bd9Sstevel@tonic-gate * o MT_WARNING (warning message) 3257c478bd9Sstevel@tonic-gate * o MT_LOG (logging message) 3267c478bd9Sstevel@tonic-gate * 3277c478bd9Sstevel@tonic-gate * Log messages only go to syslog. Warning messages only go to stderr 3287c478bd9Sstevel@tonic-gate * and only when the verbose flag is set. All other messages go by default 3297c478bd9Sstevel@tonic-gate * to the console; to syslog if syslog flag set, and to both if both 3307c478bd9Sstevel@tonic-gate * syslog and verbose are set. 3317c478bd9Sstevel@tonic-gate * 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 3347c478bd9Sstevel@tonic-gate static void 3357c478bd9Sstevel@tonic-gate ipqos_msg(enum msg_type msgt, char *format, ...) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate va_list ap; 3387c478bd9Sstevel@tonic-gate char str_buf[IPQOS_MSG_BUF_SZ]; 3397c478bd9Sstevel@tonic-gate char fmt_buf[IPQOS_MSG_BUF_SZ]; 3407c478bd9Sstevel@tonic-gate char *cp; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In ipqos_msg:\n"); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate va_start(ap, format); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* 3477c478bd9Sstevel@tonic-gate * send msgs to syslog if use_syslog set (except warning msgs), 3487c478bd9Sstevel@tonic-gate * or a log msg. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate if ((use_syslog && (msgt != MT_WARNING)) || msgt == MT_LOG) { 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* fill in format string */ 3537c478bd9Sstevel@tonic-gate (void) vsnprintf(str_buf, IPQOS_MSG_BUF_SZ, format, ap); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate * print message to syslog with appropriate severity 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate if (msgt == MT_ERROR) { 3597c478bd9Sstevel@tonic-gate syslog(LOG_ERR, str_buf); 3607c478bd9Sstevel@tonic-gate } else if (msgt == MT_LOG) { 3617c478bd9Sstevel@tonic-gate syslog(LOG_INFO, str_buf); 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * for errno message type suffix with %m for syslog to 3647c478bd9Sstevel@tonic-gate * interpret. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate } else if (msgt == MT_ENOSTR) { 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * remove any newline in message parameter. 3697c478bd9Sstevel@tonic-gate * syslog will reapply a newline for us later. 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate if ((cp = strchr(str_buf, '\n')) != NULL) 3727c478bd9Sstevel@tonic-gate *cp = '\0'; 3737c478bd9Sstevel@tonic-gate (void) strlcat(str_buf, ": %m", IPQOS_MSG_BUF_SZ); 3747c478bd9Sstevel@tonic-gate syslog(LOG_ERR, str_buf); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * send msgs to stderr if use_syslog not set (except log msgs), or 3807c478bd9Sstevel@tonic-gate * if verbose set. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate if ((!use_syslog && (msgt != MT_LOG)) || (verbose)) { 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * prefix message with appropriate severity string 3867c478bd9Sstevel@tonic-gate */ 3877c478bd9Sstevel@tonic-gate if (msgt == MT_ERROR) { 3887c478bd9Sstevel@tonic-gate (void) strlcpy(fmt_buf, gettext("Error: "), 3897c478bd9Sstevel@tonic-gate IPQOS_MSG_BUF_SZ); 3907c478bd9Sstevel@tonic-gate } else if (msgt == MT_WARNING) { 3917c478bd9Sstevel@tonic-gate if (!verbose) { /* don't show warn msg if !verbose */ 3927c478bd9Sstevel@tonic-gate va_end(ap); 3937c478bd9Sstevel@tonic-gate return; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate (void) strlcpy(fmt_buf, gettext("Warning: "), 3967c478bd9Sstevel@tonic-gate IPQOS_MSG_BUF_SZ); 3977c478bd9Sstevel@tonic-gate } else if (msgt == MT_ENOSTR) { 3987c478bd9Sstevel@tonic-gate (void) strlcpy(fmt_buf, gettext("Error: "), 3997c478bd9Sstevel@tonic-gate IPQOS_MSG_BUF_SZ); 4007c478bd9Sstevel@tonic-gate } else if (msgt == MT_LOG) { 4017c478bd9Sstevel@tonic-gate (void) strlcpy(fmt_buf, gettext("Notice: "), 4027c478bd9Sstevel@tonic-gate IPQOS_MSG_BUF_SZ); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate (void) strlcat(fmt_buf, format, IPQOS_MSG_BUF_SZ); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * for errno message type suffix message with errno string 4087c478bd9Sstevel@tonic-gate */ 4097c478bd9Sstevel@tonic-gate if (msgt == MT_ENOSTR) { 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * get rid of any newline in passed message. 4127c478bd9Sstevel@tonic-gate * we'll apply another later. 4137c478bd9Sstevel@tonic-gate */ 4147c478bd9Sstevel@tonic-gate if ((cp = strchr(fmt_buf, '\n')) != NULL) 4157c478bd9Sstevel@tonic-gate *cp = '\0'; 4167c478bd9Sstevel@tonic-gate (void) strlcat(fmt_buf, ": ", IPQOS_MSG_BUF_SZ); 4177c478bd9Sstevel@tonic-gate (void) strlcat(fmt_buf, strerror(errno), 4187c478bd9Sstevel@tonic-gate IPQOS_MSG_BUF_SZ); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * append a newline to message if not one already. 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate if ((cp = strchr(fmt_buf, '\n')) == NULL) 4257c478bd9Sstevel@tonic-gate (void) strlcat(fmt_buf, "\n", IPQOS_MSG_BUF_SZ); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt_buf, ap); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate va_end(ap); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* **************** kernel filter/class/params manipulation fns *********** */ 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * modify the kernel parameters of the action action_nm using the nvlist 4387c478bd9Sstevel@tonic-gate * parameter nvl and setting the stats according to stats_enable. 4397c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate static int 4437c478bd9Sstevel@tonic-gate modify_params( 4447c478bd9Sstevel@tonic-gate char *action_name, 4457c478bd9Sstevel@tonic-gate nvlist_t **nvl, 4467c478bd9Sstevel@tonic-gate int module_version, 4477c478bd9Sstevel@tonic-gate boolean_t stats_enable) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate int res; 4517c478bd9Sstevel@tonic-gate int created = 0; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "In modify_params: action: %s\n", action_name); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* create nvlist if NULL */ 4567c478bd9Sstevel@tonic-gate if (*nvl == NULL) { 4577c478bd9Sstevel@tonic-gate created++; 4587c478bd9Sstevel@tonic-gate res = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0); 4597c478bd9Sstevel@tonic-gate if (res != 0) { 4607c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 4617c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* add params modify config type */ 4667c478bd9Sstevel@tonic-gate res = nvlist_add_byte(*nvl, IPP_CONFIG_TYPE, IPP_SET); 4677c478bd9Sstevel@tonic-gate if (res != 0) { 4687c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 4697c478bd9Sstevel@tonic-gate goto fail; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate /* 4737c478bd9Sstevel@tonic-gate * add module version 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(*nvl, IPP_MODULE_VERSION, 4767c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 4777c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 4787c478bd9Sstevel@tonic-gate goto fail; 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* add stats_enable */ 4827c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvl, IPP_ACTION_STATS_ENABLE, 4837c478bd9Sstevel@tonic-gate (uint32_t)stats_enable); 4847c478bd9Sstevel@tonic-gate if (res != 0) { 4857c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 4867c478bd9Sstevel@tonic-gate goto fail; 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* add ipqosconf as originator */ 4907c478bd9Sstevel@tonic-gate res = add_orig_ipqosconf(*nvl); 4917c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 4927c478bd9Sstevel@tonic-gate goto fail; 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* call lib to do modify */ 4967c478bd9Sstevel@tonic-gate res = ipp_action_modify(action_name, nvl, 0); 4977c478bd9Sstevel@tonic-gate if (res != 0) { 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* invalid parameters */ 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 5027c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 5037c478bd9Sstevel@tonic-gate gettext("Invalid parameters for action %s.\n"), 5047c478bd9Sstevel@tonic-gate action_name); 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate } else if (errno == ENOENT) { 5087c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 5097c478bd9Sstevel@tonic-gate gettext("Mandatory parameter missing for " 5107c478bd9Sstevel@tonic-gate "action %s.\n"), action_name); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate } else { /* unexpected error */ 5147c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed to modify action " 5157c478bd9Sstevel@tonic-gate "%s parameters: %s.\n"), action_name, 5167c478bd9Sstevel@tonic-gate strerror(errno)); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate goto fail; 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 5237c478bd9Sstevel@tonic-gate fail: 5247c478bd9Sstevel@tonic-gate if (created && *nvl != NULL) { 5257c478bd9Sstevel@tonic-gate nvlist_free(*nvl); 5267c478bd9Sstevel@tonic-gate *nvl = NULL; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * add a class to the kernel action action_name called class_name with 5337c478bd9Sstevel@tonic-gate * stats set according to stats_enable and the first action set to 5347c478bd9Sstevel@tonic-gate * first_action. 5357c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate static int 5387c478bd9Sstevel@tonic-gate add_class( 5397c478bd9Sstevel@tonic-gate char *action_name, 5407c478bd9Sstevel@tonic-gate char *class_name, 5417c478bd9Sstevel@tonic-gate int module_version, 5427c478bd9Sstevel@tonic-gate boolean_t stats_enable, 5437c478bd9Sstevel@tonic-gate char *first_action) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate nvlist_t *nvl; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate IPQOSCDBG4(APPLY, "add_class: action: %s, class: %s, " 5497c478bd9Sstevel@tonic-gate "first_action: %s, stats: %s\n", action_name, class_name, 5507c478bd9Sstevel@tonic-gate first_action, (stats_enable == B_TRUE ? "true" : "false")); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* create nvlist */ 5547c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 5557c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 5567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* add 'add class' config type */ 5607c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_ADD_CLASS) != 0) { 5617c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 5627c478bd9Sstevel@tonic-gate goto fail; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * add module version 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 5697c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 5707c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 5717c478bd9Sstevel@tonic-gate goto fail; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* add class name */ 5757c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) { 5767c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 5777c478bd9Sstevel@tonic-gate goto fail; 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* add next action */ 5817c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_NEXT_ACTION, first_action) != 0) { 5827c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 5837c478bd9Sstevel@tonic-gate goto fail; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* add stats_enable */ 5877c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE, 5887c478bd9Sstevel@tonic-gate (uint32_t)stats_enable) != 0) { 5897c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 5907c478bd9Sstevel@tonic-gate goto fail; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate /* add ipqosconf as originator */ 5947c478bd9Sstevel@tonic-gate if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) { 5957c478bd9Sstevel@tonic-gate goto fail; 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* call lib to do modify */ 5997c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &nvl, 0) != 0) { 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate /* ipgpc max classes */ 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (errno == ENOSPC && 6047c478bd9Sstevel@tonic-gate strcmp(action_name, IPGPC_CLASSIFY) == 0) { 6057c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 6067c478bd9Sstevel@tonic-gate gettext("Max number of classes reached in %s.\n"), 6077c478bd9Sstevel@tonic-gate IPGPC_NAME); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* other errors */ 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate } else { 6127c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 6137c478bd9Sstevel@tonic-gate gettext("Failed to create class %s in action " 6147c478bd9Sstevel@tonic-gate "%s: %s.\n"), class_name, action_name, 6157c478bd9Sstevel@tonic-gate strerror(errno)); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate goto fail; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 6227c478bd9Sstevel@tonic-gate fail: 6237c478bd9Sstevel@tonic-gate nvlist_free(nvl); 6247c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * modify the class in the kernel action action_name called class_name with 6307c478bd9Sstevel@tonic-gate * stats set according to stats_enable and the first action set to 6317c478bd9Sstevel@tonic-gate * first_action. 6327c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate static int 6357c478bd9Sstevel@tonic-gate modify_class( 6367c478bd9Sstevel@tonic-gate char *action_name, 6377c478bd9Sstevel@tonic-gate char *class_name, 6387c478bd9Sstevel@tonic-gate int module_version, 6397c478bd9Sstevel@tonic-gate boolean_t stats_enable, 6407c478bd9Sstevel@tonic-gate char *first_action, 6417c478bd9Sstevel@tonic-gate enum ipp_flags flags) 6427c478bd9Sstevel@tonic-gate { 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate nvlist_t *nvl; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate IPQOSCDBG5(APPLY, "modify_class: action: %s, class: %s, first: %s, " 6477c478bd9Sstevel@tonic-gate "stats: %s, flags: %x\n", action_name, class_name, first_action, 6487c478bd9Sstevel@tonic-gate stats_enable == B_TRUE ? "true" : "false", flags); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* create nvlist */ 6527c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 6537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 6547c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* add 'modify class' config type */ 6587c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_MODIFY_CLASS) != 6597c478bd9Sstevel@tonic-gate 0) { 6607c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 6617c478bd9Sstevel@tonic-gate goto fail; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate /* 6657c478bd9Sstevel@tonic-gate * add module version 6667c478bd9Sstevel@tonic-gate */ 6677c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 6687c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 6697c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 6707c478bd9Sstevel@tonic-gate goto fail; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* add class name */ 6747c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) { 6757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 6767c478bd9Sstevel@tonic-gate goto fail; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* add next action */ 6807c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_NEXT_ACTION, first_action) != 0) { 6817c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 6827c478bd9Sstevel@tonic-gate goto fail; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* add stats enable */ 6867c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE, 6877c478bd9Sstevel@tonic-gate (uint32_t)stats_enable) != 0) { 6887c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 6897c478bd9Sstevel@tonic-gate goto fail; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate /* add originator ipqosconf */ 6937c478bd9Sstevel@tonic-gate if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) { 6947c478bd9Sstevel@tonic-gate goto fail; 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* call lib to do modify */ 6987c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &nvl, flags) != 0) { 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* generic error message */ 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 7037c478bd9Sstevel@tonic-gate gettext("Modifying class %s in action %s failed: %s.\n"), 7047c478bd9Sstevel@tonic-gate class_name, action_name, strerror(errno)); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate goto fail; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 7107c478bd9Sstevel@tonic-gate fail: 7117c478bd9Sstevel@tonic-gate nvlist_free(nvl); 7127c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * removes the class class_name from the kernel action action_name. The 7177c478bd9Sstevel@tonic-gate * flags argument can currently be set to IPP_ACTION_DESTROY which will 7187c478bd9Sstevel@tonic-gate * result in the action this class references being destroyed. 7197c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 7207c478bd9Sstevel@tonic-gate */ 7217c478bd9Sstevel@tonic-gate static int 7227c478bd9Sstevel@tonic-gate remove_class( 7237c478bd9Sstevel@tonic-gate char *action_name, 7247c478bd9Sstevel@tonic-gate char *class_name, 7257c478bd9Sstevel@tonic-gate int module_version, 7267c478bd9Sstevel@tonic-gate enum ipp_flags flags) 7277c478bd9Sstevel@tonic-gate { 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate nvlist_t *nvl; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate IPQOSCDBG3(APPLY, "remove_class: action: %s, class: %s, " 7327c478bd9Sstevel@tonic-gate "flags: %x\n", action_name, class_name, flags); 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate /* allocate nvlist */ 7357c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 7367c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 7377c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate /* add 'remove class' config type */ 7417c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_REMOVE_CLASS) != 7427c478bd9Sstevel@tonic-gate 0) { 7437c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 7447c478bd9Sstevel@tonic-gate goto fail; 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate /* 7487c478bd9Sstevel@tonic-gate * add module version 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 7517c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 7527c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 7537c478bd9Sstevel@tonic-gate goto fail; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate /* add class name */ 7577c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, class_name) != 0) { 7587c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 7597c478bd9Sstevel@tonic-gate goto fail; 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &nvl, flags) != 0) { 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate /* generic error message */ 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 7677c478bd9Sstevel@tonic-gate gettext("Removing class %s in action %s failed: %s.\n"), 7687c478bd9Sstevel@tonic-gate class_name, action_name, strerror(errno)); 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate goto fail; 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 7747c478bd9Sstevel@tonic-gate fail: 7757c478bd9Sstevel@tonic-gate nvlist_free(nvl); 7767c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * add the filter flt to the kernel action named action_name. 7817c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 7827c478bd9Sstevel@tonic-gate */ 7837c478bd9Sstevel@tonic-gate static int 7847c478bd9Sstevel@tonic-gate add_filter( 7857c478bd9Sstevel@tonic-gate char *action_name, 7867c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt, 7877c478bd9Sstevel@tonic-gate int module_version) 7887c478bd9Sstevel@tonic-gate { 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate nvlist_t *nvl = flt->nvlist; 7917c478bd9Sstevel@tonic-gate char ipvsbuf[IPQOS_INT_STR_LEN]; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate IPQOSCDBG4(APPLY, "add_filter: action: %s, filter: %s, " 7947c478bd9Sstevel@tonic-gate "instance: %d, class: %s\n", action_name, flt->name, 7957c478bd9Sstevel@tonic-gate flt->instance, flt->class_name); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate /* add 'add filter' config type to filter nvlist */ 7997c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_ADD_FILTER) != 0) { 8007c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 8017c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * add module version 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 8087c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 8097c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 8107c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* add filter name to nvlist */ 8147c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, flt->name) != 0) { 8157c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 8167c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* add class name to nvlist */ 8207c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, flt->class_name) != 8217c478bd9Sstevel@tonic-gate 0) { 8227c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 8237c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate /* add ipqosconf as originator to nvlist */ 8277c478bd9Sstevel@tonic-gate if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) { 8287c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* add ipgpc specific nv entrys */ 8327c478bd9Sstevel@tonic-gate if (strcmp(action_name, IPGPC_CLASSIFY) == 0) { 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate /* add src and dst nodes to nvlist if present */ 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate if (flt->src_nd_name != NULL && 8377c478bd9Sstevel@tonic-gate nvlist_add_string(nvl, IPGPC_SADDR_HOSTNAME, 8387c478bd9Sstevel@tonic-gate flt->src_nd_name) != 0) { 8397c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 8407c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate if (flt->dst_nd_name != NULL && 8437c478bd9Sstevel@tonic-gate nvlist_add_string(nvl, IPGPC_DADDR_HOSTNAME, 8447c478bd9Sstevel@tonic-gate flt->dst_nd_name) != 0) { 8457c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 8467c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /* 8507c478bd9Sstevel@tonic-gate * add ip_version to private list element if present. 8517c478bd9Sstevel@tonic-gate * NOTE: this value is of only real use to ipqosconf so 8527c478bd9Sstevel@tonic-gate * it is placed in this opaque private field. 8537c478bd9Sstevel@tonic-gate */ 8547c478bd9Sstevel@tonic-gate if (flt->ip_versions != 0) { 8557c478bd9Sstevel@tonic-gate (void) sprintf(ipvsbuf, "%d", flt->ip_versions); 8567c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, IPGPC_FILTER_PRIVATE, 8577c478bd9Sstevel@tonic-gate ipvsbuf) != 0) { 8587c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 8597c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* add filter instance if present */ 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE, 8667c478bd9Sstevel@tonic-gate flt->instance) != 0) { 8677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_int32"); 8687c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &flt->nvlist, 0) != 0) { 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* invalid parameters */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 8777c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 8787c478bd9Sstevel@tonic-gate gettext("Invalid/missing parameters for filter " 8797c478bd9Sstevel@tonic-gate "%s in action %s.\n"), flt->name, action_name); 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* max ipgpc filters/classes */ 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate } else if (errno == ENOSPC && 8847c478bd9Sstevel@tonic-gate strcmp(action_name, IPGPC_CLASSIFY) == 0) { 8857c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Max number of filters " 8867c478bd9Sstevel@tonic-gate "reached in action %s.\n"), IPGPC_NAME); 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate /* anything other errnos */ 8897c478bd9Sstevel@tonic-gate } else { 8907c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 8917c478bd9Sstevel@tonic-gate gettext("Failed to create filter %s in action " 8927c478bd9Sstevel@tonic-gate "%s: %s.\n"), flt->name, action_name, 8937c478bd9Sstevel@tonic-gate strerror(errno)); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * modify the filter flt in the kernel action named action_name. 9057c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 9067c478bd9Sstevel@tonic-gate */ 9077c478bd9Sstevel@tonic-gate static int 9087c478bd9Sstevel@tonic-gate modify_filter( 9097c478bd9Sstevel@tonic-gate char *action_name, 9107c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt, 9117c478bd9Sstevel@tonic-gate int module_version) 9127c478bd9Sstevel@tonic-gate { 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate nvlist_t *nvl = flt->nvlist; 9157c478bd9Sstevel@tonic-gate char ipvsbuf[IPQOS_INT_STR_LEN]; 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate IPQOSCDBG4(APPLY, "modify_filter: action: %s, filter: %s, " 9187c478bd9Sstevel@tonic-gate "instance: %d, class: %s\n", action_name, flt->name, 9197c478bd9Sstevel@tonic-gate flt->instance, flt->class_name); 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate /* show src address and dst address if present */ 9227c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 9237c478bd9Sstevel@tonic-gate if (ipqosconf_dbg_flgs & APPLY) { 9247c478bd9Sstevel@tonic-gate uint_t tmp; 9257c478bd9Sstevel@tonic-gate in6_addr_t *add; 9267c478bd9Sstevel@tonic-gate char st[100]; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate if (nvlist_lookup_uint32_array(nvl, IPGPC_SADDR, 9297c478bd9Sstevel@tonic-gate (uint32_t **)&add, &tmp) == 0) { 9307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "saddr: %s\n", 9317c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, add, st, 100)); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate if (nvlist_lookup_uint32_array(nvl, IPGPC_DADDR, 9357c478bd9Sstevel@tonic-gate (uint32_t **)&add, &tmp) == 0) { 9367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "daddr: %s\n", 9377c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, add, st, 100)); 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* add 'modify filter' config type to filters nvlist */ 9437c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, 9447c478bd9Sstevel@tonic-gate CLASSIFIER_MODIFY_FILTER) != 0) { 9457c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 9467c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate /* 9507c478bd9Sstevel@tonic-gate * add module version 9517c478bd9Sstevel@tonic-gate */ 9527c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 9537c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 9547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 9557c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* add filter name to nvlist */ 9597c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, flt->name) != 0) { 9607c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 9617c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* add class name to nvlist */ 9657c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_CLASS_NAME, flt->class_name) != 9667c478bd9Sstevel@tonic-gate 0) { 9677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 9687c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate /* add originator ipqosconf to nvlist */ 9727c478bd9Sstevel@tonic-gate if (add_orig_ipqosconf(nvl) != IPQOS_CONF_SUCCESS) { 9737c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate /* add ipgpc specific nvpairs */ 9777c478bd9Sstevel@tonic-gate if (strcmp(action_name, IPGPC_CLASSIFY) == 0) { 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate /* add src and dst nodes to nvlist if present */ 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate if (flt->src_nd_name && 9827c478bd9Sstevel@tonic-gate nvlist_add_string(nvl, IPGPC_SADDR_HOSTNAME, 9837c478bd9Sstevel@tonic-gate flt->src_nd_name) != 0) { 9847c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 9857c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate if (flt->dst_nd_name && 9887c478bd9Sstevel@tonic-gate nvlist_add_string(nvl, IPGPC_DADDR_HOSTNAME, 9897c478bd9Sstevel@tonic-gate flt->dst_nd_name) != 0) { 9907c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 9917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate /* 9957c478bd9Sstevel@tonic-gate * add ip_version to private list element if present. 9967c478bd9Sstevel@tonic-gate * NOTE: this value is of only real use to ipqosconf so 9977c478bd9Sstevel@tonic-gate * it is placed in this opaque private field. 9987c478bd9Sstevel@tonic-gate */ 9997c478bd9Sstevel@tonic-gate if (flt->ip_versions != 0) { 10007c478bd9Sstevel@tonic-gate (void) sprintf(ipvsbuf, "%d", flt->ip_versions); 10017c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, IPGPC_FILTER_PRIVATE, 10027c478bd9Sstevel@tonic-gate ipvsbuf) != 0) { 10037c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 10047c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate /* add filter instance if present */ 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE, 10117c478bd9Sstevel@tonic-gate flt->instance) != 0) { 10127c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_int32"); 10137c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &flt->nvlist, 0) != 0) { 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate /* invalid parameters */ 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 10227c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Missing/Invalid " 10237c478bd9Sstevel@tonic-gate "parameter for filter %s in action %s.\n"), 10247c478bd9Sstevel@tonic-gate flt->name, action_name); 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* any other errnos */ 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate } else { 10297c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 10307c478bd9Sstevel@tonic-gate gettext("Failed to modify filter %s in action %s: " 10317c478bd9Sstevel@tonic-gate "%s.\n"), flt->name, action_name, strerror(errno)); 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * remove the filter named filter_name instance number instance from the 10427c478bd9Sstevel@tonic-gate * kernel action action_name. 10437c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate static int 10467c478bd9Sstevel@tonic-gate remove_filter( 10477c478bd9Sstevel@tonic-gate char *action_name, 10487c478bd9Sstevel@tonic-gate char *filter_name, 10497c478bd9Sstevel@tonic-gate int instance, 10507c478bd9Sstevel@tonic-gate int module_version) 10517c478bd9Sstevel@tonic-gate { 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate nvlist_t *nvl; 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate IPQOSCDBG2(APPLY, "remove_filter: action: %s, filter: %s\n", 10567c478bd9Sstevel@tonic-gate action_name, filter_name); 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate /* create nvlist */ 10597c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 10607c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 10617c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate /* add 'remove filter' config type to list */ 10657c478bd9Sstevel@tonic-gate if (nvlist_add_byte(nvl, IPP_CONFIG_TYPE, CLASSIFIER_REMOVE_FILTER) 10667c478bd9Sstevel@tonic-gate != 0) { 10677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 10687c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate /* 10727c478bd9Sstevel@tonic-gate * add module version 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_MODULE_VERSION, 10757c478bd9Sstevel@tonic-gate (uint32_t)module_version) != 0) { 10767c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 10777c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate /* add filter name to list */ 10817c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, CLASSIFIER_FILTER_NAME, filter_name) != 0) { 10827c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 10837c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* add instance number if part of multi-instance filter */ 10877c478bd9Sstevel@tonic-gate if (instance != -1 && nvlist_add_int32(nvl, IPGPC_FILTER_INSTANCE, 10887c478bd9Sstevel@tonic-gate instance) != 0) { 10897c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_int32"); 10907c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate /* call into lib to remove */ 10947c478bd9Sstevel@tonic-gate if (ipp_action_modify(action_name, &nvl, 0) != 0) { 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate /* generic error message */ 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 10997c478bd9Sstevel@tonic-gate gettext("Removing filter %s in action %s failed: %s.\n"), 11007c478bd9Sstevel@tonic-gate filter_name, action_name, strerror(errno)); 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate /* ******************************************************************* */ 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate /* 11127c478bd9Sstevel@tonic-gate * add originator nvpair set to ipqosconf to nvl. 11137c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 11147c478bd9Sstevel@tonic-gate */ 11157c478bd9Sstevel@tonic-gate static int 11167c478bd9Sstevel@tonic-gate add_orig_ipqosconf(nvlist_t *nvl) 11177c478bd9Sstevel@tonic-gate { 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, IPP_CONFIG_ORIGINATOR, 11207c478bd9Sstevel@tonic-gate IPP_CONFIG_IPQOSCONF) != 0) { 11217c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32: originator:"); 11227c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* ************************* differencing functions ************************ */ 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate /* 11327c478bd9Sstevel@tonic-gate * compares the contents of arrays array1 and array2, both of size size, and 11337c478bd9Sstevel@tonic-gate * returns B_TRUE or B_FALSE if they're equal or not respectively. 11347c478bd9Sstevel@tonic-gate * RETURNS: B_TRUE if equal, else B_FALSE. 11357c478bd9Sstevel@tonic-gate */ 11367c478bd9Sstevel@tonic-gate static boolean_t 11377c478bd9Sstevel@tonic-gate arrays_equal( 11387c478bd9Sstevel@tonic-gate int array1[], 11397c478bd9Sstevel@tonic-gate int array2[], 11407c478bd9Sstevel@tonic-gate uint32_t size) 11417c478bd9Sstevel@tonic-gate { 11427c478bd9Sstevel@tonic-gate int x; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate for (x = 0; x < size; x++) { 11457c478bd9Sstevel@tonic-gate if (array1[x] != array2[x]) 11467c478bd9Sstevel@tonic-gate return (B_FALSE); 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate return (B_TRUE); 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate /* 11527c478bd9Sstevel@tonic-gate * difference class old against class new. It marks the new class as 11537c478bd9Sstevel@tonic-gate * modified if it is different. 11547c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_SUCCESS. 11557c478bd9Sstevel@tonic-gate */ 11567c478bd9Sstevel@tonic-gate static int 11577c478bd9Sstevel@tonic-gate diffclass( 11587c478bd9Sstevel@tonic-gate ipqos_conf_class_t *old, 11597c478bd9Sstevel@tonic-gate ipqos_conf_class_t *new) 11607c478bd9Sstevel@tonic-gate { 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In diffclass:\n"); 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* two different spec'd actions */ 11657c478bd9Sstevel@tonic-gate if (strcmp(old->alist->name, new->alist->name) != 0) { 11667c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking class %s as modified\n", new->name); 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 11697c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* different stats values */ 11737c478bd9Sstevel@tonic-gate if (old->stats_enable != new->stats_enable) { 11747c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking class %s as modified\n", new->name); 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 11777c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate /* 11847c478bd9Sstevel@tonic-gate * difference params set old against params set new of module module_name. It 11857c478bd9Sstevel@tonic-gate * marks the new params as modified if different. 11867c478bd9Sstevel@tonic-gate * RETURNS: if error IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS. 11877c478bd9Sstevel@tonic-gate */ 11887c478bd9Sstevel@tonic-gate static int 11897c478bd9Sstevel@tonic-gate diffparams( 11907c478bd9Sstevel@tonic-gate ipqos_conf_params_t *old, 11917c478bd9Sstevel@tonic-gate ipqos_conf_params_t *new, 11927c478bd9Sstevel@tonic-gate char *module_name) 11937c478bd9Sstevel@tonic-gate { 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate int diff; 11967c478bd9Sstevel@tonic-gate int res; 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In diffparams\n"); 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* diff stats */ 12017c478bd9Sstevel@tonic-gate if (old->stats_enable != new->stats_enable) { 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 12047c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate /* diff module specific params */ 12087c478bd9Sstevel@tonic-gate res = diffnvlists(old->nvlist, new->nvlist, module_name, &diff, 12097c478bd9Sstevel@tonic-gate PL_PARAMS); 12107c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 12117c478bd9Sstevel@tonic-gate return (res); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate if (diff) { 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * differences filter old against filter new of module module_name. It marks 12237c478bd9Sstevel@tonic-gate * filter new as different if so. 12247c478bd9Sstevel@tonic-gate * RETURNS: if error IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS. 12257c478bd9Sstevel@tonic-gate */ 12267c478bd9Sstevel@tonic-gate static int 12277c478bd9Sstevel@tonic-gate difffilter( 12287c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *old, 12297c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *new, 12307c478bd9Sstevel@tonic-gate char *module_name) 12317c478bd9Sstevel@tonic-gate { 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate int res; 12347c478bd9Sstevel@tonic-gate int diff; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In difffilter\n"); 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate /* compare class name */ 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate if (strcmp(old->class_name, new->class_name) != 0) { 12417c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking filter %s as modified\n", new->name); 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 12447c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate /* compare module specific params */ 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate res = diffnvlists(old->nvlist, new->nvlist, module_name, &diff, 12507c478bd9Sstevel@tonic-gate PL_FILTER); 12517c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 12527c478bd9Sstevel@tonic-gate return (res); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (diff) { 12567c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking filter %s as modified\n", new->name); 12577c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate /* 12657c478bd9Sstevel@tonic-gate * mark all the filters and classes in parameter action either 12667c478bd9Sstevel@tonic-gate * for deletion (if they are ipqosconf originated) or for modification. 12677c478bd9Sstevel@tonic-gate */ 12687c478bd9Sstevel@tonic-gate static void 12697c478bd9Sstevel@tonic-gate mark_classes_filters_del(ipqos_conf_action_t *action) 12707c478bd9Sstevel@tonic-gate { 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 12737c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In mark_classes_filters_del: action: %s\n", 12767c478bd9Sstevel@tonic-gate action->name); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* mark all non-permanent filters for del and permanent to modify */ 12797c478bd9Sstevel@tonic-gate for (flt = action->filters; flt; flt = flt->next) { 12807c478bd9Sstevel@tonic-gate if (flt->originator == IPP_CONFIG_PERMANENT) { 12817c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking prm filter %s as modified.\n", 12827c478bd9Sstevel@tonic-gate flt->name); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate flt->modified = B_TRUE; 12857c478bd9Sstevel@tonic-gate } else { 12867c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking filter %s as del.\n", 12877c478bd9Sstevel@tonic-gate flt->name); 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate flt->todel = B_TRUE; 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate /* mark all non-permanent classes for del and permanent to modify */ 12947c478bd9Sstevel@tonic-gate for (cls = action->classes; cls; cls = cls->next) { 12957c478bd9Sstevel@tonic-gate if (cls->originator == IPP_CONFIG_PERMANENT) { 12967c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking prm class %s as modified.\n", 12977c478bd9Sstevel@tonic-gate cls->name); 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate cls->modified = B_TRUE; 13007c478bd9Sstevel@tonic-gate } else { 13017c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking class %s as del.\n", 13027c478bd9Sstevel@tonic-gate cls->name); 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate cls->todel = B_TRUE; 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate /* 13107c478bd9Sstevel@tonic-gate * mark all classes and filters either new (non-permanent) or modified. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate static void 13137c478bd9Sstevel@tonic-gate mark_classes_filters_new(ipqos_conf_action_t *action) 13147c478bd9Sstevel@tonic-gate { 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 13177c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In mark_classes_filters_new: action: %s\n", 13207c478bd9Sstevel@tonic-gate action->name); 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate /* mark all permanent filters as modified and all others new */ 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate for (flt = action->filters; flt; flt = flt->next) { 13257c478bd9Sstevel@tonic-gate if (flt->originator == IPP_CONFIG_PERMANENT) { 13267c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking prm filter %s as modified.\n", 13277c478bd9Sstevel@tonic-gate flt->name); 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate flt->modified = B_TRUE; 13307c478bd9Sstevel@tonic-gate action->modified = B_TRUE; 13317c478bd9Sstevel@tonic-gate } else { 13327c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking filter %s as new.\n", 13337c478bd9Sstevel@tonic-gate flt->name); 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate flt->new = B_TRUE; 13367c478bd9Sstevel@tonic-gate } 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* mark all permanent classes as modified and all others new */ 13407c478bd9Sstevel@tonic-gate for (cls = action->classes; cls; cls = cls->next) { 13417c478bd9Sstevel@tonic-gate if (cls->originator == IPP_CONFIG_PERMANENT) { 13427c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking prm class %s as modified.\n", 13437c478bd9Sstevel@tonic-gate cls->name); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate cls->modified = B_TRUE; 13467c478bd9Sstevel@tonic-gate action->modified = B_TRUE; 13477c478bd9Sstevel@tonic-gate } else { 13487c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking class %s as new.\n", 13497c478bd9Sstevel@tonic-gate cls->name); 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate cls->new = B_TRUE; 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* 13577c478bd9Sstevel@tonic-gate * Marks all the actions and their constituent elements in conf 13587c478bd9Sstevel@tonic-gate * as new. 13597c478bd9Sstevel@tonic-gate */ 13607c478bd9Sstevel@tonic-gate static void 13617c478bd9Sstevel@tonic-gate mark_config_new( 13627c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf) 13637c478bd9Sstevel@tonic-gate { 13647c478bd9Sstevel@tonic-gate while (conf != NULL) { 13657c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking action %s as new\n", conf->name); 13667c478bd9Sstevel@tonic-gate mark_classes_filters_new(conf); 13677c478bd9Sstevel@tonic-gate conf->new = B_TRUE; 13687c478bd9Sstevel@tonic-gate conf->visited = 0; 13697c478bd9Sstevel@tonic-gate conf = conf->next; 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate /* 13747c478bd9Sstevel@tonic-gate * differences the configuration in new against old marking the actions 13757c478bd9Sstevel@tonic-gate * and their contents appropriately. 13767c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 13777c478bd9Sstevel@tonic-gate */ 13787c478bd9Sstevel@tonic-gate static int 13797c478bd9Sstevel@tonic-gate diffconf( 13807c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old, 13817c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate int res; 13857c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 13867c478bd9Sstevel@tonic-gate ipqos_conf_action_t *tmp; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate IPQOSCDBG0((L0 | DIFF), "In diffconf\n"); 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate /* check the new actions against the old */ 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate for (act = new; act; act = act->next) { 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate /* if action not in old mark it and it's contents as new */ 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate if ((tmp = actionexist(act->name, old)) == NULL) { 13977c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking act %s as new\n", act->name); 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate act->new = B_TRUE; 14007c478bd9Sstevel@tonic-gate mark_classes_filters_new(act); 14017c478bd9Sstevel@tonic-gate continue; 14027c478bd9Sstevel@tonic-gate } 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate /* if action in old diff old against new */ 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate res = diffaction(tmp, act); 14077c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 14087c478bd9Sstevel@tonic-gate return (res); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * mark actions, and their contents, in old but not new that were 14147c478bd9Sstevel@tonic-gate * created by us for del. 14157c478bd9Sstevel@tonic-gate */ 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate for (act = old; act; act = act->next) { 14187c478bd9Sstevel@tonic-gate if (act->params->originator == IPP_CONFIG_IPQOSCONF && 14197c478bd9Sstevel@tonic-gate actionexist(act->name, new) == NULL) { 14207c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking act %s for del\n", act->name); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate act->todel = B_TRUE; 14237c478bd9Sstevel@tonic-gate mark_classes_filters_del(act); 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * differences action old against action new, comparing its classes, filters 14327c478bd9Sstevel@tonic-gate * and parameters. If it is different the new action is marked as modified 14337c478bd9Sstevel@tonic-gate * and it's different sub-objects are also marked approriately. 14347c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate static int 14377c478bd9Sstevel@tonic-gate diffaction( 14387c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old, 14397c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new) 14407c478bd9Sstevel@tonic-gate { 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate int res; 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In diffaction\n"); 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* compare and mark classes */ 14477c478bd9Sstevel@tonic-gate res = diffclasses(old, new); 14487c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 14497c478bd9Sstevel@tonic-gate return (res); 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate /* compare and mark filters */ 14537c478bd9Sstevel@tonic-gate res = difffilters(old, new); 14547c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 14557c478bd9Sstevel@tonic-gate return (res); 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate /* compare and mark parameters */ 14597c478bd9Sstevel@tonic-gate res = diffparams(old->params, new->params, old->module); 14607c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 14617c478bd9Sstevel@tonic-gate return (res); 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate /* mark action as modified if params are */ 14657c478bd9Sstevel@tonic-gate if (new->params->modified == B_TRUE) { 14667c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking params for action %s modified\n", 14677c478bd9Sstevel@tonic-gate new->name); 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate /* 14767c478bd9Sstevel@tonic-gate * differences the set of classes in new against those in old, marking any 14777c478bd9Sstevel@tonic-gate * that are new/modified, approriately in the new class, and any removed 14787c478bd9Sstevel@tonic-gate * in the old class appropriately. Also marks the action which has had an 14797c478bd9Sstevel@tonic-gate * object within marked, as modified. 14807c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 14817c478bd9Sstevel@tonic-gate */ 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate static int 14847c478bd9Sstevel@tonic-gate diffclasses( 14857c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old, 14867c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new) 14877c478bd9Sstevel@tonic-gate { 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 14917c478bd9Sstevel@tonic-gate ipqos_conf_class_t *tmpc; 14927c478bd9Sstevel@tonic-gate ipqos_conf_class_t *ncls; 14937c478bd9Sstevel@tonic-gate int res; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate /* loop through old classes checking for classes not present in new */ 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate for (cls = old->classes; cls; cls = cls->next) { 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate if (classexist(cls->name, new->classes) == NULL) { 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate /* if we created original class mark for deletion */ 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate if (cls->originator == IPP_CONFIG_IPQOSCONF) { 15057c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking class %s for del\n", 15067c478bd9Sstevel@tonic-gate cls->name); 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate cls->todel = B_TRUE; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate /* mark old action */ 15117c478bd9Sstevel@tonic-gate old->modified = B_TRUE; 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate /* 15147c478bd9Sstevel@tonic-gate * if permanent class and next action created by us 15157c478bd9Sstevel@tonic-gate * copy it, set it's next action to continue and 15167c478bd9Sstevel@tonic-gate * add it to new action. This will cause the class 15177c478bd9Sstevel@tonic-gate * to be marked as and modified. This returns the class 15187c478bd9Sstevel@tonic-gate * to an assumed default state and prevents the 15197c478bd9Sstevel@tonic-gate * case where the class is pointing at an action 15207c478bd9Sstevel@tonic-gate * we want to remove and therefore couldn't without 15217c478bd9Sstevel@tonic-gate * this forced modify. 15227c478bd9Sstevel@tonic-gate */ 15237c478bd9Sstevel@tonic-gate } else if (cls->originator == IPP_CONFIG_PERMANENT && 15247c478bd9Sstevel@tonic-gate cls->alist->action && /* not virtual action */ 15257c478bd9Sstevel@tonic-gate cls->alist->action->params->originator == 15267c478bd9Sstevel@tonic-gate IPP_CONFIG_IPQOSCONF) { 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate /* copy class */ 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate res = dup_class(cls, &ncls); 15317c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 15327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate /* set next action to continue */ 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate (void) strcpy(ncls->alist->name, 15387c478bd9Sstevel@tonic-gate IPP_ANAME_CONT); 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* add to news classes to be diffed below */ 15417c478bd9Sstevel@tonic-gate ADD_TO_LIST(&new->classes, ncls); 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate /* loop through new classes checking for new / modified classes */ 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate for (cls = new->classes; cls; cls = cls->next) { 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate /* new ipqosconf class */ 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate if ((tmpc = classexist(cls->name, old->classes)) == NULL || 15537c478bd9Sstevel@tonic-gate (tmpc->originator != IPP_CONFIG_IPQOSCONF && 15547c478bd9Sstevel@tonic-gate tmpc->originator != IPP_CONFIG_PERMANENT)) { 15557c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "marking class %s new\n", 15567c478bd9Sstevel@tonic-gate cls->name); 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate cls->new = B_TRUE; 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate new->modified = B_TRUE; /* mark new action */ 15617c478bd9Sstevel@tonic-gate continue; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate /* existing ipqosconf/perm class */ 15647c478bd9Sstevel@tonic-gate } else { 15657c478bd9Sstevel@tonic-gate res = diffclass(tmpc, cls); 15667c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 15677c478bd9Sstevel@tonic-gate return (res); 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate if (cls->modified == B_TRUE) { 15717c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate /* 15807c478bd9Sstevel@tonic-gate * differences the set of filters in new against those in old, marking any 15817c478bd9Sstevel@tonic-gate * that are new/modified, approriately in the new filter/s, and any removed 15827c478bd9Sstevel@tonic-gate * in the old filter appropriately. Also marks the action which has had an 15837c478bd9Sstevel@tonic-gate * object within marked, as modified. 15847c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_SUCCESS (we return an int for symmetry with diffclasses 15857c478bd9Sstevel@tonic-gate * and difffparams). 15867c478bd9Sstevel@tonic-gate */ 15877c478bd9Sstevel@tonic-gate static int 15887c478bd9Sstevel@tonic-gate difffilters( 15897c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old, 15907c478bd9Sstevel@tonic-gate ipqos_conf_action_t *new) 15917c478bd9Sstevel@tonic-gate { 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 15947c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *tmpf; 15957c478bd9Sstevel@tonic-gate int maxi; 15967c478bd9Sstevel@tonic-gate int newi; 15977c478bd9Sstevel@tonic-gate int res; 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate /* check for new/modified filters */ 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate for (flt = new->filters; flt; flt = flt->next) { 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate /* new ipqosconf filter */ 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate if ((tmpf = filterexist(flt->name, -1, old->filters)) == NULL) { 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate /* mark all instances of this filter as new */ 16087c478bd9Sstevel@tonic-gate for (;;) { 16097c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "Marking filter %s as " 16107c478bd9Sstevel@tonic-gate "new\n", flt->name); 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate flt->new = B_TRUE; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate if (flt->next == NULL || 16167c478bd9Sstevel@tonic-gate strcmp(flt->next->name, flt->name) != 0) { 16177c478bd9Sstevel@tonic-gate break; 16187c478bd9Sstevel@tonic-gate } 16197c478bd9Sstevel@tonic-gate flt = flt->next; 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate new->modified = B_TRUE; /* mark new action */ 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate /* ipqosconf/permanent filter existed */ 16247c478bd9Sstevel@tonic-gate } else { 16257c478bd9Sstevel@tonic-gate /* 16267c478bd9Sstevel@tonic-gate * if ip node name force filter refresh - ie. mark 16277c478bd9Sstevel@tonic-gate * all old filter instances as todel and all new new. 16287c478bd9Sstevel@tonic-gate */ 16297c478bd9Sstevel@tonic-gate if (tmpf->src_nd_name || tmpf->dst_nd_name || 16307c478bd9Sstevel@tonic-gate flt->src_nd_name || flt->dst_nd_name) { 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate /* init max previous filter instance */ 16337c478bd9Sstevel@tonic-gate maxi = tmpf->instance; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate /* mark old instances for deletion */ 16367c478bd9Sstevel@tonic-gate do { 16377c478bd9Sstevel@tonic-gate IPQOSCDBG2(DIFF, "Marking filter " 16387c478bd9Sstevel@tonic-gate "%s, instance %d for del\n", 16397c478bd9Sstevel@tonic-gate tmpf->name, tmpf->instance); 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate tmpf->todel = B_TRUE; 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate /* 16447c478bd9Sstevel@tonic-gate * check and update previous instance 16457c478bd9Sstevel@tonic-gate * max. 16467c478bd9Sstevel@tonic-gate */ 16477c478bd9Sstevel@tonic-gate if (tmpf->instance > maxi) { 16487c478bd9Sstevel@tonic-gate maxi = tmpf->instance; 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate tmpf = tmpf->next; 16527c478bd9Sstevel@tonic-gate } while (tmpf != NULL && 16537c478bd9Sstevel@tonic-gate strcmp(tmpf->name, flt->name) == 0); 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* 16567c478bd9Sstevel@tonic-gate * use the max previous instance + 1 for 16577c478bd9Sstevel@tonic-gate * the start of the new instance numbers. 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate newi = (uint32_t)++maxi % INT_MAX; 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* 16627c478bd9Sstevel@tonic-gate * mark new instances for addition and 16637c478bd9Sstevel@tonic-gate * give new instance number. 16647c478bd9Sstevel@tonic-gate */ 16657c478bd9Sstevel@tonic-gate for (;;) { 16667c478bd9Sstevel@tonic-gate IPQOSCDBG2(DIFF, "Marking filter " 16677c478bd9Sstevel@tonic-gate "%s, instance %d as new\n", 16687c478bd9Sstevel@tonic-gate flt->name, newi); 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate flt->new = B_TRUE; 16717c478bd9Sstevel@tonic-gate flt->instance = newi++; 16727c478bd9Sstevel@tonic-gate if (flt->next == NULL || 16737c478bd9Sstevel@tonic-gate strcmp(flt->next->name, 16747c478bd9Sstevel@tonic-gate flt->name) != 0) { 16757c478bd9Sstevel@tonic-gate break; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate flt = flt->next; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate new->modified = B_TRUE; /* mark new action */ 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate /* mark old action */ 16827c478bd9Sstevel@tonic-gate old->modified = B_TRUE; 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* non-node name filter */ 16857c478bd9Sstevel@tonic-gate } else { 16867c478bd9Sstevel@tonic-gate /* compare and mark as modified if diff */ 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate res = difffilter(tmpf, flt, new->module); 16897c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 16907c478bd9Sstevel@tonic-gate return (res); 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate if (flt->modified == B_TRUE) { 16937c478bd9Sstevel@tonic-gate /* mark action if diff */ 16947c478bd9Sstevel@tonic-gate new->modified = B_TRUE; 16957c478bd9Sstevel@tonic-gate } 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate } 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate /* 17017c478bd9Sstevel@tonic-gate * Check for deleted ipqosconf created filters and mark 17027c478bd9Sstevel@tonic-gate * any found for deletion. 17037c478bd9Sstevel@tonic-gate * For non-ipqosconf generated filters, including permanent 17047c478bd9Sstevel@tonic-gate * ones (none of these exist at the moment) we just leave 17057c478bd9Sstevel@tonic-gate * the filter unmarked. 17067c478bd9Sstevel@tonic-gate */ 17077c478bd9Sstevel@tonic-gate for (flt = old->filters; flt; flt = flt->next) { 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate if (flt->originator == IPP_CONFIG_IPQOSCONF && 17107c478bd9Sstevel@tonic-gate filterexist(flt->name, -1, new->filters) == NULL) { 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate /* mark all old instances for deletions */ 17137c478bd9Sstevel@tonic-gate for (;;) { 17147c478bd9Sstevel@tonic-gate IPQOSCDBG2(DIFF, "marking flt %s, inst %d " 17157c478bd9Sstevel@tonic-gate "for del\n", flt->name, flt->instance); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate flt->todel = B_TRUE; 17187c478bd9Sstevel@tonic-gate old->modified = B_TRUE; /* mark old action */ 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate if (flt->next == NULL || 17217c478bd9Sstevel@tonic-gate strcmp(flt->next->name, flt->name) != 0) { 17227c478bd9Sstevel@tonic-gate break; 17237c478bd9Sstevel@tonic-gate } 17247c478bd9Sstevel@tonic-gate flt = flt->next; 17257c478bd9Sstevel@tonic-gate } 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 17307c478bd9Sstevel@tonic-gate } 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate /* 17347c478bd9Sstevel@tonic-gate * differences the elements of nvlists old and new using the types file 17357c478bd9Sstevel@tonic-gate * for module name to interpret the element types. It sets pdiff to either 17367c478bd9Sstevel@tonic-gate * 0 or 1 if they are the same or different respectively. 17377c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS. 17387c478bd9Sstevel@tonic-gate */ 17397c478bd9Sstevel@tonic-gate static int 17407c478bd9Sstevel@tonic-gate diffnvlists( 17417c478bd9Sstevel@tonic-gate nvlist_t *old, 17427c478bd9Sstevel@tonic-gate nvlist_t *new, 17437c478bd9Sstevel@tonic-gate char *module_name, 17447c478bd9Sstevel@tonic-gate int *pdiff, 17457c478bd9Sstevel@tonic-gate place_t place) 17467c478bd9Sstevel@tonic-gate { 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate int first_pass = 1; 17497c478bd9Sstevel@tonic-gate nvlist_t *tmp; 17507c478bd9Sstevel@tonic-gate int res; 17517c478bd9Sstevel@tonic-gate nvpair_t *nvp; 17527c478bd9Sstevel@tonic-gate FILE *tfp; 17537c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs; 17547c478bd9Sstevel@tonic-gate char dfltst[IPQOS_VALST_MAXLEN+1] = ""; 17557c478bd9Sstevel@tonic-gate char *lo; 17567c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 17577c478bd9Sstevel@tonic-gate char *nme; 17587c478bd9Sstevel@tonic-gate int diff; 17597c478bd9Sstevel@tonic-gate int openerr; 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In diffnvlists\n"); 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate /* open stream to types file */ 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate tfp = validmod(module_name, &openerr); 17677c478bd9Sstevel@tonic-gate if (tfp == NULL) { 17687c478bd9Sstevel@tonic-gate if (openerr) { 17697c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 17727c478bd9Sstevel@tonic-gate } 17737c478bd9Sstevel@tonic-gate start: 17747c478bd9Sstevel@tonic-gate /* 17757c478bd9Sstevel@tonic-gate * loop through each of the elements of the new list comparing 17767c478bd9Sstevel@tonic-gate * it with the old one if present. If the old one isn't present 17777c478bd9Sstevel@tonic-gate * then it is compared with the default value for that type (if 17787c478bd9Sstevel@tonic-gate * set). Any time the values are determined to be different 17797c478bd9Sstevel@tonic-gate * or the default value is to be used but isn't present the diff 17807c478bd9Sstevel@tonic-gate * param is set to 1 and we return. 17817c478bd9Sstevel@tonic-gate * 17827c478bd9Sstevel@tonic-gate * If the loop runs its course then the new and old nvlists are 17837c478bd9Sstevel@tonic-gate * reversed and the loop is entered for a second time. 17847c478bd9Sstevel@tonic-gate */ 17857c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(new, NULL); 17867c478bd9Sstevel@tonic-gate while (nvp != NULL) { 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate /* get name */ 17897c478bd9Sstevel@tonic-gate nme = nvpair_name(nvp); 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate /* 17927c478bd9Sstevel@tonic-gate * get type. 17937c478bd9Sstevel@tonic-gate */ 17947c478bd9Sstevel@tonic-gate place = PL_ANY; 17957c478bd9Sstevel@tonic-gate res = readtype(tfp, module_name, SHORT_NAME(nme), &type, 17967c478bd9Sstevel@tonic-gate &enum_nvs, dfltst, B_TRUE, &place); 17977c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 17987c478bd9Sstevel@tonic-gate return (res); 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate /* init diff to 1 */ 18027c478bd9Sstevel@tonic-gate diff = 1; 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate switch (type) { 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate /* interface name */ 18077c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_IFINDEX: { 18087c478bd9Sstevel@tonic-gate uint32_t ifidx; 18097c478bd9Sstevel@tonic-gate uint32_t oifidx; 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate /* get new value */ 18127c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &ifidx); 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate /* compare against old if present */ 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint32(old, nme, &oifidx); 18177c478bd9Sstevel@tonic-gate if (res == 0) { 18187c478bd9Sstevel@tonic-gate /* diff values */ 18197c478bd9Sstevel@tonic-gate diff = (ifidx != oifidx); 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate /* not in old so see if new value is default */ 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate } else { 18247c478bd9Sstevel@tonic-gate diff = (ifidx != 0); 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate break; 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate /* protocol */ 18297c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PROTO: { 18307c478bd9Sstevel@tonic-gate uchar_t proto; 18317c478bd9Sstevel@tonic-gate uchar_t oproto; 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, &proto); 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate res = nvlist_lookup_byte(old, nme, &oproto); 18367c478bd9Sstevel@tonic-gate if (res == 0) { 18377c478bd9Sstevel@tonic-gate diff = (proto != oproto); 18387c478bd9Sstevel@tonic-gate } else { 18397c478bd9Sstevel@tonic-gate diff = (proto != 0); 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate break; 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate /* port */ 18447c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PORT: { 18457c478bd9Sstevel@tonic-gate uint16_t port; 18467c478bd9Sstevel@tonic-gate uint16_t oport; 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16(nvp, &port); 18497c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint16(old, nme, &oport); 18507c478bd9Sstevel@tonic-gate if (res == 0) { 18517c478bd9Sstevel@tonic-gate diff = (port != oport); 18527c478bd9Sstevel@tonic-gate } else { 18537c478bd9Sstevel@tonic-gate diff = (port != 0); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate break; 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate /* action name / string */ 18587c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ACTION: 18597c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_STRING: { 18607c478bd9Sstevel@tonic-gate char *str; 18617c478bd9Sstevel@tonic-gate char *ostr; 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &str); 18647c478bd9Sstevel@tonic-gate res = nvlist_lookup_string(old, nme, &ostr); 18657c478bd9Sstevel@tonic-gate if (res == 0) { 18667c478bd9Sstevel@tonic-gate diff = strcmp(str, ostr); 18677c478bd9Sstevel@tonic-gate } else if (*dfltst) { 18687c478bd9Sstevel@tonic-gate diff = strcmp(str, dfltst); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate break; 18717c478bd9Sstevel@tonic-gate } 18727c478bd9Sstevel@tonic-gate /* address mask / address */ 18737c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ADDRESS_MASK: 18747c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ADDRESS: { 18757c478bd9Sstevel@tonic-gate in6_addr_t *in6; 18767c478bd9Sstevel@tonic-gate in6_addr_t *oin6; 18777c478bd9Sstevel@tonic-gate uint_t x; 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate /* 18807c478bd9Sstevel@tonic-gate * all addresses are stored as v6 addresses, so 18817c478bd9Sstevel@tonic-gate * a uint32_t[4] array is used. 18827c478bd9Sstevel@tonic-gate */ 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate /* lookup new value */ 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32_array(nvp, 18877c478bd9Sstevel@tonic-gate (uint32_t **)&in6, &x); 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate /* see if there's an old value and diff it */ 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint32_array(old, nme, 18927c478bd9Sstevel@tonic-gate (uint32_t **)&oin6, &x); 18937c478bd9Sstevel@tonic-gate if (res == 0) { 18947c478bd9Sstevel@tonic-gate /* diff each of the 16 v6 address bytes */ 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate for (x = 0; x < 16; x++) { 18977c478bd9Sstevel@tonic-gate if (in6->s6_addr[x] != 18987c478bd9Sstevel@tonic-gate oin6->s6_addr[x]) { 18997c478bd9Sstevel@tonic-gate diff++; 19007c478bd9Sstevel@tonic-gate break; 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate break; 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate /* boolean */ 19077c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_BOOLEAN: { 19087c478bd9Sstevel@tonic-gate boolean_t bl; 19097c478bd9Sstevel@tonic-gate boolean_t obl; 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, (uint32_t *)&bl); 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate /* see if there's an old value and diff it */ 19147c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint32(old, nme, (uint32_t *)&obl); 19157c478bd9Sstevel@tonic-gate if (res == 0) { 19167c478bd9Sstevel@tonic-gate diff = (bl != obl); 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* compare against default if present */ 19197c478bd9Sstevel@tonic-gate } else if (*dfltst) { 19207c478bd9Sstevel@tonic-gate res = readbool(dfltst, &obl); 19217c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 19227c478bd9Sstevel@tonic-gate diff = (bl != obl); 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate break; 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate /* uint 8 */ 19287c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT8: { 19297c478bd9Sstevel@tonic-gate uint8_t u8; 19307c478bd9Sstevel@tonic-gate uint8_t ou8; 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, (uchar_t *)&u8); 19337c478bd9Sstevel@tonic-gate res = nvlist_lookup_byte(old, nme, (uchar_t *)&ou8); 19347c478bd9Sstevel@tonic-gate if (res == 0) { 19357c478bd9Sstevel@tonic-gate diff = (u8 != ou8); 19367c478bd9Sstevel@tonic-gate } else if (*dfltst) { 19377c478bd9Sstevel@tonic-gate res = readuint8(dfltst, &ou8, &lo); 19387c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 19397c478bd9Sstevel@tonic-gate diff = (u8 != ou8); 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate break; 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate /* int 16 */ 19457c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT16: { 19467c478bd9Sstevel@tonic-gate int16_t i16; 19477c478bd9Sstevel@tonic-gate int16_t oi16; 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate (void) nvpair_value_int16(nvp, &i16); 19507c478bd9Sstevel@tonic-gate res = nvlist_lookup_int16(old, nme, &oi16); 19517c478bd9Sstevel@tonic-gate if (res == 0) { 19527c478bd9Sstevel@tonic-gate diff = (i16 != oi16); 19537c478bd9Sstevel@tonic-gate } else if (*dfltst) { 19547c478bd9Sstevel@tonic-gate res = readint16(dfltst, &oi16, &lo); 19557c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 19567c478bd9Sstevel@tonic-gate diff = (i16 != oi16); 19577c478bd9Sstevel@tonic-gate } 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate break; 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate /* uint16 */ 19627c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT16: { 19637c478bd9Sstevel@tonic-gate uint16_t ui16; 19647c478bd9Sstevel@tonic-gate uint16_t oui16; 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16(nvp, &ui16); 19677c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint16(old, nme, &oui16); 19687c478bd9Sstevel@tonic-gate if (res == 0) { 19697c478bd9Sstevel@tonic-gate diff = (ui16 != oui16); 19707c478bd9Sstevel@tonic-gate } else if (*dfltst) { 19717c478bd9Sstevel@tonic-gate res = readuint16(dfltst, &oui16, &lo); 19727c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 19737c478bd9Sstevel@tonic-gate diff = (ui16 != oui16); 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate break; 19777c478bd9Sstevel@tonic-gate } 19787c478bd9Sstevel@tonic-gate /* 19797c478bd9Sstevel@tonic-gate * int32 and user. 19807c478bd9Sstevel@tonic-gate * Since user uids are stored in an int32 nvpair we can use 19817c478bd9Sstevel@tonic-gate * the same comparison code. 19827c478bd9Sstevel@tonic-gate */ 19837c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_USER: 19847c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT32: { 19857c478bd9Sstevel@tonic-gate int32_t i32; 19867c478bd9Sstevel@tonic-gate int32_t oi32; 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &i32); 19897c478bd9Sstevel@tonic-gate res = nvlist_lookup_int32(old, nme, &oi32); 19907c478bd9Sstevel@tonic-gate if (res == 0) { 19917c478bd9Sstevel@tonic-gate diff = (i32 != oi32); 19927c478bd9Sstevel@tonic-gate } else if (*dfltst) { 19937c478bd9Sstevel@tonic-gate res = readint32(dfltst, &oi32, &lo); 19947c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 19957c478bd9Sstevel@tonic-gate diff = (i32 != oi32); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate } 19987c478bd9Sstevel@tonic-gate break; 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate /* uint32 */ 20017c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT32: { 20027c478bd9Sstevel@tonic-gate uint32_t ui32; 20037c478bd9Sstevel@tonic-gate uint32_t oui32; 20047c478bd9Sstevel@tonic-gate 20057c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &ui32); 20067c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint32(old, nme, &oui32); 20077c478bd9Sstevel@tonic-gate if (res == 0) { 20087c478bd9Sstevel@tonic-gate diff = (ui32 != oui32); 20097c478bd9Sstevel@tonic-gate } else if (*dfltst) { 20107c478bd9Sstevel@tonic-gate res = readuint32(dfltst, &oui32, &lo); 20117c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 20127c478bd9Sstevel@tonic-gate diff = (ui32 != oui32); 20137c478bd9Sstevel@tonic-gate } 20147c478bd9Sstevel@tonic-gate } 20157c478bd9Sstevel@tonic-gate break; 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate /* enumeration */ 20187c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ENUM: { 20197c478bd9Sstevel@tonic-gate uint32_t eval; 20207c478bd9Sstevel@tonic-gate uint32_t oeval; 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &eval); 20237c478bd9Sstevel@tonic-gate res = nvlist_lookup_uint32(old, nme, &oeval); 20247c478bd9Sstevel@tonic-gate if (res == 0) { 20257c478bd9Sstevel@tonic-gate diff = (eval != oeval); 20267c478bd9Sstevel@tonic-gate } else if (*dfltst) { 20277c478bd9Sstevel@tonic-gate res = readuint32(dfltst, &oeval, &lo); 20287c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 20297c478bd9Sstevel@tonic-gate diff = (eval != oeval); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate break; 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_M_INDEX: { 20357c478bd9Sstevel@tonic-gate uint8_t idx, oidx; 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, &idx); 20387c478bd9Sstevel@tonic-gate res = nvlist_lookup_byte(old, nme, &oidx); 20397c478bd9Sstevel@tonic-gate if (res == 0) 20407c478bd9Sstevel@tonic-gate diff = (idx != oidx); 20417c478bd9Sstevel@tonic-gate break; 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT_ARRAY: { 20447c478bd9Sstevel@tonic-gate int *oarr, *arr; 20457c478bd9Sstevel@tonic-gate uint32_t osize, size; 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate (void) nvpair_value_int32_array(nvp, &arr, &size); 20487c478bd9Sstevel@tonic-gate res = nvlist_lookup_int32_array(old, nme, &oarr, 20497c478bd9Sstevel@tonic-gate &osize); 20507c478bd9Sstevel@tonic-gate if (res == 0) 20517c478bd9Sstevel@tonic-gate diff = (arrays_equal(arr, oarr, size) == 20527c478bd9Sstevel@tonic-gate B_FALSE); 20537c478bd9Sstevel@tonic-gate break; 20547c478bd9Sstevel@tonic-gate } 20557c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 20567c478bd9Sstevel@tonic-gate default: { 20577c478bd9Sstevel@tonic-gate /* shouldn't get here as all types should be covered */ 20587c478bd9Sstevel@tonic-gate assert(1); 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate #endif 20617c478bd9Sstevel@tonic-gate } /* switch */ 20627c478bd9Sstevel@tonic-gate if (diff != 0) { 20637c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "parameter %s different\n", nme); 20647c478bd9Sstevel@tonic-gate *pdiff = 1; 20657c478bd9Sstevel@tonic-gate (void) fclose(tfp); 20667c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(new, nvp); 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate } 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate /* now compare all the stuff in the second list with the first */ 20757c478bd9Sstevel@tonic-gate if (first_pass) { 20767c478bd9Sstevel@tonic-gate tmp = old; 20777c478bd9Sstevel@tonic-gate old = new; 20787c478bd9Sstevel@tonic-gate new = tmp; 20797c478bd9Sstevel@tonic-gate first_pass = 0; 20807c478bd9Sstevel@tonic-gate goto start; 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate (void) fclose(tfp); 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate *pdiff = 0; 20867c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 20877c478bd9Sstevel@tonic-gate } 20887c478bd9Sstevel@tonic-gate 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate 20917c478bd9Sstevel@tonic-gate /* ************************** difference application *********************** */ 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* 20967c478bd9Sstevel@tonic-gate * causes all items marked as requiring change in actions and old_actions 20977c478bd9Sstevel@tonic-gate * to have the change applied. 20987c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 20997c478bd9Sstevel@tonic-gate */ 21007c478bd9Sstevel@tonic-gate static int 21017c478bd9Sstevel@tonic-gate applydiff( 21027c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 21037c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old_actions) 21047c478bd9Sstevel@tonic-gate { 21057c478bd9Sstevel@tonic-gate 21067c478bd9Sstevel@tonic-gate int res; 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In applydiff:\n"); 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate 21117c478bd9Sstevel@tonic-gate /* add each item marked as new */ 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate res = add_items(actions, B_FALSE); 21147c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 21157c478bd9Sstevel@tonic-gate return (res); 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate /* modify items marked for modification */ 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate res = modify_items(actions); 21217c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 21227c478bd9Sstevel@tonic-gate return (res); 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate /* delete items marked for deletion */ 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate res = remove_items(old_actions, B_FALSE); 21287c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 21297c478bd9Sstevel@tonic-gate return (res); 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 21337c478bd9Sstevel@tonic-gate } 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate static int 21367c478bd9Sstevel@tonic-gate add_items( 21377c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 21387c478bd9Sstevel@tonic-gate boolean_t rem_undo) 21397c478bd9Sstevel@tonic-gate { 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate int res; 21427c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In add_items, rem_undo: %u\n", rem_undo); 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate /* 21477c478bd9Sstevel@tonic-gate * we need to create ipgpc action before any others as some actions 21487c478bd9Sstevel@tonic-gate * such as ftpcl which make calls to it depend on it being there on 21497c478bd9Sstevel@tonic-gate * their creation. 21507c478bd9Sstevel@tonic-gate */ 21517c478bd9Sstevel@tonic-gate act = actionexist(IPGPC_CLASSIFY, actions); 21527c478bd9Sstevel@tonic-gate if (act && 21537c478bd9Sstevel@tonic-gate (rem_undo == B_FALSE && act->new == B_TRUE || 21547c478bd9Sstevel@tonic-gate rem_undo == B_TRUE && act->deleted == B_TRUE)) { 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate res = add_action(act); 21577c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 21587c478bd9Sstevel@tonic-gate return (res); 21597c478bd9Sstevel@tonic-gate } 21607c478bd9Sstevel@tonic-gate } 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate /* 21637c478bd9Sstevel@tonic-gate * loop though action list and add any actions marked as 21647c478bd9Sstevel@tonic-gate * new/modified action and apply any additions there, then return. 21657c478bd9Sstevel@tonic-gate */ 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate for (act = actions; act; act = act->next) { 21687c478bd9Sstevel@tonic-gate res = add_item(act, rem_undo); 21697c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 21707c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 21717c478bd9Sstevel@tonic-gate } 21727c478bd9Sstevel@tonic-gate } 21737c478bd9Sstevel@tonic-gate 21747c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 21757c478bd9Sstevel@tonic-gate } 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate /* 21797c478bd9Sstevel@tonic-gate * 21807c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 21817c478bd9Sstevel@tonic-gate */ 21827c478bd9Sstevel@tonic-gate static int 21837c478bd9Sstevel@tonic-gate add_item( 21847c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 21857c478bd9Sstevel@tonic-gate boolean_t rem_undo) 21867c478bd9Sstevel@tonic-gate { 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act = actions; 21897c478bd9Sstevel@tonic-gate int res; 21907c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 21917c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *pact; 21927c478bd9Sstevel@tonic-gate 21937c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "In add_item: action: %s, rem_undo: %u\n", 21947c478bd9Sstevel@tonic-gate actions->name, rem_undo); 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate /* if already visited return immediately */ 21977c478bd9Sstevel@tonic-gate 21987c478bd9Sstevel@tonic-gate if (act->visited == ADD_VISITED) { 21997c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Early exit due to visited\n"); 22007c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 22017c478bd9Sstevel@tonic-gate } 22027c478bd9Sstevel@tonic-gate act->visited = ADD_VISITED; 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate /* recurse to last action in tree */ 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate for (cls = act->classes; cls; cls = cls->next) { 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate /* if not virtual action */ 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate if (cls->alist->action) { 22127c478bd9Sstevel@tonic-gate res = add_item(cls->alist->action, rem_undo); 22137c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 22147c478bd9Sstevel@tonic-gate return (res); 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate } 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate for (pact = act->params->actions; pact; pact = pact->next) { 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate /* if not virtual */ 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate if (pact->action) { 22247c478bd9Sstevel@tonic-gate res = add_item(pact->action, rem_undo); 22257c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 22267c478bd9Sstevel@tonic-gate return (res); 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate } 22297c478bd9Sstevel@tonic-gate } 22307c478bd9Sstevel@tonic-gate 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate /* if action marked as new and not ipgpc, create */ 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate if (((rem_undo == B_FALSE && act->new == B_TRUE) || 22357c478bd9Sstevel@tonic-gate (rem_undo == B_TRUE && act->deleted == B_TRUE)) && 22367c478bd9Sstevel@tonic-gate strcmp(act->name, IPGPC_CLASSIFY) != 0) { 22377c478bd9Sstevel@tonic-gate res = add_action(act); 22387c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 22397c478bd9Sstevel@tonic-gate return (res); 22407c478bd9Sstevel@tonic-gate } 22417c478bd9Sstevel@tonic-gate } 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate /* add any classes and filters marked as new */ 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate if (add_classes(act->classes, act->name, act->module_version, 22467c478bd9Sstevel@tonic-gate rem_undo) != IPQOS_CONF_SUCCESS || 22477c478bd9Sstevel@tonic-gate add_filters(act->filters, act->name, act->module_version, 22487c478bd9Sstevel@tonic-gate rem_undo) != IPQOS_CONF_SUCCESS) { 22497c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate /* 22577c478bd9Sstevel@tonic-gate * Uses the contents of acts params nvlist and adds an originator 22587c478bd9Sstevel@tonic-gate * element set to ipqosconf and the stats parameter. This list 22597c478bd9Sstevel@tonic-gate * is then used as the parameter to a call to ipp_action_create to create 22607c478bd9Sstevel@tonic-gate * this action in the kernel. 22617c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on err, else IPQOS_CONF_SUCCESS. 22627c478bd9Sstevel@tonic-gate */ 22637c478bd9Sstevel@tonic-gate static int 22647c478bd9Sstevel@tonic-gate add_action(ipqos_conf_action_t *act) 22657c478bd9Sstevel@tonic-gate { 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate int res; 22687c478bd9Sstevel@tonic-gate nvlist_t **nvl; 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate IPQOSCDBG2(APPLY, "add_action: action: %s, module: %s\n", act->name, 22717c478bd9Sstevel@tonic-gate act->module); 22727c478bd9Sstevel@tonic-gate 22737c478bd9Sstevel@tonic-gate nvl = &act->params->nvlist; 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate /* alloc params nvlist if not already one */ 22767c478bd9Sstevel@tonic-gate 22777c478bd9Sstevel@tonic-gate if (*nvl == NULL) { 22787c478bd9Sstevel@tonic-gate res = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0); 22797c478bd9Sstevel@tonic-gate if (res != 0) { 22807c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 22817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 22827c478bd9Sstevel@tonic-gate } 22837c478bd9Sstevel@tonic-gate } 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate /* 22867c478bd9Sstevel@tonic-gate * add module version 22877c478bd9Sstevel@tonic-gate */ 22887c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(*nvl, IPP_MODULE_VERSION, 22897c478bd9Sstevel@tonic-gate (uint32_t)act->module_version) != 0) { 22907c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32"); 22917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 22927c478bd9Sstevel@tonic-gate } 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate /* add action stats */ 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(*nvl, IPP_ACTION_STATS_ENABLE, 22977c478bd9Sstevel@tonic-gate (uint32_t)act->params->stats_enable) != 0) { 22987c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32: action stats"); 22997c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate /* add ipqosconf originator id */ 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate if (add_orig_ipqosconf(*nvl) != IPQOS_CONF_SUCCESS) { 23057c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate /* call into lib to create action */ 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate res = ipp_action_create(act->module, act->name, nvl, 0); 23117c478bd9Sstevel@tonic-gate if (res != 0) { 23127c478bd9Sstevel@tonic-gate IPQOSCDBG2(APPLY, "Create action %s, module %s failed\n", 23137c478bd9Sstevel@tonic-gate act->name, act->module); 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate /* invalid params */ 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 23187c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 23197c478bd9Sstevel@tonic-gate gettext("Invalid Parameters for action %s.\n"), 23207c478bd9Sstevel@tonic-gate act->name); 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate } else if (errno == ENOENT) { 23237c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 23247c478bd9Sstevel@tonic-gate gettext("Missing required parameter for action " 23257c478bd9Sstevel@tonic-gate "%s.\n"), act->name); 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate } else { /* unexpected error */ 23287c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed to create action " 23297c478bd9Sstevel@tonic-gate "%s: %s.\n"), act->name, strerror(errno)); 23307c478bd9Sstevel@tonic-gate } 23317c478bd9Sstevel@tonic-gate 23327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate /* mark action as created */ 23367c478bd9Sstevel@tonic-gate act->cr_mod = B_TRUE; 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate /* 23427c478bd9Sstevel@tonic-gate * for each of the filters in parameter filters if rem_undo is false and 23437c478bd9Sstevel@tonic-gate * the filter is marked as new or if rem_undo is true and the filter is 23447c478bd9Sstevel@tonic-gate * marked as deleted then add the filter to the kernel action named by action 23457c478bd9Sstevel@tonic-gate * and if successful mark as created. 23467c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 23477c478bd9Sstevel@tonic-gate */ 23487c478bd9Sstevel@tonic-gate static int 23497c478bd9Sstevel@tonic-gate add_filters( 23507c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filters, 23517c478bd9Sstevel@tonic-gate char *action, 23527c478bd9Sstevel@tonic-gate int module_version, 23537c478bd9Sstevel@tonic-gate boolean_t rem_undo) 23547c478bd9Sstevel@tonic-gate { 23557c478bd9Sstevel@tonic-gate 23567c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In add_filters\n"); 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate /* loop through filters in filters param */ 23617c478bd9Sstevel@tonic-gate for (flt = filters; flt; flt = flt->next) { 23627c478bd9Sstevel@tonic-gate /* 23637c478bd9Sstevel@tonic-gate * skip filter if in normal mode and not new filter or 23647c478bd9Sstevel@tonic-gate * if doing rollback and filter wasn't previously deleted. 23657c478bd9Sstevel@tonic-gate */ 23667c478bd9Sstevel@tonic-gate if ((rem_undo == B_FALSE && flt->new == B_FALSE) || 23677c478bd9Sstevel@tonic-gate (rem_undo == B_TRUE && flt->deleted == B_FALSE)) { 23687c478bd9Sstevel@tonic-gate continue; 23697c478bd9Sstevel@tonic-gate } 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate /* add filter to action */ 23727c478bd9Sstevel@tonic-gate if (add_filter(action, flt, module_version) != 23737c478bd9Sstevel@tonic-gate IPQOS_CONF_SUCCESS) { 23747c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 23757c478bd9Sstevel@tonic-gate } 23767c478bd9Sstevel@tonic-gate 23777c478bd9Sstevel@tonic-gate /* mark as created */ 23787c478bd9Sstevel@tonic-gate flt->cr_mod = B_TRUE; 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate /* 23857c478bd9Sstevel@tonic-gate * for each of the classes in parameter classes if rem_undo is false and 23867c478bd9Sstevel@tonic-gate * the class is marked as new or if rem_undo is true and the class is 23877c478bd9Sstevel@tonic-gate * marked as deleted then add the class to the kernel action named by action 23887c478bd9Sstevel@tonic-gate * and if successful mark as created. 23897c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 23907c478bd9Sstevel@tonic-gate */ 23917c478bd9Sstevel@tonic-gate int 23927c478bd9Sstevel@tonic-gate add_classes( 23937c478bd9Sstevel@tonic-gate ipqos_conf_class_t *classes, 23947c478bd9Sstevel@tonic-gate char *action, 23957c478bd9Sstevel@tonic-gate int module_version, 23967c478bd9Sstevel@tonic-gate boolean_t rem_undo) { 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate int res; 23997c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In add_classes\n"); 24027c478bd9Sstevel@tonic-gate 24037c478bd9Sstevel@tonic-gate /* for each class */ 24047c478bd9Sstevel@tonic-gate for (cls = classes; cls; cls = cls->next) { 24057c478bd9Sstevel@tonic-gate /* 24067c478bd9Sstevel@tonic-gate * skip class if in normal mode and not new class or 24077c478bd9Sstevel@tonic-gate * if doing rollback and class wasn't deleted. 24087c478bd9Sstevel@tonic-gate */ 24097c478bd9Sstevel@tonic-gate if ((rem_undo == B_FALSE && cls->new == B_FALSE) || 24107c478bd9Sstevel@tonic-gate (rem_undo == B_TRUE && cls->deleted == B_FALSE)) { 24117c478bd9Sstevel@tonic-gate continue; 24127c478bd9Sstevel@tonic-gate } 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate /* add class to action */ 24157c478bd9Sstevel@tonic-gate res = add_class(action, cls->name, module_version, 24167c478bd9Sstevel@tonic-gate cls->stats_enable, cls->alist->name); 24177c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 24187c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate 24217c478bd9Sstevel@tonic-gate /* mark class as created */ 24227c478bd9Sstevel@tonic-gate cls->cr_mod = B_TRUE; 24237c478bd9Sstevel@tonic-gate } 24247c478bd9Sstevel@tonic-gate 24257c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 24267c478bd9Sstevel@tonic-gate } 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate /* 24297c478bd9Sstevel@tonic-gate * For each of the actions in actions remove the action if marked as 24307c478bd9Sstevel@tonic-gate * such or remove any objects within marked as such. 24317c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 24327c478bd9Sstevel@tonic-gate */ 24337c478bd9Sstevel@tonic-gate static int 24347c478bd9Sstevel@tonic-gate remove_items( 24357c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 24367c478bd9Sstevel@tonic-gate boolean_t add_undo) 24377c478bd9Sstevel@tonic-gate { 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate int res; 24407c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "In remove_items, add_undo: %u\n", add_undo); 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate /* 24457c478bd9Sstevel@tonic-gate * loop through actions removing any actions, or action contents 24467c478bd9Sstevel@tonic-gate * that are marked as such. 24477c478bd9Sstevel@tonic-gate */ 24487c478bd9Sstevel@tonic-gate for (act = actions; act; act = act->next) { 24497c478bd9Sstevel@tonic-gate res = remove_item(act, add_undo); 24507c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 24517c478bd9Sstevel@tonic-gate return (res); 24527c478bd9Sstevel@tonic-gate } 24537c478bd9Sstevel@tonic-gate } 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 24567c478bd9Sstevel@tonic-gate } 24577c478bd9Sstevel@tonic-gate 24587c478bd9Sstevel@tonic-gate /* 24597c478bd9Sstevel@tonic-gate * Deletes this action if marked for deletion or any of it's contents marked 24607c478bd9Sstevel@tonic-gate * for deletion. If the action is marked for deletion any actions referencing 24617c478bd9Sstevel@tonic-gate * this action are destroyed first if marked or have their contents destroyed 24627c478bd9Sstevel@tonic-gate * if marked. This is recursive. 24637c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 24647c478bd9Sstevel@tonic-gate */ 24657c478bd9Sstevel@tonic-gate static int 24667c478bd9Sstevel@tonic-gate remove_item( 24677c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act, 24687c478bd9Sstevel@tonic-gate boolean_t add_undo) 24697c478bd9Sstevel@tonic-gate { 24707c478bd9Sstevel@tonic-gate 24717c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 24727c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 24737c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *dep; 24747c478bd9Sstevel@tonic-gate int res; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate IPQOSCDBG3(L1, "In remove_item: action: %s, add_undo: %u, mod: %u\n", 24777c478bd9Sstevel@tonic-gate act->name, add_undo, act->modified); 24787c478bd9Sstevel@tonic-gate 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate /* return immmediately if previously visited in remove phase */ 24817c478bd9Sstevel@tonic-gate 24827c478bd9Sstevel@tonic-gate if (act->visited == REM_VISITED) { 24837c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Exit due to REM_VISITED set\n"); 24847c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 24857c478bd9Sstevel@tonic-gate } 24867c478bd9Sstevel@tonic-gate act->visited = REM_VISITED; 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate /* if this action is to be deleted */ 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate if (add_undo == B_FALSE && act->todel == B_TRUE || 24927c478bd9Sstevel@tonic-gate add_undo == B_TRUE && act->new == B_TRUE && 24937c478bd9Sstevel@tonic-gate act->cr_mod == B_TRUE) { 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate /* modify parent actions first */ 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate for (dep = act->dependencies; dep; dep = dep->next) { 24987c478bd9Sstevel@tonic-gate res = remove_item(dep->action, add_undo); 24997c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 25007c478bd9Sstevel@tonic-gate return (res); 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate } 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate /* delete this action */ 25057c478bd9Sstevel@tonic-gate 25067c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "deleting action %s\n", act->name); 25077c478bd9Sstevel@tonic-gate res = ipp_action_destroy(act->name, 0); 25087c478bd9Sstevel@tonic-gate if (res != 0) { 25097c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "failed to destroy action %s\n", 25107c478bd9Sstevel@tonic-gate act->name); 25117c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 25127c478bd9Sstevel@tonic-gate } 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate /* flag as deleted */ 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate act->deleted = B_TRUE; 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate /* if modified action */ 25197c478bd9Sstevel@tonic-gate 25207c478bd9Sstevel@tonic-gate } else if (act->modified == B_TRUE) { 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate /* loop through removing any filters marked for del */ 25237c478bd9Sstevel@tonic-gate 25247c478bd9Sstevel@tonic-gate for (flt = act->filters; flt; flt = flt->next) { 25257c478bd9Sstevel@tonic-gate if ((add_undo == B_FALSE && flt->todel == B_TRUE) || 25267c478bd9Sstevel@tonic-gate (add_undo == B_TRUE && flt->new == B_TRUE && 25277c478bd9Sstevel@tonic-gate flt->cr_mod == B_TRUE)) { 25287c478bd9Sstevel@tonic-gate 25297c478bd9Sstevel@tonic-gate /* do deletion */ 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate res = remove_filter(act->name, flt->name, 25327c478bd9Sstevel@tonic-gate flt->instance, act->module_version); 25337c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 25347c478bd9Sstevel@tonic-gate IPQOSCDBG2(APPLY, "failed to destroy " 25357c478bd9Sstevel@tonic-gate "filter %s, inst: %d\n", flt->name, 25367c478bd9Sstevel@tonic-gate flt->instance); 25377c478bd9Sstevel@tonic-gate 25387c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate /* flag deleted */ 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate flt->deleted = B_TRUE; 25447c478bd9Sstevel@tonic-gate } 25457c478bd9Sstevel@tonic-gate } 25467c478bd9Sstevel@tonic-gate 25477c478bd9Sstevel@tonic-gate /* remove any classes marked for del */ 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate for (cls = act->classes; cls; cls = cls->next) { 25507c478bd9Sstevel@tonic-gate if ((add_undo == B_FALSE && cls->todel == B_TRUE) || 25517c478bd9Sstevel@tonic-gate (add_undo == B_TRUE && cls->new == B_TRUE && 25527c478bd9Sstevel@tonic-gate cls->cr_mod == B_TRUE)) { 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate /* do deletion */ 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate res = remove_class(act->name, cls->name, 25577c478bd9Sstevel@tonic-gate act->module_version, 0); 25587c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 25597c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "failed to destroy " 25607c478bd9Sstevel@tonic-gate "class %s\n", cls->name); 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate /* flag deleted */ 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate cls->deleted = B_TRUE; 25687c478bd9Sstevel@tonic-gate } 25697c478bd9Sstevel@tonic-gate } 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate /* mark action as having been modified */ 25727c478bd9Sstevel@tonic-gate 25737c478bd9Sstevel@tonic-gate act->cr_mod = B_TRUE; 25747c478bd9Sstevel@tonic-gate } 25757c478bd9Sstevel@tonic-gate 25767c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 25777c478bd9Sstevel@tonic-gate } 25787c478bd9Sstevel@tonic-gate 25797c478bd9Sstevel@tonic-gate /* 25807c478bd9Sstevel@tonic-gate * for each of the actions in parameter actions apply any objects marked as 25817c478bd9Sstevel@tonic-gate * modified as a modification to the kernel action represented. 25827c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on err, else IPQOS_CONF_SUCCESS. 25837c478bd9Sstevel@tonic-gate */ 25847c478bd9Sstevel@tonic-gate static int 25857c478bd9Sstevel@tonic-gate modify_items(ipqos_conf_action_t *actions) 25867c478bd9Sstevel@tonic-gate { 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 25897c478bd9Sstevel@tonic-gate int res; 25907c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 25917c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In modify_items\n"); 25957c478bd9Sstevel@tonic-gate 25967c478bd9Sstevel@tonic-gate /* loop through actions in parameter actions */ 25977c478bd9Sstevel@tonic-gate 25987c478bd9Sstevel@tonic-gate for (act = actions; act; act = act->next) { 25997c478bd9Sstevel@tonic-gate 26007c478bd9Sstevel@tonic-gate /* skip unchanged actions */ 26017c478bd9Sstevel@tonic-gate 26027c478bd9Sstevel@tonic-gate if (act->modified == B_FALSE) { 26037c478bd9Sstevel@tonic-gate continue; 26047c478bd9Sstevel@tonic-gate } 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate /* apply any parameter mods */ 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate if (act->params->modified) { 26097c478bd9Sstevel@tonic-gate res = modify_params(act->name, 26107c478bd9Sstevel@tonic-gate &act->params->nvlist, 26117c478bd9Sstevel@tonic-gate act->module_version, act->params->stats_enable); 26127c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 26137c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 26147c478bd9Sstevel@tonic-gate } 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate act->params->cr_mod = B_TRUE; 26177c478bd9Sstevel@tonic-gate } 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate /* apply any class mods */ 26207c478bd9Sstevel@tonic-gate 26217c478bd9Sstevel@tonic-gate for (cls = act->classes; cls; cls = cls->next) { 26227c478bd9Sstevel@tonic-gate if (cls->modified) { 26237c478bd9Sstevel@tonic-gate res = modify_class(act->name, cls->name, 26247c478bd9Sstevel@tonic-gate act->module_version, cls->stats_enable, 26257c478bd9Sstevel@tonic-gate cls->alist->name, 0); 26267c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 26277c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 26287c478bd9Sstevel@tonic-gate } 26297c478bd9Sstevel@tonic-gate 26307c478bd9Sstevel@tonic-gate /* mark modification done */ 26317c478bd9Sstevel@tonic-gate cls->cr_mod = B_TRUE; 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate } 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate /* apply any filter mods */ 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate for (flt = act->filters; flt; flt = flt->next) { 26387c478bd9Sstevel@tonic-gate if (flt->modified) { 26397c478bd9Sstevel@tonic-gate res = modify_filter(act->name, flt, 26407c478bd9Sstevel@tonic-gate act->module_version); 26417c478bd9Sstevel@tonic-gate if (res != 0) { 26427c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 26437c478bd9Sstevel@tonic-gate } 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate /* mark modification done */ 26467c478bd9Sstevel@tonic-gate flt->cr_mod = B_TRUE; 26477c478bd9Sstevel@tonic-gate } 26487c478bd9Sstevel@tonic-gate } 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate /* mark action modified */ 26517c478bd9Sstevel@tonic-gate 26527c478bd9Sstevel@tonic-gate act->cr_mod = B_TRUE; 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 26567c478bd9Sstevel@tonic-gate } 26577c478bd9Sstevel@tonic-gate 26587c478bd9Sstevel@tonic-gate /* 26597c478bd9Sstevel@tonic-gate * For each of the objects of each of the actions in nactions that are 26607c478bd9Sstevel@tonic-gate * marked as having been modified the object modification is done in 26617c478bd9Sstevel@tonic-gate * reverse using the same named object from oactions. 26627c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, IPQOS_CONF_SUCCESS otherwise. 26637c478bd9Sstevel@tonic-gate */ 26647c478bd9Sstevel@tonic-gate static int 26657c478bd9Sstevel@tonic-gate undo_modifys( 26667c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oactions, 26677c478bd9Sstevel@tonic-gate ipqos_conf_action_t *nactions) 26687c478bd9Sstevel@tonic-gate { 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 26717c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 26727c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 26737c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oldact; 26747c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *oldflt; 26757c478bd9Sstevel@tonic-gate ipqos_conf_class_t *oldcls; 26767c478bd9Sstevel@tonic-gate int res; 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In undo_modifys:\n"); 26797c478bd9Sstevel@tonic-gate 26807c478bd9Sstevel@tonic-gate /* loop throught new actions */ 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate for (act = nactions; act; act = act->next) { 26837c478bd9Sstevel@tonic-gate oldact = actionexist(act->name, oactions); 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate /* 26867c478bd9Sstevel@tonic-gate * if the action was new then it will be removed and 26877c478bd9Sstevel@tonic-gate * any permamanent items that were marked for modify 26887c478bd9Sstevel@tonic-gate * will dissappear, so ignore action. 26897c478bd9Sstevel@tonic-gate */ 26907c478bd9Sstevel@tonic-gate if (oldact == NULL) { 26917c478bd9Sstevel@tonic-gate continue; 26927c478bd9Sstevel@tonic-gate } 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate /* if parameters were modified switch them back */ 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate if (act->params->modified == B_TRUE && 26977c478bd9Sstevel@tonic-gate act->params->cr_mod == B_TRUE) { 26987c478bd9Sstevel@tonic-gate res = modify_params(act->name, 26997c478bd9Sstevel@tonic-gate &oldact->params->nvlist, 27007c478bd9Sstevel@tonic-gate act->module_version, act->params->stats_enable); 27017c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27027c478bd9Sstevel@tonic-gate return (res); 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate } 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate /* for each filter in action if filter modified switch back */ 27077c478bd9Sstevel@tonic-gate 27087c478bd9Sstevel@tonic-gate for (flt = act->filters; flt; flt = flt->next) { 27097c478bd9Sstevel@tonic-gate if (flt->modified == B_TRUE && 27107c478bd9Sstevel@tonic-gate flt->cr_mod == B_TRUE) { 27117c478bd9Sstevel@tonic-gate oldflt = filterexist(flt->name, -1, 27127c478bd9Sstevel@tonic-gate oldact->filters); 27137c478bd9Sstevel@tonic-gate res = modify_filter(act->name, oldflt, 27147c478bd9Sstevel@tonic-gate act->module_version); 27157c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27167c478bd9Sstevel@tonic-gate return (res); 27177c478bd9Sstevel@tonic-gate } 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate } 27207c478bd9Sstevel@tonic-gate 27217c478bd9Sstevel@tonic-gate /* for each class in action if class modified switch back */ 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate for (cls = act->classes; cls; cls = cls->next) { 27247c478bd9Sstevel@tonic-gate if (cls->modified == B_TRUE && 27257c478bd9Sstevel@tonic-gate cls->cr_mod == B_TRUE) { 27267c478bd9Sstevel@tonic-gate oldcls = classexist(cls->name, oldact->classes); 27277c478bd9Sstevel@tonic-gate if (oldcls->alist) { 27287c478bd9Sstevel@tonic-gate res = modify_class(act->name, 27297c478bd9Sstevel@tonic-gate cls->name, act->module_version, 27307c478bd9Sstevel@tonic-gate oldcls->stats_enable, 27317c478bd9Sstevel@tonic-gate oldcls->alist->name, 0); 27327c478bd9Sstevel@tonic-gate } 27337c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27347c478bd9Sstevel@tonic-gate return (res); 27357c478bd9Sstevel@tonic-gate } 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate } 27387c478bd9Sstevel@tonic-gate } 27397c478bd9Sstevel@tonic-gate 27407c478bd9Sstevel@tonic-gate /* 27417c478bd9Sstevel@tonic-gate * Go through the old actions modifying perm filters and classes 27427c478bd9Sstevel@tonic-gate * whose action was deleted. 27437c478bd9Sstevel@tonic-gate * 27447c478bd9Sstevel@tonic-gate */ 27457c478bd9Sstevel@tonic-gate for (act = oactions; act != NULL; act = act->next) { 27467c478bd9Sstevel@tonic-gate 27477c478bd9Sstevel@tonic-gate if (act->deleted == B_FALSE) { 27487c478bd9Sstevel@tonic-gate continue; 27497c478bd9Sstevel@tonic-gate } 27507c478bd9Sstevel@tonic-gate 27517c478bd9Sstevel@tonic-gate for (flt = act->filters; flt != NULL; flt = flt->next) { 27527c478bd9Sstevel@tonic-gate if (flt->originator == IPP_CONFIG_PERMANENT) { 27537c478bd9Sstevel@tonic-gate res = modify_filter(act->name, flt, 27547c478bd9Sstevel@tonic-gate act->module_version); 27557c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27567c478bd9Sstevel@tonic-gate return (res); 27577c478bd9Sstevel@tonic-gate } 27587c478bd9Sstevel@tonic-gate } 27597c478bd9Sstevel@tonic-gate } 27607c478bd9Sstevel@tonic-gate 27617c478bd9Sstevel@tonic-gate for (cls = act->classes; cls != NULL; cls = cls->next) { 27627c478bd9Sstevel@tonic-gate if (cls->originator == IPP_CONFIG_PERMANENT) { 27637c478bd9Sstevel@tonic-gate res = modify_class(act->name, cls->name, 27647c478bd9Sstevel@tonic-gate act->module_version, cls->stats_enable, 27657c478bd9Sstevel@tonic-gate cls->alist->name, 0); 27667c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27677c478bd9Sstevel@tonic-gate return (res); 27687c478bd9Sstevel@tonic-gate } 27697c478bd9Sstevel@tonic-gate } 27707c478bd9Sstevel@tonic-gate 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate } 27737c478bd9Sstevel@tonic-gate 27747c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 27757c478bd9Sstevel@tonic-gate } 27767c478bd9Sstevel@tonic-gate 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate /* 27797c478bd9Sstevel@tonic-gate * causes all changes marked as being done in actions and old_actions 27807c478bd9Sstevel@tonic-gate * to be undone. 27817c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 27827c478bd9Sstevel@tonic-gate */ 27837c478bd9Sstevel@tonic-gate static int 27847c478bd9Sstevel@tonic-gate rollback( 27857c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 27867c478bd9Sstevel@tonic-gate ipqos_conf_action_t *old_actions) 27877c478bd9Sstevel@tonic-gate { 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate int res; 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate IPQOSCDBG0(RBK, "In rollback:\n"); 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate /* re-add items that were deleted */ 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate res = add_items(old_actions, B_TRUE); 27967c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 27977c478bd9Sstevel@tonic-gate return (res); 27987c478bd9Sstevel@tonic-gate } 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate /* change modified items back how they were */ 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate res = undo_modifys(old_actions, actions); 28037c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 28047c478bd9Sstevel@tonic-gate return (res); 28057c478bd9Sstevel@tonic-gate } 28067c478bd9Sstevel@tonic-gate 28077c478bd9Sstevel@tonic-gate /* remove new items that were added */ 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate res = remove_items(actions, B_TRUE); 28107c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 28117c478bd9Sstevel@tonic-gate return (res); 28127c478bd9Sstevel@tonic-gate } 28137c478bd9Sstevel@tonic-gate 28147c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 28157c478bd9Sstevel@tonic-gate } 28167c478bd9Sstevel@tonic-gate 28177c478bd9Sstevel@tonic-gate /* ******************************* print config **************************** */ 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gate /* 28207c478bd9Sstevel@tonic-gate * Prints the username of the user with uid 'uid' to 'fp' if the uid belongs 28217c478bd9Sstevel@tonic-gate * to a known user on the system, otherwise just print 'uid'. 28227c478bd9Sstevel@tonic-gate */ 28237c478bd9Sstevel@tonic-gate static void 28247c478bd9Sstevel@tonic-gate printuser( 28257c478bd9Sstevel@tonic-gate FILE *fp, 28267c478bd9Sstevel@tonic-gate uid_t uid) 28277c478bd9Sstevel@tonic-gate { 28287c478bd9Sstevel@tonic-gate struct passwd *pwd; 28297c478bd9Sstevel@tonic-gate 28307c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In printuser\n"); 28317c478bd9Sstevel@tonic-gate 28327c478bd9Sstevel@tonic-gate pwd = getpwuid(uid); 28337c478bd9Sstevel@tonic-gate if (pwd != NULL) { 28347c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", pwd->pw_name); 28357c478bd9Sstevel@tonic-gate } else { 28367c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", (int)uid); 28377c478bd9Sstevel@tonic-gate } 28387c478bd9Sstevel@tonic-gate } 28397c478bd9Sstevel@tonic-gate 28407c478bd9Sstevel@tonic-gate /* 28417c478bd9Sstevel@tonic-gate * print either a single value of start to fp (if start equals end), else 28427c478bd9Sstevel@tonic-gate * print start'-'end if start is the smaller of the two values, otherwise 28437c478bd9Sstevel@tonic-gate * print end'-'start. 28447c478bd9Sstevel@tonic-gate */ 28457c478bd9Sstevel@tonic-gate static void 28467c478bd9Sstevel@tonic-gate printrange( 28477c478bd9Sstevel@tonic-gate FILE *fp, 28487c478bd9Sstevel@tonic-gate uint32_t start, 28497c478bd9Sstevel@tonic-gate uint32_t end) 28507c478bd9Sstevel@tonic-gate { 28517c478bd9Sstevel@tonic-gate uint32_t tmp; 28527c478bd9Sstevel@tonic-gate 28537c478bd9Sstevel@tonic-gate if (start > end) { 28547c478bd9Sstevel@tonic-gate tmp = start; 28557c478bd9Sstevel@tonic-gate start = end; 28567c478bd9Sstevel@tonic-gate end = tmp; 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u", start); 28607c478bd9Sstevel@tonic-gate if (end != start) 28617c478bd9Sstevel@tonic-gate (void) fprintf(fp, "-%u", end); 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate /* 28657c478bd9Sstevel@tonic-gate * print the contents of the array arr to fp in the form: 28667c478bd9Sstevel@tonic-gate * {0-6:1;7-12:2;13:3.....} or {0-6:GREEN;7-12:YELLOW:...} 28677c478bd9Sstevel@tonic-gate * dependant upon whether this is an integer or enumerated array resectively 28687c478bd9Sstevel@tonic-gate * (if enum_nvs isn't set to NULL this is assumed to be an enumerated array); 28697c478bd9Sstevel@tonic-gate * where 0-6 is the range of indexes with value 1 (or GREEN), 7-12 the range 28707c478bd9Sstevel@tonic-gate * with value 2 (or YELLOW), and so forth. size is the array size and llimit 28717c478bd9Sstevel@tonic-gate * and ulimit are the lower and upper limits of the array values printed 28727c478bd9Sstevel@tonic-gate * respectively. For enumerated arrays enum_nvs carries the list of name 28737c478bd9Sstevel@tonic-gate * and value pairs and ulimit and llimit parameters are ignored and instead 28747c478bd9Sstevel@tonic-gate * determined from the enum_nvs list. 28757c478bd9Sstevel@tonic-gate */ 28767c478bd9Sstevel@tonic-gate static void 28777c478bd9Sstevel@tonic-gate print_int_array( 28787c478bd9Sstevel@tonic-gate FILE *fp, 28797c478bd9Sstevel@tonic-gate int arr[], 28807c478bd9Sstevel@tonic-gate uint32_t size, 28817c478bd9Sstevel@tonic-gate int llimit, 28827c478bd9Sstevel@tonic-gate int ulimit, 28837c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs, 28847c478bd9Sstevel@tonic-gate int tab_inserts) 28857c478bd9Sstevel@tonic-gate { 28867c478bd9Sstevel@tonic-gate int x, y; 28877c478bd9Sstevel@tonic-gate uint32_t first, last; 28887c478bd9Sstevel@tonic-gate boolean_t first_entry; /* first 'ranges:value' to be printed ? */ 28897c478bd9Sstevel@tonic-gate boolean_t first_range; /* first range for a value to be printed ? */ 28907c478bd9Sstevel@tonic-gate boolean_t found_range; /* did we find a range for this value ? */ 28917c478bd9Sstevel@tonic-gate 28927c478bd9Sstevel@tonic-gate IPQOSCDBG4(L0, "In print_int_array: size: %u, llimit: %u, ulimit: %u, " 28937c478bd9Sstevel@tonic-gate "enum_nvs: %x \n", size, llimit, ulimit, enum_nvs); 28947c478bd9Sstevel@tonic-gate 28957c478bd9Sstevel@tonic-gate /* 28967c478bd9Sstevel@tonic-gate * if an enumeration retrieve value range. 28977c478bd9Sstevel@tonic-gate */ 28987c478bd9Sstevel@tonic-gate if (enum_nvs != NULL) 28997c478bd9Sstevel@tonic-gate get_str_val_value_range(enum_nvs, &llimit, &ulimit); 29007c478bd9Sstevel@tonic-gate 29017c478bd9Sstevel@tonic-gate /* 29027c478bd9Sstevel@tonic-gate * print opening curl. 29037c478bd9Sstevel@tonic-gate */ 29047c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c\n", CURL_BEGIN); 29057c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 29067c478bd9Sstevel@tonic-gate 29077c478bd9Sstevel@tonic-gate first_entry = B_TRUE; 29087c478bd9Sstevel@tonic-gate /* 29097c478bd9Sstevel@tonic-gate * for each value in range. 29107c478bd9Sstevel@tonic-gate */ 29117c478bd9Sstevel@tonic-gate for (x = llimit; x <= ulimit; x++) { 29127c478bd9Sstevel@tonic-gate found_range = B_FALSE; 29137c478bd9Sstevel@tonic-gate first_range = B_TRUE; 29147c478bd9Sstevel@tonic-gate y = 0; 29157c478bd9Sstevel@tonic-gate /* 29167c478bd9Sstevel@tonic-gate * scan array and print ranges of indexes with value x. 29177c478bd9Sstevel@tonic-gate */ 29187c478bd9Sstevel@tonic-gate while (y < size) { 29197c478bd9Sstevel@tonic-gate /* 29207c478bd9Sstevel@tonic-gate * get first occurence of value for this range. 29217c478bd9Sstevel@tonic-gate */ 29227c478bd9Sstevel@tonic-gate while ((arr[y] != x) && (y < size)) 29237c478bd9Sstevel@tonic-gate y++; 29247c478bd9Sstevel@tonic-gate if (y == size) { 29257c478bd9Sstevel@tonic-gate break; 29267c478bd9Sstevel@tonic-gate } else { 29277c478bd9Sstevel@tonic-gate found_range = B_TRUE; 29287c478bd9Sstevel@tonic-gate } 29297c478bd9Sstevel@tonic-gate first = y; 29307c478bd9Sstevel@tonic-gate 29317c478bd9Sstevel@tonic-gate /* 29327c478bd9Sstevel@tonic-gate * get last occurence of value for this range. 29337c478bd9Sstevel@tonic-gate */ 29347c478bd9Sstevel@tonic-gate while ((arr[y] == x) && (y < size)) 29357c478bd9Sstevel@tonic-gate y++; 29367c478bd9Sstevel@tonic-gate last = y - 1; 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate /* 29397c478bd9Sstevel@tonic-gate * print entry delimiter (semi-colon)? It must be 29407c478bd9Sstevel@tonic-gate * the first range for this value and this mustn't 29417c478bd9Sstevel@tonic-gate * be the first 'ranges:value' entry. 29427c478bd9Sstevel@tonic-gate */ 29437c478bd9Sstevel@tonic-gate if (!first_entry && first_range) { 29447c478bd9Sstevel@tonic-gate (void) fprintf(fp, ";\n"); 29457c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 29467c478bd9Sstevel@tonic-gate } else { 29477c478bd9Sstevel@tonic-gate first_entry = B_FALSE; 29487c478bd9Sstevel@tonic-gate } 29497c478bd9Sstevel@tonic-gate 29507c478bd9Sstevel@tonic-gate /* 29517c478bd9Sstevel@tonic-gate * print comma (range delimeter) only if there was 29527c478bd9Sstevel@tonic-gate * a previous range for this value. 29537c478bd9Sstevel@tonic-gate */ 29547c478bd9Sstevel@tonic-gate if (!first_range) { 29557c478bd9Sstevel@tonic-gate (void) fprintf(fp, ","); 29567c478bd9Sstevel@tonic-gate } else { 29577c478bd9Sstevel@tonic-gate first_range = B_FALSE; 29587c478bd9Sstevel@tonic-gate } 29597c478bd9Sstevel@tonic-gate 29607c478bd9Sstevel@tonic-gate /* 29617c478bd9Sstevel@tonic-gate * print range. 29627c478bd9Sstevel@tonic-gate */ 29637c478bd9Sstevel@tonic-gate printrange(fp, first, last); 29647c478bd9Sstevel@tonic-gate } 29657c478bd9Sstevel@tonic-gate /* 29667c478bd9Sstevel@tonic-gate * only print a colon and value if we found a range with 29677c478bd9Sstevel@tonic-gate * this value. 29687c478bd9Sstevel@tonic-gate */ 29697c478bd9Sstevel@tonic-gate if (found_range) { 29707c478bd9Sstevel@tonic-gate (void) fprintf(fp, ":"); 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate /* 29737c478bd9Sstevel@tonic-gate * print numeric/symbolic value. 29747c478bd9Sstevel@tonic-gate */ 29757c478bd9Sstevel@tonic-gate if (enum_nvs) { 29767c478bd9Sstevel@tonic-gate printenum(fp, x, enum_nvs); 29777c478bd9Sstevel@tonic-gate } else { 29787c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%d", x); 29797c478bd9Sstevel@tonic-gate } 29807c478bd9Sstevel@tonic-gate } 29817c478bd9Sstevel@tonic-gate } 29827c478bd9Sstevel@tonic-gate 29837c478bd9Sstevel@tonic-gate /* 29847c478bd9Sstevel@tonic-gate * print closing curl. 29857c478bd9Sstevel@tonic-gate */ 29867c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 29877c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 29887c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c\n", CURL_END); 29897c478bd9Sstevel@tonic-gate } 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate /* print the protocol name for proto, or if unknown protocol number proto. */ 29927c478bd9Sstevel@tonic-gate static void 29937c478bd9Sstevel@tonic-gate printproto( 29947c478bd9Sstevel@tonic-gate FILE *fp, 29957c478bd9Sstevel@tonic-gate uint8_t proto) 29967c478bd9Sstevel@tonic-gate { 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate struct protoent *pent; 29997c478bd9Sstevel@tonic-gate 30007c478bd9Sstevel@tonic-gate pent = getprotobynumber(proto); 30017c478bd9Sstevel@tonic-gate if (pent != NULL) { 30027c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", pent->p_name); 30037c478bd9Sstevel@tonic-gate } else { 30047c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", proto); 30057c478bd9Sstevel@tonic-gate } 30067c478bd9Sstevel@tonic-gate } 30077c478bd9Sstevel@tonic-gate 30087c478bd9Sstevel@tonic-gate /* 30097c478bd9Sstevel@tonic-gate * prints the name associated with interface with index ifindex to fp. 30107c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 30117c478bd9Sstevel@tonic-gate */ 30127c478bd9Sstevel@tonic-gate static int 30137c478bd9Sstevel@tonic-gate printifname( 30147c478bd9Sstevel@tonic-gate FILE *fp, 30157c478bd9Sstevel@tonic-gate int ifindex) 30167c478bd9Sstevel@tonic-gate { 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate int s; 30197c478bd9Sstevel@tonic-gate struct lifconf lc; 30207c478bd9Sstevel@tonic-gate struct lifnum ln; 30217c478bd9Sstevel@tonic-gate struct lifreq *lr; 30227c478bd9Sstevel@tonic-gate char *buf; 30237c478bd9Sstevel@tonic-gate int len; 30247c478bd9Sstevel@tonic-gate char *cp; 30257c478bd9Sstevel@tonic-gate int ret; 30267c478bd9Sstevel@tonic-gate int x; 30277c478bd9Sstevel@tonic-gate int idx; 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate /* open socket */ 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 30327c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, gettext("opening AF_INET socket")); 30337c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30347c478bd9Sstevel@tonic-gate } 30357c478bd9Sstevel@tonic-gate 30367c478bd9Sstevel@tonic-gate /* get number of lifreq structs that need to be alloc'd for */ 30377c478bd9Sstevel@tonic-gate 30387c478bd9Sstevel@tonic-gate ln.lifn_family = AF_UNSPEC; 30397c478bd9Sstevel@tonic-gate ln.lifn_flags = 0; 30407c478bd9Sstevel@tonic-gate ret = ioctl(s, SIOCGLIFNUM, &ln); 30417c478bd9Sstevel@tonic-gate if (ret < 0) { 30427c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "SIOCLIFNUM ioctl"); 30437c478bd9Sstevel@tonic-gate (void) close(s); 30447c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30457c478bd9Sstevel@tonic-gate } 30467c478bd9Sstevel@tonic-gate 30477c478bd9Sstevel@tonic-gate /* allocate buffer for SIOGLIFCONF ioctl */ 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gate len = ln.lifn_count * sizeof (struct lifreq); 30507c478bd9Sstevel@tonic-gate buf = malloc(len); 30517c478bd9Sstevel@tonic-gate if (buf == NULL) { 30527c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 30537c478bd9Sstevel@tonic-gate (void) close(s); 30547c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30557c478bd9Sstevel@tonic-gate } 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate /* setup lifconf params for ioctl */ 30587c478bd9Sstevel@tonic-gate 30597c478bd9Sstevel@tonic-gate lc.lifc_family = AF_UNSPEC; 30607c478bd9Sstevel@tonic-gate lc.lifc_flags = 0; 30617c478bd9Sstevel@tonic-gate lc.lifc_len = len; 30627c478bd9Sstevel@tonic-gate lc.lifc_buf = buf; 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate /* do SIOCGLIFCONF ioctl */ 30657c478bd9Sstevel@tonic-gate 30667c478bd9Sstevel@tonic-gate ret = ioctl(s, SIOCGLIFCONF, &lc); 30677c478bd9Sstevel@tonic-gate if (ret < 0) { 30687c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "SIGLIFCONF"); 30697c478bd9Sstevel@tonic-gate (void) close(s); 30707c478bd9Sstevel@tonic-gate free(buf); 30717c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30727c478bd9Sstevel@tonic-gate } 30737c478bd9Sstevel@tonic-gate (void) close(s); 30747c478bd9Sstevel@tonic-gate 30757c478bd9Sstevel@tonic-gate /* 30767c478bd9Sstevel@tonic-gate * for each interface name given in the returned lifreq list get 30777c478bd9Sstevel@tonic-gate * it's index and compare with ifindex param. Break if equal. 30787c478bd9Sstevel@tonic-gate */ 30797c478bd9Sstevel@tonic-gate for (x = ln.lifn_count, lr = lc.lifc_req; x > 0; x--, lr++) { 30807c478bd9Sstevel@tonic-gate ret = readifindex(lr->lifr_name, &idx); 30817c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 30827c478bd9Sstevel@tonic-gate free(buf); 30837c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30847c478bd9Sstevel@tonic-gate } 30857c478bd9Sstevel@tonic-gate if (idx == ifindex) { 30867c478bd9Sstevel@tonic-gate break; 30877c478bd9Sstevel@tonic-gate } 30887c478bd9Sstevel@tonic-gate } 30897c478bd9Sstevel@tonic-gate free(buf); 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate if (x == 0) { 30927c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "Failed to find if index %u in returned " 30937c478bd9Sstevel@tonic-gate "if list.\n", ifindex); 30947c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 30957c478bd9Sstevel@tonic-gate } 30967c478bd9Sstevel@tonic-gate /* truncate any logical suffix */ 30977c478bd9Sstevel@tonic-gate 30987c478bd9Sstevel@tonic-gate if ((cp = strchr(lr->lifr_name, '@')) != NULL) { 30997c478bd9Sstevel@tonic-gate *cp = NULL; 31007c478bd9Sstevel@tonic-gate } 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate /* print interface name */ 31037c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", lr->lifr_name); 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 31067c478bd9Sstevel@tonic-gate } 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate /* 31097c478bd9Sstevel@tonic-gate * print to fp the enumeration clause evaluating to the value val using the 31107c478bd9Sstevel@tonic-gate * names/values given in enum_nvs. 31117c478bd9Sstevel@tonic-gate */ 31127c478bd9Sstevel@tonic-gate static void 31137c478bd9Sstevel@tonic-gate printenum( 31147c478bd9Sstevel@tonic-gate FILE *fp, 31157c478bd9Sstevel@tonic-gate uint32_t val, 31167c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs) 31177c478bd9Sstevel@tonic-gate { 31187c478bd9Sstevel@tonic-gate 31197c478bd9Sstevel@tonic-gate boolean_t isfirstval = B_TRUE; 31207c478bd9Sstevel@tonic-gate str_val_nd_t *name_val = enum_nvs; 31217c478bd9Sstevel@tonic-gate 31227c478bd9Sstevel@tonic-gate /* for each value in enum_nvs if same bit set in val print name */ 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate while (name_val) { 31257c478bd9Sstevel@tonic-gate if ((name_val->sv.value & val) == name_val->sv.value) { 31267c478bd9Sstevel@tonic-gate if (isfirstval == B_TRUE) { 31277c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s", name_val->sv.string); 31287c478bd9Sstevel@tonic-gate isfirstval = B_FALSE; 31297c478bd9Sstevel@tonic-gate } else { 31307c478bd9Sstevel@tonic-gate (void) fprintf(fp, ", %s", name_val->sv.string); 31317c478bd9Sstevel@tonic-gate } 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate name_val = name_val->next; 31347c478bd9Sstevel@tonic-gate } 31357c478bd9Sstevel@tonic-gate } 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate 31387c478bd9Sstevel@tonic-gate /* prints the service name of port, or if unknown the number to fp. */ 31397c478bd9Sstevel@tonic-gate static void 31407c478bd9Sstevel@tonic-gate printport( 31417c478bd9Sstevel@tonic-gate FILE *fp, 31427c478bd9Sstevel@tonic-gate uint16_t port) 31437c478bd9Sstevel@tonic-gate { 31447c478bd9Sstevel@tonic-gate 31457c478bd9Sstevel@tonic-gate struct servent *sent; 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate sent = getservbyport(port, NULL); 31487c478bd9Sstevel@tonic-gate if (sent != NULL) { 31497c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", sent->s_name); 31507c478bd9Sstevel@tonic-gate } else { 31517c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", ntohs(port)); 31527c478bd9Sstevel@tonic-gate } 31537c478bd9Sstevel@tonic-gate } 31547c478bd9Sstevel@tonic-gate 31557c478bd9Sstevel@tonic-gate /* 31567c478bd9Sstevel@tonic-gate * prints tp fp the name and value of all user specifiable parameters in the 31577c478bd9Sstevel@tonic-gate * nvlist. 31587c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 31597c478bd9Sstevel@tonic-gate */ 31607c478bd9Sstevel@tonic-gate static int 31617c478bd9Sstevel@tonic-gate printnvlist( 31627c478bd9Sstevel@tonic-gate FILE *fp, 31637c478bd9Sstevel@tonic-gate char *module, 31647c478bd9Sstevel@tonic-gate nvlist_t *nvl, 31657c478bd9Sstevel@tonic-gate int printall, /* are we want ip addresses printing if node name */ 31667c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt, /* used to determine if node name set */ 31677c478bd9Sstevel@tonic-gate int tab_inserts, 31687c478bd9Sstevel@tonic-gate place_t place) 31697c478bd9Sstevel@tonic-gate { 31707c478bd9Sstevel@tonic-gate FILE *tfp; 31717c478bd9Sstevel@tonic-gate nvpair_t *nvp; 31727c478bd9Sstevel@tonic-gate char *name; 31737c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 31747c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs; 31757c478bd9Sstevel@tonic-gate int ret; 31767c478bd9Sstevel@tonic-gate char dfltst[IPQOS_VALST_MAXLEN+1]; 31777c478bd9Sstevel@tonic-gate char *param; 31787c478bd9Sstevel@tonic-gate int openerr; 31797c478bd9Sstevel@tonic-gate int res; 31807c478bd9Sstevel@tonic-gate 31817c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In printnvlist\n"); 31827c478bd9Sstevel@tonic-gate 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate /* open stream to types file */ 31857c478bd9Sstevel@tonic-gate 31867c478bd9Sstevel@tonic-gate tfp = validmod(module, &openerr); 31877c478bd9Sstevel@tonic-gate if (tfp == NULL) { 31887c478bd9Sstevel@tonic-gate if (openerr) { 31897c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 31907c478bd9Sstevel@tonic-gate } 31917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 31927c478bd9Sstevel@tonic-gate } 31937c478bd9Sstevel@tonic-gate 31947c478bd9Sstevel@tonic-gate 31957c478bd9Sstevel@tonic-gate /* go through list getting param name and type and printing it */ 31967c478bd9Sstevel@tonic-gate 31977c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, NULL); 31987c478bd9Sstevel@tonic-gate while (nvp) { 31997c478bd9Sstevel@tonic-gate 32007c478bd9Sstevel@tonic-gate /* get nvpair name */ 32017c478bd9Sstevel@tonic-gate name = nvpair_name(nvp); 32027c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "processing element %s.\n", name); 32037c478bd9Sstevel@tonic-gate 32047c478bd9Sstevel@tonic-gate /* skip ipgpc params that are not explicitly user settable */ 32057c478bd9Sstevel@tonic-gate 32067c478bd9Sstevel@tonic-gate if (strcmp(name, IPGPC_FILTER_TYPE) == 0 || 32077c478bd9Sstevel@tonic-gate strcmp(name, IPGPC_SADDR_MASK) == 0 || 32087c478bd9Sstevel@tonic-gate strcmp(name, IPGPC_DADDR_MASK) == 0 || 32097c478bd9Sstevel@tonic-gate strcmp(name, IPGPC_SPORT_MASK) == 0 || 32107c478bd9Sstevel@tonic-gate strcmp(name, IPGPC_DPORT_MASK) == 0) { 32117c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, nvp); 32127c478bd9Sstevel@tonic-gate continue; 32137c478bd9Sstevel@tonic-gate } 32147c478bd9Sstevel@tonic-gate 32157c478bd9Sstevel@tonic-gate param = SHORT_NAME(name); 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate /* 32187c478bd9Sstevel@tonic-gate * get parameter type from types file. 32197c478bd9Sstevel@tonic-gate */ 32207c478bd9Sstevel@tonic-gate place = PL_ANY; 32217c478bd9Sstevel@tonic-gate ret = readtype(tfp, module, param, &type, &enum_nvs, dfltst, 32227c478bd9Sstevel@tonic-gate B_TRUE, &place); 32237c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 32247c478bd9Sstevel@tonic-gate return (ret); 32257c478bd9Sstevel@tonic-gate } 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate /* 32287c478bd9Sstevel@tonic-gate * for map entries we don't print the map value, only 32297c478bd9Sstevel@tonic-gate * the index value it was derived from. 32307c478bd9Sstevel@tonic-gate */ 32317c478bd9Sstevel@tonic-gate if (place == PL_MAP) { 32327c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, nvp); 32337c478bd9Sstevel@tonic-gate continue; 32347c478bd9Sstevel@tonic-gate } 32357c478bd9Sstevel@tonic-gate 32367c478bd9Sstevel@tonic-gate /* 32377c478bd9Sstevel@tonic-gate * the ifindex is converted to the name and printed out 32387c478bd9Sstevel@tonic-gate * so print the parameter name as ifname. 32397c478bd9Sstevel@tonic-gate */ 32407c478bd9Sstevel@tonic-gate if (strcmp(name, IPGPC_IF_INDEX) == 0) { 32417c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 32427c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", IPQOS_IFNAME_STR); 32437c478bd9Sstevel@tonic-gate /* 32447c478bd9Sstevel@tonic-gate * we may not print the address due to us instead printing 32457c478bd9Sstevel@tonic-gate * the node name in printfilter, therefore we leave the 32467c478bd9Sstevel@tonic-gate * printing of the parameter in the addresses switch case code. 32477c478bd9Sstevel@tonic-gate */ 32487c478bd9Sstevel@tonic-gate } else if ((strcmp(name, IPGPC_SADDR) != 0 && 32497c478bd9Sstevel@tonic-gate strcmp(name, IPGPC_DADDR) != 0)) { 32507c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 32517c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", param); 32527c478bd9Sstevel@tonic-gate } 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate switch (type) { 32557c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_IFINDEX: { 32567c478bd9Sstevel@tonic-gate uint32_t ifidx; 32577c478bd9Sstevel@tonic-gate 32587c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &ifidx); 32597c478bd9Sstevel@tonic-gate (void) printifname(fp, ifidx); 32607c478bd9Sstevel@tonic-gate break; 32617c478bd9Sstevel@tonic-gate } 32627c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_BOOLEAN: { 32637c478bd9Sstevel@tonic-gate boolean_t bl; 32647c478bd9Sstevel@tonic-gate 32657c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, 32667c478bd9Sstevel@tonic-gate (uint32_t *)&bl); 32677c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", 32687c478bd9Sstevel@tonic-gate bl == B_TRUE ? "true" : "false"); 32697c478bd9Sstevel@tonic-gate break; 32707c478bd9Sstevel@tonic-gate } 32717c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ACTION: { 32727c478bd9Sstevel@tonic-gate char *strval; 32737c478bd9Sstevel@tonic-gate 32747c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &strval); 32757c478bd9Sstevel@tonic-gate print_action_nm(fp, strval); 32767c478bd9Sstevel@tonic-gate break; 32777c478bd9Sstevel@tonic-gate } 32787c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_STRING: { 32797c478bd9Sstevel@tonic-gate char *strval; 32807c478bd9Sstevel@tonic-gate 32817c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &strval); 32827c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", 32837c478bd9Sstevel@tonic-gate quote_ws_string(strval)); 32847c478bd9Sstevel@tonic-gate break; 32857c478bd9Sstevel@tonic-gate } 32867c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ADDRESS: { 32877c478bd9Sstevel@tonic-gate uint_t tmp; 32887c478bd9Sstevel@tonic-gate in6_addr_t *addr; 32897c478bd9Sstevel@tonic-gate char addrstr[INET6_ADDRSTRLEN]; 32907c478bd9Sstevel@tonic-gate uchar_t ftype; 32917c478bd9Sstevel@tonic-gate int af; 32927c478bd9Sstevel@tonic-gate in6_addr_t *mask; 32937c478bd9Sstevel@tonic-gate 32947c478bd9Sstevel@tonic-gate /* 32957c478bd9Sstevel@tonic-gate * skip addresses that have node names for 32967c478bd9Sstevel@tonic-gate * non printall listings. 32977c478bd9Sstevel@tonic-gate */ 32987c478bd9Sstevel@tonic-gate if (printall == 0 && 32997c478bd9Sstevel@tonic-gate (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 33007c478bd9Sstevel@tonic-gate 0 && flt->src_nd_name || 33017c478bd9Sstevel@tonic-gate strcmp(nvpair_name(nvp), IPGPC_DADDR) == 33027c478bd9Sstevel@tonic-gate 0 && flt->dst_nd_name)) { 33037c478bd9Sstevel@tonic-gate break; 33047c478bd9Sstevel@tonic-gate } 33057c478bd9Sstevel@tonic-gate 33067c478bd9Sstevel@tonic-gate /* we skipped this above */ 33077c478bd9Sstevel@tonic-gate 33087c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 33097c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", param); 33107c478bd9Sstevel@tonic-gate 33117c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32_array(nvp, 33127c478bd9Sstevel@tonic-gate (uint32_t **)&addr, &tmp); 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate /* get filter type */ 33157c478bd9Sstevel@tonic-gate 33167c478bd9Sstevel@tonic-gate (void) nvlist_lookup_byte(nvl, 33177c478bd9Sstevel@tonic-gate IPGPC_FILTER_TYPE, &ftype); 33187c478bd9Sstevel@tonic-gate if (ftype == IPGPC_V4_FLTR) { 33197c478bd9Sstevel@tonic-gate af = AF_INET; 33207c478bd9Sstevel@tonic-gate addr = (in6_addr_t *) 33217c478bd9Sstevel@tonic-gate &V4_PART_OF_V6((*addr)); 33227c478bd9Sstevel@tonic-gate } else { 33237c478bd9Sstevel@tonic-gate af = AF_INET6; 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate /* get mask */ 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 33287c478bd9Sstevel@tonic-gate 0) { 33297c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32_array(nvl, 33307c478bd9Sstevel@tonic-gate IPGPC_SADDR_MASK, 33317c478bd9Sstevel@tonic-gate (uint32_t **)&mask, &tmp); 33327c478bd9Sstevel@tonic-gate } else { 33337c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32_array(nvl, 33347c478bd9Sstevel@tonic-gate IPGPC_DADDR_MASK, 33357c478bd9Sstevel@tonic-gate (uint32_t **)&mask, &tmp); 33367c478bd9Sstevel@tonic-gate } 33377c478bd9Sstevel@tonic-gate 33387c478bd9Sstevel@tonic-gate /* print address/mask to fp */ 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s/%u\n", 33417c478bd9Sstevel@tonic-gate inet_ntop(af, addr, addrstr, 33427c478bd9Sstevel@tonic-gate INET6_ADDRSTRLEN), masktocidr(af, mask)); 33437c478bd9Sstevel@tonic-gate break; 33447c478bd9Sstevel@tonic-gate } 33457c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ENUM: { 33467c478bd9Sstevel@tonic-gate uint32_t val; 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &val); 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate /* 33517c478bd9Sstevel@tonic-gate * print list of tokens resulting in val 33527c478bd9Sstevel@tonic-gate */ 33537c478bd9Sstevel@tonic-gate (void) fprintf(fp, "{ "); 33547c478bd9Sstevel@tonic-gate printenum(fp, val, enum_nvs); 33557c478bd9Sstevel@tonic-gate (void) fprintf(fp, " }\n"); 33567c478bd9Sstevel@tonic-gate break; 33577c478bd9Sstevel@tonic-gate } 33587c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PORT: { 33597c478bd9Sstevel@tonic-gate uint16_t port; 33607c478bd9Sstevel@tonic-gate 33617c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16(nvp, &port); 33627c478bd9Sstevel@tonic-gate printport(fp, port); 33637c478bd9Sstevel@tonic-gate break; 33647c478bd9Sstevel@tonic-gate } 33657c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PROTO: { 33667c478bd9Sstevel@tonic-gate uint8_t proto; 33677c478bd9Sstevel@tonic-gate 33687c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, &proto); 33697c478bd9Sstevel@tonic-gate printproto(fp, proto); 33707c478bd9Sstevel@tonic-gate break; 33717c478bd9Sstevel@tonic-gate } 33727c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_M_INDEX: 33737c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT8: { 33747c478bd9Sstevel@tonic-gate uchar_t u8; 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, &u8); 33777c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", u8); 33787c478bd9Sstevel@tonic-gate break; 33797c478bd9Sstevel@tonic-gate } 33807c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT16: { 33817c478bd9Sstevel@tonic-gate uint16_t u16; 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16(nvp, &u16); 33847c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", u16); 33857c478bd9Sstevel@tonic-gate break; 33867c478bd9Sstevel@tonic-gate } 33877c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT16: { 33887c478bd9Sstevel@tonic-gate int16_t i16; 33897c478bd9Sstevel@tonic-gate 33907c478bd9Sstevel@tonic-gate (void) nvpair_value_int16(nvp, &i16); 33917c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%d\n", i16); 33927c478bd9Sstevel@tonic-gate break; 33937c478bd9Sstevel@tonic-gate } 33947c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT32: { 33957c478bd9Sstevel@tonic-gate uint32_t u32; 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &u32); 33987c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%u\n", u32); 33997c478bd9Sstevel@tonic-gate break; 34007c478bd9Sstevel@tonic-gate } 34017c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT32: { 34027c478bd9Sstevel@tonic-gate int i32; 34037c478bd9Sstevel@tonic-gate 34047c478bd9Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &i32); 34057c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%d\n", i32); 34067c478bd9Sstevel@tonic-gate break; 34077c478bd9Sstevel@tonic-gate } 34087c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT_ARRAY: { 34097c478bd9Sstevel@tonic-gate str_val_nd_t *arr_enum_nvs = NULL; 34107c478bd9Sstevel@tonic-gate uint32_t size; 34117c478bd9Sstevel@tonic-gate int llimit, ulimit; 34127c478bd9Sstevel@tonic-gate int *arr; 34137c478bd9Sstevel@tonic-gate 34147c478bd9Sstevel@tonic-gate (void) nvpair_value_int32_array(nvp, &arr, 34157c478bd9Sstevel@tonic-gate &size); 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate /* 34187c478bd9Sstevel@tonic-gate * read array info from types file. 34197c478bd9Sstevel@tonic-gate */ 34207c478bd9Sstevel@tonic-gate res = read_int_array_info(dfltst, 34217c478bd9Sstevel@tonic-gate &arr_enum_nvs, &size, &llimit, &ulimit, 34227c478bd9Sstevel@tonic-gate module); 34237c478bd9Sstevel@tonic-gate 34247c478bd9Sstevel@tonic-gate /* 34257c478bd9Sstevel@tonic-gate * print array with numbers, or symbols 34267c478bd9Sstevel@tonic-gate * if enumerated. 34277c478bd9Sstevel@tonic-gate */ 34287c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 34297c478bd9Sstevel@tonic-gate print_int_array(fp, arr, size, 34307c478bd9Sstevel@tonic-gate llimit, ulimit, arr_enum_nvs, 34317c478bd9Sstevel@tonic-gate tab_inserts); 34327c478bd9Sstevel@tonic-gate if (arr_enum_nvs != NULL) { 34337c478bd9Sstevel@tonic-gate free_str_val_entrys( 34347c478bd9Sstevel@tonic-gate arr_enum_nvs); 34357c478bd9Sstevel@tonic-gate } 34367c478bd9Sstevel@tonic-gate } 34377c478bd9Sstevel@tonic-gate break; 34387c478bd9Sstevel@tonic-gate } 34397c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_USER: { 34407c478bd9Sstevel@tonic-gate uid_t uid; 34417c478bd9Sstevel@tonic-gate 34427c478bd9Sstevel@tonic-gate (void) nvpair_value_int32(nvp, (int *)&uid); 34437c478bd9Sstevel@tonic-gate printuser(fp, uid); 34447c478bd9Sstevel@tonic-gate break; 34457c478bd9Sstevel@tonic-gate } 34467c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 34477c478bd9Sstevel@tonic-gate default: { 34487c478bd9Sstevel@tonic-gate /* 34497c478bd9Sstevel@tonic-gate * we should have catered for all used data 34507c478bd9Sstevel@tonic-gate * types that readtype returns. 34517c478bd9Sstevel@tonic-gate */ 34527c478bd9Sstevel@tonic-gate assert(1); 34537c478bd9Sstevel@tonic-gate } 34547c478bd9Sstevel@tonic-gate #endif 34557c478bd9Sstevel@tonic-gate } 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, nvp); 34587c478bd9Sstevel@tonic-gate } 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gate (void) fclose(tfp); 34617c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 34627c478bd9Sstevel@tonic-gate } 34637c478bd9Sstevel@tonic-gate 34647c478bd9Sstevel@tonic-gate /* 34657c478bd9Sstevel@tonic-gate * print a parameter clause for the parmeters given in params to fp. 34667c478bd9Sstevel@tonic-gate * If printall is set, then the originator of the parameter object is printed. 34677c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 34687c478bd9Sstevel@tonic-gate */ 34697c478bd9Sstevel@tonic-gate static int 34707c478bd9Sstevel@tonic-gate printparams( 34717c478bd9Sstevel@tonic-gate FILE *fp, 34727c478bd9Sstevel@tonic-gate char *module, 34737c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params, 34747c478bd9Sstevel@tonic-gate int printall, 34757c478bd9Sstevel@tonic-gate int tab_inserts) 34767c478bd9Sstevel@tonic-gate { 34777c478bd9Sstevel@tonic-gate 34787c478bd9Sstevel@tonic-gate int res; 34797c478bd9Sstevel@tonic-gate 34807c478bd9Sstevel@tonic-gate /* print opening clause */ 34817c478bd9Sstevel@tonic-gate 34827c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 34837c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_PARAMS_STR " {\n"); 34847c478bd9Sstevel@tonic-gate 34857c478bd9Sstevel@tonic-gate /* print originator name if printall flag set */ 34867c478bd9Sstevel@tonic-gate 34877c478bd9Sstevel@tonic-gate if (printall) { 34887c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 34897c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "Originator %s\n", 34907c478bd9Sstevel@tonic-gate quote_ws_string(get_originator_nm(params->originator))); 34917c478bd9Sstevel@tonic-gate } 34927c478bd9Sstevel@tonic-gate 34937c478bd9Sstevel@tonic-gate /* print global stats */ 34947c478bd9Sstevel@tonic-gate 34957c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 34967c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_GLOBAL_STATS_STR " %s\n", 34977c478bd9Sstevel@tonic-gate params->stats_enable == B_TRUE ? "true" : "false"); 34987c478bd9Sstevel@tonic-gate 34997c478bd9Sstevel@tonic-gate /* print module specific parameters */ 35007c478bd9Sstevel@tonic-gate res = printnvlist(fp, module, params->nvlist, printall, NULL, 35017c478bd9Sstevel@tonic-gate tab_inserts + 1, PL_PARAMS); 35027c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 35037c478bd9Sstevel@tonic-gate return (res); 35047c478bd9Sstevel@tonic-gate } 35057c478bd9Sstevel@tonic-gate 35067c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 35077c478bd9Sstevel@tonic-gate (void) fprintf(fp, "}\n"); 35087c478bd9Sstevel@tonic-gate 35097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 35107c478bd9Sstevel@tonic-gate } 35117c478bd9Sstevel@tonic-gate 35127c478bd9Sstevel@tonic-gate /* 35137c478bd9Sstevel@tonic-gate * print the interpreted name of the action_nm parameter if it is a special 35147c478bd9Sstevel@tonic-gate * action, else action_nm verbatim to fp parameter. 35157c478bd9Sstevel@tonic-gate */ 35167c478bd9Sstevel@tonic-gate static void 35177c478bd9Sstevel@tonic-gate print_action_nm(FILE *fp, char *action_nm) 35187c478bd9Sstevel@tonic-gate { 35197c478bd9Sstevel@tonic-gate 35207c478bd9Sstevel@tonic-gate if (strcmp(action_nm, IPP_ANAME_CONT) == 0) { 35217c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_CONT_STR "\n"); 35227c478bd9Sstevel@tonic-gate } else if (strcmp(action_nm, IPP_ANAME_DEFER) == 0) { 35237c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_DEFER_STR "\n"); 35247c478bd9Sstevel@tonic-gate } else if (strcmp(action_nm, IPP_ANAME_DROP) == 0) { 35257c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_DROP_STR "\n"); 35267c478bd9Sstevel@tonic-gate } else { 35277c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", quote_ws_string(action_nm)); 35287c478bd9Sstevel@tonic-gate } 35297c478bd9Sstevel@tonic-gate } 35307c478bd9Sstevel@tonic-gate 35317c478bd9Sstevel@tonic-gate /* 35327c478bd9Sstevel@tonic-gate * print a class clause for class to fp. If printall is set the originator 35337c478bd9Sstevel@tonic-gate * is printed. 35347c478bd9Sstevel@tonic-gate */ 35357c478bd9Sstevel@tonic-gate static void 35367c478bd9Sstevel@tonic-gate printclass( 35377c478bd9Sstevel@tonic-gate FILE *fp, 35387c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class, 35397c478bd9Sstevel@tonic-gate int printall, 35407c478bd9Sstevel@tonic-gate int tab_inserts) 35417c478bd9Sstevel@tonic-gate { 35427c478bd9Sstevel@tonic-gate 35437c478bd9Sstevel@tonic-gate /* print opening clause */ 35447c478bd9Sstevel@tonic-gate 35457c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 35467c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_CLASS_STR " {\n"); 35477c478bd9Sstevel@tonic-gate 35487c478bd9Sstevel@tonic-gate 35497c478bd9Sstevel@tonic-gate /* if printall flag print originator name */ 35507c478bd9Sstevel@tonic-gate 35517c478bd9Sstevel@tonic-gate if (printall) { 35527c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 35537c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "Originator %s\n", 35547c478bd9Sstevel@tonic-gate get_originator_nm(class->originator)); 35557c478bd9Sstevel@tonic-gate } 35567c478bd9Sstevel@tonic-gate 35577c478bd9Sstevel@tonic-gate /* print name, next action and stats enable */ 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 35607c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_NAME_STR " %s\n", 35617c478bd9Sstevel@tonic-gate quote_ws_string(class->name)); 35627c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 35637c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_NEXT_ACTION_STR " "); 35647c478bd9Sstevel@tonic-gate print_action_nm(fp, class->alist->name); 35657c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 35667c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_STATS_ENABLE_STR " %s\n", 35677c478bd9Sstevel@tonic-gate class->stats_enable == B_TRUE ? "true" : "false"); 35687c478bd9Sstevel@tonic-gate 35697c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 35707c478bd9Sstevel@tonic-gate (void) fprintf(fp, "}\n"); 35717c478bd9Sstevel@tonic-gate } 35727c478bd9Sstevel@tonic-gate 35737c478bd9Sstevel@tonic-gate /* 35747c478bd9Sstevel@tonic-gate * Returns a ptr to the originator name associated with origid. If unknown 35757c478bd9Sstevel@tonic-gate * id returns ptr to "unknown". 35767c478bd9Sstevel@tonic-gate * RETURNS: ptr to originator name, or if id not known "unknown". 35777c478bd9Sstevel@tonic-gate */ 35787c478bd9Sstevel@tonic-gate static char * 35797c478bd9Sstevel@tonic-gate get_originator_nm(uint32_t origid) 35807c478bd9Sstevel@tonic-gate { 35817c478bd9Sstevel@tonic-gate 35827c478bd9Sstevel@tonic-gate int x; 35837c478bd9Sstevel@tonic-gate 35847c478bd9Sstevel@tonic-gate /* scan originators table for origid */ 35857c478bd9Sstevel@tonic-gate 35867c478bd9Sstevel@tonic-gate for (x = 0; originators[x].value != -1 && 35877c478bd9Sstevel@tonic-gate originators[x].value != origid; x++) {} 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate /* if we've reached end of array due to unknown type return "unknown" */ 35907c478bd9Sstevel@tonic-gate 35917c478bd9Sstevel@tonic-gate if (originators[x].value == -1) { 35927c478bd9Sstevel@tonic-gate return ("unknown"); 35937c478bd9Sstevel@tonic-gate } 35947c478bd9Sstevel@tonic-gate 35957c478bd9Sstevel@tonic-gate return (originators[x].string); 35967c478bd9Sstevel@tonic-gate } 35977c478bd9Sstevel@tonic-gate 35987c478bd9Sstevel@tonic-gate /* 35997c478bd9Sstevel@tonic-gate * print a filter clause for filter pointed to by filter out to fp. If printall 36007c478bd9Sstevel@tonic-gate * is set then the originator is printed, for filters with node names instance 36017c478bd9Sstevel@tonic-gate * numbers are printed, and the filter pointer isn't advanced to point at the 36027c478bd9Sstevel@tonic-gate * last instance of the printed filter. 36037c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 36047c478bd9Sstevel@tonic-gate */ 36057c478bd9Sstevel@tonic-gate static int 36067c478bd9Sstevel@tonic-gate printfilter( 36077c478bd9Sstevel@tonic-gate FILE *fp, 36087c478bd9Sstevel@tonic-gate char *module, 36097c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **filter, 36107c478bd9Sstevel@tonic-gate int printall, 36117c478bd9Sstevel@tonic-gate int tab_inserts) 36127c478bd9Sstevel@tonic-gate { 36137c478bd9Sstevel@tonic-gate 36147c478bd9Sstevel@tonic-gate int res; 36157c478bd9Sstevel@tonic-gate 36167c478bd9Sstevel@tonic-gate /* print opening clause */ 36177c478bd9Sstevel@tonic-gate 36187c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 36197c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_FILTER_STR " {\n"); 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate /* print originator if printall flag set */ 36227c478bd9Sstevel@tonic-gate 36237c478bd9Sstevel@tonic-gate if (printall) { 36247c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36257c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "Originator %s\n", 36267c478bd9Sstevel@tonic-gate quote_ws_string(get_originator_nm((*filter)->originator))); 36277c478bd9Sstevel@tonic-gate } 36287c478bd9Sstevel@tonic-gate 36297c478bd9Sstevel@tonic-gate /* print name and class */ 36307c478bd9Sstevel@tonic-gate 36317c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36327c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_NAME_STR " %s\n", 36337c478bd9Sstevel@tonic-gate quote_ws_string((*filter)->name)); 36347c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36357c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_CLASS_STR " %s\n", 36367c478bd9Sstevel@tonic-gate quote_ws_string((*filter)->class_name)); 36377c478bd9Sstevel@tonic-gate 36387c478bd9Sstevel@tonic-gate /* print the instance if printall and potential mhomed addresses */ 36397c478bd9Sstevel@tonic-gate 36407c478bd9Sstevel@tonic-gate if (printall && ((*filter)->src_nd_name || (*filter)->dst_nd_name)) { 36417c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36427c478bd9Sstevel@tonic-gate (void) fprintf(fp, "Instance %u\n", (*filter)->instance); 36437c478bd9Sstevel@tonic-gate } 36447c478bd9Sstevel@tonic-gate 36457c478bd9Sstevel@tonic-gate /* print node names if any */ 36467c478bd9Sstevel@tonic-gate 36477c478bd9Sstevel@tonic-gate if ((*filter)->src_nd_name) { 36487c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36497c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s %s\n", strchr(IPGPC_SADDR, '.') + 1, 36507c478bd9Sstevel@tonic-gate (*filter)->src_nd_name); 36517c478bd9Sstevel@tonic-gate } 36527c478bd9Sstevel@tonic-gate if ((*filter)->dst_nd_name) { 36537c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36547c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s %s\n", strchr(IPGPC_DADDR, '.') + 1, 36557c478bd9Sstevel@tonic-gate (*filter)->dst_nd_name); 36567c478bd9Sstevel@tonic-gate } 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate /* print ip_version enumeration if set */ 36597c478bd9Sstevel@tonic-gate 36607c478bd9Sstevel@tonic-gate if ((*filter)->ip_versions != 0) { 36617c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 36627c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_IP_VERSION_STR " {"); 36637c478bd9Sstevel@tonic-gate if (VERSION_IS_V4(*filter)) { 36647c478bd9Sstevel@tonic-gate (void) fprintf(fp, " V4"); 36657c478bd9Sstevel@tonic-gate } 36667c478bd9Sstevel@tonic-gate if (VERSION_IS_V6(*filter)) { 36677c478bd9Sstevel@tonic-gate (void) fprintf(fp, " V6"); 36687c478bd9Sstevel@tonic-gate } 36697c478bd9Sstevel@tonic-gate (void) fprintf(fp, " }\n"); 36707c478bd9Sstevel@tonic-gate } 36717c478bd9Sstevel@tonic-gate 36727c478bd9Sstevel@tonic-gate /* print other module specific parameters parameters */ 36737c478bd9Sstevel@tonic-gate 36747c478bd9Sstevel@tonic-gate res = printnvlist(fp, module, (*filter)->nvlist, printall, *filter, 36757c478bd9Sstevel@tonic-gate tab_inserts + 1, PL_FILTER); 36767c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 36777c478bd9Sstevel@tonic-gate return (res); 36787c478bd9Sstevel@tonic-gate } 36797c478bd9Sstevel@tonic-gate 36807c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 36817c478bd9Sstevel@tonic-gate (void) fprintf(fp, "}\n"); 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate /* 36847c478bd9Sstevel@tonic-gate * if not printall advance filter parameter to last instance of this 36857c478bd9Sstevel@tonic-gate * filter. 36867c478bd9Sstevel@tonic-gate */ 36877c478bd9Sstevel@tonic-gate 36887c478bd9Sstevel@tonic-gate if (!printall) { 36897c478bd9Sstevel@tonic-gate for (;;) { 36907c478bd9Sstevel@tonic-gate if ((*filter)->next == NULL || 36917c478bd9Sstevel@tonic-gate strcmp((*filter)->name, (*filter)->next->name) != 36927c478bd9Sstevel@tonic-gate 0) { 36937c478bd9Sstevel@tonic-gate break; 36947c478bd9Sstevel@tonic-gate } 36957c478bd9Sstevel@tonic-gate *filter = (*filter)->next; 36967c478bd9Sstevel@tonic-gate } 36977c478bd9Sstevel@tonic-gate } 36987c478bd9Sstevel@tonic-gate 36997c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 37007c478bd9Sstevel@tonic-gate } 37017c478bd9Sstevel@tonic-gate 37027c478bd9Sstevel@tonic-gate /* 37037c478bd9Sstevel@tonic-gate * Returns a pointer to str if no whitespace is present, else it returns 37047c478bd9Sstevel@tonic-gate * a pointer to a string with the contents of str enclose in double quotes. 37057c478bd9Sstevel@tonic-gate * This returned strings contents may change in subsequent calls so a copy 37067c478bd9Sstevel@tonic-gate * should be made of it if the caller wishes to retain it. 37077c478bd9Sstevel@tonic-gate */ 37087c478bd9Sstevel@tonic-gate static char * 37097c478bd9Sstevel@tonic-gate quote_ws_string(const char *str) 37107c478bd9Sstevel@tonic-gate { 37117c478bd9Sstevel@tonic-gate static char *buf = NULL; 37127c478bd9Sstevel@tonic-gate const char *cp; /* we don't modify the contents of str so const */ 37137c478bd9Sstevel@tonic-gate 37147c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In quote_ws_string\n"); 37157c478bd9Sstevel@tonic-gate 37167c478bd9Sstevel@tonic-gate /* 37177c478bd9Sstevel@tonic-gate * Just return str if no whitespace. 37187c478bd9Sstevel@tonic-gate */ 37197c478bd9Sstevel@tonic-gate for (cp = str; (*cp != '\0') && !isspace(*cp); cp++) 37207c478bd9Sstevel@tonic-gate ; 37217c478bd9Sstevel@tonic-gate if (*cp == '\0') 37227c478bd9Sstevel@tonic-gate return ((char *)str); 37237c478bd9Sstevel@tonic-gate 37247c478bd9Sstevel@tonic-gate if (buf == NULL) { 37257c478bd9Sstevel@tonic-gate /* 37267c478bd9Sstevel@tonic-gate * if first run just allocate buffer of 37277c478bd9Sstevel@tonic-gate * strlen(str) + 2 quote characters + NULL terminator. 37287c478bd9Sstevel@tonic-gate */ 37297c478bd9Sstevel@tonic-gate buf = malloc(strlen(str) + 3); 37307c478bd9Sstevel@tonic-gate } else if ((strlen(str) + 2) > strlen(buf)) { 37317c478bd9Sstevel@tonic-gate /* 37327c478bd9Sstevel@tonic-gate * Not first run, so check if we have a big enough buffer 37337c478bd9Sstevel@tonic-gate * and if not reallocate the buffer to a sufficient size. 37347c478bd9Sstevel@tonic-gate */ 37357c478bd9Sstevel@tonic-gate buf = realloc(buf, strlen(str) + 3); 37367c478bd9Sstevel@tonic-gate } 37377c478bd9Sstevel@tonic-gate if (buf == NULL) 37387c478bd9Sstevel@tonic-gate return (""); 37397c478bd9Sstevel@tonic-gate 37407c478bd9Sstevel@tonic-gate /* 37417c478bd9Sstevel@tonic-gate * copy string into buffer with quotes. 37427c478bd9Sstevel@tonic-gate */ 37437c478bd9Sstevel@tonic-gate (void) strcpy(buf, "\""); 37447c478bd9Sstevel@tonic-gate (void) strcat(buf, str); 37457c478bd9Sstevel@tonic-gate (void) strcat(buf, "\""); 37467c478bd9Sstevel@tonic-gate 37477c478bd9Sstevel@tonic-gate return (buf); 37487c478bd9Sstevel@tonic-gate } 37497c478bd9Sstevel@tonic-gate 37507c478bd9Sstevel@tonic-gate /* 37517c478bd9Sstevel@tonic-gate * print an action clause for action to fp. If the printall flag is set 37527c478bd9Sstevel@tonic-gate * then all filters and classes (regardless of their originator) and 37537c478bd9Sstevel@tonic-gate * their originators are displayed. 37547c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 37557c478bd9Sstevel@tonic-gate */ 37567c478bd9Sstevel@tonic-gate static int 37577c478bd9Sstevel@tonic-gate printaction( 37587c478bd9Sstevel@tonic-gate FILE *fp, 37597c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action, 37607c478bd9Sstevel@tonic-gate int printall, 37617c478bd9Sstevel@tonic-gate int tab_inserts) 37627c478bd9Sstevel@tonic-gate { 37637c478bd9Sstevel@tonic-gate 37647c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 37657c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 37667c478bd9Sstevel@tonic-gate int res; 37677c478bd9Sstevel@tonic-gate 37687c478bd9Sstevel@tonic-gate /* print opening clause, module and name */ 37697c478bd9Sstevel@tonic-gate 37707c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 37717c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_ACTION_STR " {\n"); 37727c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 37737c478bd9Sstevel@tonic-gate (void) fprintf(fp, IPQOS_CONF_MODULE_STR " %s\n", 37747c478bd9Sstevel@tonic-gate quote_ws_string(action->module)); 37757c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts + 1); 37767c478bd9Sstevel@tonic-gate (void) fprintf(fp, "name %s\n", quote_ws_string(action->name)); 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate /* print params clause */ 37797c478bd9Sstevel@tonic-gate 37807c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 37817c478bd9Sstevel@tonic-gate res = printparams(fp, action->module, action->params, printall, 37827c478bd9Sstevel@tonic-gate tab_inserts + 1); 37837c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 37847c478bd9Sstevel@tonic-gate return (res); 37857c478bd9Sstevel@tonic-gate } 37867c478bd9Sstevel@tonic-gate 37877c478bd9Sstevel@tonic-gate /* 37887c478bd9Sstevel@tonic-gate * print classes clause for each class if printall is set, else 37897c478bd9Sstevel@tonic-gate * just ipqosconf created or permanent classes. 37907c478bd9Sstevel@tonic-gate */ 37917c478bd9Sstevel@tonic-gate for (cls = action->classes; cls != NULL; cls = cls->next) { 37927c478bd9Sstevel@tonic-gate if (printall || 37937c478bd9Sstevel@tonic-gate cls->originator == IPP_CONFIG_IPQOSCONF || 37947c478bd9Sstevel@tonic-gate cls->originator == IPP_CONFIG_PERMANENT) { 37957c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 37967c478bd9Sstevel@tonic-gate printclass(fp, cls, printall, tab_inserts + 1); 37977c478bd9Sstevel@tonic-gate } 37987c478bd9Sstevel@tonic-gate } 37997c478bd9Sstevel@tonic-gate 38007c478bd9Sstevel@tonic-gate /* 38017c478bd9Sstevel@tonic-gate * print filter clause for each filter if printall is set, else 38027c478bd9Sstevel@tonic-gate * just ipqosconf created or permanent filters. 38037c478bd9Sstevel@tonic-gate */ 38047c478bd9Sstevel@tonic-gate for (flt = action->filters; flt != NULL; flt = flt->next) { 38057c478bd9Sstevel@tonic-gate if (printall || 38067c478bd9Sstevel@tonic-gate flt->originator == IPP_CONFIG_IPQOSCONF || 38077c478bd9Sstevel@tonic-gate flt->originator == IPP_CONFIG_PERMANENT) { 38087c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 38097c478bd9Sstevel@tonic-gate res = printfilter(fp, action->module, &flt, printall, 38107c478bd9Sstevel@tonic-gate tab_inserts + 1); 38117c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 38127c478bd9Sstevel@tonic-gate return (res); 38137c478bd9Sstevel@tonic-gate } 38147c478bd9Sstevel@tonic-gate } 38157c478bd9Sstevel@tonic-gate } 38167c478bd9Sstevel@tonic-gate 38177c478bd9Sstevel@tonic-gate PRINT_TABS(fp, tab_inserts); 38187c478bd9Sstevel@tonic-gate (void) fprintf(fp, "}\n"); 38197c478bd9Sstevel@tonic-gate 38207c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 38217c478bd9Sstevel@tonic-gate } 38227c478bd9Sstevel@tonic-gate 38237c478bd9Sstevel@tonic-gate 38247c478bd9Sstevel@tonic-gate 38257c478bd9Sstevel@tonic-gate /* *************************************************************** */ 38267c478bd9Sstevel@tonic-gate 38277c478bd9Sstevel@tonic-gate 38287c478bd9Sstevel@tonic-gate static void 38297c478bd9Sstevel@tonic-gate list_end( 38307c478bd9Sstevel@tonic-gate ipqos_list_el_t **listp, 38317c478bd9Sstevel@tonic-gate ipqos_list_el_t ***lendpp) 38327c478bd9Sstevel@tonic-gate { 38337c478bd9Sstevel@tonic-gate *lendpp = listp; 38347c478bd9Sstevel@tonic-gate while (**lendpp != NULL) { 38357c478bd9Sstevel@tonic-gate *lendpp = &(**lendpp)->next; 38367c478bd9Sstevel@tonic-gate } 38377c478bd9Sstevel@tonic-gate } 38387c478bd9Sstevel@tonic-gate 38397c478bd9Sstevel@tonic-gate static void 38407c478bd9Sstevel@tonic-gate add_to_list( 38417c478bd9Sstevel@tonic-gate ipqos_list_el_t **listp, 38427c478bd9Sstevel@tonic-gate ipqos_list_el_t *el) 38437c478bd9Sstevel@tonic-gate { 38447c478bd9Sstevel@tonic-gate el->next = *listp; 38457c478bd9Sstevel@tonic-gate *listp = el; 38467c478bd9Sstevel@tonic-gate } 38477c478bd9Sstevel@tonic-gate 38487c478bd9Sstevel@tonic-gate /* 38497c478bd9Sstevel@tonic-gate * given mask calculates the number of bits it spans. The mask must be 38507c478bd9Sstevel@tonic-gate * continuous. 38517c478bd9Sstevel@tonic-gate * RETURNS: number of bits spanned. 38527c478bd9Sstevel@tonic-gate */ 38537c478bd9Sstevel@tonic-gate static int 38547c478bd9Sstevel@tonic-gate masktocidr( 38557c478bd9Sstevel@tonic-gate int af, 38567c478bd9Sstevel@tonic-gate in6_addr_t *mask) 38577c478bd9Sstevel@tonic-gate { 38587c478bd9Sstevel@tonic-gate int zeros = 0; 38597c478bd9Sstevel@tonic-gate int byte; 38607c478bd9Sstevel@tonic-gate int cidr; 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate /* 38637c478bd9Sstevel@tonic-gate * loop through from lowest byte to highest byte counting the 38647c478bd9Sstevel@tonic-gate * number of zero bits till hitting a one bit. 38657c478bd9Sstevel@tonic-gate */ 38667c478bd9Sstevel@tonic-gate for (byte = 15; byte >= 0; byte--) { 38677c478bd9Sstevel@tonic-gate /* 38687c478bd9Sstevel@tonic-gate * zero byte, so add 8 to zeros. 38697c478bd9Sstevel@tonic-gate */ 38707c478bd9Sstevel@tonic-gate if (mask->s6_addr[byte] == 0) { 38717c478bd9Sstevel@tonic-gate zeros += 8; 38727c478bd9Sstevel@tonic-gate /* 38737c478bd9Sstevel@tonic-gate * non-zero byte, add zero count to zeros. 38747c478bd9Sstevel@tonic-gate */ 38757c478bd9Sstevel@tonic-gate } else { 38767c478bd9Sstevel@tonic-gate zeros += (ffs((int)mask->s6_addr[byte]) - 1); 38777c478bd9Sstevel@tonic-gate break; 38787c478bd9Sstevel@tonic-gate } 38797c478bd9Sstevel@tonic-gate } 38807c478bd9Sstevel@tonic-gate /* 38817c478bd9Sstevel@tonic-gate * translate zero bits to 32 or 128 bit mask based on af. 38827c478bd9Sstevel@tonic-gate */ 38837c478bd9Sstevel@tonic-gate if (af == AF_INET) { 38847c478bd9Sstevel@tonic-gate cidr = 32 - zeros; 38857c478bd9Sstevel@tonic-gate } else { 38867c478bd9Sstevel@tonic-gate cidr = 128 - zeros; 38877c478bd9Sstevel@tonic-gate } 38887c478bd9Sstevel@tonic-gate 38897c478bd9Sstevel@tonic-gate return (cidr); 38907c478bd9Sstevel@tonic-gate } 38917c478bd9Sstevel@tonic-gate 38927c478bd9Sstevel@tonic-gate /* 38937c478bd9Sstevel@tonic-gate * Sets the first prefix_len bits in the v4 or v6 address (based upon af) 38947c478bd9Sstevel@tonic-gate * contained in the v6 address referenced by addr to 1. 38957c478bd9Sstevel@tonic-gate */ 38967c478bd9Sstevel@tonic-gate static void 38977c478bd9Sstevel@tonic-gate setmask(int prefix_len, in6_addr_t *addr, int af) 38987c478bd9Sstevel@tonic-gate { 38997c478bd9Sstevel@tonic-gate 39007c478bd9Sstevel@tonic-gate int i; 39017c478bd9Sstevel@tonic-gate int shift; 39027c478bd9Sstevel@tonic-gate int maskstartbit = 128 - prefix_len; 39037c478bd9Sstevel@tonic-gate int end_u32; 39047c478bd9Sstevel@tonic-gate 39057c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "In setmask, prefix_len: %u, af: %s\n", prefix_len, 39067c478bd9Sstevel@tonic-gate af == AF_INET ? "AF_INET" : "AF_INET6"); 39077c478bd9Sstevel@tonic-gate 39087c478bd9Sstevel@tonic-gate /* zero addr */ 39097c478bd9Sstevel@tonic-gate bzero(addr, sizeof (in6_addr_t)); 39107c478bd9Sstevel@tonic-gate 39117c478bd9Sstevel@tonic-gate 39127c478bd9Sstevel@tonic-gate /* set which 32bits in *addr are relevant to this af */ 39137c478bd9Sstevel@tonic-gate 39147c478bd9Sstevel@tonic-gate if (af == AF_INET) { 39157c478bd9Sstevel@tonic-gate end_u32 = 3; 39167c478bd9Sstevel@tonic-gate maskstartbit = 32 - prefix_len; 39177c478bd9Sstevel@tonic-gate /* AF_INET6 */ 39187c478bd9Sstevel@tonic-gate } else { 39197c478bd9Sstevel@tonic-gate end_u32 = 0; 39207c478bd9Sstevel@tonic-gate } 39217c478bd9Sstevel@tonic-gate /* 39227c478bd9Sstevel@tonic-gate * go through each of the 32bit quantities in 128 bit in6_addr_t 39237c478bd9Sstevel@tonic-gate * and set appropriate bits according to prefix_len. 39247c478bd9Sstevel@tonic-gate */ 39257c478bd9Sstevel@tonic-gate for (i = 3; i >= end_u32; i--) { 39267c478bd9Sstevel@tonic-gate 39277c478bd9Sstevel@tonic-gate /* does the prefix apply to this 32bits? */ 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate if (maskstartbit < ((4 - i) * 32)) { 39307c478bd9Sstevel@tonic-gate 39317c478bd9Sstevel@tonic-gate /* is this 32bits fully masked? */ 39327c478bd9Sstevel@tonic-gate 39337c478bd9Sstevel@tonic-gate if (maskstartbit <= ((3 - i) * 32)) { 39347c478bd9Sstevel@tonic-gate shift = 0; 39357c478bd9Sstevel@tonic-gate } else { 39367c478bd9Sstevel@tonic-gate shift = maskstartbit % 32; 39377c478bd9Sstevel@tonic-gate } 39387c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] = (uint32_t)~0; 39397c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] = 39407c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] >> shift; 39417c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] = 39427c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] << shift; 39437c478bd9Sstevel@tonic-gate } 39447c478bd9Sstevel@tonic-gate 39457c478bd9Sstevel@tonic-gate /* translate to NBO */ 39467c478bd9Sstevel@tonic-gate addr->_S6_un._S6_u32[i] = htonl(addr->_S6_un._S6_u32[i]); 39477c478bd9Sstevel@tonic-gate } 39487c478bd9Sstevel@tonic-gate } 39497c478bd9Sstevel@tonic-gate 39507c478bd9Sstevel@tonic-gate /* 39517c478bd9Sstevel@tonic-gate * search nvlist for an element with the name specified and return a ptr 39527c478bd9Sstevel@tonic-gate * to it if found. 39537c478bd9Sstevel@tonic-gate * RETURNS: pointer to nvpair named name if found, else NULL. 39547c478bd9Sstevel@tonic-gate */ 39557c478bd9Sstevel@tonic-gate static nvpair_t * 39567c478bd9Sstevel@tonic-gate find_nvpair(nvlist_t *nvl, char *name) 39577c478bd9Sstevel@tonic-gate { 39587c478bd9Sstevel@tonic-gate 39597c478bd9Sstevel@tonic-gate nvpair_t *nvp; 39607c478bd9Sstevel@tonic-gate nvpair_t *match = NULL; 39617c478bd9Sstevel@tonic-gate char *nvp_name; 39627c478bd9Sstevel@tonic-gate 39637c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In find_nvpair\n"); 39647c478bd9Sstevel@tonic-gate 39657c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, NULL); 39667c478bd9Sstevel@tonic-gate while (nvp) { 39677c478bd9Sstevel@tonic-gate nvp_name = nvpair_name(nvp); 39687c478bd9Sstevel@tonic-gate if (strcmp(name, nvp_name) == 0) { 39697c478bd9Sstevel@tonic-gate match = nvp; 39707c478bd9Sstevel@tonic-gate } 39717c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl, nvp); 39727c478bd9Sstevel@tonic-gate } 39737c478bd9Sstevel@tonic-gate 39747c478bd9Sstevel@tonic-gate return (match); 39757c478bd9Sstevel@tonic-gate } 39767c478bd9Sstevel@tonic-gate 39777c478bd9Sstevel@tonic-gate /* 39787c478bd9Sstevel@tonic-gate * returns a string containing module_name '.' name. 39797c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS. 39807c478bd9Sstevel@tonic-gate */ 39817c478bd9Sstevel@tonic-gate static char * 39827c478bd9Sstevel@tonic-gate prepend_module_name( 39837c478bd9Sstevel@tonic-gate char *name, 39847c478bd9Sstevel@tonic-gate char *module) 39857c478bd9Sstevel@tonic-gate { 39867c478bd9Sstevel@tonic-gate 39877c478bd9Sstevel@tonic-gate char *ret; 39887c478bd9Sstevel@tonic-gate 39897c478bd9Sstevel@tonic-gate IPQOSCDBG0(L2, "In prepend_module_name\n"); 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate ret = malloc(strlen(module) + strlen(".") + strlen(name) + 1); 39927c478bd9Sstevel@tonic-gate if (ret == NULL) { 39937c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 39947c478bd9Sstevel@tonic-gate return (NULL); 39957c478bd9Sstevel@tonic-gate } 39967c478bd9Sstevel@tonic-gate 39977c478bd9Sstevel@tonic-gate (void) strcpy(ret, module); 39987c478bd9Sstevel@tonic-gate (void) strcat(ret, "."); 39997c478bd9Sstevel@tonic-gate (void) strcat(ret, name); 40007c478bd9Sstevel@tonic-gate 40017c478bd9Sstevel@tonic-gate return (ret); 40027c478bd9Sstevel@tonic-gate } 40037c478bd9Sstevel@tonic-gate 40047c478bd9Sstevel@tonic-gate #if 0 40057c478bd9Sstevel@tonic-gate 40067c478bd9Sstevel@tonic-gate /* 40077c478bd9Sstevel@tonic-gate * check if element with matching s1 and s2 string is in table table. 40087c478bd9Sstevel@tonic-gate * RETURNS: 1 if found else 0. 40097c478bd9Sstevel@tonic-gate */ 40107c478bd9Sstevel@tonic-gate static int 40117c478bd9Sstevel@tonic-gate in_str_str_table( 40127c478bd9Sstevel@tonic-gate str_str_t *table, 40137c478bd9Sstevel@tonic-gate char *s1, 40147c478bd9Sstevel@tonic-gate char *s2) 40157c478bd9Sstevel@tonic-gate { 40167c478bd9Sstevel@tonic-gate 40177c478bd9Sstevel@tonic-gate str_str_t *ss = table; 40187c478bd9Sstevel@tonic-gate 40197c478bd9Sstevel@tonic-gate /* loop through table till matched or end */ 40207c478bd9Sstevel@tonic-gate 40217c478bd9Sstevel@tonic-gate while (ss->s1[0] != '\0' && 40227c478bd9Sstevel@tonic-gate (strcmp(ss->s1, s1) != 0 || strcmp(ss->s2, s2) != 0)) { 40237c478bd9Sstevel@tonic-gate ss++; 40247c478bd9Sstevel@tonic-gate } 40257c478bd9Sstevel@tonic-gate 40267c478bd9Sstevel@tonic-gate if (ss->s1[0] != '\0') { 40277c478bd9Sstevel@tonic-gate return (1); 40287c478bd9Sstevel@tonic-gate } 40297c478bd9Sstevel@tonic-gate 40307c478bd9Sstevel@tonic-gate return (0); 40317c478bd9Sstevel@tonic-gate } 40327c478bd9Sstevel@tonic-gate #endif /* 0 */ 40337c478bd9Sstevel@tonic-gate 40347c478bd9Sstevel@tonic-gate /* 40357c478bd9Sstevel@tonic-gate * check whether name is a valid action/class/filter name. 40367c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if invalid name else IPQOS_CONF_SUCCESS. 40377c478bd9Sstevel@tonic-gate */ 40387c478bd9Sstevel@tonic-gate static int 40397c478bd9Sstevel@tonic-gate valid_name(char *name) 40407c478bd9Sstevel@tonic-gate { 40417c478bd9Sstevel@tonic-gate 40427c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In valid_name: name: %s\n", name); 40437c478bd9Sstevel@tonic-gate 40447c478bd9Sstevel@tonic-gate /* first char can't be '!' */ 40457c478bd9Sstevel@tonic-gate if (name[0] == '!') { 40467c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Name not allowed to start with " 40477c478bd9Sstevel@tonic-gate "'!', line %u.\n"), lineno); 40487c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 40497c478bd9Sstevel@tonic-gate } 40507c478bd9Sstevel@tonic-gate 40517c478bd9Sstevel@tonic-gate /* can't exceed IPQOS_CONF_NAME_LEN size */ 40527c478bd9Sstevel@tonic-gate if (strlen(name) >= IPQOS_CONF_NAME_LEN) { 40537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Name exceeds maximum name length " 40547c478bd9Sstevel@tonic-gate "line %u.\n"), lineno); 40557c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 40567c478bd9Sstevel@tonic-gate } 40577c478bd9Sstevel@tonic-gate 40587c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 40597c478bd9Sstevel@tonic-gate } 40607c478bd9Sstevel@tonic-gate 40617c478bd9Sstevel@tonic-gate /* ********************* string value manip fns ************************** */ 40627c478bd9Sstevel@tonic-gate 40637c478bd9Sstevel@tonic-gate 40647c478bd9Sstevel@tonic-gate /* 40657c478bd9Sstevel@tonic-gate * searches through the str_val_nd_t list of string value pairs finding 40667c478bd9Sstevel@tonic-gate * the minimum and maximum values for value and places them in the 40677c478bd9Sstevel@tonic-gate * integers pointed at by min and max. 40687c478bd9Sstevel@tonic-gate */ 40697c478bd9Sstevel@tonic-gate static void 40707c478bd9Sstevel@tonic-gate get_str_val_value_range( 40717c478bd9Sstevel@tonic-gate str_val_nd_t *svnp, 40727c478bd9Sstevel@tonic-gate int *min, 40737c478bd9Sstevel@tonic-gate int *max) 40747c478bd9Sstevel@tonic-gate { 40757c478bd9Sstevel@tonic-gate if (svnp != NULL) { 40767c478bd9Sstevel@tonic-gate *min = *max = svnp->sv.value; 40777c478bd9Sstevel@tonic-gate svnp = svnp->next; 40787c478bd9Sstevel@tonic-gate } 40797c478bd9Sstevel@tonic-gate while (svnp != NULL) { 40807c478bd9Sstevel@tonic-gate if (svnp->sv.value > *max) 40817c478bd9Sstevel@tonic-gate *max = svnp->sv.value; 40827c478bd9Sstevel@tonic-gate if (svnp->sv.value < *min) 40837c478bd9Sstevel@tonic-gate *min = svnp->sv.value; 40847c478bd9Sstevel@tonic-gate svnp = svnp->next; 40857c478bd9Sstevel@tonic-gate } 40867c478bd9Sstevel@tonic-gate } 40877c478bd9Sstevel@tonic-gate 40887c478bd9Sstevel@tonic-gate /* 40897c478bd9Sstevel@tonic-gate * add an entry with string string and value val to sv_entrys. 40907c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 40917c478bd9Sstevel@tonic-gate */ 40927c478bd9Sstevel@tonic-gate static int 40937c478bd9Sstevel@tonic-gate add_str_val_entry( 40947c478bd9Sstevel@tonic-gate str_val_nd_t **sv_entrys, 40957c478bd9Sstevel@tonic-gate char *string, 40967c478bd9Sstevel@tonic-gate uint32_t val) 40977c478bd9Sstevel@tonic-gate { 40987c478bd9Sstevel@tonic-gate 40997c478bd9Sstevel@tonic-gate str_val_nd_t *sv_entry; 41007c478bd9Sstevel@tonic-gate 41017c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "In add_str_val_entry: string: %s, val: %u\n", string, 41027c478bd9Sstevel@tonic-gate val); 41037c478bd9Sstevel@tonic-gate 41047c478bd9Sstevel@tonic-gate /* alloc new node */ 41057c478bd9Sstevel@tonic-gate 41067c478bd9Sstevel@tonic-gate sv_entry = malloc(sizeof (str_val_nd_t)); 41077c478bd9Sstevel@tonic-gate if (sv_entry == NULL) { 41087c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 41097c478bd9Sstevel@tonic-gate } 41107c478bd9Sstevel@tonic-gate 41117c478bd9Sstevel@tonic-gate /* populate node */ 41127c478bd9Sstevel@tonic-gate 41137c478bd9Sstevel@tonic-gate sv_entry->sv.string = malloc(strlen(string) + 1); 41147c478bd9Sstevel@tonic-gate if (sv_entry->sv.string == NULL) { 41157c478bd9Sstevel@tonic-gate free(sv_entry); 41167c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 41177c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 41187c478bd9Sstevel@tonic-gate } else { 41197c478bd9Sstevel@tonic-gate (void) strcpy(sv_entry->sv.string, string); 41207c478bd9Sstevel@tonic-gate } 41217c478bd9Sstevel@tonic-gate sv_entry->sv.value = val; 41227c478bd9Sstevel@tonic-gate 41237c478bd9Sstevel@tonic-gate /* place at start of sv_entrys list */ 41247c478bd9Sstevel@tonic-gate 41257c478bd9Sstevel@tonic-gate sv_entry->next = *sv_entrys; 41267c478bd9Sstevel@tonic-gate *sv_entrys = sv_entry; 41277c478bd9Sstevel@tonic-gate 41287c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 41297c478bd9Sstevel@tonic-gate } 41307c478bd9Sstevel@tonic-gate 41317c478bd9Sstevel@tonic-gate 41327c478bd9Sstevel@tonic-gate /* frees all the elements of sv_entrys. */ 41337c478bd9Sstevel@tonic-gate static void 41347c478bd9Sstevel@tonic-gate free_str_val_entrys( 41357c478bd9Sstevel@tonic-gate str_val_nd_t *sv_entrys) 41367c478bd9Sstevel@tonic-gate { 41377c478bd9Sstevel@tonic-gate 41387c478bd9Sstevel@tonic-gate str_val_nd_t *sve = sv_entrys; 41397c478bd9Sstevel@tonic-gate str_val_nd_t *tmp; 41407c478bd9Sstevel@tonic-gate 41417c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In free_str_val_entrys\n"); 41427c478bd9Sstevel@tonic-gate 41437c478bd9Sstevel@tonic-gate while (sve) { 41447c478bd9Sstevel@tonic-gate free(sve->sv.string); 41457c478bd9Sstevel@tonic-gate tmp = sve->next; 41467c478bd9Sstevel@tonic-gate free(sve); 41477c478bd9Sstevel@tonic-gate sve = tmp; 41487c478bd9Sstevel@tonic-gate } 41497c478bd9Sstevel@tonic-gate } 41507c478bd9Sstevel@tonic-gate 41517c478bd9Sstevel@tonic-gate /* 41527c478bd9Sstevel@tonic-gate * finds the value associated with string and assigns it to value ref'd by 41537c478bd9Sstevel@tonic-gate * val. 41547c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if string not found, else IPQOS_CONF_SUCCESS. 41557c478bd9Sstevel@tonic-gate */ 41567c478bd9Sstevel@tonic-gate static int 41577c478bd9Sstevel@tonic-gate str_val_list_lookup( 41587c478bd9Sstevel@tonic-gate str_val_nd_t *svs, 41597c478bd9Sstevel@tonic-gate char *string, 41607c478bd9Sstevel@tonic-gate uint32_t *val) 41617c478bd9Sstevel@tonic-gate { 41627c478bd9Sstevel@tonic-gate 41637c478bd9Sstevel@tonic-gate str_val_nd_t *sv = svs; 41647c478bd9Sstevel@tonic-gate 41657c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In str_val_list_lookup: %s\n", string); 41667c478bd9Sstevel@tonic-gate 41677c478bd9Sstevel@tonic-gate /* loop through list and exit when found or list end */ 41687c478bd9Sstevel@tonic-gate 41697c478bd9Sstevel@tonic-gate while (sv != NULL) { 41707c478bd9Sstevel@tonic-gate if (strcmp(sv->sv.string, string) == 0) { 41717c478bd9Sstevel@tonic-gate break; 41727c478bd9Sstevel@tonic-gate } 41737c478bd9Sstevel@tonic-gate sv = sv->next; 41747c478bd9Sstevel@tonic-gate } 41757c478bd9Sstevel@tonic-gate 41767c478bd9Sstevel@tonic-gate /* ret error if not found */ 41777c478bd9Sstevel@tonic-gate 41787c478bd9Sstevel@tonic-gate if (sv == NULL) { 41797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 41807c478bd9Sstevel@tonic-gate } 41817c478bd9Sstevel@tonic-gate 41827c478bd9Sstevel@tonic-gate *val = sv->sv.value; 41837c478bd9Sstevel@tonic-gate 41847c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "svll: Value returned is %u\n", *val); 41857c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 41867c478bd9Sstevel@tonic-gate } 41877c478bd9Sstevel@tonic-gate 41887c478bd9Sstevel@tonic-gate 41897c478bd9Sstevel@tonic-gate /* ************************ conf file read fns ***************************** */ 41907c478bd9Sstevel@tonic-gate 41917c478bd9Sstevel@tonic-gate /* 41927c478bd9Sstevel@tonic-gate * Reads a uid or username from string 'str' and assigns either the uid 41937c478bd9Sstevel@tonic-gate * or associated uid respectively to storage pointed at by 'uid'. The 41947c478bd9Sstevel@tonic-gate * function determines whether to read a uid by checking whether the first 41957c478bd9Sstevel@tonic-gate * character of 'str' is numeric, in which case it reads a uid; otherwise it 41967c478bd9Sstevel@tonic-gate * assumes a username. 41977c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if a NULL string pointer is passed, the read uid 41987c478bd9Sstevel@tonic-gate * doesn't have an entry on the system, or the read username doesn't have an 41997c478bd9Sstevel@tonic-gate * entry on the system. 42007c478bd9Sstevel@tonic-gate */ 42017c478bd9Sstevel@tonic-gate static int 42027c478bd9Sstevel@tonic-gate readuser( 42037c478bd9Sstevel@tonic-gate char *str, 42047c478bd9Sstevel@tonic-gate uid_t *uid) 42057c478bd9Sstevel@tonic-gate { 42067c478bd9Sstevel@tonic-gate struct passwd *pwd; 42077c478bd9Sstevel@tonic-gate char *lo; 42087c478bd9Sstevel@tonic-gate 42097c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "In readuser, str: %s\n", str); 42107c478bd9Sstevel@tonic-gate 42117c478bd9Sstevel@tonic-gate if (str == NULL) 42127c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42137c478bd9Sstevel@tonic-gate /* 42147c478bd9Sstevel@tonic-gate * Check if this appears to be a uid, and if so check that a 42157c478bd9Sstevel@tonic-gate * corresponding user exists. 42167c478bd9Sstevel@tonic-gate */ 42177c478bd9Sstevel@tonic-gate if (isdigit((int)str[0])) { 42187c478bd9Sstevel@tonic-gate /* 42197c478bd9Sstevel@tonic-gate * Read a 32bit integer and check in doing so that 42207c478bd9Sstevel@tonic-gate * we have consumed the whole string. 42217c478bd9Sstevel@tonic-gate */ 42227c478bd9Sstevel@tonic-gate if (readint32(str, (int *)uid, &lo) != IPQOS_CONF_SUCCESS || 42237c478bd9Sstevel@tonic-gate *lo != '\0') 42247c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42257c478bd9Sstevel@tonic-gate if (getpwuid(*uid) == NULL) 42267c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42277c478bd9Sstevel@tonic-gate 42287c478bd9Sstevel@tonic-gate } else { /* This must be a username, so lookup the uid. */ 42297c478bd9Sstevel@tonic-gate pwd = getpwnam(str); 42307c478bd9Sstevel@tonic-gate if (pwd == NULL) { 42317c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42327c478bd9Sstevel@tonic-gate } else { 42337c478bd9Sstevel@tonic-gate *uid = pwd->pw_uid; 42347c478bd9Sstevel@tonic-gate } 42357c478bd9Sstevel@tonic-gate } 42367c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 42377c478bd9Sstevel@tonic-gate } 42387c478bd9Sstevel@tonic-gate 42397c478bd9Sstevel@tonic-gate /* 42407c478bd9Sstevel@tonic-gate * Reads a range from range_st, either of form 'a-b' or simply 'a'. 42417c478bd9Sstevel@tonic-gate * In the former case lower and upper have their values set to a 42427c478bd9Sstevel@tonic-gate * and b respectively; in the later lower and upper have both 42437c478bd9Sstevel@tonic-gate * their values set to a. 42447c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if there's a parse error, else IPQOS_CONF_SUCCESS. 42457c478bd9Sstevel@tonic-gate */ 42467c478bd9Sstevel@tonic-gate static int 42477c478bd9Sstevel@tonic-gate readrange( 42487c478bd9Sstevel@tonic-gate char *range_st, 42497c478bd9Sstevel@tonic-gate int *lower, 42507c478bd9Sstevel@tonic-gate int *upper) 42517c478bd9Sstevel@tonic-gate { 42527c478bd9Sstevel@tonic-gate char *cp; 42537c478bd9Sstevel@tonic-gate char *end, *end2; 42547c478bd9Sstevel@tonic-gate 42557c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "In readrange: string: %s\n", range_st); 42567c478bd9Sstevel@tonic-gate 42577c478bd9Sstevel@tonic-gate /* 42587c478bd9Sstevel@tonic-gate * get range boundarys. 42597c478bd9Sstevel@tonic-gate */ 42607c478bd9Sstevel@tonic-gate cp = strchr(range_st, '-'); 42617c478bd9Sstevel@tonic-gate 42627c478bd9Sstevel@tonic-gate if (cp != NULL) { /* we have a range */ 42637c478bd9Sstevel@tonic-gate *cp++ = '\0'; 42647c478bd9Sstevel@tonic-gate *lower = (int)strtol(range_st, &end, 10); 42657c478bd9Sstevel@tonic-gate *upper = (int)strtol(cp, &end2, 10); 42667c478bd9Sstevel@tonic-gate SKIPWS(end); 42677c478bd9Sstevel@tonic-gate SKIPWS(end2); 42687c478bd9Sstevel@tonic-gate if ((range_st == end) || (*end != NULL) || 42697c478bd9Sstevel@tonic-gate (cp == end) || (*end2 != NULL)) { 42707c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Failed reading a-b\n"); 42717c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42727c478bd9Sstevel@tonic-gate } 42737c478bd9Sstevel@tonic-gate 42747c478bd9Sstevel@tonic-gate } else { /* single value */ 42757c478bd9Sstevel@tonic-gate 42767c478bd9Sstevel@tonic-gate *lower = *upper = (int)strtol(range_st, &end, 10); 42777c478bd9Sstevel@tonic-gate SKIPWS(end); 42787c478bd9Sstevel@tonic-gate if ((range_st == end) || (*end != NULL)) { 42797c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Failed reading a\n"); 42807c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 42817c478bd9Sstevel@tonic-gate } 42827c478bd9Sstevel@tonic-gate } 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 42857c478bd9Sstevel@tonic-gate } 42867c478bd9Sstevel@tonic-gate 42877c478bd9Sstevel@tonic-gate /* 42887c478bd9Sstevel@tonic-gate * Reads the values of an integer array from fp whose format is: 42897c478bd9Sstevel@tonic-gate * '{'RANGE[,RANGE[..]]:VALUE[;RANGE:VALUE[..]]'}', creates an array of size 42907c478bd9Sstevel@tonic-gate * arr_size, applies the values to it and points arrp at this array. 42917c478bd9Sstevel@tonic-gate * RANGE is one set of array indexes over which this value is to 42927c478bd9Sstevel@tonic-gate * be applied, and VALUE either an integer within the range 42937c478bd9Sstevel@tonic-gate * llimit - ulimit, or if enum_nvs isn't NULL, an enumeration value 42947c478bd9Sstevel@tonic-gate * found in the list enum_nvs. Those values which aren't explicity set 42957c478bd9Sstevel@tonic-gate * will be set to -1. 42967c478bd9Sstevel@tonic-gate * 42977c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on resource or parse error, else IPQOS_CONF_SUCCESS. 42987c478bd9Sstevel@tonic-gate */ 42997c478bd9Sstevel@tonic-gate static int 43007c478bd9Sstevel@tonic-gate read_int_array( 43017c478bd9Sstevel@tonic-gate FILE *fp, 43027c478bd9Sstevel@tonic-gate char *first_token, 43037c478bd9Sstevel@tonic-gate int **arrp, 43047c478bd9Sstevel@tonic-gate uint32_t arr_size, 43057c478bd9Sstevel@tonic-gate int llimit, 43067c478bd9Sstevel@tonic-gate int ulimit, 43077c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs) 43087c478bd9Sstevel@tonic-gate { 43097c478bd9Sstevel@tonic-gate 43107c478bd9Sstevel@tonic-gate char buf[5 * IPQOS_CONF_LINEBUF_SZ]; 43117c478bd9Sstevel@tonic-gate char *token; 43127c478bd9Sstevel@tonic-gate char *range; 43137c478bd9Sstevel@tonic-gate char *ranges; 43147c478bd9Sstevel@tonic-gate char *svalue; 43157c478bd9Sstevel@tonic-gate int value; 43167c478bd9Sstevel@tonic-gate int res; 43177c478bd9Sstevel@tonic-gate char *entry; 43187c478bd9Sstevel@tonic-gate char *tmp; 43197c478bd9Sstevel@tonic-gate char *end; 43207c478bd9Sstevel@tonic-gate int lower, upper; 43217c478bd9Sstevel@tonic-gate int x; 43227c478bd9Sstevel@tonic-gate uint32_t startln; 43237c478bd9Sstevel@tonic-gate 43247c478bd9Sstevel@tonic-gate IPQOSCDBG4(L0, "In read_int_array: size: %u, lower: %u, upper: %u, " 43257c478bd9Sstevel@tonic-gate "first_token: %s\n", arr_size, llimit, ulimit, first_token); 43267c478bd9Sstevel@tonic-gate 43277c478bd9Sstevel@tonic-gate /* 43287c478bd9Sstevel@tonic-gate * read beginning curl. 43297c478bd9Sstevel@tonic-gate */ 43307c478bd9Sstevel@tonic-gate if (first_token[0] != CURL_BEGIN) { 43317c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("\'{\' missing at line " 43327c478bd9Sstevel@tonic-gate "%u.\n"), lineno); 43337c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 43347c478bd9Sstevel@tonic-gate } 43357c478bd9Sstevel@tonic-gate 43367c478bd9Sstevel@tonic-gate /* 43377c478bd9Sstevel@tonic-gate * allocate and initialise array for holding read values. 43387c478bd9Sstevel@tonic-gate */ 43397c478bd9Sstevel@tonic-gate *arrp = malloc(arr_size * sizeof (int)); 43407c478bd9Sstevel@tonic-gate if (*arrp == NULL) { 43417c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 43427c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 43437c478bd9Sstevel@tonic-gate } 43447c478bd9Sstevel@tonic-gate (void) memset(*arrp, -1, arr_size * sizeof (int)); 43457c478bd9Sstevel@tonic-gate 43467c478bd9Sstevel@tonic-gate /* 43477c478bd9Sstevel@tonic-gate * read whole array declaration string into buffer. 43487c478bd9Sstevel@tonic-gate * this is because readtoken doesn't interpret our 43497c478bd9Sstevel@tonic-gate * delimeter values specially and may return them 43507c478bd9Sstevel@tonic-gate * within another string. 43517c478bd9Sstevel@tonic-gate */ 43527c478bd9Sstevel@tonic-gate startln = lineno; /* store starting lineno for error reports */ 43537c478bd9Sstevel@tonic-gate buf[0] = '\0'; 43547c478bd9Sstevel@tonic-gate res = readtoken(fp, &token); 43557c478bd9Sstevel@tonic-gate while ((res != IPQOS_CONF_CURL_END) && (res != IPQOS_CONF_ERR) && 43567c478bd9Sstevel@tonic-gate (res != IPQOS_CONF_EOF)) { 43577c478bd9Sstevel@tonic-gate (void) strlcat(buf, token, sizeof (buf)); 43587c478bd9Sstevel@tonic-gate free(token); 43597c478bd9Sstevel@tonic-gate res = readtoken(fp, &token); 43607c478bd9Sstevel@tonic-gate } 43617c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_CURL_END) { 43627c478bd9Sstevel@tonic-gate goto array_err; 43637c478bd9Sstevel@tonic-gate } 43647c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "array declaration buffer contains: %s\n", buf); 43657c478bd9Sstevel@tonic-gate 43667c478bd9Sstevel@tonic-gate /* 43677c478bd9Sstevel@tonic-gate * loop reading "ranges ':' value;" till end of buffer. 43687c478bd9Sstevel@tonic-gate */ 43697c478bd9Sstevel@tonic-gate entry = strtok(buf, ";"); 43707c478bd9Sstevel@tonic-gate while (entry != NULL) { 43717c478bd9Sstevel@tonic-gate svalue = strchr(entry, ':'); 43727c478bd9Sstevel@tonic-gate if (svalue == NULL) { /* missing value string */ 43737c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Missing value string\n"); 43747c478bd9Sstevel@tonic-gate goto array_err; 43757c478bd9Sstevel@tonic-gate } 43767c478bd9Sstevel@tonic-gate *svalue++ = '\0'; 43777c478bd9Sstevel@tonic-gate ranges = entry; 43787c478bd9Sstevel@tonic-gate 43797c478bd9Sstevel@tonic-gate /* 43807c478bd9Sstevel@tonic-gate * get value of number or enumerated symbol. 43817c478bd9Sstevel@tonic-gate */ 43827c478bd9Sstevel@tonic-gate if (enum_nvs) { 43837c478bd9Sstevel@tonic-gate /* 43847c478bd9Sstevel@tonic-gate * get rid of surrounding whitespace so as not to 43857c478bd9Sstevel@tonic-gate * confuse read_enum_value. 43867c478bd9Sstevel@tonic-gate */ 43877c478bd9Sstevel@tonic-gate SKIPWS(svalue); 43887c478bd9Sstevel@tonic-gate tmp = svalue; 43897c478bd9Sstevel@tonic-gate while (*tmp != '\0') { 43907c478bd9Sstevel@tonic-gate if (isspace(*tmp)) { 43917c478bd9Sstevel@tonic-gate *tmp = '\0'; 43927c478bd9Sstevel@tonic-gate break; 43937c478bd9Sstevel@tonic-gate } else { 43947c478bd9Sstevel@tonic-gate tmp++; 43957c478bd9Sstevel@tonic-gate } 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate 43987c478bd9Sstevel@tonic-gate /* 43997c478bd9Sstevel@tonic-gate * read enumeration value. 44007c478bd9Sstevel@tonic-gate */ 44017c478bd9Sstevel@tonic-gate res = read_enum_value(NULL, svalue, enum_nvs, 44027c478bd9Sstevel@tonic-gate (uint32_t *)&value); 44037c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) 44047c478bd9Sstevel@tonic-gate goto array_err; 44057c478bd9Sstevel@tonic-gate } else { 44067c478bd9Sstevel@tonic-gate value = (int)strtol(svalue, &end, 10); 44077c478bd9Sstevel@tonic-gate SKIPWS(end); 44087c478bd9Sstevel@tonic-gate if ((svalue == end) || (*end != NULL)) { 44097c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Invalid value\n"); 44107c478bd9Sstevel@tonic-gate goto array_err; 44117c478bd9Sstevel@tonic-gate } 44127c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "value: %u\n", value); 44137c478bd9Sstevel@tonic-gate 44147c478bd9Sstevel@tonic-gate /* 44157c478bd9Sstevel@tonic-gate * check value within valid range. 44167c478bd9Sstevel@tonic-gate */ 44177c478bd9Sstevel@tonic-gate if ((value < llimit) || (value > ulimit)) { 44187c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "value out of range\n"); 44197c478bd9Sstevel@tonic-gate goto array_err; 44207c478bd9Sstevel@tonic-gate } 44217c478bd9Sstevel@tonic-gate } 44227c478bd9Sstevel@tonic-gate 44237c478bd9Sstevel@tonic-gate /* 44247c478bd9Sstevel@tonic-gate * loop reading ranges for this value. 44257c478bd9Sstevel@tonic-gate */ 44267c478bd9Sstevel@tonic-gate range = strtok_r(ranges, ",", &tmp); 44277c478bd9Sstevel@tonic-gate while (range != NULL) { 44287c478bd9Sstevel@tonic-gate res = readrange(range, &lower, &upper); 44297c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) 44307c478bd9Sstevel@tonic-gate goto array_err; 44317c478bd9Sstevel@tonic-gate IPQOSCDBG2(L0, "range: %u - %u\n", lower, upper); 44327c478bd9Sstevel@tonic-gate 44337c478bd9Sstevel@tonic-gate 44347c478bd9Sstevel@tonic-gate if (upper < lower) { 44357c478bd9Sstevel@tonic-gate uint32_t u = lower; 44367c478bd9Sstevel@tonic-gate lower = upper; 44377c478bd9Sstevel@tonic-gate upper = u; 44387c478bd9Sstevel@tonic-gate } 44397c478bd9Sstevel@tonic-gate 44407c478bd9Sstevel@tonic-gate /* 44417c478bd9Sstevel@tonic-gate * check range valid for array size. 44427c478bd9Sstevel@tonic-gate */ 44437c478bd9Sstevel@tonic-gate if ((lower < 0) || (upper > arr_size)) { 44447c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Range out of array " 44457c478bd9Sstevel@tonic-gate "dimensions\n"); 44467c478bd9Sstevel@tonic-gate goto array_err; 44477c478bd9Sstevel@tonic-gate } 44487c478bd9Sstevel@tonic-gate 44497c478bd9Sstevel@tonic-gate /* 44507c478bd9Sstevel@tonic-gate * add this value to array indexes within range. 44517c478bd9Sstevel@tonic-gate */ 44527c478bd9Sstevel@tonic-gate for (x = lower; x <= upper; x++) 44537c478bd9Sstevel@tonic-gate (*arrp)[x] = value; 44547c478bd9Sstevel@tonic-gate 44557c478bd9Sstevel@tonic-gate /* 44567c478bd9Sstevel@tonic-gate * get next range. 44577c478bd9Sstevel@tonic-gate */ 44587c478bd9Sstevel@tonic-gate range = strtok_r(NULL, ",", &tmp); 44597c478bd9Sstevel@tonic-gate } 44607c478bd9Sstevel@tonic-gate 44617c478bd9Sstevel@tonic-gate entry = strtok(NULL, ";"); 44627c478bd9Sstevel@tonic-gate } 44637c478bd9Sstevel@tonic-gate 44647c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 44657c478bd9Sstevel@tonic-gate 44667c478bd9Sstevel@tonic-gate array_err: 44677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 44687c478bd9Sstevel@tonic-gate gettext("Array declaration line %u is invalid.\n"), startln); 44697c478bd9Sstevel@tonic-gate free(*arrp); 44707c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 44717c478bd9Sstevel@tonic-gate } 44727c478bd9Sstevel@tonic-gate 44737c478bd9Sstevel@tonic-gate static int 44747c478bd9Sstevel@tonic-gate readllong(char *str, long long *llp, char **lo) 44757c478bd9Sstevel@tonic-gate { 44767c478bd9Sstevel@tonic-gate 44777c478bd9Sstevel@tonic-gate *llp = strtoll(str, lo, 0); 44787c478bd9Sstevel@tonic-gate if (*lo == str) { 44797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 44807c478bd9Sstevel@tonic-gate } 44817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 44827c478bd9Sstevel@tonic-gate } 44837c478bd9Sstevel@tonic-gate 44847c478bd9Sstevel@tonic-gate static int 44857c478bd9Sstevel@tonic-gate readuint8(char *str, uint8_t *ui8, char **lo) 44867c478bd9Sstevel@tonic-gate { 44877c478bd9Sstevel@tonic-gate 44887c478bd9Sstevel@tonic-gate long long tmp; 44897c478bd9Sstevel@tonic-gate 44907c478bd9Sstevel@tonic-gate if (readllong(str, &tmp, lo) != 0) { 44917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 44927c478bd9Sstevel@tonic-gate } 44937c478bd9Sstevel@tonic-gate if (tmp > UCHAR_MAX || tmp < 0) { 44947c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 44957c478bd9Sstevel@tonic-gate } 44967c478bd9Sstevel@tonic-gate *ui8 = (uint8_t)tmp; 44977c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 44987c478bd9Sstevel@tonic-gate } 44997c478bd9Sstevel@tonic-gate 45007c478bd9Sstevel@tonic-gate static int 45017c478bd9Sstevel@tonic-gate readuint16(char *str, uint16_t *ui16, char **lo) 45027c478bd9Sstevel@tonic-gate { 45037c478bd9Sstevel@tonic-gate long long tmp; 45047c478bd9Sstevel@tonic-gate 45057c478bd9Sstevel@tonic-gate if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) { 45067c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45077c478bd9Sstevel@tonic-gate } 45087c478bd9Sstevel@tonic-gate if (tmp > USHRT_MAX || tmp < 0) { 45097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45107c478bd9Sstevel@tonic-gate } 45117c478bd9Sstevel@tonic-gate *ui16 = (uint16_t)tmp; 45127c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 45137c478bd9Sstevel@tonic-gate } 45147c478bd9Sstevel@tonic-gate 45157c478bd9Sstevel@tonic-gate static int 45167c478bd9Sstevel@tonic-gate readint16(char *str, int16_t *i16, char **lo) 45177c478bd9Sstevel@tonic-gate { 45187c478bd9Sstevel@tonic-gate long long tmp; 45197c478bd9Sstevel@tonic-gate 45207c478bd9Sstevel@tonic-gate if (readllong(str, &tmp, lo) != 0) { 45217c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45227c478bd9Sstevel@tonic-gate } 45237c478bd9Sstevel@tonic-gate if (tmp > SHRT_MAX || tmp < SHRT_MIN) { 45247c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45257c478bd9Sstevel@tonic-gate } 45267c478bd9Sstevel@tonic-gate *i16 = (int16_t)tmp; 45277c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 45287c478bd9Sstevel@tonic-gate } 45297c478bd9Sstevel@tonic-gate 45307c478bd9Sstevel@tonic-gate static int 45317c478bd9Sstevel@tonic-gate readint32(char *str, int *i32, char **lo) 45327c478bd9Sstevel@tonic-gate { 45337c478bd9Sstevel@tonic-gate long long tmp; 45347c478bd9Sstevel@tonic-gate 45357c478bd9Sstevel@tonic-gate if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) { 45367c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45377c478bd9Sstevel@tonic-gate } 45387c478bd9Sstevel@tonic-gate if (tmp > INT_MAX || tmp < INT_MIN) { 45397c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45407c478bd9Sstevel@tonic-gate } 45417c478bd9Sstevel@tonic-gate *i32 = tmp; 45427c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 45437c478bd9Sstevel@tonic-gate } 45447c478bd9Sstevel@tonic-gate 45457c478bd9Sstevel@tonic-gate static int 45467c478bd9Sstevel@tonic-gate readuint32(char *str, uint32_t *ui32, char **lo) 45477c478bd9Sstevel@tonic-gate { 45487c478bd9Sstevel@tonic-gate long long tmp; 45497c478bd9Sstevel@tonic-gate 45507c478bd9Sstevel@tonic-gate if (readllong(str, &tmp, lo) != IPQOS_CONF_SUCCESS) { 45517c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45527c478bd9Sstevel@tonic-gate } 45537c478bd9Sstevel@tonic-gate if (tmp > UINT_MAX || tmp < 0) { 45547c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45557c478bd9Sstevel@tonic-gate } 45567c478bd9Sstevel@tonic-gate *ui32 = (uint32_t)tmp; 45577c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 45587c478bd9Sstevel@tonic-gate } 45597c478bd9Sstevel@tonic-gate 45607c478bd9Sstevel@tonic-gate /* 45617c478bd9Sstevel@tonic-gate * retrieves the index associated with the interface named ifname and assigns 45627c478bd9Sstevel@tonic-gate * it to the int pointed to by ifindex. 45637c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 45647c478bd9Sstevel@tonic-gate */ 45657c478bd9Sstevel@tonic-gate static int 45667c478bd9Sstevel@tonic-gate readifindex( 45677c478bd9Sstevel@tonic-gate char *ifname, 45687c478bd9Sstevel@tonic-gate int *ifindex) 45697c478bd9Sstevel@tonic-gate { 45707c478bd9Sstevel@tonic-gate 45717c478bd9Sstevel@tonic-gate int s; 45727c478bd9Sstevel@tonic-gate struct lifreq lifrq; 45737c478bd9Sstevel@tonic-gate 45747c478bd9Sstevel@tonic-gate 45757c478bd9Sstevel@tonic-gate /* open socket */ 45767c478bd9Sstevel@tonic-gate 45777c478bd9Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 45787c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, gettext("opening AF_INET socket")); 45797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45807c478bd9Sstevel@tonic-gate } 45817c478bd9Sstevel@tonic-gate 45827c478bd9Sstevel@tonic-gate /* copy ifname into lifreq */ 45837c478bd9Sstevel@tonic-gate 45847c478bd9Sstevel@tonic-gate (void) strlcpy(lifrq.lifr_name, ifname, LIFNAMSIZ); 45857c478bd9Sstevel@tonic-gate 45867c478bd9Sstevel@tonic-gate /* do SIOGLIFINDEX ioctl */ 45877c478bd9Sstevel@tonic-gate 45887c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifrq) == -1) { 45897c478bd9Sstevel@tonic-gate (void) close(s); 45907c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 45917c478bd9Sstevel@tonic-gate } 45927c478bd9Sstevel@tonic-gate 45937c478bd9Sstevel@tonic-gate /* Warn if a virtual interface is specified */ 45947c478bd9Sstevel@tonic-gate if ((ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrq) != -1) && 45957c478bd9Sstevel@tonic-gate (lifrq.lifr_flags & IFF_VIRTUAL)) { 45967c478bd9Sstevel@tonic-gate ipqos_msg(MT_WARNING, gettext("Invalid interface")); 45977c478bd9Sstevel@tonic-gate } 45987c478bd9Sstevel@tonic-gate (void) close(s); 45997c478bd9Sstevel@tonic-gate *ifindex = lifrq.lifr_index; 46007c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 46017c478bd9Sstevel@tonic-gate } 46027c478bd9Sstevel@tonic-gate 46037c478bd9Sstevel@tonic-gate /* 46047c478bd9Sstevel@tonic-gate * Case insensitively compares the string in str with IPQOS_CONF_TRUE_STR 46057c478bd9Sstevel@tonic-gate * and IPQOS_CONF_FALSE_STR and sets boolean pointed to by bool accordingly. 46067c478bd9Sstevel@tonic-gate * RETURNS: if failure to match either IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS. 46077c478bd9Sstevel@tonic-gate */ 46087c478bd9Sstevel@tonic-gate static int 46097c478bd9Sstevel@tonic-gate readbool(char *str, boolean_t *bool) 46107c478bd9Sstevel@tonic-gate { 46117c478bd9Sstevel@tonic-gate 46127c478bd9Sstevel@tonic-gate if (strcasecmp(str, IPQOS_CONF_TRUE_STR) == 0) { 46137c478bd9Sstevel@tonic-gate *bool = B_TRUE; 46147c478bd9Sstevel@tonic-gate } else if (strcasecmp(str, IPQOS_CONF_FALSE_STR) == 0) { 46157c478bd9Sstevel@tonic-gate *bool = B_FALSE; 46167c478bd9Sstevel@tonic-gate } else { 46177c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 46187c478bd9Sstevel@tonic-gate } 46197c478bd9Sstevel@tonic-gate 46207c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 46217c478bd9Sstevel@tonic-gate } 46227c478bd9Sstevel@tonic-gate 46237c478bd9Sstevel@tonic-gate /* 46247c478bd9Sstevel@tonic-gate * reads a protocol name/number from proto_str and assigns the number 46257c478bd9Sstevel@tonic-gate * to the uint8 ref'd by proto. 46267c478bd9Sstevel@tonic-gate * RETURNS: If not a valid name or protocol number IPQOS_CONF_ERR, else 46277c478bd9Sstevel@tonic-gate * IPQOS_CONF_SUCCESS. 46287c478bd9Sstevel@tonic-gate */ 46297c478bd9Sstevel@tonic-gate static int 46307c478bd9Sstevel@tonic-gate readproto(char *proto_str, uint8_t *proto) 46317c478bd9Sstevel@tonic-gate { 46327c478bd9Sstevel@tonic-gate 46337c478bd9Sstevel@tonic-gate struct protoent *pent; 46347c478bd9Sstevel@tonic-gate char *lo; 46357c478bd9Sstevel@tonic-gate int res; 46367c478bd9Sstevel@tonic-gate 46377c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In readproto: string: %s\n", proto_str); 46387c478bd9Sstevel@tonic-gate 46397c478bd9Sstevel@tonic-gate /* try name lookup */ 46407c478bd9Sstevel@tonic-gate 46417c478bd9Sstevel@tonic-gate pent = getprotobyname(proto_str); 46427c478bd9Sstevel@tonic-gate if (pent) { 46437c478bd9Sstevel@tonic-gate *proto = pent->p_proto; 46447c478bd9Sstevel@tonic-gate 46457c478bd9Sstevel@tonic-gate /* check valid protocol number */ 46467c478bd9Sstevel@tonic-gate } else { 46477c478bd9Sstevel@tonic-gate res = readuint8(proto_str, proto, &lo); 46487c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS || proto == 0) { 46497c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 46507c478bd9Sstevel@tonic-gate } 46517c478bd9Sstevel@tonic-gate } 46527c478bd9Sstevel@tonic-gate 46537c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 46547c478bd9Sstevel@tonic-gate } 46557c478bd9Sstevel@tonic-gate 46567c478bd9Sstevel@tonic-gate /* 46577c478bd9Sstevel@tonic-gate * reads either a port service, or a port number from port_str and assigns 46587c478bd9Sstevel@tonic-gate * the associated port number to short ref'd by port. 46597c478bd9Sstevel@tonic-gate * RETURNS: If invalid name and number IPQOS_CONF_ERR, else IPQOS_CONF_SUCCESS. 46607c478bd9Sstevel@tonic-gate */ 46617c478bd9Sstevel@tonic-gate static int 46627c478bd9Sstevel@tonic-gate readport(char *port_str, uint16_t *port) 46637c478bd9Sstevel@tonic-gate { 46647c478bd9Sstevel@tonic-gate 46657c478bd9Sstevel@tonic-gate struct servent *sent; 46667c478bd9Sstevel@tonic-gate char *tmp; 46677c478bd9Sstevel@tonic-gate 46687c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In readport: string: %s\n", port_str); 46697c478bd9Sstevel@tonic-gate 46707c478bd9Sstevel@tonic-gate /* try service name lookup */ 46717c478bd9Sstevel@tonic-gate sent = getservbyname(port_str, NULL); 46727c478bd9Sstevel@tonic-gate 46737c478bd9Sstevel@tonic-gate /* failed name lookup so read port number */ 46747c478bd9Sstevel@tonic-gate if (sent == NULL) { 46757c478bd9Sstevel@tonic-gate if (readuint16(port_str, port, &tmp) != IPQOS_CONF_SUCCESS || 46767c478bd9Sstevel@tonic-gate *port == 0) { 46777c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 46787c478bd9Sstevel@tonic-gate } 46797c478bd9Sstevel@tonic-gate *port = htons(*port); 46807c478bd9Sstevel@tonic-gate } else { 46817c478bd9Sstevel@tonic-gate *port = sent->s_port; 46827c478bd9Sstevel@tonic-gate } 46837c478bd9Sstevel@tonic-gate 46847c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 46857c478bd9Sstevel@tonic-gate } 46867c478bd9Sstevel@tonic-gate 46877c478bd9Sstevel@tonic-gate 46887c478bd9Sstevel@tonic-gate /* 46897c478bd9Sstevel@tonic-gate * Reads a curly brace, a string enclosed in double quotes, or a whitespace/ 46907c478bd9Sstevel@tonic-gate * curly brace delimited string. If a double quote enclosed string the 46917c478bd9Sstevel@tonic-gate * closing quotes need to be on the same line. 46927c478bd9Sstevel@tonic-gate * RETURNS: 46937c478bd9Sstevel@tonic-gate * on reading a CURL_BEGIN token it returns IPQOS_CONF_CURL_BEGIN, 46947c478bd9Sstevel@tonic-gate * on reading a CURL_END token it returns IPQOS_CONF_CURL_END, 46957c478bd9Sstevel@tonic-gate * on reading another valid token it returns IPQOS_CONF_SUCCESS. 46967c478bd9Sstevel@tonic-gate * for each of these token is set to point at the read string. 46977c478bd9Sstevel@tonic-gate * at EOF it returns IPQOS_CONF_EOF and if errors it returns IPQOS_CONF_ERR. 46987c478bd9Sstevel@tonic-gate */ 46997c478bd9Sstevel@tonic-gate static int 47007c478bd9Sstevel@tonic-gate readtoken( 47017c478bd9Sstevel@tonic-gate FILE *fp, 47027c478bd9Sstevel@tonic-gate char **token) 47037c478bd9Sstevel@tonic-gate { 47047c478bd9Sstevel@tonic-gate 47057c478bd9Sstevel@tonic-gate char *st, *tmp; 47067c478bd9Sstevel@tonic-gate int len; 47077c478bd9Sstevel@tonic-gate int quoted = 0; 47087c478bd9Sstevel@tonic-gate char *cmnt; 47097c478bd9Sstevel@tonic-gate char *bpos; 47107c478bd9Sstevel@tonic-gate int rembuf; 47117c478bd9Sstevel@tonic-gate 47127c478bd9Sstevel@tonic-gate static char *lo; 47137c478bd9Sstevel@tonic-gate static char *buf = NULL; 47147c478bd9Sstevel@tonic-gate static int bufsize; 47157c478bd9Sstevel@tonic-gate 47167c478bd9Sstevel@tonic-gate /* if first call initialize line buf to default size */ 47177c478bd9Sstevel@tonic-gate 47187c478bd9Sstevel@tonic-gate if (buf == NULL) { 47197c478bd9Sstevel@tonic-gate bufsize = IPQOS_CONF_LINEBUF_SZ; 47207c478bd9Sstevel@tonic-gate buf = malloc(bufsize); 47217c478bd9Sstevel@tonic-gate if (buf == NULL) { 47227c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 47237c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 47247c478bd9Sstevel@tonic-gate } 47257c478bd9Sstevel@tonic-gate } 47267c478bd9Sstevel@tonic-gate 47277c478bd9Sstevel@tonic-gate /* set buffer postition and size to use whole buffer */ 47287c478bd9Sstevel@tonic-gate 47297c478bd9Sstevel@tonic-gate bpos = buf; 47307c478bd9Sstevel@tonic-gate rembuf = bufsize; 47317c478bd9Sstevel@tonic-gate 47327c478bd9Sstevel@tonic-gate 47337c478bd9Sstevel@tonic-gate /* 47347c478bd9Sstevel@tonic-gate * loop reading lines until we've read a line with a non-whitespace 47357c478bd9Sstevel@tonic-gate * char. 47367c478bd9Sstevel@tonic-gate */ 47377c478bd9Sstevel@tonic-gate 47387c478bd9Sstevel@tonic-gate do { 47397c478bd9Sstevel@tonic-gate /* if no leftover from previous invocation */ 47407c478bd9Sstevel@tonic-gate 47417c478bd9Sstevel@tonic-gate if (lo == NULL) { 47427c478bd9Sstevel@tonic-gate 47437c478bd9Sstevel@tonic-gate /* 47447c478bd9Sstevel@tonic-gate * loop reading into buffer doubling if necessary until 47457c478bd9Sstevel@tonic-gate * we have either read a complete line or reached the 47467c478bd9Sstevel@tonic-gate * end of file. 47477c478bd9Sstevel@tonic-gate */ 47487c478bd9Sstevel@tonic-gate for (;;) { 47497c478bd9Sstevel@tonic-gate st = fgets(bpos, rembuf, fp); 47507c478bd9Sstevel@tonic-gate 47517c478bd9Sstevel@tonic-gate if (st == NULL) { 47527c478bd9Sstevel@tonic-gate 47537c478bd9Sstevel@tonic-gate /* if read error */ 47547c478bd9Sstevel@tonic-gate if (ferror(fp)) { 47557c478bd9Sstevel@tonic-gate free(buf); 47567c478bd9Sstevel@tonic-gate buf = NULL; 47577c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 47587c478bd9Sstevel@tonic-gate "fgets"); 47597c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate /* end of file */ 47627c478bd9Sstevel@tonic-gate } else { 47637c478bd9Sstevel@tonic-gate free(buf); 47647c478bd9Sstevel@tonic-gate buf = NULL; 47657c478bd9Sstevel@tonic-gate *token = NULL; 47667c478bd9Sstevel@tonic-gate return (IPQOS_CONF_EOF); 47677c478bd9Sstevel@tonic-gate } 47687c478bd9Sstevel@tonic-gate } else { 47697c478bd9Sstevel@tonic-gate /* if read a newline */ 47707c478bd9Sstevel@tonic-gate 47717c478bd9Sstevel@tonic-gate if (buf[strlen(buf) - 1] == '\n') { 47727c478bd9Sstevel@tonic-gate lineno++; 47737c478bd9Sstevel@tonic-gate break; 47747c478bd9Sstevel@tonic-gate 47757c478bd9Sstevel@tonic-gate /* if read the last line */ 47767c478bd9Sstevel@tonic-gate 47777c478bd9Sstevel@tonic-gate } else if (feof(fp)) { 47787c478bd9Sstevel@tonic-gate break; 47797c478bd9Sstevel@tonic-gate 47807c478bd9Sstevel@tonic-gate /* 47817c478bd9Sstevel@tonic-gate * not read a full line so buffer size 47827c478bd9Sstevel@tonic-gate * is too small, double it and retry. 47837c478bd9Sstevel@tonic-gate */ 47847c478bd9Sstevel@tonic-gate } else { 47857c478bd9Sstevel@tonic-gate bufsize *= 2; 47867c478bd9Sstevel@tonic-gate tmp = realloc(buf, bufsize); 47877c478bd9Sstevel@tonic-gate if (tmp == NULL) { 47887c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 47897c478bd9Sstevel@tonic-gate "realloc"); 47907c478bd9Sstevel@tonic-gate free(buf); 47917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 47927c478bd9Sstevel@tonic-gate } else { 47937c478bd9Sstevel@tonic-gate buf = tmp; 47947c478bd9Sstevel@tonic-gate } 47957c478bd9Sstevel@tonic-gate 47967c478bd9Sstevel@tonic-gate /* 47977c478bd9Sstevel@tonic-gate * make parameters to fgets read 47987c478bd9Sstevel@tonic-gate * into centre of doubled buffer 47997c478bd9Sstevel@tonic-gate * so we retain what we've 48007c478bd9Sstevel@tonic-gate * already read. 48017c478bd9Sstevel@tonic-gate */ 48027c478bd9Sstevel@tonic-gate bpos = &buf[(bufsize / 2) - 1]; 48037c478bd9Sstevel@tonic-gate rembuf = (bufsize / 2) + 1; 48047c478bd9Sstevel@tonic-gate } 48057c478bd9Sstevel@tonic-gate } 48067c478bd9Sstevel@tonic-gate } 48077c478bd9Sstevel@tonic-gate 48087c478bd9Sstevel@tonic-gate st = buf; 48097c478bd9Sstevel@tonic-gate 48107c478bd9Sstevel@tonic-gate /* previous leftover, assign to st */ 48117c478bd9Sstevel@tonic-gate 48127c478bd9Sstevel@tonic-gate } else { 48137c478bd9Sstevel@tonic-gate st = lo; 48147c478bd9Sstevel@tonic-gate lo = NULL; 48157c478bd9Sstevel@tonic-gate } 48167c478bd9Sstevel@tonic-gate 48177c478bd9Sstevel@tonic-gate /* truncate at comment */ 48187c478bd9Sstevel@tonic-gate 48197c478bd9Sstevel@tonic-gate cmnt = strchr(st, '#'); 48207c478bd9Sstevel@tonic-gate if (cmnt) { 48217c478bd9Sstevel@tonic-gate *cmnt = '\0'; 48227c478bd9Sstevel@tonic-gate } 48237c478bd9Sstevel@tonic-gate 48247c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 48257c478bd9Sstevel@tonic-gate 4826f7819bf9SToomas Soome while (isspace(*st) && *st != '\0') { 48277c478bd9Sstevel@tonic-gate st++; 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate 48307c478bd9Sstevel@tonic-gate } while (*st == '\0'); 48317c478bd9Sstevel@tonic-gate 48327c478bd9Sstevel@tonic-gate 48337c478bd9Sstevel@tonic-gate /* find end of token */ 48347c478bd9Sstevel@tonic-gate 48357c478bd9Sstevel@tonic-gate tmp = st; 48367c478bd9Sstevel@tonic-gate 48377c478bd9Sstevel@tonic-gate /* if curl advance 1 char */ 48387c478bd9Sstevel@tonic-gate 48397c478bd9Sstevel@tonic-gate if (*tmp == CURL_BEGIN || *tmp == CURL_END) { 48407c478bd9Sstevel@tonic-gate tmp++; 48417c478bd9Sstevel@tonic-gate 48427c478bd9Sstevel@tonic-gate 48437c478bd9Sstevel@tonic-gate /* if dbl quote read until matching quote */ 48447c478bd9Sstevel@tonic-gate 48457c478bd9Sstevel@tonic-gate } else if (*tmp == '"') { 48467c478bd9Sstevel@tonic-gate quoted++; 48477c478bd9Sstevel@tonic-gate tmp = ++st; 48487c478bd9Sstevel@tonic-gate 48497c478bd9Sstevel@tonic-gate while (*tmp != '"' && *tmp != '\n' && *tmp != '\0') { 48507c478bd9Sstevel@tonic-gate tmp++; 48517c478bd9Sstevel@tonic-gate } 48527c478bd9Sstevel@tonic-gate if (*tmp != '"') { 48537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Quoted string exceeds " 48547c478bd9Sstevel@tonic-gate "line, line %u.\n"), lineno); 48557c478bd9Sstevel@tonic-gate free(buf); 48567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 48577c478bd9Sstevel@tonic-gate } 48587c478bd9Sstevel@tonic-gate 48597c478bd9Sstevel@tonic-gate /* normal token */ 48607c478bd9Sstevel@tonic-gate } else { 48617c478bd9Sstevel@tonic-gate /* find first whitespace, curl, newline or string end */ 48627c478bd9Sstevel@tonic-gate 48637c478bd9Sstevel@tonic-gate while (!isspace(*tmp) && *tmp != CURL_BEGIN && 48647c478bd9Sstevel@tonic-gate *tmp != CURL_END && *tmp != '\n' && *tmp != '\0') { 48657c478bd9Sstevel@tonic-gate tmp++; 48667c478bd9Sstevel@tonic-gate } 48677c478bd9Sstevel@tonic-gate } 48687c478bd9Sstevel@tonic-gate 48697c478bd9Sstevel@tonic-gate /* copy token to return */ 48707c478bd9Sstevel@tonic-gate len = tmp - st; 48717c478bd9Sstevel@tonic-gate *token = malloc(len + 1); 48727c478bd9Sstevel@tonic-gate if (!*token) { 48737c478bd9Sstevel@tonic-gate free(buf); 48747c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 48757c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 48767c478bd9Sstevel@tonic-gate } 48777c478bd9Sstevel@tonic-gate bcopy(st, *token, len); 48787c478bd9Sstevel@tonic-gate (*token)[len] = '\0'; 48797c478bd9Sstevel@tonic-gate 48807c478bd9Sstevel@tonic-gate /* if just read quoted string remove quote from remaining string */ 48817c478bd9Sstevel@tonic-gate 48827c478bd9Sstevel@tonic-gate if (quoted) { 48837c478bd9Sstevel@tonic-gate tmp++; 48847c478bd9Sstevel@tonic-gate } 48857c478bd9Sstevel@tonic-gate 48867c478bd9Sstevel@tonic-gate /* if not end of string, store rest for latter parsing */ 48877c478bd9Sstevel@tonic-gate 48887c478bd9Sstevel@tonic-gate if (*tmp != '\0' && *tmp != '\n') { 48897c478bd9Sstevel@tonic-gate lo = tmp; 48907c478bd9Sstevel@tonic-gate } 48917c478bd9Sstevel@tonic-gate 48927c478bd9Sstevel@tonic-gate /* for curl_end and curl_begin return special ret codes */ 48937c478bd9Sstevel@tonic-gate 48947c478bd9Sstevel@tonic-gate if ((*token)[1] == '\0') { 48957c478bd9Sstevel@tonic-gate if (**token == CURL_BEGIN) { 48967c478bd9Sstevel@tonic-gate return (IPQOS_CONF_CURL_BEGIN); 48977c478bd9Sstevel@tonic-gate } else if (**token == CURL_END) { 48987c478bd9Sstevel@tonic-gate return (IPQOS_CONF_CURL_END); 48997c478bd9Sstevel@tonic-gate } 49007c478bd9Sstevel@tonic-gate } 49017c478bd9Sstevel@tonic-gate 49027c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 49037c478bd9Sstevel@tonic-gate } 49047c478bd9Sstevel@tonic-gate 49057c478bd9Sstevel@tonic-gate /* 49067c478bd9Sstevel@tonic-gate * Reads an enumeration bitmask definition from line. The format is: 49077c478bd9Sstevel@tonic-gate * { NAME=VAL, NAME2=VAL2 }. The resulting names and values are returned. 49087c478bd9Sstevel@tonic-gate * RETURNS: NULL on error, else ptr to name/values. 49097c478bd9Sstevel@tonic-gate */ 49107c478bd9Sstevel@tonic-gate static str_val_nd_t * 49117c478bd9Sstevel@tonic-gate read_enum_nvs(char *line, char *module_name) 49127c478bd9Sstevel@tonic-gate { 49137c478bd9Sstevel@tonic-gate 49147c478bd9Sstevel@tonic-gate str_val_nd_t *enum_vals = NULL; 49157c478bd9Sstevel@tonic-gate char *cp; 49167c478bd9Sstevel@tonic-gate char *start; 49177c478bd9Sstevel@tonic-gate char *name = NULL; 49187c478bd9Sstevel@tonic-gate int len; 49197c478bd9Sstevel@tonic-gate uint32_t val; 49207c478bd9Sstevel@tonic-gate int ret; 49217c478bd9Sstevel@tonic-gate int readc; 49227c478bd9Sstevel@tonic-gate 49237c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In read_enum_nvs, line: %s\n", line); 49247c478bd9Sstevel@tonic-gate 49257c478bd9Sstevel@tonic-gate /* read opening brace */ 49267c478bd9Sstevel@tonic-gate 49277c478bd9Sstevel@tonic-gate cp = strchr(line, CURL_BEGIN); 49287c478bd9Sstevel@tonic-gate if (cp == NULL) { 49297c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "missing curl begin\n"); 49307c478bd9Sstevel@tonic-gate goto fail; 49317c478bd9Sstevel@tonic-gate } else { 49327c478bd9Sstevel@tonic-gate start = cp + 1; 49337c478bd9Sstevel@tonic-gate } 49347c478bd9Sstevel@tonic-gate 49357c478bd9Sstevel@tonic-gate /* 49367c478bd9Sstevel@tonic-gate * loop reading 'name = value' entrys seperated by comma until 49377c478bd9Sstevel@tonic-gate * reach closing brace. 49387c478bd9Sstevel@tonic-gate */ 49397c478bd9Sstevel@tonic-gate 49407c478bd9Sstevel@tonic-gate for (;;) { 49417c478bd9Sstevel@tonic-gate SKIPWS(start); 49427c478bd9Sstevel@tonic-gate if (*start == '\0') { 49437c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "missing closing bracket\n"); 49447c478bd9Sstevel@tonic-gate goto fail; 49457c478bd9Sstevel@tonic-gate } 49467c478bd9Sstevel@tonic-gate 49477c478bd9Sstevel@tonic-gate /* 49487c478bd9Sstevel@tonic-gate * read name - read until whitespace, '=', closing curl, 49497c478bd9Sstevel@tonic-gate * or string end. 49507c478bd9Sstevel@tonic-gate */ 49517c478bd9Sstevel@tonic-gate 49527c478bd9Sstevel@tonic-gate for (cp = start; 49537c478bd9Sstevel@tonic-gate !isspace(*cp) && *cp != '=' && *cp != CURL_END && 49547c478bd9Sstevel@tonic-gate *cp != '\0'; cp++) {} 49557c478bd9Sstevel@tonic-gate 49567c478bd9Sstevel@tonic-gate if (*cp == '\0') { 49577c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Unexpected line end in enum def'n\n"); 49587c478bd9Sstevel@tonic-gate goto fail; 49597c478bd9Sstevel@tonic-gate 49607c478bd9Sstevel@tonic-gate /* finished definition, exit loop */ 49617c478bd9Sstevel@tonic-gate } else if (*cp == CURL_END) { 49627c478bd9Sstevel@tonic-gate break; 49637c478bd9Sstevel@tonic-gate } 49647c478bd9Sstevel@tonic-gate 49657c478bd9Sstevel@tonic-gate /* store name */ 49667c478bd9Sstevel@tonic-gate 49677c478bd9Sstevel@tonic-gate len = cp - start; 49687c478bd9Sstevel@tonic-gate name = malloc(len + 1); 49697c478bd9Sstevel@tonic-gate if (name == NULL) { 49707c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 49717c478bd9Sstevel@tonic-gate goto fail; 49727c478bd9Sstevel@tonic-gate } 49737c478bd9Sstevel@tonic-gate bcopy(start, name, len); 49747c478bd9Sstevel@tonic-gate name[len] = NULL; 49757c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "Stored name: %s\n", name); 49767c478bd9Sstevel@tonic-gate 49777c478bd9Sstevel@tonic-gate /* read assignment */ 49787c478bd9Sstevel@tonic-gate 49797c478bd9Sstevel@tonic-gate start = strchr(cp, '='); 49807c478bd9Sstevel@tonic-gate if (start == NULL) { 49817c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Missing = in enum def'n\n"); 49827c478bd9Sstevel@tonic-gate goto fail; 49837c478bd9Sstevel@tonic-gate } 49847c478bd9Sstevel@tonic-gate 49857c478bd9Sstevel@tonic-gate /* read value */ 49867c478bd9Sstevel@tonic-gate 49877c478bd9Sstevel@tonic-gate ret = sscanf(++start, "%x%n", &val, &readc); 49887c478bd9Sstevel@tonic-gate if (ret != 1) { 49897c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "sscanf of value failed, string: %s\n", 49907c478bd9Sstevel@tonic-gate cp); 49917c478bd9Sstevel@tonic-gate goto fail; 49927c478bd9Sstevel@tonic-gate } 49937c478bd9Sstevel@tonic-gate 49947c478bd9Sstevel@tonic-gate /* add name value to set */ 49957c478bd9Sstevel@tonic-gate 49967c478bd9Sstevel@tonic-gate ret = add_str_val_entry(&enum_vals, name, val); 49977c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 49987c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Failed to add str_val entry\n"); 49997c478bd9Sstevel@tonic-gate goto fail; 50007c478bd9Sstevel@tonic-gate } 50017c478bd9Sstevel@tonic-gate free(name); 50027c478bd9Sstevel@tonic-gate name = NULL; 50037c478bd9Sstevel@tonic-gate 50047c478bd9Sstevel@tonic-gate /* try reading comma */ 50057c478bd9Sstevel@tonic-gate cp = strchr(start, ','); 50067c478bd9Sstevel@tonic-gate 50077c478bd9Sstevel@tonic-gate if (cp != NULL) { 50087c478bd9Sstevel@tonic-gate start = cp + 1; 50097c478bd9Sstevel@tonic-gate 50107c478bd9Sstevel@tonic-gate /* no comma, advance to char past value last read */ 50117c478bd9Sstevel@tonic-gate } else { 50127c478bd9Sstevel@tonic-gate start += readc; 50137c478bd9Sstevel@tonic-gate } 50147c478bd9Sstevel@tonic-gate } 50157c478bd9Sstevel@tonic-gate 50167c478bd9Sstevel@tonic-gate return (enum_vals); 50177c478bd9Sstevel@tonic-gate fail: 50187c478bd9Sstevel@tonic-gate free_str_val_entrys(enum_vals); 50197c478bd9Sstevel@tonic-gate if (name != NULL) 50207c478bd9Sstevel@tonic-gate free(name); 50217c478bd9Sstevel@tonic-gate 50227c478bd9Sstevel@tonic-gate /* if a parse error */ 50237c478bd9Sstevel@tonic-gate 50247c478bd9Sstevel@tonic-gate if (errno == 0) { 50257c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Types file for module %s is " 50267c478bd9Sstevel@tonic-gate "corrupt.\n"), module_name); 50277c478bd9Sstevel@tonic-gate } 50287c478bd9Sstevel@tonic-gate 50297c478bd9Sstevel@tonic-gate return (NULL); 50307c478bd9Sstevel@tonic-gate } 50317c478bd9Sstevel@tonic-gate 50327c478bd9Sstevel@tonic-gate /* 50337c478bd9Sstevel@tonic-gate * Given mapped_list with is a comma seperated list of map names, and value, 50347c478bd9Sstevel@tonic-gate * which is used to index into these maps, the function creates x new entries 50357c478bd9Sstevel@tonic-gate * in nvpp, where x is the number of map names specified. Each of these 50367c478bd9Sstevel@tonic-gate * entries has the value from the map in the position indexed by value and 50377c478bd9Sstevel@tonic-gate * with name module.${MAP_NAME}. The maps are contained in the modules config 50387c478bd9Sstevel@tonic-gate * file and have the form: 50397c478bd9Sstevel@tonic-gate * map map1 uint32 1,23,32,45,3 50407c478bd9Sstevel@tonic-gate * As you can see the map values are uint32, and along with uint8 are the 50417c478bd9Sstevel@tonic-gate * only supported types at the moment. 50427c478bd9Sstevel@tonic-gate * 50437c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if one of the maps specified in mapped_list 50447c478bd9Sstevel@tonic-gate * doesn't exist, if value is not a valid map position for a map, or if 50457c478bd9Sstevel@tonic-gate * there's a resource failure. otherwise IPQOS_CONF_SUCCESS is returned. 50467c478bd9Sstevel@tonic-gate */ 50477c478bd9Sstevel@tonic-gate static int 50487c478bd9Sstevel@tonic-gate read_mapped_values( 50497c478bd9Sstevel@tonic-gate FILE *tfp, 50507c478bd9Sstevel@tonic-gate nvlist_t **nvlp, 50517c478bd9Sstevel@tonic-gate char *module, 50527c478bd9Sstevel@tonic-gate char *mapped_list, 50537c478bd9Sstevel@tonic-gate int value) 50547c478bd9Sstevel@tonic-gate { 50557c478bd9Sstevel@tonic-gate char *map_name, *lastparam, *tmpname; 50567c478bd9Sstevel@tonic-gate int res; 50577c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 50587c478bd9Sstevel@tonic-gate char dfltst[IPQOS_VALST_MAXLEN+1] = ""; 50597c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs; 50607c478bd9Sstevel@tonic-gate place_t place; 50617c478bd9Sstevel@tonic-gate 50627c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In read_mapped_values\n"); 50637c478bd9Sstevel@tonic-gate 50647c478bd9Sstevel@tonic-gate map_name = (char *)strtok_r(mapped_list, ",", &lastparam); 50657c478bd9Sstevel@tonic-gate while (map_name != NULL) { 50667c478bd9Sstevel@tonic-gate char *tokval, *lastval; 50677c478bd9Sstevel@tonic-gate int index = 0; 50687c478bd9Sstevel@tonic-gate 50697c478bd9Sstevel@tonic-gate /* 50707c478bd9Sstevel@tonic-gate * get map info from types file. 50717c478bd9Sstevel@tonic-gate */ 50727c478bd9Sstevel@tonic-gate place = PL_MAP; 50737c478bd9Sstevel@tonic-gate res = readtype(tfp, module, map_name, &type, &enum_nvs, 50747c478bd9Sstevel@tonic-gate dfltst, B_FALSE, &place); 50757c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 50767c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 50777c478bd9Sstevel@tonic-gate } 50787c478bd9Sstevel@tonic-gate 50797c478bd9Sstevel@tonic-gate /* 50807c478bd9Sstevel@tonic-gate * Just keep browsing the list till we get to the element 50817c478bd9Sstevel@tonic-gate * with the index from the value parameter or the end. 50827c478bd9Sstevel@tonic-gate */ 50837c478bd9Sstevel@tonic-gate tokval = (char *)strtok_r(dfltst, ",", &lastval); 50847c478bd9Sstevel@tonic-gate for (;;) { 50857c478bd9Sstevel@tonic-gate if (tokval == NULL) { 50867c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 50877c478bd9Sstevel@tonic-gate gettext("Invalid value, %u, line %u.\n"), 50887c478bd9Sstevel@tonic-gate value, lineno); 50897c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 50907c478bd9Sstevel@tonic-gate } 50917c478bd9Sstevel@tonic-gate if (index++ == value) { 50927c478bd9Sstevel@tonic-gate break; 50937c478bd9Sstevel@tonic-gate } 50947c478bd9Sstevel@tonic-gate tokval = (char *)strtok_r(NULL, ",", &lastval); 50957c478bd9Sstevel@tonic-gate } 50967c478bd9Sstevel@tonic-gate 50977c478bd9Sstevel@tonic-gate 50987c478bd9Sstevel@tonic-gate /* 50997c478bd9Sstevel@tonic-gate * create fully qualified parameter name for map value. 51007c478bd9Sstevel@tonic-gate */ 51017c478bd9Sstevel@tonic-gate tmpname = prepend_module_name(map_name, module); 51027c478bd9Sstevel@tonic-gate if (tmpname == NULL) { 51037c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 51047c478bd9Sstevel@tonic-gate } 51057c478bd9Sstevel@tonic-gate 51067c478bd9Sstevel@tonic-gate /* 51077c478bd9Sstevel@tonic-gate * add map value with fqn to parameter nvlist. 51087c478bd9Sstevel@tonic-gate */ 51097c478bd9Sstevel@tonic-gate IPQOSCDBG2(L0, "Adding map %s, value %u to nvlist\n", 51107c478bd9Sstevel@tonic-gate tmpname, atoi(tokval)); 51117c478bd9Sstevel@tonic-gate switch (type) { 51127c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT8: { 51137c478bd9Sstevel@tonic-gate res = nvlist_add_byte(*nvlp, tmpname, 51147c478bd9Sstevel@tonic-gate (uint8_t)atoi(tokval)); 51157c478bd9Sstevel@tonic-gate if (res != 0) { 51167c478bd9Sstevel@tonic-gate free(tmpname); 51177c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 51187c478bd9Sstevel@tonic-gate "nvlist_add_uint8"); 51197c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 51207c478bd9Sstevel@tonic-gate } 51217c478bd9Sstevel@tonic-gate break; 51227c478bd9Sstevel@tonic-gate } 51237c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT32: { 51247c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvlp, tmpname, 51257c478bd9Sstevel@tonic-gate (uint32_t)atoi(tokval)); 51267c478bd9Sstevel@tonic-gate if (res != 0) { 51277c478bd9Sstevel@tonic-gate free(tmpname); 51287c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 51297c478bd9Sstevel@tonic-gate "nvlist_add_uint32"); 51307c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 51317c478bd9Sstevel@tonic-gate } 51327c478bd9Sstevel@tonic-gate break; 51337c478bd9Sstevel@tonic-gate } 51347c478bd9Sstevel@tonic-gate default: { 51357c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 51367c478bd9Sstevel@tonic-gate gettext("Types file for module %s is " 51377c478bd9Sstevel@tonic-gate "corrupt.\n"), module); 51387c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "Unsupported map type for " 51397c478bd9Sstevel@tonic-gate "parameter %s given in types file.\n", 51407c478bd9Sstevel@tonic-gate map_name); 51417c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 51427c478bd9Sstevel@tonic-gate } 51437c478bd9Sstevel@tonic-gate } 51447c478bd9Sstevel@tonic-gate free(tmpname); 51457c478bd9Sstevel@tonic-gate 51467c478bd9Sstevel@tonic-gate map_name = (char *)strtok_r(NULL, ",", &lastparam); 51477c478bd9Sstevel@tonic-gate } 51487c478bd9Sstevel@tonic-gate 51497c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 51507c478bd9Sstevel@tonic-gate } 51517c478bd9Sstevel@tonic-gate 51527c478bd9Sstevel@tonic-gate /* 51537c478bd9Sstevel@tonic-gate * Parses the string info_str into it's components. Its format is: 51547c478bd9Sstevel@tonic-gate * SIZE','[ENUM_DEF | RANGE], where SIZE is the size of the array, 51557c478bd9Sstevel@tonic-gate * ENUM_DEF is the definition of the enumeration for this array, 51567c478bd9Sstevel@tonic-gate * and RANGE is the set of values this array can accept. In 51577c478bd9Sstevel@tonic-gate * the event this array has an enumeration definition enum_nvs is 51587c478bd9Sstevel@tonic-gate * set to point at a str_val_nd_t structure which stores the names 51597c478bd9Sstevel@tonic-gate * and values associated with this enumeration. Otherwise, if this 51607c478bd9Sstevel@tonic-gate * is not an enumerated array, lower and upper are set to the lower 51617c478bd9Sstevel@tonic-gate * and upper values of RANGE. 51627c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR due to unexpected parse errors, else 51637c478bd9Sstevel@tonic-gate * IPQOS_CONF_SUCCESS. 51647c478bd9Sstevel@tonic-gate */ 51657c478bd9Sstevel@tonic-gate static int 51667c478bd9Sstevel@tonic-gate read_int_array_info( 51677c478bd9Sstevel@tonic-gate char *info_str, 51687c478bd9Sstevel@tonic-gate str_val_nd_t **enum_nvs, 51697c478bd9Sstevel@tonic-gate uint32_t *size, 51707c478bd9Sstevel@tonic-gate int *lower, 51717c478bd9Sstevel@tonic-gate int *upper, 51727c478bd9Sstevel@tonic-gate char *module) 51737c478bd9Sstevel@tonic-gate { 51747c478bd9Sstevel@tonic-gate int res; 51757c478bd9Sstevel@tonic-gate char *end; 51767c478bd9Sstevel@tonic-gate char *token; 51777c478bd9Sstevel@tonic-gate char *tmp; 51787c478bd9Sstevel@tonic-gate 51797c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "In read_array_info: info_str: %s\n", 51807c478bd9Sstevel@tonic-gate (info_str != NULL) ? info_str : "NULL"); 51817c478bd9Sstevel@tonic-gate 51827c478bd9Sstevel@tonic-gate if (info_str == NULL) { 51837c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Null info string\n"); 51847c478bd9Sstevel@tonic-gate goto fail; 51857c478bd9Sstevel@tonic-gate } 51867c478bd9Sstevel@tonic-gate 51877c478bd9Sstevel@tonic-gate /* 51887c478bd9Sstevel@tonic-gate * read size. 51897c478bd9Sstevel@tonic-gate */ 51907c478bd9Sstevel@tonic-gate token = strtok(info_str, ","); 51917c478bd9Sstevel@tonic-gate *size = (uint32_t)strtol(token, &end, 10); 51927c478bd9Sstevel@tonic-gate SKIPWS(end); 51937c478bd9Sstevel@tonic-gate if ((end == token) || (*end != NULL)) { 51947c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Invalid size\n"); 51957c478bd9Sstevel@tonic-gate goto fail; 51967c478bd9Sstevel@tonic-gate } 51977c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "read size: %u\n", *size); 51987c478bd9Sstevel@tonic-gate 51997c478bd9Sstevel@tonic-gate /* 52007c478bd9Sstevel@tonic-gate * check we have another string. 52017c478bd9Sstevel@tonic-gate */ 52027c478bd9Sstevel@tonic-gate token = strtok(NULL, "\n"); 52037c478bd9Sstevel@tonic-gate if (token == NULL) { 52047c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Missing range/enum def\n"); 52057c478bd9Sstevel@tonic-gate goto fail; 52067c478bd9Sstevel@tonic-gate } 52077c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "range/enum def: %s\n", token); 52087c478bd9Sstevel@tonic-gate 52097c478bd9Sstevel@tonic-gate /* 52107c478bd9Sstevel@tonic-gate * check if enumeration set or integer set and read enumeration 52117c478bd9Sstevel@tonic-gate * definition or integer range respectively. 52127c478bd9Sstevel@tonic-gate */ 52137c478bd9Sstevel@tonic-gate tmp = strchr(token, CURL_BEGIN); 52147c478bd9Sstevel@tonic-gate if (tmp == NULL) { /* a numeric range */ 52157c478bd9Sstevel@tonic-gate res = readrange(token, lower, upper); 52167c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 52177c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Failed reading range\n"); 52187c478bd9Sstevel@tonic-gate goto fail; 52197c478bd9Sstevel@tonic-gate } 52207c478bd9Sstevel@tonic-gate } else { /* an enumeration */ 52217c478bd9Sstevel@tonic-gate *enum_nvs = read_enum_nvs(token, module); 52227c478bd9Sstevel@tonic-gate if (*enum_nvs == NULL) { 52237c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Failed reading enum def\n"); 52247c478bd9Sstevel@tonic-gate goto fail; 52257c478bd9Sstevel@tonic-gate } 52267c478bd9Sstevel@tonic-gate } 52277c478bd9Sstevel@tonic-gate 52287c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 52297c478bd9Sstevel@tonic-gate fail: 52307c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 52317c478bd9Sstevel@tonic-gate gettext("Types file for module %s is corrupt.\n"), module); 52327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 52337c478bd9Sstevel@tonic-gate } 52347c478bd9Sstevel@tonic-gate 52357c478bd9Sstevel@tonic-gate /* 52367c478bd9Sstevel@tonic-gate * reads the value of an enumeration parameter from first_token and fp. 52377c478bd9Sstevel@tonic-gate * first_token is the first token of the value. 52387c478bd9Sstevel@tonic-gate * The format expected is NAME | { NAME1 [, NAME2 ] [, NAME3 ] }. 52397c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 52407c478bd9Sstevel@tonic-gate */ 52417c478bd9Sstevel@tonic-gate static int 52427c478bd9Sstevel@tonic-gate read_enum_value( 52437c478bd9Sstevel@tonic-gate FILE *fp, 52447c478bd9Sstevel@tonic-gate char *first_token, 52457c478bd9Sstevel@tonic-gate str_val_nd_t *enum_vals, 52467c478bd9Sstevel@tonic-gate uint32_t *val) 52477c478bd9Sstevel@tonic-gate { 52487c478bd9Sstevel@tonic-gate 52497c478bd9Sstevel@tonic-gate uint32_t u32; 52507c478bd9Sstevel@tonic-gate int ret; 52517c478bd9Sstevel@tonic-gate char *tk; 52527c478bd9Sstevel@tonic-gate char *lo = NULL; 52537c478bd9Sstevel@tonic-gate char *cm; 52547c478bd9Sstevel@tonic-gate int name_expected = 0; 52557c478bd9Sstevel@tonic-gate 52567c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In read_enum_value\n"); 52577c478bd9Sstevel@tonic-gate 52587c478bd9Sstevel@tonic-gate /* init param val */ 52597c478bd9Sstevel@tonic-gate *val = 0; 52607c478bd9Sstevel@tonic-gate 52617c478bd9Sstevel@tonic-gate /* first token not curl_begin, so lookup its value */ 52627c478bd9Sstevel@tonic-gate 52637c478bd9Sstevel@tonic-gate if (*first_token != CURL_BEGIN) { 52647c478bd9Sstevel@tonic-gate ret = str_val_list_lookup(enum_vals, first_token, val); 52657c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 52667c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 52677c478bd9Sstevel@tonic-gate gettext("Unrecognized value, %s, line %u.\n"), 52687c478bd9Sstevel@tonic-gate first_token, lineno); 52697c478bd9Sstevel@tonic-gate return (ret); 52707c478bd9Sstevel@tonic-gate } 52717c478bd9Sstevel@tonic-gate 52727c478bd9Sstevel@tonic-gate /* curl_begin, so read values till curl_end, dicing at ',' */ 52737c478bd9Sstevel@tonic-gate } else { 52747c478bd9Sstevel@tonic-gate 52757c478bd9Sstevel@tonic-gate name_expected++; 52767c478bd9Sstevel@tonic-gate 52777c478bd9Sstevel@tonic-gate for (;;) { 52787c478bd9Sstevel@tonic-gate 52797c478bd9Sstevel@tonic-gate /* 52807c478bd9Sstevel@tonic-gate * no leftover from pervious iteration so read new 52817c478bd9Sstevel@tonic-gate * token. This leftover happens because readtoken 52827c478bd9Sstevel@tonic-gate * doesn't interpret comma's as special characters 52837c478bd9Sstevel@tonic-gate * and thus could return 'val1,val2' as one token. 52847c478bd9Sstevel@tonic-gate * If this happens the val1 will be used in the 52857c478bd9Sstevel@tonic-gate * current iteration and what follows saved in lo 52867c478bd9Sstevel@tonic-gate * for processing by successive iterations. 52877c478bd9Sstevel@tonic-gate */ 52887c478bd9Sstevel@tonic-gate 52897c478bd9Sstevel@tonic-gate if (lo == NULL) { 52907c478bd9Sstevel@tonic-gate ret = readtoken(fp, &tk); 52917c478bd9Sstevel@tonic-gate if (ret == IPQOS_CONF_ERR) { 52927c478bd9Sstevel@tonic-gate return (ret); 52937c478bd9Sstevel@tonic-gate } else if (ret == IPQOS_CONF_EOF) { 52947c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 52957c478bd9Sstevel@tonic-gate gettext("Unexpected EOF.\n")); 52967c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 52977c478bd9Sstevel@tonic-gate 52987c478bd9Sstevel@tonic-gate } 52997c478bd9Sstevel@tonic-gate } else { /* previous leftover, so use it */ 53007c478bd9Sstevel@tonic-gate 53017c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "Using leftover %s.\n", lo); 53027c478bd9Sstevel@tonic-gate tk = lo; 53037c478bd9Sstevel@tonic-gate lo = NULL; 53047c478bd9Sstevel@tonic-gate } 53057c478bd9Sstevel@tonic-gate 53067c478bd9Sstevel@tonic-gate if (name_expected) { 53077c478bd9Sstevel@tonic-gate if (ret == IPQOS_CONF_CURL_END || 53087c478bd9Sstevel@tonic-gate tk[0] == ',') { 53097c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 53107c478bd9Sstevel@tonic-gate gettext("Malformed value list " 53117c478bd9Sstevel@tonic-gate "line %u.\n"), lineno); 53127c478bd9Sstevel@tonic-gate free(tk); 53137c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 53147c478bd9Sstevel@tonic-gate } 53157c478bd9Sstevel@tonic-gate 53167c478bd9Sstevel@tonic-gate /* 53177c478bd9Sstevel@tonic-gate * check if this token contains a ',' and 53187c478bd9Sstevel@tonic-gate * if so store it and what follows for next 53197c478bd9Sstevel@tonic-gate * iteration. 53207c478bd9Sstevel@tonic-gate */ 53217c478bd9Sstevel@tonic-gate cm = strchr(tk, ','); 53227c478bd9Sstevel@tonic-gate if (cm != NULL) { 53237c478bd9Sstevel@tonic-gate lo = malloc(strlen(cm) + 1); 53247c478bd9Sstevel@tonic-gate if (lo == NULL) { 53257c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 53267c478bd9Sstevel@tonic-gate free(tk); 53277c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 53287c478bd9Sstevel@tonic-gate } 53297c478bd9Sstevel@tonic-gate 53307c478bd9Sstevel@tonic-gate (void) strcpy(lo, cm); 53317c478bd9Sstevel@tonic-gate *cm = '\0'; 53327c478bd9Sstevel@tonic-gate } 53337c478bd9Sstevel@tonic-gate 53347c478bd9Sstevel@tonic-gate 53357c478bd9Sstevel@tonic-gate /* get name value and add to total val */ 53367c478bd9Sstevel@tonic-gate 53377c478bd9Sstevel@tonic-gate ret = str_val_list_lookup(enum_vals, tk, &u32); 53387c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 53397c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 53407c478bd9Sstevel@tonic-gate gettext("Unrecognized value, %s, " 53417c478bd9Sstevel@tonic-gate "line %u.\n"), tk, lineno); 53427c478bd9Sstevel@tonic-gate free(tk); 53437c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 53447c478bd9Sstevel@tonic-gate } 53457c478bd9Sstevel@tonic-gate 53467c478bd9Sstevel@tonic-gate *val = *val | u32; 53477c478bd9Sstevel@tonic-gate name_expected--; 53487c478bd9Sstevel@tonic-gate 53497c478bd9Sstevel@tonic-gate /* comma or curl end accepted */ 53507c478bd9Sstevel@tonic-gate } else { 53517c478bd9Sstevel@tonic-gate 53527c478bd9Sstevel@tonic-gate /* we've reached curl_end so break */ 53537c478bd9Sstevel@tonic-gate 53547c478bd9Sstevel@tonic-gate if (ret == IPQOS_CONF_CURL_END) { 53557c478bd9Sstevel@tonic-gate free(tk); 53567c478bd9Sstevel@tonic-gate break; 53577c478bd9Sstevel@tonic-gate 53587c478bd9Sstevel@tonic-gate /* not curl end and not comma */ 53597c478bd9Sstevel@tonic-gate 53607c478bd9Sstevel@tonic-gate } else if (tk[0] != ',') { 53617c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 53627c478bd9Sstevel@tonic-gate gettext("Malformed value list " 53637c478bd9Sstevel@tonic-gate "line %u.\n"), lineno); 53647c478bd9Sstevel@tonic-gate free(tk); 53657c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 53667c478bd9Sstevel@tonic-gate } 53677c478bd9Sstevel@tonic-gate 53687c478bd9Sstevel@tonic-gate /* 53697c478bd9Sstevel@tonic-gate * store anything after the comma for next 53707c478bd9Sstevel@tonic-gate * iteration. 53717c478bd9Sstevel@tonic-gate */ 53727c478bd9Sstevel@tonic-gate if (tk[1] != '\0') { 53737c478bd9Sstevel@tonic-gate lo = malloc(strlen(&tk[1]) + 1); 53747c478bd9Sstevel@tonic-gate if (lo == NULL) { 53757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 53767c478bd9Sstevel@tonic-gate free(tk); 53777c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 53787c478bd9Sstevel@tonic-gate } 53797c478bd9Sstevel@tonic-gate (void) strcpy(lo, &tk[1]); 53807c478bd9Sstevel@tonic-gate } 53817c478bd9Sstevel@tonic-gate 53827c478bd9Sstevel@tonic-gate name_expected++; 53837c478bd9Sstevel@tonic-gate } 53847c478bd9Sstevel@tonic-gate 53857c478bd9Sstevel@tonic-gate free(tk); 53867c478bd9Sstevel@tonic-gate } 53877c478bd9Sstevel@tonic-gate } 53887c478bd9Sstevel@tonic-gate 53897c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "value returned is: %u\n", *val); 53907c478bd9Sstevel@tonic-gate 53917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 53927c478bd9Sstevel@tonic-gate } 53937c478bd9Sstevel@tonic-gate 53947c478bd9Sstevel@tonic-gate /* 53957c478bd9Sstevel@tonic-gate * read the set of permanent classes/filter from the types file ref'd by tfp 53967c478bd9Sstevel@tonic-gate * and store them in a string table pointed to by perm_items, 53977c478bd9Sstevel@tonic-gate * with *nitems getting set to number of items read. perm_filters is set 53987c478bd9Sstevel@tonic-gate * to 1 if we're searching for permanent filters, else 0 for classes. 53997c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS. 54007c478bd9Sstevel@tonic-gate */ 54017c478bd9Sstevel@tonic-gate static int 54027c478bd9Sstevel@tonic-gate read_perm_items( 54037c478bd9Sstevel@tonic-gate int perm_filters, 54047c478bd9Sstevel@tonic-gate FILE *tfp, 54057c478bd9Sstevel@tonic-gate char *module_name, 54067c478bd9Sstevel@tonic-gate char ***perm_items, 54077c478bd9Sstevel@tonic-gate int *nitems) 54087c478bd9Sstevel@tonic-gate { 54097c478bd9Sstevel@tonic-gate 54107c478bd9Sstevel@tonic-gate char lbuf[IPQOS_CONF_TYPE_LINE_LEN]; 54117c478bd9Sstevel@tonic-gate int cnt = 0; 54127c478bd9Sstevel@tonic-gate char name[IPQOS_CONF_NAME_LEN+1]; 54137c478bd9Sstevel@tonic-gate char foo[IPQOS_CONF_NAME_LEN+1]; 54147c478bd9Sstevel@tonic-gate int res; 54157c478bd9Sstevel@tonic-gate char **items = NULL; 54167c478bd9Sstevel@tonic-gate char **tmp; 54177c478bd9Sstevel@tonic-gate char *marker; 54187c478bd9Sstevel@tonic-gate 54197c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In read_perm_items\n"); 54207c478bd9Sstevel@tonic-gate 54217c478bd9Sstevel@tonic-gate 54227c478bd9Sstevel@tonic-gate /* seek to start of types file */ 54237c478bd9Sstevel@tonic-gate 54247c478bd9Sstevel@tonic-gate if (fseek(tfp, 0, SEEK_SET) != 0) { 54257c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fseek"); 54267c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 54277c478bd9Sstevel@tonic-gate } 54287c478bd9Sstevel@tonic-gate 54297c478bd9Sstevel@tonic-gate /* select which marker were looking for */ 54307c478bd9Sstevel@tonic-gate 54317c478bd9Sstevel@tonic-gate if (perm_filters) { 54327c478bd9Sstevel@tonic-gate marker = IPQOS_CONF_PERM_FILTER_MK; 54337c478bd9Sstevel@tonic-gate } else { 54347c478bd9Sstevel@tonic-gate marker = IPQOS_CONF_PERM_CLASS_MK; 54357c478bd9Sstevel@tonic-gate } 54367c478bd9Sstevel@tonic-gate 54377c478bd9Sstevel@tonic-gate /* scan file line by line till end */ 54387c478bd9Sstevel@tonic-gate 54397c478bd9Sstevel@tonic-gate while (fgets(lbuf, IPQOS_CONF_TYPE_LINE_LEN, tfp) != NULL) { 54407c478bd9Sstevel@tonic-gate 54417c478bd9Sstevel@tonic-gate /* 54427c478bd9Sstevel@tonic-gate * if the line is marked as containing a default item name 54437c478bd9Sstevel@tonic-gate * read the name, extend the items string array 54447c478bd9Sstevel@tonic-gate * and store the string off the array. 54457c478bd9Sstevel@tonic-gate */ 54467c478bd9Sstevel@tonic-gate if (strncmp(lbuf, marker, strlen(marker)) == 0) { 54477c478bd9Sstevel@tonic-gate 54487c478bd9Sstevel@tonic-gate res = sscanf(lbuf, 54497c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_NAME_LEN) "s" 54507c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_NAME_LEN) "s", 54517c478bd9Sstevel@tonic-gate foo, name); 54527c478bd9Sstevel@tonic-gate if (res < 2) { 54537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 54547c478bd9Sstevel@tonic-gate gettext("Types file for module %s is " 54557c478bd9Sstevel@tonic-gate "corrupt.\n"), module_name); 54567c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "Missing name with a %s.\n", 54577c478bd9Sstevel@tonic-gate marker); 54587c478bd9Sstevel@tonic-gate goto fail; 54597c478bd9Sstevel@tonic-gate } 54607c478bd9Sstevel@tonic-gate 54617c478bd9Sstevel@tonic-gate /* extend items array to accomodate new item */ 54627c478bd9Sstevel@tonic-gate 54637c478bd9Sstevel@tonic-gate tmp = realloc(items, (cnt + 1) * sizeof (char *)); 54647c478bd9Sstevel@tonic-gate if (tmp == NULL) { 54657c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "realloc"); 54667c478bd9Sstevel@tonic-gate goto fail; 54677c478bd9Sstevel@tonic-gate } else { 54687c478bd9Sstevel@tonic-gate items = tmp; 54697c478bd9Sstevel@tonic-gate } 54707c478bd9Sstevel@tonic-gate 54717c478bd9Sstevel@tonic-gate /* copy and store item name */ 54727c478bd9Sstevel@tonic-gate 54737c478bd9Sstevel@tonic-gate items[cnt] = malloc(strlen(name) + 1); 54747c478bd9Sstevel@tonic-gate if (items[cnt] == NULL) { 54757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 54767c478bd9Sstevel@tonic-gate goto fail; 54777c478bd9Sstevel@tonic-gate } 54787c478bd9Sstevel@tonic-gate 54797c478bd9Sstevel@tonic-gate (void) strcpy(items[cnt], name); 54807c478bd9Sstevel@tonic-gate cnt++; 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate 54837c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "stored %s in perm items array\n", 54847c478bd9Sstevel@tonic-gate name); 54857c478bd9Sstevel@tonic-gate } 54867c478bd9Sstevel@tonic-gate } 54877c478bd9Sstevel@tonic-gate 54887c478bd9Sstevel@tonic-gate *perm_items = items; 54897c478bd9Sstevel@tonic-gate *nitems = cnt; 54907c478bd9Sstevel@tonic-gate 54917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 54927c478bd9Sstevel@tonic-gate fail: 54937c478bd9Sstevel@tonic-gate for (cnt--; cnt >= 0; cnt--) 54947c478bd9Sstevel@tonic-gate free(items[cnt]); 54957c478bd9Sstevel@tonic-gate free(items); 54967c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 54977c478bd9Sstevel@tonic-gate } 54987c478bd9Sstevel@tonic-gate 54997c478bd9Sstevel@tonic-gate /* 55007c478bd9Sstevel@tonic-gate * Searches types file ref'd by tfp for the parameter named name 55017c478bd9Sstevel@tonic-gate * with the place corresponding with place parameter. The format 55027c478bd9Sstevel@tonic-gate * of the lines in the file are: 55037c478bd9Sstevel@tonic-gate * PLACE NAME TYPE [ ENUM_DEF ] [ DEFAULT_STR ] 55047c478bd9Sstevel@tonic-gate * The ENUM_DEF is an enumeration definition and is only present 55057c478bd9Sstevel@tonic-gate * for parameters of type enum. DEFAULT_STR is a default value for 55067c478bd9Sstevel@tonic-gate * this parameter. If present type is set to the appropriate type 55077c478bd9Sstevel@tonic-gate * enumeration and dfltst filled with DEFAULT_STR if one was set. 55087c478bd9Sstevel@tonic-gate * Also if the type is enum enum_nvps is made to point at a 55097c478bd9Sstevel@tonic-gate * set of name value pairs representing ENUM_DEF. 55107c478bd9Sstevel@tonic-gate * 55117c478bd9Sstevel@tonic-gate * RETURNS: If any resource errors occur, or a matching parameter 55127c478bd9Sstevel@tonic-gate * isn't found IPQOS_CONF_ERR is returned, else IPQOS_CONF_SUCCESS. 55137c478bd9Sstevel@tonic-gate */ 55147c478bd9Sstevel@tonic-gate static int 55157c478bd9Sstevel@tonic-gate readtype( 55167c478bd9Sstevel@tonic-gate FILE *tfp, 55177c478bd9Sstevel@tonic-gate char *module_name, 55187c478bd9Sstevel@tonic-gate char *name, 55197c478bd9Sstevel@tonic-gate ipqos_nvtype_t *type, 55207c478bd9Sstevel@tonic-gate str_val_nd_t **enum_nvps, 55217c478bd9Sstevel@tonic-gate char *dfltst, 55227c478bd9Sstevel@tonic-gate boolean_t allow_ipgpc_priv, 55237c478bd9Sstevel@tonic-gate place_t *place) 55247c478bd9Sstevel@tonic-gate { 55257c478bd9Sstevel@tonic-gate 55267c478bd9Sstevel@tonic-gate int ac; 55277c478bd9Sstevel@tonic-gate char lbuf[IPQOS_CONF_TYPE_LINE_LEN]; 55287c478bd9Sstevel@tonic-gate char param[IPQOS_CONF_PNAME_LEN+1]; 55297c478bd9Sstevel@tonic-gate char typest[IPQOS_CONF_TYPE_LEN+1]; 55307c478bd9Sstevel@tonic-gate char place_st[IPQOS_CONF_TYPE_LEN+1]; 55317c478bd9Sstevel@tonic-gate char *cp; 55327c478bd9Sstevel@tonic-gate int x; 55337c478bd9Sstevel@tonic-gate char *ipgpc_nm; 55347c478bd9Sstevel@tonic-gate int found = 0; 55357c478bd9Sstevel@tonic-gate 55367c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In readtype: param: %s\n", name); 55377c478bd9Sstevel@tonic-gate 55387c478bd9Sstevel@tonic-gate 55397c478bd9Sstevel@tonic-gate /* 55407c478bd9Sstevel@tonic-gate * if allow_ipgpc_priv is true then we allow ipgpc parameters that are 55417c478bd9Sstevel@tonic-gate * private between ipqosconf and ipgpc. eg. address masks, port masks. 55427c478bd9Sstevel@tonic-gate */ 55437c478bd9Sstevel@tonic-gate if (allow_ipgpc_priv && strcmp(module_name, IPGPC_NAME) == 0) { 55447c478bd9Sstevel@tonic-gate ipgpc_nm = prepend_module_name(name, IPGPC_NAME); 55457c478bd9Sstevel@tonic-gate if (ipgpc_nm == NULL) { 55467c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 55477c478bd9Sstevel@tonic-gate } 55487c478bd9Sstevel@tonic-gate 55497c478bd9Sstevel@tonic-gate if (strcmp(ipgpc_nm, IPGPC_SADDR_MASK) == 0 || 55507c478bd9Sstevel@tonic-gate strcmp(ipgpc_nm, IPGPC_DADDR_MASK) == 0) { 55517c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_ADDRESS_MASK; 55527c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 55537c478bd9Sstevel@tonic-gate } else if (strcmp(ipgpc_nm, IPGPC_SPORT_MASK) == 0 || 55547c478bd9Sstevel@tonic-gate strcmp(ipgpc_nm, IPGPC_DPORT_MASK) == 0) { 55557c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_UINT16; 55567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 55577c478bd9Sstevel@tonic-gate } else if (strcmp(ipgpc_nm, IPGPC_FILTER_TYPE) == 0) { 55587c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_UINT32; 55597c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 55607c478bd9Sstevel@tonic-gate } else if (strcmp(ipgpc_nm, IPGPC_IF_INDEX) == 0) { 55617c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_IFINDEX; 55627c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 55637c478bd9Sstevel@tonic-gate } 55647c478bd9Sstevel@tonic-gate 55657c478bd9Sstevel@tonic-gate free(ipgpc_nm); 55667c478bd9Sstevel@tonic-gate } 55677c478bd9Sstevel@tonic-gate 55687c478bd9Sstevel@tonic-gate /* 55697c478bd9Sstevel@tonic-gate * read upto and including module version line. 55707c478bd9Sstevel@tonic-gate */ 55717c478bd9Sstevel@tonic-gate if (read_tfile_ver(tfp, IPQOS_MOD_STR, module_name) == -1) 55727c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 55737c478bd9Sstevel@tonic-gate 55747c478bd9Sstevel@tonic-gate 55757c478bd9Sstevel@tonic-gate /* 55767c478bd9Sstevel@tonic-gate * loop reading lines of the types file until named parameter 55777c478bd9Sstevel@tonic-gate * found or EOF. 55787c478bd9Sstevel@tonic-gate */ 55797c478bd9Sstevel@tonic-gate while (fgets(lbuf, IPQOS_CONF_TYPE_LINE_LEN, tfp) != NULL) { 55807c478bd9Sstevel@tonic-gate 55817c478bd9Sstevel@tonic-gate /* 55827c478bd9Sstevel@tonic-gate * check whether blank or commented line; if so skip 55837c478bd9Sstevel@tonic-gate */ 55847c478bd9Sstevel@tonic-gate for (cp = lbuf; isspace(*cp) && *cp != '\0'; cp++) {} 55857c478bd9Sstevel@tonic-gate if (*cp == '\0' || *cp == '#') { 55867c478bd9Sstevel@tonic-gate continue; 55877c478bd9Sstevel@tonic-gate } 55887c478bd9Sstevel@tonic-gate 55897c478bd9Sstevel@tonic-gate dfltst[0] = '\0'; 55907c478bd9Sstevel@tonic-gate 55917c478bd9Sstevel@tonic-gate /* 55927c478bd9Sstevel@tonic-gate * read place, param, type and if present default str 55937c478bd9Sstevel@tonic-gate * from line. 55947c478bd9Sstevel@tonic-gate */ 55957c478bd9Sstevel@tonic-gate ac = sscanf(lbuf, 55967c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_TYPE_LEN) "s " 55977c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_PNAME_LEN) "s " 55987c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_TYPE_LEN) "s " 55997c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_VALST_MAXLEN) "s", 56007c478bd9Sstevel@tonic-gate place_st, param, typest, dfltst); 56017c478bd9Sstevel@tonic-gate if (ac < 3) { 56027c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 56037c478bd9Sstevel@tonic-gate gettext("Types file for module %s is corrupt.\n"), 56047c478bd9Sstevel@tonic-gate module_name); 56057c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "sscanf failed to read 3 strings.\n"); 56067c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 56077c478bd9Sstevel@tonic-gate } 56087c478bd9Sstevel@tonic-gate 56097c478bd9Sstevel@tonic-gate /* 56107c478bd9Sstevel@tonic-gate * if the place and name match no need to look any further. 56117c478bd9Sstevel@tonic-gate */ 56127c478bd9Sstevel@tonic-gate if ((*place == PL_ANY) || 56137c478bd9Sstevel@tonic-gate ((*place == PL_PARAMS) && 56147c478bd9Sstevel@tonic-gate strcmp(place_st, IPQOS_PLACE_PRM_STR) == 0) || 56157c478bd9Sstevel@tonic-gate ((*place == PL_FILTER) && 56167c478bd9Sstevel@tonic-gate strcmp(place_st, IPQOS_PLACE_FILTER_STR) == 0) || 56177c478bd9Sstevel@tonic-gate ((*place == PL_MAP) && 56187c478bd9Sstevel@tonic-gate strcmp(place_st, IPQOS_PLACE_MAP_STR) == 0)) { 56197c478bd9Sstevel@tonic-gate if (strcmp(param, name) == 0) { 56207c478bd9Sstevel@tonic-gate found++; 56217c478bd9Sstevel@tonic-gate break; 56227c478bd9Sstevel@tonic-gate } 56237c478bd9Sstevel@tonic-gate } 56247c478bd9Sstevel@tonic-gate } 56257c478bd9Sstevel@tonic-gate if (found == 0) { 56267c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 56277c478bd9Sstevel@tonic-gate gettext("Invalid parameter, %s, line %u.\n"), name, 56287c478bd9Sstevel@tonic-gate lineno); 56297c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 56307c478bd9Sstevel@tonic-gate } 56317c478bd9Sstevel@tonic-gate 56327c478bd9Sstevel@tonic-gate /* 56337c478bd9Sstevel@tonic-gate * set the place parameter to the actual place when the PL_ANY flag 56347c478bd9Sstevel@tonic-gate * was set. 56357c478bd9Sstevel@tonic-gate */ 56367c478bd9Sstevel@tonic-gate if (*place == PL_ANY) { 56377c478bd9Sstevel@tonic-gate if (strcmp(place_st, IPQOS_PLACE_PRM_STR) == 0) { 56387c478bd9Sstevel@tonic-gate *place = PL_PARAMS; 56397c478bd9Sstevel@tonic-gate } else if (strcmp(place_st, IPQOS_PLACE_FILTER_STR) == 0) { 56407c478bd9Sstevel@tonic-gate *place = PL_FILTER; 56417c478bd9Sstevel@tonic-gate } else if (strcmp(place_st, IPQOS_PLACE_MAP_STR) == 0) { 56427c478bd9Sstevel@tonic-gate *place = PL_MAP; 56437c478bd9Sstevel@tonic-gate } 56447c478bd9Sstevel@tonic-gate } 56457c478bd9Sstevel@tonic-gate 56467c478bd9Sstevel@tonic-gate /* 56477c478bd9Sstevel@tonic-gate * get type enumeration 56487c478bd9Sstevel@tonic-gate */ 56497c478bd9Sstevel@tonic-gate for (x = 0; nv_types[x].string[0]; x++) { 56507c478bd9Sstevel@tonic-gate if (strcmp(nv_types[x].string, typest) == 0) { 56517c478bd9Sstevel@tonic-gate break; 56527c478bd9Sstevel@tonic-gate } 56537c478bd9Sstevel@tonic-gate } 56547c478bd9Sstevel@tonic-gate /* 56557c478bd9Sstevel@tonic-gate * check that we have a type corresponding with the one the types 56567c478bd9Sstevel@tonic-gate * file specifies. 56577c478bd9Sstevel@tonic-gate */ 56587c478bd9Sstevel@tonic-gate if (nv_types[x].string[0] == '\0') { 56597c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 56607c478bd9Sstevel@tonic-gate gettext("Types file for module %s is corrupt.\n"), 56617c478bd9Sstevel@tonic-gate module_name); 56627c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 56637c478bd9Sstevel@tonic-gate } 56647c478bd9Sstevel@tonic-gate *type = nv_types[x].value; 56657c478bd9Sstevel@tonic-gate 56667c478bd9Sstevel@tonic-gate /* 56677c478bd9Sstevel@tonic-gate * if enumeration type get set of name/vals and any default value 56687c478bd9Sstevel@tonic-gate */ 56697c478bd9Sstevel@tonic-gate if (*type == IPQOS_DATA_TYPE_ENUM) { 56707c478bd9Sstevel@tonic-gate *enum_nvps = read_enum_nvs(lbuf, module_name); 56717c478bd9Sstevel@tonic-gate if (*enum_nvps == NULL) { 56727c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 56737c478bd9Sstevel@tonic-gate } 56747c478bd9Sstevel@tonic-gate 56757c478bd9Sstevel@tonic-gate dfltst[0] = '\0'; 56767c478bd9Sstevel@tonic-gate cp = strchr(lbuf, CURL_END); 56777c478bd9Sstevel@tonic-gate (void) sscanf(++cp, 56787c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_VALST_MAXLEN) "s", dfltst); 56797c478bd9Sstevel@tonic-gate } 56807c478bd9Sstevel@tonic-gate 56817c478bd9Sstevel@tonic-gate 56827c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "read type: %s default: %s\n", nv_types[x].string, 56837c478bd9Sstevel@tonic-gate *dfltst ? dfltst : "None"); 56847c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 56857c478bd9Sstevel@tonic-gate } 56867c478bd9Sstevel@tonic-gate 56877c478bd9Sstevel@tonic-gate 56887c478bd9Sstevel@tonic-gate /* 56897c478bd9Sstevel@tonic-gate * Reads a name and a value from file ref'd by cfp into list indirectly 56907c478bd9Sstevel@tonic-gate * ref'd by nvlp; If this list is NULL it will be created to accomodate 56917c478bd9Sstevel@tonic-gate * the name/value. The name must be either a special token for 56927c478bd9Sstevel@tonic-gate * for the place, or be present in the module types file ref'd by tfp. 56937c478bd9Sstevel@tonic-gate * *type is set to the enumeration of the type of the parameter and 56947c478bd9Sstevel@tonic-gate * nvp to point at the element with the nvlp ref'd list. 56957c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_CURL_END if read CURL_END as name, 56967c478bd9Sstevel@tonic-gate * IPQOS_CONF_ERR on errors, else IPQOS_CONF_SUCCESS. 56977c478bd9Sstevel@tonic-gate */ 56987c478bd9Sstevel@tonic-gate static int 56997c478bd9Sstevel@tonic-gate readnvpair( 57007c478bd9Sstevel@tonic-gate FILE *cfp, 57017c478bd9Sstevel@tonic-gate FILE *tfp, 57027c478bd9Sstevel@tonic-gate nvlist_t **nvlp, 57037c478bd9Sstevel@tonic-gate nvpair_t **nvp, 57047c478bd9Sstevel@tonic-gate ipqos_nvtype_t *type, 57057c478bd9Sstevel@tonic-gate place_t place, 57067c478bd9Sstevel@tonic-gate char *module_name) 57077c478bd9Sstevel@tonic-gate { 57087c478bd9Sstevel@tonic-gate 57097c478bd9Sstevel@tonic-gate char *name = NULL; 57107c478bd9Sstevel@tonic-gate char *valst = NULL; 57117c478bd9Sstevel@tonic-gate int res; 57127c478bd9Sstevel@tonic-gate char *tmp; 57137c478bd9Sstevel@tonic-gate str_val_nd_t *enum_nvs = NULL; 57147c478bd9Sstevel@tonic-gate char dfltst[IPQOS_VALST_MAXLEN+1]; 57157c478bd9Sstevel@tonic-gate 57167c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "in readnvpair\n"); 57177c478bd9Sstevel@tonic-gate 57187c478bd9Sstevel@tonic-gate /* 57197c478bd9Sstevel@tonic-gate * read nvpair name 57207c478bd9Sstevel@tonic-gate */ 57217c478bd9Sstevel@tonic-gate res = readtoken(cfp, &name); 57227c478bd9Sstevel@tonic-gate 57237c478bd9Sstevel@tonic-gate /* 57247c478bd9Sstevel@tonic-gate * if reached eof, curl end or error encountered return to caller 57257c478bd9Sstevel@tonic-gate */ 57267c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_EOF) { 57277c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n")); 57287c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 57297c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_ERR) { 57307c478bd9Sstevel@tonic-gate return (res); 57317c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 57327c478bd9Sstevel@tonic-gate free(name); 57337c478bd9Sstevel@tonic-gate return (res); 57347c478bd9Sstevel@tonic-gate } 57357c478bd9Sstevel@tonic-gate 57367c478bd9Sstevel@tonic-gate /* 57377c478bd9Sstevel@tonic-gate * read nvpair value 57387c478bd9Sstevel@tonic-gate */ 57397c478bd9Sstevel@tonic-gate res = readtoken(cfp, &valst); 57407c478bd9Sstevel@tonic-gate 57417c478bd9Sstevel@tonic-gate /* 57427c478bd9Sstevel@tonic-gate * check we've read a valid value 57437c478bd9Sstevel@tonic-gate */ 57447c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS && res != IPQOS_CONF_CURL_BEGIN) { 57457c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_EOF) { 57467c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n")); 57477c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 57487c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 57497c478bd9Sstevel@tonic-gate gettext("Missing parameter value line %u.\n"), 57507c478bd9Sstevel@tonic-gate lineno); 57517c478bd9Sstevel@tonic-gate free(valst); 57527c478bd9Sstevel@tonic-gate } /* we do nothing special for IPQOS_CONF_ERR */ 57537c478bd9Sstevel@tonic-gate free(name); 57547c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 57557c478bd9Sstevel@tonic-gate } 57567c478bd9Sstevel@tonic-gate 57577c478bd9Sstevel@tonic-gate /* 57587c478bd9Sstevel@tonic-gate * check for generic parameters. 57597c478bd9Sstevel@tonic-gate */ 57607c478bd9Sstevel@tonic-gate 57617c478bd9Sstevel@tonic-gate if ((place == PL_CLASS) && 57627c478bd9Sstevel@tonic-gate strcmp(name, IPQOS_CONF_NEXT_ACTION_STR) == 0) { 57637c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_ACTION; 57647c478bd9Sstevel@tonic-gate 57657c478bd9Sstevel@tonic-gate } else if (place == PL_PARAMS && 57667c478bd9Sstevel@tonic-gate strcmp(name, IPQOS_CONF_GLOBAL_STATS_STR) == 0 || 57677c478bd9Sstevel@tonic-gate place == PL_CLASS && 57687c478bd9Sstevel@tonic-gate strcmp(name, IPQOS_CONF_STATS_ENABLE_STR) == 0) { 57697c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_BOOLEAN; 57707c478bd9Sstevel@tonic-gate 57717c478bd9Sstevel@tonic-gate } else if (tfp == NULL || 57727c478bd9Sstevel@tonic-gate ((place != PL_PARAMS) && strcmp(name, IPQOS_CONF_NAME_STR) == 0) || 57737c478bd9Sstevel@tonic-gate (place == PL_FILTER) && (strcmp(name, IPQOS_CONF_CLASS_STR) == 57747c478bd9Sstevel@tonic-gate 0) || 57757c478bd9Sstevel@tonic-gate (place == PL_ACTION) && (strcmp(name, IPQOS_CONF_MODULE_STR) == 57767c478bd9Sstevel@tonic-gate 0)) { 57777c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_STRING; 57787c478bd9Sstevel@tonic-gate 57797c478bd9Sstevel@tonic-gate } else { /* if not generic parameter */ 57807c478bd9Sstevel@tonic-gate /* 57817c478bd9Sstevel@tonic-gate * get type from types file 57827c478bd9Sstevel@tonic-gate */ 57837c478bd9Sstevel@tonic-gate if (readtype(tfp, module_name, name, type, &enum_nvs, dfltst, 57847c478bd9Sstevel@tonic-gate B_FALSE, &place) != IPQOS_CONF_SUCCESS) { 57857c478bd9Sstevel@tonic-gate free(name); 57867c478bd9Sstevel@tonic-gate free(valst); 57877c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 57887c478bd9Sstevel@tonic-gate } 57897c478bd9Sstevel@tonic-gate 57907c478bd9Sstevel@tonic-gate /* 57917c478bd9Sstevel@tonic-gate * get full module prefix parameter name 57927c478bd9Sstevel@tonic-gate */ 57937c478bd9Sstevel@tonic-gate tmp = name; 57947c478bd9Sstevel@tonic-gate if ((name = prepend_module_name(name, module_name)) == NULL) { 57957c478bd9Sstevel@tonic-gate name = tmp; 57967c478bd9Sstevel@tonic-gate goto fail; 57977c478bd9Sstevel@tonic-gate } 57987c478bd9Sstevel@tonic-gate free(tmp); 57997c478bd9Sstevel@tonic-gate } 58007c478bd9Sstevel@tonic-gate 58017c478bd9Sstevel@tonic-gate IPQOSCDBG3(L1, "NVP, name: %s, str_value: %s, type: %s\n", name, 58027c478bd9Sstevel@tonic-gate valst, nv_types[*type].string); 58037c478bd9Sstevel@tonic-gate 58047c478bd9Sstevel@tonic-gate 58057c478bd9Sstevel@tonic-gate /* 58067c478bd9Sstevel@tonic-gate * create nvlist if not present already 58077c478bd9Sstevel@tonic-gate */ 58087c478bd9Sstevel@tonic-gate if (*nvlp == NULL) { 58097c478bd9Sstevel@tonic-gate res = nvlist_alloc(nvlp, NV_UNIQUE_NAME, 0); 58107c478bd9Sstevel@tonic-gate if (res != 0) { 58117c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_alloc"); 58127c478bd9Sstevel@tonic-gate free(name); 58137c478bd9Sstevel@tonic-gate free(valst); 58147c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 58157c478bd9Sstevel@tonic-gate } 58167c478bd9Sstevel@tonic-gate } 58177c478bd9Sstevel@tonic-gate 58187c478bd9Sstevel@tonic-gate /* 58197c478bd9Sstevel@tonic-gate * check we haven't already read this parameter 58207c478bd9Sstevel@tonic-gate */ 58217c478bd9Sstevel@tonic-gate if (find_nvpair(*nvlp, name)) { 58227c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Duplicate parameter line %u.\n"), 58237c478bd9Sstevel@tonic-gate lineno); 58247c478bd9Sstevel@tonic-gate goto fail; 58257c478bd9Sstevel@tonic-gate } 58267c478bd9Sstevel@tonic-gate 58277c478bd9Sstevel@tonic-gate /* 58287c478bd9Sstevel@tonic-gate * convert value string to appropriate type and add to nvlist 58297c478bd9Sstevel@tonic-gate */ 58307c478bd9Sstevel@tonic-gate 58317c478bd9Sstevel@tonic-gate switch (*type) { 58327c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_IFNAME: { 58337c478bd9Sstevel@tonic-gate uint32_t ifidx; 58347c478bd9Sstevel@tonic-gate 58357c478bd9Sstevel@tonic-gate res = readifindex(valst, (int *)&ifidx); 58367c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 58377c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvlp, IPGPC_IF_INDEX, 58387c478bd9Sstevel@tonic-gate ifidx); 58397c478bd9Sstevel@tonic-gate if (res != 0) { 58407c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 58417c478bd9Sstevel@tonic-gate "nvlist_add_uint32"); 58427c478bd9Sstevel@tonic-gate goto fail; 58437c478bd9Sstevel@tonic-gate } 58447c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(*nvlp, name); 58457c478bd9Sstevel@tonic-gate /* 58467c478bd9Sstevel@tonic-gate * change name to point at the name of the 58477c478bd9Sstevel@tonic-gate * new ifindex nvlist entry as name is used 58487c478bd9Sstevel@tonic-gate * later in the function. 58497c478bd9Sstevel@tonic-gate */ 58507c478bd9Sstevel@tonic-gate free(name); 58517c478bd9Sstevel@tonic-gate name = malloc(strlen(IPGPC_IF_INDEX) + 1); 58527c478bd9Sstevel@tonic-gate if (name == NULL) { 58537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 58547c478bd9Sstevel@tonic-gate goto fail; 58557c478bd9Sstevel@tonic-gate } 58567c478bd9Sstevel@tonic-gate (void) strcpy(name, IPGPC_IF_INDEX); 58577c478bd9Sstevel@tonic-gate } 58587c478bd9Sstevel@tonic-gate break; 58597c478bd9Sstevel@tonic-gate } 58607c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PROTO: { 58617c478bd9Sstevel@tonic-gate uint8_t proto; 58627c478bd9Sstevel@tonic-gate 58637c478bd9Sstevel@tonic-gate res = readproto(valst, &proto); 58647c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 58657c478bd9Sstevel@tonic-gate res = nvlist_add_byte(*nvlp, name, proto); 58667c478bd9Sstevel@tonic-gate if (res != 0) { 58677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 58687c478bd9Sstevel@tonic-gate goto fail; 58697c478bd9Sstevel@tonic-gate } 58707c478bd9Sstevel@tonic-gate } 58717c478bd9Sstevel@tonic-gate break; 58727c478bd9Sstevel@tonic-gate } 58737c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_PORT: { 58747c478bd9Sstevel@tonic-gate uint16_t port; 58757c478bd9Sstevel@tonic-gate 58767c478bd9Sstevel@tonic-gate res = readport(valst, &port); 58777c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 58787c478bd9Sstevel@tonic-gate 58797c478bd9Sstevel@tonic-gate /* add port */ 58807c478bd9Sstevel@tonic-gate 58817c478bd9Sstevel@tonic-gate res = nvlist_add_uint16(*nvlp, name, port); 58827c478bd9Sstevel@tonic-gate if (res != 0) { 58837c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 58847c478bd9Sstevel@tonic-gate "nvlist_add_uint16"); 58857c478bd9Sstevel@tonic-gate goto fail; 58867c478bd9Sstevel@tonic-gate } 58877c478bd9Sstevel@tonic-gate 58887c478bd9Sstevel@tonic-gate /* add appropriate all ones port mask */ 58897c478bd9Sstevel@tonic-gate 58907c478bd9Sstevel@tonic-gate if (strcmp(name, IPGPC_DPORT) == 0) { 58917c478bd9Sstevel@tonic-gate res = nvlist_add_uint16(*nvlp, 58927c478bd9Sstevel@tonic-gate IPGPC_DPORT_MASK, ~0); 58937c478bd9Sstevel@tonic-gate 58947c478bd9Sstevel@tonic-gate } else if (strcmp(name, IPGPC_SPORT) == 0) { 58957c478bd9Sstevel@tonic-gate res = nvlist_add_uint16(*nvlp, 58967c478bd9Sstevel@tonic-gate IPGPC_SPORT_MASK, ~0); 58977c478bd9Sstevel@tonic-gate } 58987c478bd9Sstevel@tonic-gate if (res != 0) { 58997c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59007c478bd9Sstevel@tonic-gate "nvlist_add_uint16"); 59017c478bd9Sstevel@tonic-gate goto fail; 59027c478bd9Sstevel@tonic-gate } 59037c478bd9Sstevel@tonic-gate } 59047c478bd9Sstevel@tonic-gate break; 59057c478bd9Sstevel@tonic-gate } 59067c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ADDRESS: 59077c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ACTION: 59087c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_STRING: 59097c478bd9Sstevel@tonic-gate res = nvlist_add_string(*nvlp, name, valst); 59107c478bd9Sstevel@tonic-gate if (res != 0) { 59117c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_string"); 59127c478bd9Sstevel@tonic-gate goto fail; 59137c478bd9Sstevel@tonic-gate } 59147c478bd9Sstevel@tonic-gate break; 59157c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_BOOLEAN: { 59167c478bd9Sstevel@tonic-gate boolean_t b; 59177c478bd9Sstevel@tonic-gate 59187c478bd9Sstevel@tonic-gate res = readbool(valst, &b); 59197c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59207c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvlp, name, 59217c478bd9Sstevel@tonic-gate (uint32_t)b); 59227c478bd9Sstevel@tonic-gate if (res != 0) { 59237c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59247c478bd9Sstevel@tonic-gate "nvlist_add_uint32"); 59257c478bd9Sstevel@tonic-gate goto fail; 59267c478bd9Sstevel@tonic-gate } 59277c478bd9Sstevel@tonic-gate } 59287c478bd9Sstevel@tonic-gate break; 59297c478bd9Sstevel@tonic-gate } 59307c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT8: { 59317c478bd9Sstevel@tonic-gate uint8_t u8; 59327c478bd9Sstevel@tonic-gate 59337c478bd9Sstevel@tonic-gate res = readuint8(valst, &u8, &tmp); 59347c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59357c478bd9Sstevel@tonic-gate res = nvlist_add_byte(*nvlp, name, u8); 59367c478bd9Sstevel@tonic-gate if (res != 0) { 59377c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 59387c478bd9Sstevel@tonic-gate goto fail; 59397c478bd9Sstevel@tonic-gate } 59407c478bd9Sstevel@tonic-gate } 59417c478bd9Sstevel@tonic-gate break; 59427c478bd9Sstevel@tonic-gate } 59437c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT16: { 59447c478bd9Sstevel@tonic-gate int16_t i16; 59457c478bd9Sstevel@tonic-gate 59467c478bd9Sstevel@tonic-gate res = readint16(valst, &i16, &tmp); 59477c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59487c478bd9Sstevel@tonic-gate res = nvlist_add_int16(*nvlp, name, i16); 59497c478bd9Sstevel@tonic-gate if (res != 0) { 59507c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59517c478bd9Sstevel@tonic-gate "nvlist_add_int16"); 59527c478bd9Sstevel@tonic-gate goto fail; 59537c478bd9Sstevel@tonic-gate } 59547c478bd9Sstevel@tonic-gate } 59557c478bd9Sstevel@tonic-gate break; 59567c478bd9Sstevel@tonic-gate } 59577c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT16: { 59587c478bd9Sstevel@tonic-gate uint16_t u16; 59597c478bd9Sstevel@tonic-gate 59607c478bd9Sstevel@tonic-gate res = readuint16(valst, &u16, &tmp); 59617c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59627c478bd9Sstevel@tonic-gate res = nvlist_add_uint16(*nvlp, name, u16); 59637c478bd9Sstevel@tonic-gate if (res != 0) { 59647c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59657c478bd9Sstevel@tonic-gate "nvlist_add_int16"); 59667c478bd9Sstevel@tonic-gate goto fail; 59677c478bd9Sstevel@tonic-gate } 59687c478bd9Sstevel@tonic-gate } 59697c478bd9Sstevel@tonic-gate break; 59707c478bd9Sstevel@tonic-gate } 59717c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT32: { 59727c478bd9Sstevel@tonic-gate int i32; 59737c478bd9Sstevel@tonic-gate 59747c478bd9Sstevel@tonic-gate res = readint32(valst, &i32, &tmp); 59757c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59767c478bd9Sstevel@tonic-gate res = nvlist_add_int32(*nvlp, name, i32); 59777c478bd9Sstevel@tonic-gate if (res != 0) { 59787c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59797c478bd9Sstevel@tonic-gate "nvlist_add_int32"); 59807c478bd9Sstevel@tonic-gate goto fail; 59817c478bd9Sstevel@tonic-gate } 59827c478bd9Sstevel@tonic-gate } 59837c478bd9Sstevel@tonic-gate break; 59847c478bd9Sstevel@tonic-gate } 59857c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_UINT32: { 59867c478bd9Sstevel@tonic-gate uint32_t u32; 59877c478bd9Sstevel@tonic-gate 59887c478bd9Sstevel@tonic-gate res = readuint32(valst, &u32, &tmp); 59897c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 59907c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvlp, name, u32); 59917c478bd9Sstevel@tonic-gate if (res != 0) { 59927c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 59937c478bd9Sstevel@tonic-gate "nvlist_add_uint32"); 59947c478bd9Sstevel@tonic-gate goto fail; 59957c478bd9Sstevel@tonic-gate } 59967c478bd9Sstevel@tonic-gate } 59977c478bd9Sstevel@tonic-gate break; 59987c478bd9Sstevel@tonic-gate } 59997c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_ENUM: { 60007c478bd9Sstevel@tonic-gate uint32_t val; 60017c478bd9Sstevel@tonic-gate 60027c478bd9Sstevel@tonic-gate res = read_enum_value(cfp, valst, enum_nvs, &val); 60037c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 60047c478bd9Sstevel@tonic-gate res = nvlist_add_uint32(*nvlp, name, val); 60057c478bd9Sstevel@tonic-gate if (res != 0) { 60067c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 60077c478bd9Sstevel@tonic-gate "nvlist_add_uint32"); 60087c478bd9Sstevel@tonic-gate goto fail; 60097c478bd9Sstevel@tonic-gate } 60107c478bd9Sstevel@tonic-gate } else { 60117c478bd9Sstevel@tonic-gate goto fail; 60127c478bd9Sstevel@tonic-gate } 60137c478bd9Sstevel@tonic-gate break; 60147c478bd9Sstevel@tonic-gate } 60157c478bd9Sstevel@tonic-gate /* 60167c478bd9Sstevel@tonic-gate * For now the dfltst contains a comma separated list of the 60177c478bd9Sstevel@tonic-gate * type we need this parameter to be mapped to. 60187c478bd9Sstevel@tonic-gate * read_mapped_values will fill in all the mapped parameters 60197c478bd9Sstevel@tonic-gate * and their values in the nvlist. 60207c478bd9Sstevel@tonic-gate */ 60217c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_M_INDEX: { 60227c478bd9Sstevel@tonic-gate uint8_t u8; 60237c478bd9Sstevel@tonic-gate 60247c478bd9Sstevel@tonic-gate res = readuint8(valst, &u8, &tmp); 60257c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 60267c478bd9Sstevel@tonic-gate res = nvlist_add_byte(*nvlp, name, u8); 60277c478bd9Sstevel@tonic-gate if (res != 0) { 60287c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 60297c478bd9Sstevel@tonic-gate "nvlist_add_uint8"); 60307c478bd9Sstevel@tonic-gate goto fail; 60317c478bd9Sstevel@tonic-gate } 60327c478bd9Sstevel@tonic-gate } else { 60337c478bd9Sstevel@tonic-gate *type = IPQOS_DATA_TYPE_UINT8; 60347c478bd9Sstevel@tonic-gate break; 60357c478bd9Sstevel@tonic-gate } 60367c478bd9Sstevel@tonic-gate res = read_mapped_values(tfp, nvlp, module_name, 60377c478bd9Sstevel@tonic-gate dfltst, u8); 60387c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 60397c478bd9Sstevel@tonic-gate goto fail; 60407c478bd9Sstevel@tonic-gate } 60417c478bd9Sstevel@tonic-gate break; 60427c478bd9Sstevel@tonic-gate } 60437c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_INT_ARRAY: { 60447c478bd9Sstevel@tonic-gate str_val_nd_t *arr_enum_nvs = NULL; 60457c478bd9Sstevel@tonic-gate uint32_t size; 60467c478bd9Sstevel@tonic-gate int llimit = 0, ulimit = 0; 60477c478bd9Sstevel@tonic-gate int *arr; 60487c478bd9Sstevel@tonic-gate 60497c478bd9Sstevel@tonic-gate /* 60507c478bd9Sstevel@tonic-gate * read array info from types file. 60517c478bd9Sstevel@tonic-gate */ 60527c478bd9Sstevel@tonic-gate res = read_int_array_info(dfltst, &arr_enum_nvs, &size, 60537c478bd9Sstevel@tonic-gate &llimit, &ulimit, module_name); 60547c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 60557c478bd9Sstevel@tonic-gate goto fail; 60567c478bd9Sstevel@tonic-gate } 60577c478bd9Sstevel@tonic-gate 60587c478bd9Sstevel@tonic-gate /* 60597c478bd9Sstevel@tonic-gate * read array contents from config file and construct 60607c478bd9Sstevel@tonic-gate * array with them. 60617c478bd9Sstevel@tonic-gate */ 60627c478bd9Sstevel@tonic-gate res = read_int_array(cfp, valst, &arr, size, llimit, 60637c478bd9Sstevel@tonic-gate ulimit, arr_enum_nvs); 60647c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 60657c478bd9Sstevel@tonic-gate goto fail; 60667c478bd9Sstevel@tonic-gate } 60677c478bd9Sstevel@tonic-gate 60687c478bd9Sstevel@tonic-gate /* 60697c478bd9Sstevel@tonic-gate * add array to nvlist. 60707c478bd9Sstevel@tonic-gate */ 60717c478bd9Sstevel@tonic-gate res = nvlist_add_int32_array(*nvlp, name, arr, size); 60727c478bd9Sstevel@tonic-gate if (res != 0) { 60737c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_int32"); 60747c478bd9Sstevel@tonic-gate goto fail; 60757c478bd9Sstevel@tonic-gate } 60767c478bd9Sstevel@tonic-gate 60777c478bd9Sstevel@tonic-gate /* 60787c478bd9Sstevel@tonic-gate * free uneeded resources. 60797c478bd9Sstevel@tonic-gate */ 60807c478bd9Sstevel@tonic-gate free(arr); 60817c478bd9Sstevel@tonic-gate if (arr_enum_nvs) 60827c478bd9Sstevel@tonic-gate free_str_val_entrys(arr_enum_nvs); 60837c478bd9Sstevel@tonic-gate 60847c478bd9Sstevel@tonic-gate break; 60857c478bd9Sstevel@tonic-gate } 60867c478bd9Sstevel@tonic-gate case IPQOS_DATA_TYPE_USER: { 60877c478bd9Sstevel@tonic-gate uid_t uid; 60887c478bd9Sstevel@tonic-gate 60897c478bd9Sstevel@tonic-gate res = readuser(valst, &uid); 60907c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 60917c478bd9Sstevel@tonic-gate res = nvlist_add_int32(*nvlp, name, (int)uid); 60927c478bd9Sstevel@tonic-gate if (res != 0) { 60937c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 60947c478bd9Sstevel@tonic-gate "nvlist_add_int32"); 60957c478bd9Sstevel@tonic-gate goto fail; 60967c478bd9Sstevel@tonic-gate } 60977c478bd9Sstevel@tonic-gate } 60987c478bd9Sstevel@tonic-gate break; 60997c478bd9Sstevel@tonic-gate } 61007c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 61017c478bd9Sstevel@tonic-gate default: { 61027c478bd9Sstevel@tonic-gate /* 61037c478bd9Sstevel@tonic-gate * we shouldn't have a type that doesn't have a switch 61047c478bd9Sstevel@tonic-gate * entry. 61057c478bd9Sstevel@tonic-gate */ 61067c478bd9Sstevel@tonic-gate assert(1); 61077c478bd9Sstevel@tonic-gate } 61087c478bd9Sstevel@tonic-gate #endif 61097c478bd9Sstevel@tonic-gate } 61107c478bd9Sstevel@tonic-gate if (res != 0) { 61117c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Invalid %s, line %u.\n"), 61127c478bd9Sstevel@tonic-gate nv_types[*type].string, lineno); 61137c478bd9Sstevel@tonic-gate goto fail; 61147c478bd9Sstevel@tonic-gate } 61157c478bd9Sstevel@tonic-gate 61167c478bd9Sstevel@tonic-gate /* set the nvp parameter to point at the newly added nvlist entry */ 61177c478bd9Sstevel@tonic-gate 61187c478bd9Sstevel@tonic-gate *nvp = find_nvpair(*nvlp, name); 61197c478bd9Sstevel@tonic-gate 61207c478bd9Sstevel@tonic-gate free(name); 61217c478bd9Sstevel@tonic-gate free(valst); 61227c478bd9Sstevel@tonic-gate if (enum_nvs) 61237c478bd9Sstevel@tonic-gate free_str_val_entrys(enum_nvs); 61247c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 61257c478bd9Sstevel@tonic-gate fail: 61267c478bd9Sstevel@tonic-gate if (name != NULL) 61277c478bd9Sstevel@tonic-gate free(name); 61287c478bd9Sstevel@tonic-gate if (valst != NULL) 61297c478bd9Sstevel@tonic-gate free(valst); 61307c478bd9Sstevel@tonic-gate if (enum_nvs != NULL) 61317c478bd9Sstevel@tonic-gate free_str_val_entrys(enum_nvs); 61327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 61337c478bd9Sstevel@tonic-gate } 61347c478bd9Sstevel@tonic-gate 61357c478bd9Sstevel@tonic-gate /* 61367c478bd9Sstevel@tonic-gate * read a parameter clause from cfp into *params. 61377c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 61387c478bd9Sstevel@tonic-gate */ 61397c478bd9Sstevel@tonic-gate static int 61407c478bd9Sstevel@tonic-gate readparams( 61417c478bd9Sstevel@tonic-gate FILE *cfp, 61427c478bd9Sstevel@tonic-gate FILE *tfp, 61437c478bd9Sstevel@tonic-gate char *module_name, 61447c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params) 61457c478bd9Sstevel@tonic-gate { 61467c478bd9Sstevel@tonic-gate 61477c478bd9Sstevel@tonic-gate int res; 61487c478bd9Sstevel@tonic-gate nvpair_t *nvp; 61497c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 61507c478bd9Sstevel@tonic-gate boolean_t bl; 61517c478bd9Sstevel@tonic-gate char *nm; 61527c478bd9Sstevel@tonic-gate char *action; 61537c478bd9Sstevel@tonic-gate char tmp[IPQOS_CONF_PNAME_LEN]; 61547c478bd9Sstevel@tonic-gate int read_stats = 0; 61557c478bd9Sstevel@tonic-gate 61567c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in readparams\n"); 61577c478bd9Sstevel@tonic-gate 61587c478bd9Sstevel@tonic-gate /* read beginning curl */ 61597c478bd9Sstevel@tonic-gate 61607c478bd9Sstevel@tonic-gate res = read_curl_begin(cfp); 61617c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 61627c478bd9Sstevel@tonic-gate return (res); 61637c478bd9Sstevel@tonic-gate } 61647c478bd9Sstevel@tonic-gate 61657c478bd9Sstevel@tonic-gate /* 61667c478bd9Sstevel@tonic-gate * loop reading nvpairs, adding to params nvlist until encounter 61677c478bd9Sstevel@tonic-gate * CURL_END. 61687c478bd9Sstevel@tonic-gate */ 61697c478bd9Sstevel@tonic-gate for (;;) { 61707c478bd9Sstevel@tonic-gate /* read nvpair */ 61717c478bd9Sstevel@tonic-gate 61727c478bd9Sstevel@tonic-gate res = readnvpair(cfp, tfp, ¶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 62797c478bd9Sstevel@tonic-gate dup_class( 62807c478bd9Sstevel@tonic-gate ipqos_conf_class_t *src, 62817c478bd9Sstevel@tonic-gate ipqos_conf_class_t **dst) 62827c478bd9Sstevel@tonic-gate { 62837c478bd9Sstevel@tonic-gate 62847c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 62857c478bd9Sstevel@tonic-gate int res; 62867c478bd9Sstevel@tonic-gate 62877c478bd9Sstevel@tonic-gate IPQOSCDBG1(DIFF, "In dup_class: class: %s\n", src->name); 62887c478bd9Sstevel@tonic-gate cls = alloc_class(); 62897c478bd9Sstevel@tonic-gate if (cls == NULL) { 62907c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 62917c478bd9Sstevel@tonic-gate } 62927c478bd9Sstevel@tonic-gate 62937c478bd9Sstevel@tonic-gate /* struct copy */ 62947c478bd9Sstevel@tonic-gate *cls = *src; 62957c478bd9Sstevel@tonic-gate 62967c478bd9Sstevel@tonic-gate /* we're not interested in the nvlist for a class */ 62977c478bd9Sstevel@tonic-gate cls->nvlist = NULL; 62987c478bd9Sstevel@tonic-gate 62997c478bd9Sstevel@tonic-gate 63007c478bd9Sstevel@tonic-gate /* copy first action reference */ 63017c478bd9Sstevel@tonic-gate cls->alist = NULL; 63027c478bd9Sstevel@tonic-gate res = add_aref(&cls->alist, src->alist->field, src->alist->name); 63037c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 63047c478bd9Sstevel@tonic-gate free(cls); 63057c478bd9Sstevel@tonic-gate return (res); 63067c478bd9Sstevel@tonic-gate } 63077c478bd9Sstevel@tonic-gate 63087c478bd9Sstevel@tonic-gate *dst = cls; 63097c478bd9Sstevel@tonic-gate 63107c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 63117c478bd9Sstevel@tonic-gate } 63127c478bd9Sstevel@tonic-gate 63137c478bd9Sstevel@tonic-gate /* 63147c478bd9Sstevel@tonic-gate * create a zero'd class struct and return a ptr to it. 63157c478bd9Sstevel@tonic-gate * RETURNS: ptr to struct on success, NULL otherwise. 63167c478bd9Sstevel@tonic-gate */ 63177c478bd9Sstevel@tonic-gate static ipqos_conf_class_t * 63187c478bd9Sstevel@tonic-gate alloc_class() 63197c478bd9Sstevel@tonic-gate { 63207c478bd9Sstevel@tonic-gate 63217c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class; 63227c478bd9Sstevel@tonic-gate 63237c478bd9Sstevel@tonic-gate class = malloc(sizeof (ipqos_conf_class_t)); 63247c478bd9Sstevel@tonic-gate if (class) { 63257c478bd9Sstevel@tonic-gate bzero(class, sizeof (ipqos_conf_class_t)); 63267c478bd9Sstevel@tonic-gate } else { 63277c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 63287c478bd9Sstevel@tonic-gate } 63297c478bd9Sstevel@tonic-gate 63307c478bd9Sstevel@tonic-gate return (class); 63317c478bd9Sstevel@tonic-gate } 63327c478bd9Sstevel@tonic-gate 63337c478bd9Sstevel@tonic-gate /* frees up all memory occupied by a filter struct and its contents. */ 63347c478bd9Sstevel@tonic-gate static void 63357c478bd9Sstevel@tonic-gate free_class(ipqos_conf_class_t *cls) 63367c478bd9Sstevel@tonic-gate { 63377c478bd9Sstevel@tonic-gate 63387c478bd9Sstevel@tonic-gate if (cls == NULL) 63397c478bd9Sstevel@tonic-gate return; 63407c478bd9Sstevel@tonic-gate 63417c478bd9Sstevel@tonic-gate /* free its nvlist if present */ 63427c478bd9Sstevel@tonic-gate 63437c478bd9Sstevel@tonic-gate nvlist_free(cls->nvlist); 63447c478bd9Sstevel@tonic-gate 63457c478bd9Sstevel@tonic-gate /* free its action refs if present */ 63467c478bd9Sstevel@tonic-gate 63477c478bd9Sstevel@tonic-gate if (cls->alist) 63487c478bd9Sstevel@tonic-gate free_arefs(cls->alist); 63497c478bd9Sstevel@tonic-gate 63507c478bd9Sstevel@tonic-gate /* finally free class itself */ 63517c478bd9Sstevel@tonic-gate free(cls); 63527c478bd9Sstevel@tonic-gate } 63537c478bd9Sstevel@tonic-gate 63547c478bd9Sstevel@tonic-gate /* 63557c478bd9Sstevel@tonic-gate * Checks whether there is a class called class_nm in classes list. 63567c478bd9Sstevel@tonic-gate * RETURNS: ptr to first matched class, else if not matched NULL. 63577c478bd9Sstevel@tonic-gate */ 63587c478bd9Sstevel@tonic-gate static ipqos_conf_class_t * 63597c478bd9Sstevel@tonic-gate classexist( 63607c478bd9Sstevel@tonic-gate char *class_nm, 63617c478bd9Sstevel@tonic-gate ipqos_conf_class_t *classes) 63627c478bd9Sstevel@tonic-gate { 63637c478bd9Sstevel@tonic-gate 63647c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 63657c478bd9Sstevel@tonic-gate 63667c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In classexist: name: %s\n", class_nm); 63677c478bd9Sstevel@tonic-gate 63687c478bd9Sstevel@tonic-gate for (cls = classes; cls; cls = cls->next) { 63697c478bd9Sstevel@tonic-gate if (strcmp(class_nm, cls->name) == 0) { 63707c478bd9Sstevel@tonic-gate break; 63717c478bd9Sstevel@tonic-gate } 63727c478bd9Sstevel@tonic-gate } 63737c478bd9Sstevel@tonic-gate 63747c478bd9Sstevel@tonic-gate return (cls); 63757c478bd9Sstevel@tonic-gate } 63767c478bd9Sstevel@tonic-gate 63777c478bd9Sstevel@tonic-gate 63787c478bd9Sstevel@tonic-gate 63797c478bd9Sstevel@tonic-gate /* ************************** filter manip fns **************************** */ 63807c478bd9Sstevel@tonic-gate 63817c478bd9Sstevel@tonic-gate 63827c478bd9Sstevel@tonic-gate 63837c478bd9Sstevel@tonic-gate /* 63847c478bd9Sstevel@tonic-gate * Checks whether there is a filter called filter_nm with instance number 63857c478bd9Sstevel@tonic-gate * instance in filters list created by us or permanent. Instance value -1 63867c478bd9Sstevel@tonic-gate * is a wildcard. 63877c478bd9Sstevel@tonic-gate * RETURNS: ptr to first matched filter, else if not matched NULL. 63887c478bd9Sstevel@tonic-gate */ 63897c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t * 63907c478bd9Sstevel@tonic-gate filterexist( 63917c478bd9Sstevel@tonic-gate char *filter_nm, 63927c478bd9Sstevel@tonic-gate int instance, 63937c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filters) 63947c478bd9Sstevel@tonic-gate { 63957c478bd9Sstevel@tonic-gate 63967c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "In filterexist: name :%s, inst: %d\n", filter_nm, 63977c478bd9Sstevel@tonic-gate instance); 63987c478bd9Sstevel@tonic-gate 63997c478bd9Sstevel@tonic-gate while (filters) { 64007c478bd9Sstevel@tonic-gate if (strcmp(filters->name, filter_nm) == 0 && 64017c478bd9Sstevel@tonic-gate (instance == -1 || filters->instance == instance) && 64027c478bd9Sstevel@tonic-gate (filters->originator == IPP_CONFIG_IPQOSCONF || 64037c478bd9Sstevel@tonic-gate filters->originator == IPP_CONFIG_PERMANENT)) { 64047c478bd9Sstevel@tonic-gate break; 64057c478bd9Sstevel@tonic-gate } 64067c478bd9Sstevel@tonic-gate filters = filters->next; 64077c478bd9Sstevel@tonic-gate } 64087c478bd9Sstevel@tonic-gate return (filters); 64097c478bd9Sstevel@tonic-gate } 64107c478bd9Sstevel@tonic-gate 64117c478bd9Sstevel@tonic-gate /* 64127c478bd9Sstevel@tonic-gate * allocate and zero a filter structure. 64137c478bd9Sstevel@tonic-gate * RETURNS: NULL on error, else ptr to filter struct. 64147c478bd9Sstevel@tonic-gate */ 64157c478bd9Sstevel@tonic-gate static ipqos_conf_filter_t * 64167c478bd9Sstevel@tonic-gate alloc_filter() 64177c478bd9Sstevel@tonic-gate { 64187c478bd9Sstevel@tonic-gate 64197c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 64207c478bd9Sstevel@tonic-gate 64217c478bd9Sstevel@tonic-gate flt = malloc(sizeof (ipqos_conf_filter_t)); 64227c478bd9Sstevel@tonic-gate if (flt) { 64237c478bd9Sstevel@tonic-gate bzero(flt, sizeof (ipqos_conf_filter_t)); 64247c478bd9Sstevel@tonic-gate flt->instance = -1; 64257c478bd9Sstevel@tonic-gate } else { 64267c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 64277c478bd9Sstevel@tonic-gate } 64287c478bd9Sstevel@tonic-gate 64297c478bd9Sstevel@tonic-gate return (flt); 64307c478bd9Sstevel@tonic-gate } 64317c478bd9Sstevel@tonic-gate 64327c478bd9Sstevel@tonic-gate /* free flt and all it's contents. */ 64337c478bd9Sstevel@tonic-gate 64347c478bd9Sstevel@tonic-gate static void 64357c478bd9Sstevel@tonic-gate free_filter(ipqos_conf_filter_t *flt) 64367c478bd9Sstevel@tonic-gate { 64377c478bd9Sstevel@tonic-gate 64387c478bd9Sstevel@tonic-gate IPQOSCDBG2(L1, "In free_filter: filter: %s, inst: %d\n", flt->name, 64397c478bd9Sstevel@tonic-gate flt->instance); 64407c478bd9Sstevel@tonic-gate 64417c478bd9Sstevel@tonic-gate if (flt == NULL) 64427c478bd9Sstevel@tonic-gate return; 64437c478bd9Sstevel@tonic-gate 64447c478bd9Sstevel@tonic-gate if (flt->src_nd_name) 64457c478bd9Sstevel@tonic-gate free(flt->src_nd_name); 64467c478bd9Sstevel@tonic-gate if (flt->dst_nd_name) 64477c478bd9Sstevel@tonic-gate free(flt->dst_nd_name); 64487c478bd9Sstevel@tonic-gate if (flt->nvlist) { 64497c478bd9Sstevel@tonic-gate nvlist_free(flt->nvlist); 64507c478bd9Sstevel@tonic-gate } 64517c478bd9Sstevel@tonic-gate free(flt); 64527c478bd9Sstevel@tonic-gate } 64537c478bd9Sstevel@tonic-gate 64547c478bd9Sstevel@tonic-gate /* 64557c478bd9Sstevel@tonic-gate * makes a copy of ofilter and its contents and points nfilter at it. It 64567c478bd9Sstevel@tonic-gate * also adds an instance number to the filter and if either saddr or 64577c478bd9Sstevel@tonic-gate * daddr are non-null that address to the filters nvlist along with 64587c478bd9Sstevel@tonic-gate * an all 1s address mask and the af. 64597c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 64607c478bd9Sstevel@tonic-gate */ 64617c478bd9Sstevel@tonic-gate static int 64627c478bd9Sstevel@tonic-gate dup_filter( 64637c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *ofilter, 64647c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **nfilter, 64657c478bd9Sstevel@tonic-gate int af, 64667c478bd9Sstevel@tonic-gate int inv6, /* if saddr or daddr set and v4 filter are they in v6 addr */ 64677c478bd9Sstevel@tonic-gate void *saddr, 64687c478bd9Sstevel@tonic-gate void *daddr, 64697c478bd9Sstevel@tonic-gate int inst) 64707c478bd9Sstevel@tonic-gate { 64717c478bd9Sstevel@tonic-gate 64727c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *nf; 64737c478bd9Sstevel@tonic-gate int res; 64747c478bd9Sstevel@tonic-gate in6_addr_t v6addr; 64757c478bd9Sstevel@tonic-gate in6_addr_t all_1s_v6; 64767c478bd9Sstevel@tonic-gate 64777c478bd9Sstevel@tonic-gate IPQOSCDBG4(MHME, "In dup_filter: name: %s, af: %u, inv6: %u, ins: %d\n", 64787c478bd9Sstevel@tonic-gate ofilter->name, af, inv6, inst); 64797c478bd9Sstevel@tonic-gate 64807c478bd9Sstevel@tonic-gate /* show src address and dst address if present */ 64817c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 64827c478bd9Sstevel@tonic-gate if (ipqosconf_dbg_flgs & MHME) { 64837c478bd9Sstevel@tonic-gate char st[100]; 64847c478bd9Sstevel@tonic-gate 64857c478bd9Sstevel@tonic-gate if (saddr) { 64867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "saddr: %s\n", 64877c478bd9Sstevel@tonic-gate inet_ntop(inv6 ? AF_INET6 : AF_INET, saddr, st, 64887c478bd9Sstevel@tonic-gate 100)); 64897c478bd9Sstevel@tonic-gate } 64907c478bd9Sstevel@tonic-gate 64917c478bd9Sstevel@tonic-gate if (daddr) { 64927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "daddr: %s\n", 64937c478bd9Sstevel@tonic-gate inet_ntop(inv6 ? AF_INET6 : AF_INET, daddr, st, 64947c478bd9Sstevel@tonic-gate 100)); 64957c478bd9Sstevel@tonic-gate } 64967c478bd9Sstevel@tonic-gate } 64977c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 64987c478bd9Sstevel@tonic-gate 64997c478bd9Sstevel@tonic-gate /* init local v6 address to 0 */ 65007c478bd9Sstevel@tonic-gate (void) bzero(&v6addr, sizeof (in6_addr_t)); 65017c478bd9Sstevel@tonic-gate 65027c478bd9Sstevel@tonic-gate /* create an all 1s address for use as mask */ 65037c478bd9Sstevel@tonic-gate (void) memset(&all_1s_v6, ~0, sizeof (in6_addr_t)); 65047c478bd9Sstevel@tonic-gate 65057c478bd9Sstevel@tonic-gate /* create a new filter */ 65067c478bd9Sstevel@tonic-gate 65077c478bd9Sstevel@tonic-gate nf = alloc_filter(); 65087c478bd9Sstevel@tonic-gate if (nf == NULL) { 65097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 65107c478bd9Sstevel@tonic-gate } 65117c478bd9Sstevel@tonic-gate 65127c478bd9Sstevel@tonic-gate /* struct copy old filter to new */ 65137c478bd9Sstevel@tonic-gate *nf = *ofilter; 65147c478bd9Sstevel@tonic-gate 65157c478bd9Sstevel@tonic-gate /* copy src filters nvlist if there is one to copy */ 65167c478bd9Sstevel@tonic-gate 65177c478bd9Sstevel@tonic-gate if (ofilter->nvlist) { 65187c478bd9Sstevel@tonic-gate res = nvlist_dup(ofilter->nvlist, &nf->nvlist, 0); 65197c478bd9Sstevel@tonic-gate if (res != 0) { 65207c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_dup"); 65217c478bd9Sstevel@tonic-gate goto fail; 65227c478bd9Sstevel@tonic-gate } 65237c478bd9Sstevel@tonic-gate } 65247c478bd9Sstevel@tonic-gate 65257c478bd9Sstevel@tonic-gate /* copy src and dst node names if present */ 65267c478bd9Sstevel@tonic-gate 65277c478bd9Sstevel@tonic-gate if (ofilter->src_nd_name) { 65287c478bd9Sstevel@tonic-gate nf->src_nd_name = malloc(strlen(ofilter->src_nd_name) + 1); 65297c478bd9Sstevel@tonic-gate if (nf->src_nd_name == NULL) { 65307c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 65317c478bd9Sstevel@tonic-gate goto fail; 65327c478bd9Sstevel@tonic-gate } 65337c478bd9Sstevel@tonic-gate (void) strcpy(nf->src_nd_name, ofilter->src_nd_name); 65347c478bd9Sstevel@tonic-gate } 65357c478bd9Sstevel@tonic-gate if (ofilter->dst_nd_name) { 65367c478bd9Sstevel@tonic-gate nf->dst_nd_name = malloc(strlen(ofilter->dst_nd_name) + 1); 65377c478bd9Sstevel@tonic-gate if (nf->dst_nd_name == NULL) { 65387c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 65397c478bd9Sstevel@tonic-gate goto fail; 65407c478bd9Sstevel@tonic-gate } 65417c478bd9Sstevel@tonic-gate (void) strcpy(nf->dst_nd_name, ofilter->dst_nd_name); 65427c478bd9Sstevel@tonic-gate } 65437c478bd9Sstevel@tonic-gate 65447c478bd9Sstevel@tonic-gate /* add filter addresses type */ 65457c478bd9Sstevel@tonic-gate 65467c478bd9Sstevel@tonic-gate res = nvlist_add_byte(nf->nvlist, IPGPC_FILTER_TYPE, 65477c478bd9Sstevel@tonic-gate af == AF_INET ? IPGPC_V4_FLTR : IPGPC_V6_FLTR); 65487c478bd9Sstevel@tonic-gate if (res != 0) { 65497c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_byte"); 65507c478bd9Sstevel@tonic-gate goto fail; 65517c478bd9Sstevel@tonic-gate } 65527c478bd9Sstevel@tonic-gate IPQOSCDBG1(MHME, "adding address type %s in dup filter\n", 65537c478bd9Sstevel@tonic-gate af == AF_INET ? "AF_INET" : "AF_INET6"); 65547c478bd9Sstevel@tonic-gate 65557c478bd9Sstevel@tonic-gate /* add saddr if present */ 65567c478bd9Sstevel@tonic-gate 65577c478bd9Sstevel@tonic-gate if (saddr) { 65587c478bd9Sstevel@tonic-gate if (af == AF_INET && !inv6) { 65597c478bd9Sstevel@tonic-gate V4_PART_OF_V6(v6addr) = *(uint32_t *)saddr; 65607c478bd9Sstevel@tonic-gate saddr = &v6addr; 65617c478bd9Sstevel@tonic-gate } 65627c478bd9Sstevel@tonic-gate 65637c478bd9Sstevel@tonic-gate /* add address and all 1's mask */ 65647c478bd9Sstevel@tonic-gate 65657c478bd9Sstevel@tonic-gate if (nvlist_add_uint32_array(nf->nvlist, IPGPC_SADDR, 65667c478bd9Sstevel@tonic-gate (uint32_t *)saddr, 4) != 0 || 65677c478bd9Sstevel@tonic-gate nvlist_add_uint32_array(nf->nvlist, IPGPC_SADDR_MASK, 65687c478bd9Sstevel@tonic-gate (uint32_t *)&all_1s_v6, 4) != 0) { 65697c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32_array"); 65707c478bd9Sstevel@tonic-gate goto fail; 65717c478bd9Sstevel@tonic-gate } 65727c478bd9Sstevel@tonic-gate 65737c478bd9Sstevel@tonic-gate } 65747c478bd9Sstevel@tonic-gate 65757c478bd9Sstevel@tonic-gate /* add daddr if present */ 65767c478bd9Sstevel@tonic-gate 65777c478bd9Sstevel@tonic-gate if (daddr) { 65787c478bd9Sstevel@tonic-gate if (af == AF_INET && !inv6) { 65797c478bd9Sstevel@tonic-gate V4_PART_OF_V6(v6addr) = *(uint32_t *)daddr; 65807c478bd9Sstevel@tonic-gate daddr = &v6addr; 65817c478bd9Sstevel@tonic-gate } 65827c478bd9Sstevel@tonic-gate 65837c478bd9Sstevel@tonic-gate /* add address and all 1's mask */ 65847c478bd9Sstevel@tonic-gate 65857c478bd9Sstevel@tonic-gate if (nvlist_add_uint32_array(nf->nvlist, IPGPC_DADDR, 65867c478bd9Sstevel@tonic-gate (uint32_t *)daddr, 4) != 0 || 65877c478bd9Sstevel@tonic-gate nvlist_add_uint32_array(nf->nvlist, IPGPC_DADDR_MASK, 65887c478bd9Sstevel@tonic-gate (uint32_t *)&all_1s_v6, 4) != 0) { 65897c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvlist_add_uint32_array"); 65907c478bd9Sstevel@tonic-gate goto fail; 65917c478bd9Sstevel@tonic-gate } 65927c478bd9Sstevel@tonic-gate } 65937c478bd9Sstevel@tonic-gate 65947c478bd9Sstevel@tonic-gate /* add filter instance */ 65957c478bd9Sstevel@tonic-gate 65967c478bd9Sstevel@tonic-gate nf->instance = inst; 65977c478bd9Sstevel@tonic-gate 65987c478bd9Sstevel@tonic-gate *nfilter = nf; 65997c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 66007c478bd9Sstevel@tonic-gate fail: 66017c478bd9Sstevel@tonic-gate free_filter(nf); 66027c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 66037c478bd9Sstevel@tonic-gate } 66047c478bd9Sstevel@tonic-gate 66057c478bd9Sstevel@tonic-gate 66067c478bd9Sstevel@tonic-gate 66077c478bd9Sstevel@tonic-gate /* ************************* action manip fns ********************** */ 66087c478bd9Sstevel@tonic-gate 66097c478bd9Sstevel@tonic-gate 66107c478bd9Sstevel@tonic-gate 66117c478bd9Sstevel@tonic-gate /* 66127c478bd9Sstevel@tonic-gate * create and zero action structure and a params structure hung off of it. 66137c478bd9Sstevel@tonic-gate * RETURNS: ptr to allocated action on success, else NULL. 66147c478bd9Sstevel@tonic-gate */ 66157c478bd9Sstevel@tonic-gate static ipqos_conf_action_t * 66167c478bd9Sstevel@tonic-gate alloc_action() 66177c478bd9Sstevel@tonic-gate { 66187c478bd9Sstevel@tonic-gate 66197c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action; 66207c478bd9Sstevel@tonic-gate 66217c478bd9Sstevel@tonic-gate action = (ipqos_conf_action_t *)malloc(sizeof (ipqos_conf_action_t)); 66227c478bd9Sstevel@tonic-gate if (action == NULL) { 66237c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 66247c478bd9Sstevel@tonic-gate return (action); 66257c478bd9Sstevel@tonic-gate } 66267c478bd9Sstevel@tonic-gate bzero(action, sizeof (ipqos_conf_action_t)); 66277c478bd9Sstevel@tonic-gate 66287c478bd9Sstevel@tonic-gate action->params = (ipqos_conf_params_t *) 66297c478bd9Sstevel@tonic-gate malloc(sizeof (ipqos_conf_params_t)); 66307c478bd9Sstevel@tonic-gate if (action->params == NULL) { 66317c478bd9Sstevel@tonic-gate free(action); 66327c478bd9Sstevel@tonic-gate return (NULL); 66337c478bd9Sstevel@tonic-gate } 66347c478bd9Sstevel@tonic-gate bzero(action->params, sizeof (ipqos_conf_params_t)); 66357c478bd9Sstevel@tonic-gate action->params->stats_enable = B_FALSE; 66367c478bd9Sstevel@tonic-gate 66377c478bd9Sstevel@tonic-gate return (action); 66387c478bd9Sstevel@tonic-gate } 66397c478bd9Sstevel@tonic-gate 66407c478bd9Sstevel@tonic-gate /* 66417c478bd9Sstevel@tonic-gate * free all the memory used in all the actions in actions list. 66427c478bd9Sstevel@tonic-gate */ 66437c478bd9Sstevel@tonic-gate static void 66447c478bd9Sstevel@tonic-gate free_actions( 66457c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions) 66467c478bd9Sstevel@tonic-gate { 66477c478bd9Sstevel@tonic-gate 66487c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act = actions; 66497c478bd9Sstevel@tonic-gate ipqos_conf_action_t *next; 66507c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt, *nf; 66517c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls, *nc; 66527c478bd9Sstevel@tonic-gate 66537c478bd9Sstevel@tonic-gate while (act != NULL) { 66547c478bd9Sstevel@tonic-gate /* free parameters */ 66557c478bd9Sstevel@tonic-gate 66567c478bd9Sstevel@tonic-gate if (act->params != NULL) { 66577c478bd9Sstevel@tonic-gate free_arefs(act->params->actions); 66587c478bd9Sstevel@tonic-gate if (act->params->nvlist != NULL) { 66597c478bd9Sstevel@tonic-gate nvlist_free(act->params->nvlist); 66607c478bd9Sstevel@tonic-gate } 66617c478bd9Sstevel@tonic-gate free(act->params); 66627c478bd9Sstevel@tonic-gate } 66637c478bd9Sstevel@tonic-gate 66647c478bd9Sstevel@tonic-gate /* free action nvlist */ 66657c478bd9Sstevel@tonic-gate 66667c478bd9Sstevel@tonic-gate if (act->nvlist != NULL) 66677c478bd9Sstevel@tonic-gate free(act->nvlist); 66687c478bd9Sstevel@tonic-gate 66697c478bd9Sstevel@tonic-gate /* free filters */ 66707c478bd9Sstevel@tonic-gate 66717c478bd9Sstevel@tonic-gate flt = act->filters; 66727c478bd9Sstevel@tonic-gate while (flt != NULL) { 66737c478bd9Sstevel@tonic-gate nf = flt->next; 66747c478bd9Sstevel@tonic-gate free_filter(flt); 66757c478bd9Sstevel@tonic-gate flt = nf; 66767c478bd9Sstevel@tonic-gate } 66777c478bd9Sstevel@tonic-gate 66787c478bd9Sstevel@tonic-gate /* free classes */ 66797c478bd9Sstevel@tonic-gate 66807c478bd9Sstevel@tonic-gate cls = act->classes; 66817c478bd9Sstevel@tonic-gate while (cls != NULL) { 66827c478bd9Sstevel@tonic-gate nc = cls->next; 66837c478bd9Sstevel@tonic-gate free_class(cls); 66847c478bd9Sstevel@tonic-gate cls = nc; 66857c478bd9Sstevel@tonic-gate } 66867c478bd9Sstevel@tonic-gate 66877c478bd9Sstevel@tonic-gate /* free permanent classes table */ 66887c478bd9Sstevel@tonic-gate cleanup_string_table(act->perm_classes, act->num_perm_classes); 66897c478bd9Sstevel@tonic-gate 66907c478bd9Sstevel@tonic-gate /* free filters to retry */ 66917c478bd9Sstevel@tonic-gate 66927c478bd9Sstevel@tonic-gate flt = act->retry_filters; 66937c478bd9Sstevel@tonic-gate while (flt != NULL) { 66947c478bd9Sstevel@tonic-gate nf = flt->next; 66957c478bd9Sstevel@tonic-gate free_filter(flt); 66967c478bd9Sstevel@tonic-gate flt = nf; 66977c478bd9Sstevel@tonic-gate } 66987c478bd9Sstevel@tonic-gate 66997c478bd9Sstevel@tonic-gate /* free dependency pointers */ 67007c478bd9Sstevel@tonic-gate free_arefs(act->dependencies); 67017c478bd9Sstevel@tonic-gate 67027c478bd9Sstevel@tonic-gate next = act->next; 67037c478bd9Sstevel@tonic-gate free(act); 67047c478bd9Sstevel@tonic-gate act = next; 67057c478bd9Sstevel@tonic-gate } 67067c478bd9Sstevel@tonic-gate } 67077c478bd9Sstevel@tonic-gate 67087c478bd9Sstevel@tonic-gate /* 67097c478bd9Sstevel@tonic-gate * Checks whether there is an action called action_name in actions list. 67107c478bd9Sstevel@tonic-gate * RETURNS: ptr to first matched action, else if not matched NULL. 67117c478bd9Sstevel@tonic-gate * 67127c478bd9Sstevel@tonic-gate */ 67137c478bd9Sstevel@tonic-gate static ipqos_conf_action_t * 67147c478bd9Sstevel@tonic-gate actionexist( 67157c478bd9Sstevel@tonic-gate char *action_name, 67167c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions) 67177c478bd9Sstevel@tonic-gate { 67187c478bd9Sstevel@tonic-gate 67197c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In actionexist: name: %s\n", action_name); 67207c478bd9Sstevel@tonic-gate 67217c478bd9Sstevel@tonic-gate while (actions) { 67227c478bd9Sstevel@tonic-gate if (strcmp(action_name, actions->name) == 0) { 67237c478bd9Sstevel@tonic-gate break; 67247c478bd9Sstevel@tonic-gate } 67257c478bd9Sstevel@tonic-gate actions = actions->next; 67267c478bd9Sstevel@tonic-gate } 67277c478bd9Sstevel@tonic-gate 67287c478bd9Sstevel@tonic-gate return (actions); 67297c478bd9Sstevel@tonic-gate } 67307c478bd9Sstevel@tonic-gate 67317c478bd9Sstevel@tonic-gate /* **************************** act ref manip fns ******************** */ 67327c478bd9Sstevel@tonic-gate 67337c478bd9Sstevel@tonic-gate 67347c478bd9Sstevel@tonic-gate /* 67357c478bd9Sstevel@tonic-gate * add an action reference element with parameter field and action 67367c478bd9Sstevel@tonic-gate * action_name to arefs. 67377c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 67387c478bd9Sstevel@tonic-gate */ 67397c478bd9Sstevel@tonic-gate static int 67407c478bd9Sstevel@tonic-gate add_aref( 67417c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t **arefs, 67427c478bd9Sstevel@tonic-gate char *field, 67437c478bd9Sstevel@tonic-gate char *action_name) 67447c478bd9Sstevel@tonic-gate { 67457c478bd9Sstevel@tonic-gate 67467c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *aref; 67477c478bd9Sstevel@tonic-gate 67487c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "add_aref: action: %s.\n", action_name); 67497c478bd9Sstevel@tonic-gate 67507c478bd9Sstevel@tonic-gate /* allocate zero'd aref */ 67517c478bd9Sstevel@tonic-gate 67527c478bd9Sstevel@tonic-gate aref = malloc(sizeof (ipqos_conf_act_ref_t)); 67537c478bd9Sstevel@tonic-gate if (aref == NULL) { 67547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 67557c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 67567c478bd9Sstevel@tonic-gate } 67577c478bd9Sstevel@tonic-gate (void) bzero(aref, sizeof (ipqos_conf_act_ref_t)); 67587c478bd9Sstevel@tonic-gate 67597c478bd9Sstevel@tonic-gate /* copy parameter name if present */ 67607c478bd9Sstevel@tonic-gate 67617c478bd9Sstevel@tonic-gate if (field) 67627c478bd9Sstevel@tonic-gate (void) strlcpy(aref->field, field, IPQOS_CONF_PNAME_LEN); 67637c478bd9Sstevel@tonic-gate 67647c478bd9Sstevel@tonic-gate /* copy action name */ 67657c478bd9Sstevel@tonic-gate (void) strlcpy(aref->name, action_name, IPQOS_CONF_NAME_LEN); 67667c478bd9Sstevel@tonic-gate 67677c478bd9Sstevel@tonic-gate /* place at head of list */ 67687c478bd9Sstevel@tonic-gate 67697c478bd9Sstevel@tonic-gate aref->next = *arefs; 67707c478bd9Sstevel@tonic-gate *arefs = aref; 67717c478bd9Sstevel@tonic-gate 67727c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 67737c478bd9Sstevel@tonic-gate } 67747c478bd9Sstevel@tonic-gate 67757c478bd9Sstevel@tonic-gate /* 67767c478bd9Sstevel@tonic-gate * free all the memory used by the action references in arefs. 67777c478bd9Sstevel@tonic-gate */ 67787c478bd9Sstevel@tonic-gate static void 67797c478bd9Sstevel@tonic-gate free_arefs( 67807c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *arefs) 67817c478bd9Sstevel@tonic-gate { 67827c478bd9Sstevel@tonic-gate 67837c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *aref = arefs; 67847c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *next; 67857c478bd9Sstevel@tonic-gate 67867c478bd9Sstevel@tonic-gate while (aref) { 67877c478bd9Sstevel@tonic-gate nvlist_free(aref->nvlist); 67887c478bd9Sstevel@tonic-gate next = aref->next; 67897c478bd9Sstevel@tonic-gate free(aref); 67907c478bd9Sstevel@tonic-gate aref = next; 67917c478bd9Sstevel@tonic-gate } 67927c478bd9Sstevel@tonic-gate } 67937c478bd9Sstevel@tonic-gate 67947c478bd9Sstevel@tonic-gate 67957c478bd9Sstevel@tonic-gate 67967c478bd9Sstevel@tonic-gate /* *************************************************************** */ 67977c478bd9Sstevel@tonic-gate 67987c478bd9Sstevel@tonic-gate 67997c478bd9Sstevel@tonic-gate 68007c478bd9Sstevel@tonic-gate /* 68017c478bd9Sstevel@tonic-gate * checks whether aname is a valid action name. 68027c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if invalid, else IPQOS_CONF_SUCCESS. 68037c478bd9Sstevel@tonic-gate */ 68047c478bd9Sstevel@tonic-gate static int 68057c478bd9Sstevel@tonic-gate valid_aname(char *aname) 68067c478bd9Sstevel@tonic-gate { 68077c478bd9Sstevel@tonic-gate 68087c478bd9Sstevel@tonic-gate /* 68097c478bd9Sstevel@tonic-gate * dissallow the use of the name of a virtual action, either 68107c478bd9Sstevel@tonic-gate * the ipqosconf name, or the longer ipp names. 68117c478bd9Sstevel@tonic-gate */ 68127c478bd9Sstevel@tonic-gate if (strcmp(aname, IPQOS_CONF_CONT_STR) == 0 || 68137c478bd9Sstevel@tonic-gate strcmp(aname, IPQOS_CONF_DEFER_STR) == 0 || 68147c478bd9Sstevel@tonic-gate strcmp(aname, IPQOS_CONF_DROP_STR) == 0 || 68157c478bd9Sstevel@tonic-gate virtual_action(aname)) { 68167c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Invalid action name line %u.\n"), 68177c478bd9Sstevel@tonic-gate lineno); 68187c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 68197c478bd9Sstevel@tonic-gate } 68207c478bd9Sstevel@tonic-gate 68217c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 68227c478bd9Sstevel@tonic-gate } 68237c478bd9Sstevel@tonic-gate 68247c478bd9Sstevel@tonic-gate /* 68257c478bd9Sstevel@tonic-gate * Opens a stream to the types file for module module_name (assuming 68267c478bd9Sstevel@tonic-gate * that the file path is TYPES_FILE_DIR/module_name.types). if 68277c478bd9Sstevel@tonic-gate * a file open failure occurs, *openerr is set to 1. 68287c478bd9Sstevel@tonic-gate * RETURNS: NULL on error, else stream ptr to module types file. 68297c478bd9Sstevel@tonic-gate */ 68307c478bd9Sstevel@tonic-gate static FILE * 68317c478bd9Sstevel@tonic-gate validmod( 68327c478bd9Sstevel@tonic-gate char *module_name, 68337c478bd9Sstevel@tonic-gate int *openerr) 68347c478bd9Sstevel@tonic-gate { 68357c478bd9Sstevel@tonic-gate 68367c478bd9Sstevel@tonic-gate FILE *fp; 68377c478bd9Sstevel@tonic-gate char *path; 68387c478bd9Sstevel@tonic-gate 68397c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In validmod: module_name: %s\n", module_name); 68407c478bd9Sstevel@tonic-gate 68417c478bd9Sstevel@tonic-gate *openerr = 0; 68427c478bd9Sstevel@tonic-gate 68437c478bd9Sstevel@tonic-gate /* create modules type file path */ 68447c478bd9Sstevel@tonic-gate 68457c478bd9Sstevel@tonic-gate path = malloc(strlen(TYPES_FILE_DIR) + strlen(module_name) + 68467c478bd9Sstevel@tonic-gate strlen(".types") + 1); 68477c478bd9Sstevel@tonic-gate if (path == NULL) { 68487c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 68497c478bd9Sstevel@tonic-gate return (NULL); 68507c478bd9Sstevel@tonic-gate } 68517c478bd9Sstevel@tonic-gate (void) strcpy(path, TYPES_FILE_DIR); 68527c478bd9Sstevel@tonic-gate (void) strcat(path, module_name); 68537c478bd9Sstevel@tonic-gate (void) strcat(path, ".types"); 68547c478bd9Sstevel@tonic-gate 68557c478bd9Sstevel@tonic-gate 68567c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "opening file %s\n", path); 68577c478bd9Sstevel@tonic-gate 68587c478bd9Sstevel@tonic-gate /* open stream to types file */ 68597c478bd9Sstevel@tonic-gate 68607c478bd9Sstevel@tonic-gate fp = fopen(path, "r"); 68617c478bd9Sstevel@tonic-gate if (fp == NULL) { 68627c478bd9Sstevel@tonic-gate (*openerr)++; 68637c478bd9Sstevel@tonic-gate } 68647c478bd9Sstevel@tonic-gate 68657c478bd9Sstevel@tonic-gate free(path); 68667c478bd9Sstevel@tonic-gate return (fp); 68677c478bd9Sstevel@tonic-gate } 68687c478bd9Sstevel@tonic-gate 68697c478bd9Sstevel@tonic-gate 68707c478bd9Sstevel@tonic-gate /* 68717c478bd9Sstevel@tonic-gate * read a class clause from cfp into a class struct and point class at this. 68727c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 68737c478bd9Sstevel@tonic-gate */ 68747c478bd9Sstevel@tonic-gate static int 68757c478bd9Sstevel@tonic-gate readclass( 68767c478bd9Sstevel@tonic-gate FILE *cfp, 68777c478bd9Sstevel@tonic-gate char *module_name, 68787c478bd9Sstevel@tonic-gate ipqos_conf_class_t **class, 68797c478bd9Sstevel@tonic-gate char **perm_classes, 68807c478bd9Sstevel@tonic-gate int num_perm_classes) 68817c478bd9Sstevel@tonic-gate { 68827c478bd9Sstevel@tonic-gate 68837c478bd9Sstevel@tonic-gate int nm, act; 68847c478bd9Sstevel@tonic-gate int res; 68857c478bd9Sstevel@tonic-gate nvpair_t *nvp; 68867c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 68877c478bd9Sstevel@tonic-gate char *name; 68887c478bd9Sstevel@tonic-gate char *action; 68897c478bd9Sstevel@tonic-gate int stats; 68907c478bd9Sstevel@tonic-gate 68917c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in readclass\n"); 68927c478bd9Sstevel@tonic-gate 68937c478bd9Sstevel@tonic-gate /* create and zero class struct */ 68947c478bd9Sstevel@tonic-gate 68957c478bd9Sstevel@tonic-gate *class = alloc_class(); 68967c478bd9Sstevel@tonic-gate if (!*class) { 68977c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 68987c478bd9Sstevel@tonic-gate } 68997c478bd9Sstevel@tonic-gate (*class)->originator = IPP_CONFIG_IPQOSCONF; 69007c478bd9Sstevel@tonic-gate 69017c478bd9Sstevel@tonic-gate /* get starting line for error reporting */ 69027c478bd9Sstevel@tonic-gate (*class)->lineno = lineno; 69037c478bd9Sstevel@tonic-gate 69047c478bd9Sstevel@tonic-gate /* read curl_begin */ 69057c478bd9Sstevel@tonic-gate 69067c478bd9Sstevel@tonic-gate res = read_curl_begin(cfp); 69077c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 69087c478bd9Sstevel@tonic-gate goto fail; 69097c478bd9Sstevel@tonic-gate } 69107c478bd9Sstevel@tonic-gate 69117c478bd9Sstevel@tonic-gate /* loop reading parameters till read curl_end */ 69127c478bd9Sstevel@tonic-gate 69137c478bd9Sstevel@tonic-gate stats = nm = act = 0; 69147c478bd9Sstevel@tonic-gate for (;;) { 69157c478bd9Sstevel@tonic-gate /* read nvpair */ 69167c478bd9Sstevel@tonic-gate res = readnvpair(cfp, NULL, &(*class)->nvlist, 69177c478bd9Sstevel@tonic-gate &nvp, &type, PL_CLASS, module_name); 69187c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR) { 69197c478bd9Sstevel@tonic-gate goto fail; 69207c478bd9Sstevel@tonic-gate 69217c478bd9Sstevel@tonic-gate /* reached end of class clause */ 69227c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 69237c478bd9Sstevel@tonic-gate break; 69247c478bd9Sstevel@tonic-gate } 69257c478bd9Sstevel@tonic-gate 69267c478bd9Sstevel@tonic-gate /* 69277c478bd9Sstevel@tonic-gate * catch name and action nv pairs and stats if present 69287c478bd9Sstevel@tonic-gate * and place values in class structure. 69297c478bd9Sstevel@tonic-gate */ 69307c478bd9Sstevel@tonic-gate 69317c478bd9Sstevel@tonic-gate /* name */ 69327c478bd9Sstevel@tonic-gate 69337c478bd9Sstevel@tonic-gate if (nm == 0 && 69347c478bd9Sstevel@tonic-gate strcmp(nvpair_name(nvp), IPQOS_CONF_NAME_STR) == 0) { 69357c478bd9Sstevel@tonic-gate 69367c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &name); 69377c478bd9Sstevel@tonic-gate 69387c478bd9Sstevel@tonic-gate if (valid_name(name) != IPQOS_CONF_SUCCESS) { 69397c478bd9Sstevel@tonic-gate goto fail; 69407c478bd9Sstevel@tonic-gate } 69417c478bd9Sstevel@tonic-gate (void) strcpy((*class)->name, name); 69427c478bd9Sstevel@tonic-gate nm++; 69437c478bd9Sstevel@tonic-gate 69447c478bd9Sstevel@tonic-gate /* next action */ 69457c478bd9Sstevel@tonic-gate 69467c478bd9Sstevel@tonic-gate } else if (act == 0 && 69477c478bd9Sstevel@tonic-gate strcmp(nvpair_name(nvp), IPQOS_CONF_NEXT_ACTION_STR) == 0) { 69487c478bd9Sstevel@tonic-gate 69497c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &action); 69507c478bd9Sstevel@tonic-gate 69517c478bd9Sstevel@tonic-gate /* 69527c478bd9Sstevel@tonic-gate * if next action string continue string set action to 69537c478bd9Sstevel@tonic-gate * IPP_ANAME_CONT, else if drop string IPP_ANAME_DROP 69547c478bd9Sstevel@tonic-gate */ 69557c478bd9Sstevel@tonic-gate if (strcmp(action, IPQOS_CONF_CONT_STR) == 0) { 69567c478bd9Sstevel@tonic-gate action = IPP_ANAME_CONT; 69577c478bd9Sstevel@tonic-gate } else if (strcmp(action, IPQOS_CONF_DROP_STR) == 0) { 69587c478bd9Sstevel@tonic-gate action = IPP_ANAME_DROP; 69597c478bd9Sstevel@tonic-gate } 69607c478bd9Sstevel@tonic-gate 69617c478bd9Sstevel@tonic-gate /* add an action reference to action list */ 69627c478bd9Sstevel@tonic-gate 69637c478bd9Sstevel@tonic-gate res = add_aref(&(*class)->alist, 69647c478bd9Sstevel@tonic-gate IPQOS_CONF_NEXT_ACTION_STR, action); 69657c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 69667c478bd9Sstevel@tonic-gate goto fail; 69677c478bd9Sstevel@tonic-gate } 69687c478bd9Sstevel@tonic-gate act++; 69697c478bd9Sstevel@tonic-gate 69707c478bd9Sstevel@tonic-gate /* class stats enable */ 69717c478bd9Sstevel@tonic-gate 69727c478bd9Sstevel@tonic-gate } else if (stats == 0 && 69737c478bd9Sstevel@tonic-gate strcmp(nvpair_name(nvp), IPQOS_CONF_STATS_ENABLE_STR) == 69747c478bd9Sstevel@tonic-gate 0) { 69757c478bd9Sstevel@tonic-gate boolean_t bl; 69767c478bd9Sstevel@tonic-gate 69777c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, (uint32_t *)&bl); 69787c478bd9Sstevel@tonic-gate (*class)->stats_enable = bl; 69797c478bd9Sstevel@tonic-gate 69807c478bd9Sstevel@tonic-gate stats++; 69817c478bd9Sstevel@tonic-gate 69827c478bd9Sstevel@tonic-gate /* no other / duplicate parameters allowed */ 69837c478bd9Sstevel@tonic-gate 69847c478bd9Sstevel@tonic-gate } else { 69857c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 69867c478bd9Sstevel@tonic-gate gettext("Unexpected parameter line %u.\n"), lineno); 69877c478bd9Sstevel@tonic-gate goto fail; 69887c478bd9Sstevel@tonic-gate } 69897c478bd9Sstevel@tonic-gate } 69907c478bd9Sstevel@tonic-gate if (nm == 0 || act == 0) { 69917c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 69927c478bd9Sstevel@tonic-gate gettext("Missing class name/next action before line %u.\n"), 69937c478bd9Sstevel@tonic-gate lineno); 69947c478bd9Sstevel@tonic-gate goto fail; 69957c478bd9Sstevel@tonic-gate } 69967c478bd9Sstevel@tonic-gate 69977c478bd9Sstevel@tonic-gate /* change class originator field to permanent if permanent class */ 69987c478bd9Sstevel@tonic-gate 69997c478bd9Sstevel@tonic-gate if (in_string_table(perm_classes, num_perm_classes, (*class)->name)) { 70007c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "Setting class %s as permanent.\n", (*class)->name); 70017c478bd9Sstevel@tonic-gate (*class)->originator = IPP_CONFIG_PERMANENT; 70027c478bd9Sstevel@tonic-gate } 70037c478bd9Sstevel@tonic-gate 70047c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 70057c478bd9Sstevel@tonic-gate fail: 70067c478bd9Sstevel@tonic-gate if (*class) 70077c478bd9Sstevel@tonic-gate free_class(*class); 70087c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 70097c478bd9Sstevel@tonic-gate } 70107c478bd9Sstevel@tonic-gate 70117c478bd9Sstevel@tonic-gate /* 70127c478bd9Sstevel@tonic-gate * This function assumes either src_nd_name or dst_node_nm are set in filter. 70137c478bd9Sstevel@tonic-gate * 70147c478bd9Sstevel@tonic-gate * Creates one of more copies of filter according to the ip versions 70157c478bd9Sstevel@tonic-gate * requested (or assumed) and the resolution of the src and dst address 70167c478bd9Sstevel@tonic-gate * node names if spec'd. If both node names are spec'd then a filter is 70177c478bd9Sstevel@tonic-gate * created for each pair of addresses (one from each node name) that is 70187c478bd9Sstevel@tonic-gate * compatible with the chosen address family, otherwise a filter copy is 70197c478bd9Sstevel@tonic-gate * created for just each address of the single node name that is 70207c478bd9Sstevel@tonic-gate * compatible. 70217c478bd9Sstevel@tonic-gate * If filter->ip_versions has been set that is used to determine the 70227c478bd9Sstevel@tonic-gate * af's we will create filters for, else if a numeric address was 70237c478bd9Sstevel@tonic-gate * added the family of that will be used, otherwise we fall back 70247c478bd9Sstevel@tonic-gate * to both v4 and v6 addresses. 70257c478bd9Sstevel@tonic-gate * 70267c478bd9Sstevel@tonic-gate * Any name lookup failures that occur are checked to see whether the failure 70277c478bd9Sstevel@tonic-gate * was a soft or hard failure and the nlerr field of filter set accordingly 70287c478bd9Sstevel@tonic-gate * before the error is returned. 70297c478bd9Sstevel@tonic-gate * 70307c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on any error, else IPQOS_CONF_SUCCESS. 70317c478bd9Sstevel@tonic-gate */ 70327c478bd9Sstevel@tonic-gate 70337c478bd9Sstevel@tonic-gate static int 70347c478bd9Sstevel@tonic-gate domultihome( 70357c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter, 70367c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **flist, 70377c478bd9Sstevel@tonic-gate boolean_t last_retry) 70387c478bd9Sstevel@tonic-gate { 70397c478bd9Sstevel@tonic-gate 70407c478bd9Sstevel@tonic-gate uint32_t ftype; 70417c478bd9Sstevel@tonic-gate int v4 = 1, v6 = 1; /* default lookup family is v4 and v6 */ 70427c478bd9Sstevel@tonic-gate int saf, daf; 70437c478bd9Sstevel@tonic-gate struct hostent *shp = NULL; 70447c478bd9Sstevel@tonic-gate struct hostent *dhp = NULL; 70457c478bd9Sstevel@tonic-gate in6_addr_t daddr, saddr; 70467c478bd9Sstevel@tonic-gate int idx = 0; 70477c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *nfilter; 70487c478bd9Sstevel@tonic-gate int res; 70497c478bd9Sstevel@tonic-gate int ernum; 70507c478bd9Sstevel@tonic-gate int in32b = 0; 70517c478bd9Sstevel@tonic-gate char **sp, **dp; 70527c478bd9Sstevel@tonic-gate 70537c478bd9Sstevel@tonic-gate IPQOSCDBG3(MHME, "In domultihome: filter: %s, src_node: %s, " 70547c478bd9Sstevel@tonic-gate "dst_node: %s\n", filter->name, 70557c478bd9Sstevel@tonic-gate (filter->src_nd_name ? filter->src_nd_name : "NULL"), 70567c478bd9Sstevel@tonic-gate (filter->dst_nd_name ? filter->dst_nd_name : "NULL")); 70577c478bd9Sstevel@tonic-gate 70587c478bd9Sstevel@tonic-gate /* check if we've read an ip_version request to get the versions */ 70597c478bd9Sstevel@tonic-gate 70607c478bd9Sstevel@tonic-gate if (filter->ip_versions != 0) { 70617c478bd9Sstevel@tonic-gate v4 = VERSION_IS_V4(filter); 70627c478bd9Sstevel@tonic-gate v6 = VERSION_IS_V6(filter); 70637c478bd9Sstevel@tonic-gate 70647c478bd9Sstevel@tonic-gate /* otherwise check if we've read a numeric address and get versions */ 70657c478bd9Sstevel@tonic-gate 70667c478bd9Sstevel@tonic-gate } else if (nvlist_lookup_uint32(filter->nvlist, IPGPC_FILTER_TYPE, 70677c478bd9Sstevel@tonic-gate &ftype) == 0) { 70687c478bd9Sstevel@tonic-gate if (ftype == IPGPC_V4_FLTR) { 70697c478bd9Sstevel@tonic-gate v6--; 70707c478bd9Sstevel@tonic-gate } else { 70717c478bd9Sstevel@tonic-gate v4--; 70727c478bd9Sstevel@tonic-gate } 70737c478bd9Sstevel@tonic-gate } 70747c478bd9Sstevel@tonic-gate 70757c478bd9Sstevel@tonic-gate /* read saddrs if src node name */ 70767c478bd9Sstevel@tonic-gate 70777c478bd9Sstevel@tonic-gate if (filter->src_nd_name) { 70787c478bd9Sstevel@tonic-gate 70797c478bd9Sstevel@tonic-gate /* v4 only address */ 70807c478bd9Sstevel@tonic-gate 70817c478bd9Sstevel@tonic-gate if (v4 && !v6) { 70827c478bd9Sstevel@tonic-gate in32b++; 70837c478bd9Sstevel@tonic-gate shp = getipnodebyname(filter->src_nd_name, AF_INET, 70847c478bd9Sstevel@tonic-gate AI_ADDRCONFIG, &ernum); 70857c478bd9Sstevel@tonic-gate 70867c478bd9Sstevel@tonic-gate /* v6 only */ 70877c478bd9Sstevel@tonic-gate 70887c478bd9Sstevel@tonic-gate } else if (v6 && !v4) { 70897c478bd9Sstevel@tonic-gate shp = getipnodebyname(filter->src_nd_name, AF_INET6, 70907c478bd9Sstevel@tonic-gate AI_DEFAULT, &ernum); 70917c478bd9Sstevel@tonic-gate 70927c478bd9Sstevel@tonic-gate /* v4 and v6 */ 70937c478bd9Sstevel@tonic-gate 70947c478bd9Sstevel@tonic-gate } else if (v6 && v4) { 70957c478bd9Sstevel@tonic-gate shp = getipnodebyname(filter->src_nd_name, AF_INET6, 70967c478bd9Sstevel@tonic-gate AI_DEFAULT|AI_ALL, &ernum); 70977c478bd9Sstevel@tonic-gate } 70987c478bd9Sstevel@tonic-gate 70997c478bd9Sstevel@tonic-gate #ifdef TESTING_RETRY 71007c478bd9Sstevel@tonic-gate if (!last_retry) { 71017c478bd9Sstevel@tonic-gate filter->nlerr = IPQOS_LOOKUP_RETRY; 71027c478bd9Sstevel@tonic-gate goto fail; 71037c478bd9Sstevel@tonic-gate } 71047c478bd9Sstevel@tonic-gate #endif 71057c478bd9Sstevel@tonic-gate 71067c478bd9Sstevel@tonic-gate /* 71077c478bd9Sstevel@tonic-gate * if lookup error determine whether it was a soft or hard 71087c478bd9Sstevel@tonic-gate * failure and mark as such in filter. 71097c478bd9Sstevel@tonic-gate */ 71107c478bd9Sstevel@tonic-gate if (shp == NULL) { 71117c478bd9Sstevel@tonic-gate if (ernum != TRY_AGAIN) { 71127c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed to " 71137c478bd9Sstevel@tonic-gate "resolve src host name for filter at " 71147c478bd9Sstevel@tonic-gate "line %u, ignoring filter.\n"), 71157c478bd9Sstevel@tonic-gate filter->lineno); 71167c478bd9Sstevel@tonic-gate filter->nlerr = IPQOS_LOOKUP_FAIL; 71177c478bd9Sstevel@tonic-gate } else { 71187c478bd9Sstevel@tonic-gate if (last_retry) { 71197c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed " 71207c478bd9Sstevel@tonic-gate "to resolve src host name for " 71217c478bd9Sstevel@tonic-gate "filter at line %u, ignoring " 71227c478bd9Sstevel@tonic-gate "filter.\n"), filter->lineno); 71237c478bd9Sstevel@tonic-gate } 71247c478bd9Sstevel@tonic-gate filter->nlerr = IPQOS_LOOKUP_RETRY; 71257c478bd9Sstevel@tonic-gate } 71267c478bd9Sstevel@tonic-gate goto fail; 71277c478bd9Sstevel@tonic-gate } 71287c478bd9Sstevel@tonic-gate } 71297c478bd9Sstevel@tonic-gate 71307c478bd9Sstevel@tonic-gate /* read daddrs if dst node name */ 71317c478bd9Sstevel@tonic-gate if (filter->dst_nd_name) { 71327c478bd9Sstevel@tonic-gate 71337c478bd9Sstevel@tonic-gate /* v4 only address */ 71347c478bd9Sstevel@tonic-gate 71357c478bd9Sstevel@tonic-gate if (v4 && !v6) { 71367c478bd9Sstevel@tonic-gate in32b++; 71377c478bd9Sstevel@tonic-gate dhp = getipnodebyname(filter->dst_nd_name, AF_INET, 71387c478bd9Sstevel@tonic-gate AI_ADDRCONFIG, &ernum); 71397c478bd9Sstevel@tonic-gate 71407c478bd9Sstevel@tonic-gate /* v6 only */ 71417c478bd9Sstevel@tonic-gate 71427c478bd9Sstevel@tonic-gate } else if (v6 && !v4) { 71437c478bd9Sstevel@tonic-gate dhp = getipnodebyname(filter->dst_nd_name, AF_INET6, 71447c478bd9Sstevel@tonic-gate AI_DEFAULT, &ernum); 71457c478bd9Sstevel@tonic-gate 71467c478bd9Sstevel@tonic-gate /* v6 and v4 addresses */ 71477c478bd9Sstevel@tonic-gate 71487c478bd9Sstevel@tonic-gate } else { 71497c478bd9Sstevel@tonic-gate dhp = getipnodebyname(filter->dst_nd_name, AF_INET6, 71507c478bd9Sstevel@tonic-gate AI_DEFAULT|AI_ALL, &ernum); 71517c478bd9Sstevel@tonic-gate } 71527c478bd9Sstevel@tonic-gate 71537c478bd9Sstevel@tonic-gate if (dhp == NULL) { 71547c478bd9Sstevel@tonic-gate if (ernum != TRY_AGAIN) { 71557c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed to " 71567c478bd9Sstevel@tonic-gate "resolve dst host name for filter at " 71577c478bd9Sstevel@tonic-gate "line %u, ignoring filter.\n"), 71587c478bd9Sstevel@tonic-gate filter->lineno); 71597c478bd9Sstevel@tonic-gate filter->nlerr = IPQOS_LOOKUP_FAIL; 71607c478bd9Sstevel@tonic-gate } else { 71617c478bd9Sstevel@tonic-gate if (last_retry) { 71627c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Failed " 71637c478bd9Sstevel@tonic-gate "to resolve dst host name for " 71647c478bd9Sstevel@tonic-gate "filter at line %u, ignoring " 71657c478bd9Sstevel@tonic-gate "filter.\n"), filter->lineno); 71667c478bd9Sstevel@tonic-gate } 71677c478bd9Sstevel@tonic-gate filter->nlerr = IPQOS_LOOKUP_RETRY; 71687c478bd9Sstevel@tonic-gate } 71697c478bd9Sstevel@tonic-gate goto fail; 71707c478bd9Sstevel@tonic-gate } 71717c478bd9Sstevel@tonic-gate } 71727c478bd9Sstevel@tonic-gate 71737c478bd9Sstevel@tonic-gate /* 71747c478bd9Sstevel@tonic-gate * if src and dst node name, create set of filters; one for each 71757c478bd9Sstevel@tonic-gate * src and dst address of matching types. 71767c478bd9Sstevel@tonic-gate */ 71777c478bd9Sstevel@tonic-gate if (filter->src_nd_name && filter->dst_nd_name) { 71787c478bd9Sstevel@tonic-gate 71797c478bd9Sstevel@tonic-gate for (sp = shp->h_addr_list; *sp != NULL; sp++) { 71807c478bd9Sstevel@tonic-gate (void) bcopy(*sp, &saddr, shp->h_length); 71817c478bd9Sstevel@tonic-gate 71827c478bd9Sstevel@tonic-gate /* get saddr family */ 71837c478bd9Sstevel@tonic-gate 71847c478bd9Sstevel@tonic-gate if (in32b || IN6_IS_ADDR_V4MAPPED(&saddr)) { 71857c478bd9Sstevel@tonic-gate saf = AF_INET; 71867c478bd9Sstevel@tonic-gate } else { 71877c478bd9Sstevel@tonic-gate saf = AF_INET6; 71887c478bd9Sstevel@tonic-gate } 71897c478bd9Sstevel@tonic-gate 71907c478bd9Sstevel@tonic-gate for (dp = dhp->h_addr_list; *dp != NULL; dp++) { 71917c478bd9Sstevel@tonic-gate (void) bcopy(*dp, &daddr, dhp->h_length); 71927c478bd9Sstevel@tonic-gate 71937c478bd9Sstevel@tonic-gate /* get daddr family */ 71947c478bd9Sstevel@tonic-gate 71957c478bd9Sstevel@tonic-gate if (in32b || IN6_IS_ADDR_V4MAPPED(&daddr)) { 71967c478bd9Sstevel@tonic-gate daf = AF_INET; 71977c478bd9Sstevel@tonic-gate } else { 71987c478bd9Sstevel@tonic-gate daf = AF_INET6; 71997c478bd9Sstevel@tonic-gate } 72007c478bd9Sstevel@tonic-gate 72017c478bd9Sstevel@tonic-gate /* 72027c478bd9Sstevel@tonic-gate * if saddr and daddr same af duplicate 72037c478bd9Sstevel@tonic-gate * filter adding addresses and new instance 72047c478bd9Sstevel@tonic-gate * number and add to flist filter list. 72057c478bd9Sstevel@tonic-gate */ 72067c478bd9Sstevel@tonic-gate 72077c478bd9Sstevel@tonic-gate if (daf == saf) { 72087c478bd9Sstevel@tonic-gate 72097c478bd9Sstevel@tonic-gate res = dup_filter(filter, &nfilter, saf, 72107c478bd9Sstevel@tonic-gate !in32b, &saddr, &daddr, ++idx); 72117c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 72127c478bd9Sstevel@tonic-gate goto fail; 72137c478bd9Sstevel@tonic-gate } 72147c478bd9Sstevel@tonic-gate ADD_TO_LIST(flist, nfilter); 72157c478bd9Sstevel@tonic-gate } 72167c478bd9Sstevel@tonic-gate } 72177c478bd9Sstevel@tonic-gate } 72187c478bd9Sstevel@tonic-gate 72197c478bd9Sstevel@tonic-gate /* if src name only create set of filters, one for each node address */ 72207c478bd9Sstevel@tonic-gate 72217c478bd9Sstevel@tonic-gate } else if (filter->src_nd_name) { 72227c478bd9Sstevel@tonic-gate 72237c478bd9Sstevel@tonic-gate for (sp = shp->h_addr_list; *sp != NULL; sp++) { 72247c478bd9Sstevel@tonic-gate (void) bcopy(*sp, &saddr, shp->h_length); 72257c478bd9Sstevel@tonic-gate 72267c478bd9Sstevel@tonic-gate /* get af */ 72277c478bd9Sstevel@tonic-gate 72287c478bd9Sstevel@tonic-gate if (in32b || IN6_IS_ADDR_V4MAPPED(&saddr)) { 72297c478bd9Sstevel@tonic-gate saf = AF_INET; 72307c478bd9Sstevel@tonic-gate } else { 72317c478bd9Sstevel@tonic-gate saf = AF_INET6; 72327c478bd9Sstevel@tonic-gate } 72337c478bd9Sstevel@tonic-gate 72347c478bd9Sstevel@tonic-gate 72357c478bd9Sstevel@tonic-gate /* 72367c478bd9Sstevel@tonic-gate * dup filter adding saddr and new instance num and 72377c478bd9Sstevel@tonic-gate * add to flist filter list. 72387c478bd9Sstevel@tonic-gate */ 72397c478bd9Sstevel@tonic-gate res = dup_filter(filter, &nfilter, saf, !in32b, &saddr, 72407c478bd9Sstevel@tonic-gate NULL, ++idx); 72417c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 72427c478bd9Sstevel@tonic-gate goto fail; 72437c478bd9Sstevel@tonic-gate } 72447c478bd9Sstevel@tonic-gate 72457c478bd9Sstevel@tonic-gate ADD_TO_LIST(flist, nfilter); 72467c478bd9Sstevel@tonic-gate 72477c478bd9Sstevel@tonic-gate } 72487c478bd9Sstevel@tonic-gate 72497c478bd9Sstevel@tonic-gate /* if dname only create set of filters, one for each node address */ 72507c478bd9Sstevel@tonic-gate 72517c478bd9Sstevel@tonic-gate } else { 72527c478bd9Sstevel@tonic-gate for (dp = dhp->h_addr_list; *dp != NULL; dp++) { 72537c478bd9Sstevel@tonic-gate (void) bcopy(*dp, &daddr, dhp->h_length); 72547c478bd9Sstevel@tonic-gate 72557c478bd9Sstevel@tonic-gate /* get af */ 72567c478bd9Sstevel@tonic-gate 72577c478bd9Sstevel@tonic-gate if (in32b || IN6_IS_ADDR_V4MAPPED(&daddr)) { 72587c478bd9Sstevel@tonic-gate daf = AF_INET; 72597c478bd9Sstevel@tonic-gate } else { 72607c478bd9Sstevel@tonic-gate daf = AF_INET6; 72617c478bd9Sstevel@tonic-gate } 72627c478bd9Sstevel@tonic-gate 72637c478bd9Sstevel@tonic-gate /* 72647c478bd9Sstevel@tonic-gate * dup filter adding daddr and new instance num and 72657c478bd9Sstevel@tonic-gate * add to flist filter list. 72667c478bd9Sstevel@tonic-gate */ 72677c478bd9Sstevel@tonic-gate res = dup_filter(filter, &nfilter, daf, !in32b, NULL, 72687c478bd9Sstevel@tonic-gate &daddr, ++idx); 72697c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 72707c478bd9Sstevel@tonic-gate goto fail; 72717c478bd9Sstevel@tonic-gate } 72727c478bd9Sstevel@tonic-gate 72737c478bd9Sstevel@tonic-gate ADD_TO_LIST(flist, nfilter); 72747c478bd9Sstevel@tonic-gate } 72757c478bd9Sstevel@tonic-gate } 72767c478bd9Sstevel@tonic-gate 72777c478bd9Sstevel@tonic-gate if (shp) 72787c478bd9Sstevel@tonic-gate freehostent(shp); 72797c478bd9Sstevel@tonic-gate if (dhp) 72807c478bd9Sstevel@tonic-gate freehostent(dhp); 72817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 72827c478bd9Sstevel@tonic-gate fail: 72837c478bd9Sstevel@tonic-gate /* 72847c478bd9Sstevel@tonic-gate * should really clean up any filters that we have created, 72857c478bd9Sstevel@tonic-gate * however, free_actions called from readaction will cleam them up. 72867c478bd9Sstevel@tonic-gate */ 72877c478bd9Sstevel@tonic-gate if (shp) 72887c478bd9Sstevel@tonic-gate freehostent(shp); 72897c478bd9Sstevel@tonic-gate if (dhp) 72907c478bd9Sstevel@tonic-gate freehostent(dhp); 72917c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 72927c478bd9Sstevel@tonic-gate } 72937c478bd9Sstevel@tonic-gate 72947c478bd9Sstevel@tonic-gate 72957c478bd9Sstevel@tonic-gate /* 72967c478bd9Sstevel@tonic-gate * read a filter clause from cfp into a filter struct and point filter 72977c478bd9Sstevel@tonic-gate * at this. 72987c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 72997c478bd9Sstevel@tonic-gate */ 73007c478bd9Sstevel@tonic-gate static int 73017c478bd9Sstevel@tonic-gate readfilter( 73027c478bd9Sstevel@tonic-gate FILE *cfp, 73037c478bd9Sstevel@tonic-gate FILE *tfp, 73047c478bd9Sstevel@tonic-gate char *module_name, 73057c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **filter, 73067c478bd9Sstevel@tonic-gate char **perm_filters, 73077c478bd9Sstevel@tonic-gate int num_perm_filters) 73087c478bd9Sstevel@tonic-gate { 73097c478bd9Sstevel@tonic-gate 73107c478bd9Sstevel@tonic-gate int res; 73117c478bd9Sstevel@tonic-gate int nm, cls, ipv; 73127c478bd9Sstevel@tonic-gate in6_addr_t mask; 73137c478bd9Sstevel@tonic-gate char *addr_str; 73147c478bd9Sstevel@tonic-gate char *sl = NULL; 73157c478bd9Sstevel@tonic-gate in6_addr_t addr; 73167c478bd9Sstevel@tonic-gate int sa; 73177c478bd9Sstevel@tonic-gate struct hostent *hp; 73187c478bd9Sstevel@tonic-gate int err_num; 73197c478bd9Sstevel@tonic-gate int v4 = 0, v6 = 0; 73207c478bd9Sstevel@tonic-gate uchar_t mlen; 73217c478bd9Sstevel@tonic-gate char *tmp; 73227c478bd9Sstevel@tonic-gate nvpair_t *nvp; 73237c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 73247c478bd9Sstevel@tonic-gate char *name; 73257c478bd9Sstevel@tonic-gate char *class; 73267c478bd9Sstevel@tonic-gate uchar_t b; 73277c478bd9Sstevel@tonic-gate in6_addr_t v6addr; 73287c478bd9Sstevel@tonic-gate 73297c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in readfilter\n"); 73307c478bd9Sstevel@tonic-gate 73317c478bd9Sstevel@tonic-gate 73327c478bd9Sstevel@tonic-gate /* create and zero filter struct */ 73337c478bd9Sstevel@tonic-gate 73347c478bd9Sstevel@tonic-gate *filter = alloc_filter(); 73357c478bd9Sstevel@tonic-gate if (*filter == NULL) { 73367c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 73377c478bd9Sstevel@tonic-gate } 73387c478bd9Sstevel@tonic-gate (*filter)->originator = IPP_CONFIG_IPQOSCONF; 73397c478bd9Sstevel@tonic-gate 73407c478bd9Sstevel@tonic-gate /* get starting line for error reporting */ 73417c478bd9Sstevel@tonic-gate (*filter)->lineno = lineno; 73427c478bd9Sstevel@tonic-gate 73437c478bd9Sstevel@tonic-gate /* read beginning curl */ 73447c478bd9Sstevel@tonic-gate 73457c478bd9Sstevel@tonic-gate res = read_curl_begin(cfp); 73467c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 73477c478bd9Sstevel@tonic-gate goto fail; 73487c478bd9Sstevel@tonic-gate } 73497c478bd9Sstevel@tonic-gate 73507c478bd9Sstevel@tonic-gate 73517c478bd9Sstevel@tonic-gate /* 73527c478bd9Sstevel@tonic-gate * loop reading nvpairs onto nvlist until encounter CURL_END 73537c478bd9Sstevel@tonic-gate */ 73547c478bd9Sstevel@tonic-gate ipv = nm = cls = 0; 73557c478bd9Sstevel@tonic-gate for (;;) { 73567c478bd9Sstevel@tonic-gate /* read nvpair */ 73577c478bd9Sstevel@tonic-gate 73587c478bd9Sstevel@tonic-gate res = readnvpair(cfp, tfp, &(*filter)->nvlist, 73597c478bd9Sstevel@tonic-gate &nvp, &type, PL_FILTER, module_name); 73607c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR) { 73617c478bd9Sstevel@tonic-gate goto fail; 73627c478bd9Sstevel@tonic-gate 73637c478bd9Sstevel@tonic-gate /* reached the end of filter definition */ 73647c478bd9Sstevel@tonic-gate 73657c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 73667c478bd9Sstevel@tonic-gate break; 73677c478bd9Sstevel@tonic-gate } 73687c478bd9Sstevel@tonic-gate 73697c478bd9Sstevel@tonic-gate /* 73707c478bd9Sstevel@tonic-gate * catch name and class and place value into filter 73717c478bd9Sstevel@tonic-gate * structure. 73727c478bd9Sstevel@tonic-gate */ 73737c478bd9Sstevel@tonic-gate 73747c478bd9Sstevel@tonic-gate /* read filter name */ 73757c478bd9Sstevel@tonic-gate 73767c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), IPQOS_CONF_NAME_STR) == 0) { 73777c478bd9Sstevel@tonic-gate if (nm != 0) { 73787c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 73797c478bd9Sstevel@tonic-gate gettext("Duplicate parameter line %u.\n"), 73807c478bd9Sstevel@tonic-gate lineno); 73817c478bd9Sstevel@tonic-gate goto fail; 73827c478bd9Sstevel@tonic-gate } 73837c478bd9Sstevel@tonic-gate 73847c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &name); 73857c478bd9Sstevel@tonic-gate if (valid_name(name) != IPQOS_CONF_SUCCESS) { 73867c478bd9Sstevel@tonic-gate goto fail; 73877c478bd9Sstevel@tonic-gate } 73887c478bd9Sstevel@tonic-gate 73897c478bd9Sstevel@tonic-gate (void) strcpy((*filter)->name, name); 73907c478bd9Sstevel@tonic-gate (void) nvlist_remove_all((*filter)->nvlist, 73917c478bd9Sstevel@tonic-gate IPQOS_CONF_NAME_STR); 73927c478bd9Sstevel@tonic-gate nm++; 73937c478bd9Sstevel@tonic-gate 73947c478bd9Sstevel@tonic-gate /* read class name */ 73957c478bd9Sstevel@tonic-gate 73967c478bd9Sstevel@tonic-gate } else if (strcmp(nvpair_name(nvp), IPQOS_CONF_CLASS_STR) == 73977c478bd9Sstevel@tonic-gate 0) { 73987c478bd9Sstevel@tonic-gate if (cls != 0) { 73997c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 74007c478bd9Sstevel@tonic-gate gettext("Duplicate parameter line %u.\n"), 74017c478bd9Sstevel@tonic-gate lineno); 74027c478bd9Sstevel@tonic-gate goto fail; 74037c478bd9Sstevel@tonic-gate } 74047c478bd9Sstevel@tonic-gate 74057c478bd9Sstevel@tonic-gate if (nvpair_value_string(nvp, &class) != 0) { 74067c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "nvpair_value_string"); 74077c478bd9Sstevel@tonic-gate break; 74087c478bd9Sstevel@tonic-gate } 74097c478bd9Sstevel@tonic-gate if (valid_name(class) != IPQOS_CONF_SUCCESS) { 74107c478bd9Sstevel@tonic-gate goto fail; 74117c478bd9Sstevel@tonic-gate } 74127c478bd9Sstevel@tonic-gate (void) strcpy((*filter)->class_name, class); 74137c478bd9Sstevel@tonic-gate (void) nvlist_remove_all((*filter)->nvlist, 74147c478bd9Sstevel@tonic-gate IPQOS_CONF_CLASS_STR); 74157c478bd9Sstevel@tonic-gate cls++; 74167c478bd9Sstevel@tonic-gate 74177c478bd9Sstevel@tonic-gate /* 74187c478bd9Sstevel@tonic-gate * if a src or dst ip node name/address. For those that 74197c478bd9Sstevel@tonic-gate * are determined to be addresses we convert them from 74207c478bd9Sstevel@tonic-gate * strings here and add to the filter nvlist; for node names 74217c478bd9Sstevel@tonic-gate * we add the name to the filter struct for readaction to 74227c478bd9Sstevel@tonic-gate * process. 74237c478bd9Sstevel@tonic-gate */ 74247c478bd9Sstevel@tonic-gate } else if (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 0 || 74257c478bd9Sstevel@tonic-gate strcmp(nvpair_name(nvp), IPGPC_DADDR) == 0) { 74267c478bd9Sstevel@tonic-gate 74277c478bd9Sstevel@tonic-gate sa = 0; 74287c478bd9Sstevel@tonic-gate 74297c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), IPGPC_SADDR) == 0) { 74307c478bd9Sstevel@tonic-gate sa++; 74317c478bd9Sstevel@tonic-gate } 74327c478bd9Sstevel@tonic-gate 74337c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &addr_str); 74347c478bd9Sstevel@tonic-gate 74357c478bd9Sstevel@tonic-gate /* 74367c478bd9Sstevel@tonic-gate * get the address mask if present. 74377c478bd9Sstevel@tonic-gate * make a copy so that the nvlist element that 74387c478bd9Sstevel@tonic-gate * it is part of doesn't dissapear and causes probs. 74397c478bd9Sstevel@tonic-gate */ 74407c478bd9Sstevel@tonic-gate sl = strchr(addr_str, '/'); 74417c478bd9Sstevel@tonic-gate if (sl) { 74427c478bd9Sstevel@tonic-gate *sl = '\0'; 74437c478bd9Sstevel@tonic-gate tmp = malloc(strlen(++sl) + 1); 74447c478bd9Sstevel@tonic-gate if (tmp == NULL) { 74457c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 74467c478bd9Sstevel@tonic-gate goto fail; 74477c478bd9Sstevel@tonic-gate } 74487c478bd9Sstevel@tonic-gate (void) strcpy(tmp, sl); 74497c478bd9Sstevel@tonic-gate sl = tmp; 74507c478bd9Sstevel@tonic-gate } 74517c478bd9Sstevel@tonic-gate 74527c478bd9Sstevel@tonic-gate 74537c478bd9Sstevel@tonic-gate /* if a numeric address */ 74547c478bd9Sstevel@tonic-gate 74557c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, addr_str, &addr) == 1 || 74567c478bd9Sstevel@tonic-gate inet_pton(AF_INET6, addr_str, &addr) == 1) { 74577c478bd9Sstevel@tonic-gate 74587c478bd9Sstevel@tonic-gate /* get address */ 74597c478bd9Sstevel@tonic-gate 74607c478bd9Sstevel@tonic-gate hp = getipnodebyname(addr_str, AF_INET6, 74617c478bd9Sstevel@tonic-gate AI_DEFAULT, &err_num); 74627c478bd9Sstevel@tonic-gate if (hp == NULL) { 74637c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 74647c478bd9Sstevel@tonic-gate "getipnodebyname"); 74657c478bd9Sstevel@tonic-gate goto fail; 74667c478bd9Sstevel@tonic-gate } 74677c478bd9Sstevel@tonic-gate 74687c478bd9Sstevel@tonic-gate (void) bcopy(hp->h_addr_list[0], &v6addr, 74697c478bd9Sstevel@tonic-gate hp->h_length); 74707c478bd9Sstevel@tonic-gate freehostent(hp); 74717c478bd9Sstevel@tonic-gate 74727c478bd9Sstevel@tonic-gate /* determine address type */ 74737c478bd9Sstevel@tonic-gate 74747c478bd9Sstevel@tonic-gate v4 = IN6_IS_ADDR_V4MAPPED(&v6addr); 74757c478bd9Sstevel@tonic-gate if (!v4) { 74767c478bd9Sstevel@tonic-gate v6++; 74777c478bd9Sstevel@tonic-gate } 74787c478bd9Sstevel@tonic-gate 74797c478bd9Sstevel@tonic-gate /* 74807c478bd9Sstevel@tonic-gate * check any previous addresses have same 74817c478bd9Sstevel@tonic-gate * version. 74827c478bd9Sstevel@tonic-gate */ 74837c478bd9Sstevel@tonic-gate if (nvlist_lookup_byte((*filter)->nvlist, 74847c478bd9Sstevel@tonic-gate IPGPC_FILTER_TYPE, &b) == 0) { 74857c478bd9Sstevel@tonic-gate if (v4 && b != IPGPC_V4_FLTR || 74867c478bd9Sstevel@tonic-gate v6 && b != IPGPC_V6_FLTR) { 74877c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 74887c478bd9Sstevel@tonic-gate gettext("Incompatible " 74897c478bd9Sstevel@tonic-gate "address version line " 74907c478bd9Sstevel@tonic-gate "%u.\n"), lineno); 74917c478bd9Sstevel@tonic-gate goto fail; 74927c478bd9Sstevel@tonic-gate } 74937c478bd9Sstevel@tonic-gate } 74947c478bd9Sstevel@tonic-gate 74957c478bd9Sstevel@tonic-gate /* 74967c478bd9Sstevel@tonic-gate * check that if ip_version spec'd it 74977c478bd9Sstevel@tonic-gate * corresponds. 74987c478bd9Sstevel@tonic-gate */ 74997c478bd9Sstevel@tonic-gate if ((*filter)->ip_versions != 0) { 75007c478bd9Sstevel@tonic-gate if (v4 && !VERSION_IS_V4(*filter) || 75017c478bd9Sstevel@tonic-gate v6 && !VERSION_IS_V6(*filter)) { 75027c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 75037c478bd9Sstevel@tonic-gate gettext("Incompatible " 75047c478bd9Sstevel@tonic-gate "address version line %u" 75057c478bd9Sstevel@tonic-gate ".\n"), lineno); 75067c478bd9Sstevel@tonic-gate goto fail; 75077c478bd9Sstevel@tonic-gate } 75087c478bd9Sstevel@tonic-gate } 75097c478bd9Sstevel@tonic-gate 75107c478bd9Sstevel@tonic-gate /* add the address type */ 75117c478bd9Sstevel@tonic-gate 75127c478bd9Sstevel@tonic-gate res = nvlist_add_byte( 75137c478bd9Sstevel@tonic-gate (*filter)->nvlist, IPGPC_FILTER_TYPE, 75147c478bd9Sstevel@tonic-gate v4 ? IPGPC_V4_FLTR : IPGPC_V6_FLTR); 75157c478bd9Sstevel@tonic-gate if (res != 0) { 75167c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 75177c478bd9Sstevel@tonic-gate "nvlist_add_byte"); 75187c478bd9Sstevel@tonic-gate goto fail; 75197c478bd9Sstevel@tonic-gate } 75207c478bd9Sstevel@tonic-gate 75217c478bd9Sstevel@tonic-gate /* add address to list */ 75227c478bd9Sstevel@tonic-gate 75237c478bd9Sstevel@tonic-gate res = nvlist_add_uint32_array((*filter)->nvlist, 75247c478bd9Sstevel@tonic-gate sa ? IPGPC_SADDR : IPGPC_DADDR, 75257c478bd9Sstevel@tonic-gate (uint32_t *)&v6addr, 4); 75267c478bd9Sstevel@tonic-gate if (res != 0) { 75277c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 75287c478bd9Sstevel@tonic-gate "nvlist_add_uint32_array"); 75297c478bd9Sstevel@tonic-gate goto fail; 75307c478bd9Sstevel@tonic-gate } 75317c478bd9Sstevel@tonic-gate 75327c478bd9Sstevel@tonic-gate 75337c478bd9Sstevel@tonic-gate /* 75347c478bd9Sstevel@tonic-gate * add mask entry in list. 75357c478bd9Sstevel@tonic-gate */ 75367c478bd9Sstevel@tonic-gate 75377c478bd9Sstevel@tonic-gate if (sl) { /* have CIDR mask */ 75387c478bd9Sstevel@tonic-gate char *lo; 75397c478bd9Sstevel@tonic-gate res = readuint8(sl, &mlen, &lo); 75407c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS || 75417c478bd9Sstevel@tonic-gate v4 && mlen > 32 || 75427c478bd9Sstevel@tonic-gate !v4 && mlen > 128 || 75437c478bd9Sstevel@tonic-gate mlen == 0) { 75447c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 75457c478bd9Sstevel@tonic-gate gettext("Invalid CIDR " 75467c478bd9Sstevel@tonic-gate "mask line %u.\n"), lineno); 75477c478bd9Sstevel@tonic-gate goto fail; 75487c478bd9Sstevel@tonic-gate } 75497c478bd9Sstevel@tonic-gate setmask(mlen, &mask, 75507c478bd9Sstevel@tonic-gate v4 ? AF_INET : AF_INET6); 75517c478bd9Sstevel@tonic-gate free(sl); 75527c478bd9Sstevel@tonic-gate } else { 75537c478bd9Sstevel@tonic-gate /* no CIDR mask spec'd - use all 1s */ 75547c478bd9Sstevel@tonic-gate 75557c478bd9Sstevel@tonic-gate (void) memset(&mask, ~0, 75567c478bd9Sstevel@tonic-gate sizeof (in6_addr_t)); 75577c478bd9Sstevel@tonic-gate } 75587c478bd9Sstevel@tonic-gate res = nvlist_add_uint32_array((*filter)->nvlist, 75597c478bd9Sstevel@tonic-gate sa ? IPGPC_SADDR_MASK : IPGPC_DADDR_MASK, 75607c478bd9Sstevel@tonic-gate (uint32_t *)&mask, 4); 75617c478bd9Sstevel@tonic-gate if (res != 0) { 75627c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 75637c478bd9Sstevel@tonic-gate "nvlist_add_uint32_arr"); 75647c478bd9Sstevel@tonic-gate goto fail; 75657c478bd9Sstevel@tonic-gate } 75667c478bd9Sstevel@tonic-gate 75677c478bd9Sstevel@tonic-gate /* inet_pton returns fail - we assume a node name */ 75687c478bd9Sstevel@tonic-gate 75697c478bd9Sstevel@tonic-gate } else { 75707c478bd9Sstevel@tonic-gate /* 75717c478bd9Sstevel@tonic-gate * doesn't make sense to have a mask 75727c478bd9Sstevel@tonic-gate * with a node name. 75737c478bd9Sstevel@tonic-gate */ 75747c478bd9Sstevel@tonic-gate if (sl) { 75757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 75767c478bd9Sstevel@tonic-gate gettext("Address masks aren't " 75777c478bd9Sstevel@tonic-gate "allowed for host names line " 75787c478bd9Sstevel@tonic-gate "%u.\n"), lineno); 75797c478bd9Sstevel@tonic-gate goto fail; 75807c478bd9Sstevel@tonic-gate } 75817c478bd9Sstevel@tonic-gate 75827c478bd9Sstevel@tonic-gate /* 75837c478bd9Sstevel@tonic-gate * store node name in filter struct for 75847c478bd9Sstevel@tonic-gate * later resolution. 75857c478bd9Sstevel@tonic-gate */ 75867c478bd9Sstevel@tonic-gate if (sa) { 75877c478bd9Sstevel@tonic-gate (*filter)->src_nd_name = 75887c478bd9Sstevel@tonic-gate malloc(strlen(addr_str) + 1); 75897c478bd9Sstevel@tonic-gate (void) strcpy((*filter)->src_nd_name, 75907c478bd9Sstevel@tonic-gate addr_str); 75917c478bd9Sstevel@tonic-gate } else { 75927c478bd9Sstevel@tonic-gate (*filter)->dst_nd_name = 75937c478bd9Sstevel@tonic-gate malloc(strlen(addr_str) + 1); 75947c478bd9Sstevel@tonic-gate (void) strcpy((*filter)->dst_nd_name, 75957c478bd9Sstevel@tonic-gate addr_str); 75967c478bd9Sstevel@tonic-gate } 75977c478bd9Sstevel@tonic-gate } 75987c478bd9Sstevel@tonic-gate 75997c478bd9Sstevel@tonic-gate /* ip_version enumeration */ 76007c478bd9Sstevel@tonic-gate 76017c478bd9Sstevel@tonic-gate } else if (strcmp(nvpair_name(nvp), IPQOS_CONF_IP_VERSION) == 76027c478bd9Sstevel@tonic-gate 0) { 76037c478bd9Sstevel@tonic-gate /* check we haven't read ip_version before */ 76047c478bd9Sstevel@tonic-gate if (ipv) { 76057c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 76067c478bd9Sstevel@tonic-gate gettext("Duplicate parameter line %u.\n"), 76077c478bd9Sstevel@tonic-gate lineno); 76087c478bd9Sstevel@tonic-gate goto fail; 76097c478bd9Sstevel@tonic-gate } 76107c478bd9Sstevel@tonic-gate ipv++; 76117c478bd9Sstevel@tonic-gate 76127c478bd9Sstevel@tonic-gate /* get bitmask value */ 76137c478bd9Sstevel@tonic-gate 76147c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, 76157c478bd9Sstevel@tonic-gate &(*filter)->ip_versions); 76167c478bd9Sstevel@tonic-gate 76177c478bd9Sstevel@tonic-gate /* 76187c478bd9Sstevel@tonic-gate * check that if either ip address is spec'd it 76197c478bd9Sstevel@tonic-gate * corresponds. 76207c478bd9Sstevel@tonic-gate */ 76217c478bd9Sstevel@tonic-gate if (v4 && !VERSION_IS_V4(*filter) || 76227c478bd9Sstevel@tonic-gate v6 && !VERSION_IS_V6(*filter)) { 76237c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Incompatible " 76247c478bd9Sstevel@tonic-gate "address version line %u.\n"), lineno); 76257c478bd9Sstevel@tonic-gate goto fail; 76267c478bd9Sstevel@tonic-gate } 76277c478bd9Sstevel@tonic-gate 76287c478bd9Sstevel@tonic-gate /* remove ip_version from nvlist */ 76297c478bd9Sstevel@tonic-gate 76307c478bd9Sstevel@tonic-gate (void) nvlist_remove_all((*filter)->nvlist, 76317c478bd9Sstevel@tonic-gate IPQOS_CONF_IP_VERSION); 76327c478bd9Sstevel@tonic-gate } 76337c478bd9Sstevel@tonic-gate } 76347c478bd9Sstevel@tonic-gate if (nm == 0 || cls == 0) { 76357c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Missing filter/class name " 76367c478bd9Sstevel@tonic-gate "before line %u.\n"), lineno); 76377c478bd9Sstevel@tonic-gate goto fail; 76387c478bd9Sstevel@tonic-gate } 76397c478bd9Sstevel@tonic-gate 76407c478bd9Sstevel@tonic-gate if (in_string_table(perm_filters, num_perm_filters, (*filter)->name)) { 76417c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "Setting filter %s as permanent.\n", 76427c478bd9Sstevel@tonic-gate (*filter)->name); 76437c478bd9Sstevel@tonic-gate 76447c478bd9Sstevel@tonic-gate (*filter)->originator = IPP_CONFIG_PERMANENT; 76457c478bd9Sstevel@tonic-gate } 76467c478bd9Sstevel@tonic-gate 76477c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 76487c478bd9Sstevel@tonic-gate fail: 76497c478bd9Sstevel@tonic-gate if (*filter) 76507c478bd9Sstevel@tonic-gate free_filter(*filter); 76517c478bd9Sstevel@tonic-gate if (hp) 76527c478bd9Sstevel@tonic-gate freehostent(hp); 76537c478bd9Sstevel@tonic-gate if (sl) 76547c478bd9Sstevel@tonic-gate free(sl); 76557c478bd9Sstevel@tonic-gate 76567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 76577c478bd9Sstevel@tonic-gate } 76587c478bd9Sstevel@tonic-gate 76597c478bd9Sstevel@tonic-gate /* 76607c478bd9Sstevel@tonic-gate * reads the curl begin token from cfp stream. 76617c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if not read successfully, else IPQOS_CONF_SUCCES. 76627c478bd9Sstevel@tonic-gate */ 76637c478bd9Sstevel@tonic-gate static int 76647c478bd9Sstevel@tonic-gate read_curl_begin(FILE *cfp) 76657c478bd9Sstevel@tonic-gate { 76667c478bd9Sstevel@tonic-gate 76677c478bd9Sstevel@tonic-gate int res; 76687c478bd9Sstevel@tonic-gate char *st; 76697c478bd9Sstevel@tonic-gate 76707c478bd9Sstevel@tonic-gate res = readtoken(cfp, &st); 76717c478bd9Sstevel@tonic-gate 76727c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_CURL_BEGIN) { 76737c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_EOF) { 76747c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n")); 76757c478bd9Sstevel@tonic-gate 76767c478bd9Sstevel@tonic-gate /* if CURL_END or something else */ 76777c478bd9Sstevel@tonic-gate } else if (res != IPQOS_CONF_ERR) { 76787c478bd9Sstevel@tonic-gate free(st); 76797c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("\'{\' missing at line " 76807c478bd9Sstevel@tonic-gate "%u.\n"), lineno); 76817c478bd9Sstevel@tonic-gate } 76827c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 76837c478bd9Sstevel@tonic-gate } 76847c478bd9Sstevel@tonic-gate 76857c478bd9Sstevel@tonic-gate free(st); 76867c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 76877c478bd9Sstevel@tonic-gate } 76887c478bd9Sstevel@tonic-gate 76897c478bd9Sstevel@tonic-gate /* 76907c478bd9Sstevel@tonic-gate * This function parses the parameter string version into a version of the 76917c478bd9Sstevel@tonic-gate * form "%u.%u" (as a sscanf format string). It then encodes this into an 76927c478bd9Sstevel@tonic-gate * int and returns this encoding. 76937c478bd9Sstevel@tonic-gate * RETURNS: -1 if an invalid string, else the integer encoding. 76947c478bd9Sstevel@tonic-gate */ 76957c478bd9Sstevel@tonic-gate static int 76967c478bd9Sstevel@tonic-gate ver_str_to_int( 76977c478bd9Sstevel@tonic-gate char *version) 76987c478bd9Sstevel@tonic-gate { 76997c478bd9Sstevel@tonic-gate uint32_t major, minor; 77007c478bd9Sstevel@tonic-gate int ver; 77017c478bd9Sstevel@tonic-gate 77027c478bd9Sstevel@tonic-gate if (sscanf(version, "%u.%u", &major, &minor) != 2) { 77037c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "Failed to process version number string\n"); 77047c478bd9Sstevel@tonic-gate return (-1); 77057c478bd9Sstevel@tonic-gate } 77067c478bd9Sstevel@tonic-gate 77077c478bd9Sstevel@tonic-gate ver = (int)((major * 10000) + minor); 77087c478bd9Sstevel@tonic-gate return (ver); 77097c478bd9Sstevel@tonic-gate } 77107c478bd9Sstevel@tonic-gate 77117c478bd9Sstevel@tonic-gate /* 77127c478bd9Sstevel@tonic-gate * This function scans through the stream fp line by line looking for 77137c478bd9Sstevel@tonic-gate * a line beginning with version_tag and returns a integer encoding of 77147c478bd9Sstevel@tonic-gate * the version following it. 77157c478bd9Sstevel@tonic-gate * 77167c478bd9Sstevel@tonic-gate * RETURNS: If the version definition isn't found or the version is not 77177c478bd9Sstevel@tonic-gate * a valid version (%u.%u) then -1 is returned, else an integer encoding 77187c478bd9Sstevel@tonic-gate * of the read version. 77197c478bd9Sstevel@tonic-gate */ 77207c478bd9Sstevel@tonic-gate static int 77217c478bd9Sstevel@tonic-gate read_tfile_ver( 77227c478bd9Sstevel@tonic-gate FILE *fp, 77237c478bd9Sstevel@tonic-gate char *version_tag, 77247c478bd9Sstevel@tonic-gate char *module_name) 77257c478bd9Sstevel@tonic-gate { 77267c478bd9Sstevel@tonic-gate char lbuf[IPQOS_CONF_LINEBUF_SZ]; 77277c478bd9Sstevel@tonic-gate char buf[IPQOS_CONF_LINEBUF_SZ+1]; 77287c478bd9Sstevel@tonic-gate char buf2[IPQOS_CONF_LINEBUF_SZ+1]; 77297c478bd9Sstevel@tonic-gate int found = 0; 77307c478bd9Sstevel@tonic-gate int version; 77317c478bd9Sstevel@tonic-gate 77327c478bd9Sstevel@tonic-gate /* 77337c478bd9Sstevel@tonic-gate * reset to file start 77347c478bd9Sstevel@tonic-gate */ 77357c478bd9Sstevel@tonic-gate if (fseek(fp, 0, SEEK_SET) != 0) { 77367c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fseek"); 77377c478bd9Sstevel@tonic-gate return (-1); 77387c478bd9Sstevel@tonic-gate } 77397c478bd9Sstevel@tonic-gate 77407c478bd9Sstevel@tonic-gate /* 77417c478bd9Sstevel@tonic-gate * loop reading lines till found the one beginning with version_tag. 77427c478bd9Sstevel@tonic-gate */ 77437c478bd9Sstevel@tonic-gate while (fgets(lbuf, IPQOS_CONF_LINEBUF_SZ, fp) != NULL) { 77447c478bd9Sstevel@tonic-gate if ((sscanf(lbuf, 77457c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_LINEBUF_SZ) "s" 77467c478bd9Sstevel@tonic-gate "%" VAL2STR(IPQOS_CONF_LINEBUF_SZ) "s", 77477c478bd9Sstevel@tonic-gate buf, buf2) == 2) && 77487c478bd9Sstevel@tonic-gate (strcmp(buf, version_tag) == 0)) { 77497c478bd9Sstevel@tonic-gate found++; 77507c478bd9Sstevel@tonic-gate break; 77517c478bd9Sstevel@tonic-gate } 77527c478bd9Sstevel@tonic-gate } 77537c478bd9Sstevel@tonic-gate if (found == 0) { 77547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Types file for module %s is " 77557c478bd9Sstevel@tonic-gate "corrupt.\n"), module_name); 77567c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "Couldn't find %s in types file\n", 77577c478bd9Sstevel@tonic-gate version_tag); 77587c478bd9Sstevel@tonic-gate return (-1); 77597c478bd9Sstevel@tonic-gate } 77607c478bd9Sstevel@tonic-gate 77617c478bd9Sstevel@tonic-gate /* 77627c478bd9Sstevel@tonic-gate * convert version string into int. 77637c478bd9Sstevel@tonic-gate */ 77647c478bd9Sstevel@tonic-gate if ((version = ver_str_to_int(buf2)) == -1) { 77657c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Types file for module %s is " 77667c478bd9Sstevel@tonic-gate "corrupt.\n"), module_name); 77677c478bd9Sstevel@tonic-gate return (-1); 77687c478bd9Sstevel@tonic-gate } 77697c478bd9Sstevel@tonic-gate 77707c478bd9Sstevel@tonic-gate return (version); 77717c478bd9Sstevel@tonic-gate } 77727c478bd9Sstevel@tonic-gate 77737c478bd9Sstevel@tonic-gate /* 77747c478bd9Sstevel@tonic-gate * read action clause and params/classes/filters clauses within and 77757c478bd9Sstevel@tonic-gate * store in and hang off an action structure, and point action at it. 77767c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 77777c478bd9Sstevel@tonic-gate */ 77787c478bd9Sstevel@tonic-gate static int 77797c478bd9Sstevel@tonic-gate readaction( 77807c478bd9Sstevel@tonic-gate FILE *cfp, 77817c478bd9Sstevel@tonic-gate ipqos_conf_action_t **action) 77827c478bd9Sstevel@tonic-gate { 77837c478bd9Sstevel@tonic-gate 77847c478bd9Sstevel@tonic-gate char *st; 77857c478bd9Sstevel@tonic-gate FILE *tfp = NULL; 77867c478bd9Sstevel@tonic-gate int nm, md; 77877c478bd9Sstevel@tonic-gate int readprms = 0; 77887c478bd9Sstevel@tonic-gate int res; 77897c478bd9Sstevel@tonic-gate char *strval; 77907c478bd9Sstevel@tonic-gate char *name; 77917c478bd9Sstevel@tonic-gate nvpair_t *nvp; 77927c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 77937c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter; 77947c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class; 77957c478bd9Sstevel@tonic-gate int oe; 77967c478bd9Sstevel@tonic-gate char **perm_filters; 77977c478bd9Sstevel@tonic-gate int num_perm_filters; 77987c478bd9Sstevel@tonic-gate int tf_fmt_ver; 77997c478bd9Sstevel@tonic-gate 78007c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in readaction\n"); 78017c478bd9Sstevel@tonic-gate 78027c478bd9Sstevel@tonic-gate res = readtoken(cfp, &st); 78037c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR || res == IPQOS_CONF_EOF) { 78047c478bd9Sstevel@tonic-gate return (res); 78057c478bd9Sstevel@tonic-gate } else if (strcmp(st, IPQOS_CONF_ACTION_STR) != 0) { 78067c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Missing %s token line " 78077c478bd9Sstevel@tonic-gate "%u.\n"), IPQOS_CONF_ACTION_STR, lineno); 78087c478bd9Sstevel@tonic-gate free(st); 78097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 78107c478bd9Sstevel@tonic-gate } 78117c478bd9Sstevel@tonic-gate free(st); 78127c478bd9Sstevel@tonic-gate 78137c478bd9Sstevel@tonic-gate /* create action structure */ 78147c478bd9Sstevel@tonic-gate 78157c478bd9Sstevel@tonic-gate *action = alloc_action(); 78167c478bd9Sstevel@tonic-gate if (*action == NULL) { 78177c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 78187c478bd9Sstevel@tonic-gate } 78197c478bd9Sstevel@tonic-gate (*action)->params->originator = IPP_CONFIG_IPQOSCONF; 78207c478bd9Sstevel@tonic-gate 78217c478bd9Sstevel@tonic-gate 78227c478bd9Sstevel@tonic-gate /* get starting line for error reporting */ 78237c478bd9Sstevel@tonic-gate (*action)->lineno = lineno; 78247c478bd9Sstevel@tonic-gate 78257c478bd9Sstevel@tonic-gate /* read beginning curl */ 78267c478bd9Sstevel@tonic-gate 78277c478bd9Sstevel@tonic-gate res = read_curl_begin(cfp); 78287c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 78297c478bd9Sstevel@tonic-gate goto fail; 78307c478bd9Sstevel@tonic-gate } 78317c478bd9Sstevel@tonic-gate 78327c478bd9Sstevel@tonic-gate /* loop till read both action name and module */ 78337c478bd9Sstevel@tonic-gate 78347c478bd9Sstevel@tonic-gate nm = md = 0; 78357c478bd9Sstevel@tonic-gate do { 78367c478bd9Sstevel@tonic-gate /* read nvpair */ 78377c478bd9Sstevel@tonic-gate 78387c478bd9Sstevel@tonic-gate res = readnvpair(cfp, NULL, &(*action)->nvlist, &nvp, &type, 78397c478bd9Sstevel@tonic-gate PL_ACTION, NULL); 78407c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR) { 78417c478bd9Sstevel@tonic-gate goto fail; 78427c478bd9Sstevel@tonic-gate 78437c478bd9Sstevel@tonic-gate /* read curl_end */ 78447c478bd9Sstevel@tonic-gate 78457c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 78467c478bd9Sstevel@tonic-gate if (nm == 0 || md == 0) { 78477c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 78487c478bd9Sstevel@tonic-gate gettext("Missing action name/ module " 78497c478bd9Sstevel@tonic-gate "before line %u.\n"), lineno); 78507c478bd9Sstevel@tonic-gate goto fail; 78517c478bd9Sstevel@tonic-gate } 78527c478bd9Sstevel@tonic-gate } 78537c478bd9Sstevel@tonic-gate 78547c478bd9Sstevel@tonic-gate 78557c478bd9Sstevel@tonic-gate /* store name and module in action structure */ 78567c478bd9Sstevel@tonic-gate 78577c478bd9Sstevel@tonic-gate name = nvpair_name(nvp); 78587c478bd9Sstevel@tonic-gate 78597c478bd9Sstevel@tonic-gate /* read action name */ 78607c478bd9Sstevel@tonic-gate 78617c478bd9Sstevel@tonic-gate if (nm == 0 && strcmp(name, IPQOS_CONF_NAME_STR) == 0) { 78627c478bd9Sstevel@tonic-gate 78637c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &strval); 78647c478bd9Sstevel@tonic-gate 78657c478bd9Sstevel@tonic-gate /* check name is valid */ 78667c478bd9Sstevel@tonic-gate 78677c478bd9Sstevel@tonic-gate if (valid_name(strval) != IPQOS_CONF_SUCCESS || 78687c478bd9Sstevel@tonic-gate valid_aname(strval) != IPQOS_CONF_SUCCESS) { 78697c478bd9Sstevel@tonic-gate goto fail; 78707c478bd9Sstevel@tonic-gate } 78717c478bd9Sstevel@tonic-gate 78727c478bd9Sstevel@tonic-gate /* store and remove from list */ 78737c478bd9Sstevel@tonic-gate 78747c478bd9Sstevel@tonic-gate (void) strcpy((*action)->name, strval); 78757c478bd9Sstevel@tonic-gate /* remove name from nvlist */ 78767c478bd9Sstevel@tonic-gate (void) nvlist_remove_all((*action)->nvlist, 78777c478bd9Sstevel@tonic-gate IPQOS_CONF_NAME_STR); 78787c478bd9Sstevel@tonic-gate 78797c478bd9Sstevel@tonic-gate nm++; 78807c478bd9Sstevel@tonic-gate 78817c478bd9Sstevel@tonic-gate /* read module name */ 78827c478bd9Sstevel@tonic-gate 78837c478bd9Sstevel@tonic-gate } else if (md == 0 && 78847c478bd9Sstevel@tonic-gate strcmp(name, IPQOS_CONF_MODULE_STR) == 0) { 78857c478bd9Sstevel@tonic-gate /* 78867c478bd9Sstevel@tonic-gate * check that module has a type file and get 78877c478bd9Sstevel@tonic-gate * open stream to it. 78887c478bd9Sstevel@tonic-gate */ 78897c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &strval); 78907c478bd9Sstevel@tonic-gate if ((tfp = validmod(strval, &oe)) == NULL) { 78917c478bd9Sstevel@tonic-gate if (oe) { 78927c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 78937c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 78947c478bd9Sstevel@tonic-gate gettext("Invalid " 78957c478bd9Sstevel@tonic-gate "module name line %u.\n"), 78967c478bd9Sstevel@tonic-gate lineno); 78977c478bd9Sstevel@tonic-gate } else { 78987c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 78997c478bd9Sstevel@tonic-gate } 79007c478bd9Sstevel@tonic-gate } 79017c478bd9Sstevel@tonic-gate goto fail; 79027c478bd9Sstevel@tonic-gate } 79037c478bd9Sstevel@tonic-gate 79047c478bd9Sstevel@tonic-gate /* 79057c478bd9Sstevel@tonic-gate * move module name to action struct 79067c478bd9Sstevel@tonic-gate */ 79077c478bd9Sstevel@tonic-gate (void) strlcpy((*action)->module, strval, 79087c478bd9Sstevel@tonic-gate IPQOS_CONF_NAME_LEN); 79097c478bd9Sstevel@tonic-gate (void) nvlist_remove_all((*action)->nvlist, 79107c478bd9Sstevel@tonic-gate IPQOS_CONF_MODULE_STR); 79117c478bd9Sstevel@tonic-gate md++; 79127c478bd9Sstevel@tonic-gate 79137c478bd9Sstevel@tonic-gate /* duplicate/other parameter */ 79147c478bd9Sstevel@tonic-gate 79157c478bd9Sstevel@tonic-gate } else { 79167c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 79177c478bd9Sstevel@tonic-gate gettext("Unexpected parameter line %u.\n"), 79187c478bd9Sstevel@tonic-gate lineno); 79197c478bd9Sstevel@tonic-gate goto fail; 79207c478bd9Sstevel@tonic-gate } 79217c478bd9Sstevel@tonic-gate 79227c478bd9Sstevel@tonic-gate } while (nm == 0 || md == 0); 79237c478bd9Sstevel@tonic-gate 79247c478bd9Sstevel@tonic-gate /* 79257c478bd9Sstevel@tonic-gate * check that if the ipgpc action it is named correctly 79267c478bd9Sstevel@tonic-gate */ 79277c478bd9Sstevel@tonic-gate if ((strcmp((*action)->module, IPGPC_NAME) == 0) && 79287c478bd9Sstevel@tonic-gate (strcmp((*action)->name, IPGPC_CLASSIFY) != 0)) { 79297c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 79307c478bd9Sstevel@tonic-gate gettext("%s action has incorrect name line %u.\n"), 79317c478bd9Sstevel@tonic-gate IPGPC_NAME, (*action)->lineno); 79327c478bd9Sstevel@tonic-gate goto fail; 79337c478bd9Sstevel@tonic-gate } 79347c478bd9Sstevel@tonic-gate 79357c478bd9Sstevel@tonic-gate /* get list of permanent classes */ 79367c478bd9Sstevel@tonic-gate 79377c478bd9Sstevel@tonic-gate res = read_perm_items(0, tfp, (*action)->module, 79387c478bd9Sstevel@tonic-gate &(*action)->perm_classes, &(*action)->num_perm_classes); 79397c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 79407c478bd9Sstevel@tonic-gate goto fail; 79417c478bd9Sstevel@tonic-gate } 79427c478bd9Sstevel@tonic-gate 79437c478bd9Sstevel@tonic-gate /* get list of permanent filters */ 79447c478bd9Sstevel@tonic-gate 79457c478bd9Sstevel@tonic-gate res = read_perm_items(1, tfp, (*action)->module, 79467c478bd9Sstevel@tonic-gate &perm_filters, &num_perm_filters); 79477c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 79487c478bd9Sstevel@tonic-gate goto fail; 79497c478bd9Sstevel@tonic-gate } 79507c478bd9Sstevel@tonic-gate 79517c478bd9Sstevel@tonic-gate /* 79527c478bd9Sstevel@tonic-gate * get types file format version and check its supported. 79537c478bd9Sstevel@tonic-gate */ 79547c478bd9Sstevel@tonic-gate if ((tf_fmt_ver = read_tfile_ver(tfp, IPQOS_FMT_STR, 79557c478bd9Sstevel@tonic-gate (*action)->module)) == -1) 79567c478bd9Sstevel@tonic-gate goto fail; 79577c478bd9Sstevel@tonic-gate if (IPP_MAJOR_MODULE_VER(tf_fmt_ver) > 1 || 79587c478bd9Sstevel@tonic-gate IPP_MINOR_MODULE_VER(tf_fmt_ver) > 0) { 79597c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Types file for module %s is " 79607c478bd9Sstevel@tonic-gate "incompatible.\n"), (*action)->module); 79617c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "Unsupported fmt major/minor version\n"); 79627c478bd9Sstevel@tonic-gate goto fail; 79637c478bd9Sstevel@tonic-gate } 79647c478bd9Sstevel@tonic-gate 79657c478bd9Sstevel@tonic-gate /* 79667c478bd9Sstevel@tonic-gate * get module version 79677c478bd9Sstevel@tonic-gate */ 79687c478bd9Sstevel@tonic-gate if (((*action)->module_version = read_tfile_ver(tfp, IPQOS_MOD_STR, 79697c478bd9Sstevel@tonic-gate (*action)->module)) == -1) 79707c478bd9Sstevel@tonic-gate goto fail; 79717c478bd9Sstevel@tonic-gate 79727c478bd9Sstevel@tonic-gate /* read filter/class/params blocks until CURL_END */ 79737c478bd9Sstevel@tonic-gate 79747c478bd9Sstevel@tonic-gate for (;;) { 79757c478bd9Sstevel@tonic-gate /* read token */ 79767c478bd9Sstevel@tonic-gate res = readtoken(cfp, &st); 79777c478bd9Sstevel@tonic-gate 79787c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR) { 79797c478bd9Sstevel@tonic-gate goto fail; 79807c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_EOF) { 79817c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Unexpected EOF.\n")); 79827c478bd9Sstevel@tonic-gate goto fail; 79837c478bd9Sstevel@tonic-gate 79847c478bd9Sstevel@tonic-gate /* read CURL_END - end of action definition */ 79857c478bd9Sstevel@tonic-gate 79867c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_CURL_END) { 79877c478bd9Sstevel@tonic-gate free(st); 79887c478bd9Sstevel@tonic-gate break; 79897c478bd9Sstevel@tonic-gate } 79907c478bd9Sstevel@tonic-gate 79917c478bd9Sstevel@tonic-gate 79927c478bd9Sstevel@tonic-gate /* 79937c478bd9Sstevel@tonic-gate * read in either a filter/class or parameter block. 79947c478bd9Sstevel@tonic-gate */ 79957c478bd9Sstevel@tonic-gate 79967c478bd9Sstevel@tonic-gate /* read filter */ 79977c478bd9Sstevel@tonic-gate 79987c478bd9Sstevel@tonic-gate if (strcmp(st, IPQOS_CONF_FILTER_STR) == 0) { 79997c478bd9Sstevel@tonic-gate free(st); 80007c478bd9Sstevel@tonic-gate 80017c478bd9Sstevel@tonic-gate res = readfilter(cfp, tfp, (*action)->module, &filter, 80027c478bd9Sstevel@tonic-gate perm_filters, num_perm_filters); 80037c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 80047c478bd9Sstevel@tonic-gate goto fail; 80057c478bd9Sstevel@tonic-gate } 80067c478bd9Sstevel@tonic-gate 80077c478bd9Sstevel@tonic-gate /* 80087c478bd9Sstevel@tonic-gate * if we read a host name for either src or dst addr 80097c478bd9Sstevel@tonic-gate * resolve the hostnames and create the appropriate 80107c478bd9Sstevel@tonic-gate * number of filters. 80117c478bd9Sstevel@tonic-gate */ 80127c478bd9Sstevel@tonic-gate 80137c478bd9Sstevel@tonic-gate if (filter->src_nd_name || filter->dst_nd_name) { 80147c478bd9Sstevel@tonic-gate 80157c478bd9Sstevel@tonic-gate res = domultihome(filter, &(*action)->filters, 80167c478bd9Sstevel@tonic-gate B_FALSE); 80177c478bd9Sstevel@tonic-gate /* 80187c478bd9Sstevel@tonic-gate * if a lookup fails and the filters 80197c478bd9Sstevel@tonic-gate * marked as retry we add it to a list 80207c478bd9Sstevel@tonic-gate * for another attempt later, otherwise 80217c478bd9Sstevel@tonic-gate * it is thrown away. 80227c478bd9Sstevel@tonic-gate */ 80237c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 80247c478bd9Sstevel@tonic-gate 80257c478bd9Sstevel@tonic-gate /* if not name lookup problem */ 80267c478bd9Sstevel@tonic-gate 80277c478bd9Sstevel@tonic-gate if (filter->nlerr == 0) { 80287c478bd9Sstevel@tonic-gate free_filter(filter); 80297c478bd9Sstevel@tonic-gate goto fail; 80307c478bd9Sstevel@tonic-gate 80317c478bd9Sstevel@tonic-gate /* name lookup problem */ 80327c478bd9Sstevel@tonic-gate 80337c478bd9Sstevel@tonic-gate /* 80347c478bd9Sstevel@tonic-gate * if intermitent lookup failure 80357c478bd9Sstevel@tonic-gate * add to list of filters to 80367c478bd9Sstevel@tonic-gate * retry later. 80377c478bd9Sstevel@tonic-gate */ 80387c478bd9Sstevel@tonic-gate } else if (filter->nlerr == 80397c478bd9Sstevel@tonic-gate IPQOS_LOOKUP_RETRY) { 80407c478bd9Sstevel@tonic-gate filter->nlerr = 0; 80417c478bd9Sstevel@tonic-gate ADD_TO_LIST( 80427c478bd9Sstevel@tonic-gate &(*action)->retry_filters, 80437c478bd9Sstevel@tonic-gate filter); 80447c478bd9Sstevel@tonic-gate /* 80457c478bd9Sstevel@tonic-gate * for non-existing names 80467c478bd9Sstevel@tonic-gate * ignore the filter. 80477c478bd9Sstevel@tonic-gate */ 80487c478bd9Sstevel@tonic-gate } else { 80497c478bd9Sstevel@tonic-gate free_filter(filter); 80507c478bd9Sstevel@tonic-gate } 80517c478bd9Sstevel@tonic-gate 80527c478bd9Sstevel@tonic-gate /* creation of new filters successful */ 80537c478bd9Sstevel@tonic-gate 80547c478bd9Sstevel@tonic-gate } else { 80557c478bd9Sstevel@tonic-gate free_filter(filter); 80567c478bd9Sstevel@tonic-gate } 80577c478bd9Sstevel@tonic-gate 80587c478bd9Sstevel@tonic-gate /* non-node name filter */ 80597c478bd9Sstevel@tonic-gate 80607c478bd9Sstevel@tonic-gate } else { 80617c478bd9Sstevel@tonic-gate ADD_TO_LIST(&(*action)->filters, filter); 80627c478bd9Sstevel@tonic-gate } 80637c478bd9Sstevel@tonic-gate 80647c478bd9Sstevel@tonic-gate /* read class */ 80657c478bd9Sstevel@tonic-gate 80667c478bd9Sstevel@tonic-gate } else if (strcmp(st, IPQOS_CONF_CLASS_STR) == 0) { 80677c478bd9Sstevel@tonic-gate free(st); 80687c478bd9Sstevel@tonic-gate res = readclass(cfp, (*action)->module, &class, 80697c478bd9Sstevel@tonic-gate (*action)->perm_classes, 80707c478bd9Sstevel@tonic-gate (*action)->num_perm_classes); 80717c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 80727c478bd9Sstevel@tonic-gate goto fail; 80737c478bd9Sstevel@tonic-gate } 80747c478bd9Sstevel@tonic-gate 80757c478bd9Sstevel@tonic-gate ADD_TO_LIST(&(*action)->classes, class); 80767c478bd9Sstevel@tonic-gate 80777c478bd9Sstevel@tonic-gate /* read params */ 80787c478bd9Sstevel@tonic-gate 80797c478bd9Sstevel@tonic-gate } else if (strcmp(st, IPQOS_CONF_PARAMS_STR) == 0) { 80807c478bd9Sstevel@tonic-gate free(st); 80817c478bd9Sstevel@tonic-gate if (readprms) { 80827c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 80837c478bd9Sstevel@tonic-gate gettext("Second parameter clause not " 80847c478bd9Sstevel@tonic-gate "supported line %u.\n"), lineno); 80857c478bd9Sstevel@tonic-gate goto fail; 80867c478bd9Sstevel@tonic-gate } 80877c478bd9Sstevel@tonic-gate res = readparams(cfp, tfp, (*action)->module, 80887c478bd9Sstevel@tonic-gate (*action)->params); 80897c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 80907c478bd9Sstevel@tonic-gate goto fail; 80917c478bd9Sstevel@tonic-gate } 80927c478bd9Sstevel@tonic-gate readprms++; 80937c478bd9Sstevel@tonic-gate 80947c478bd9Sstevel@tonic-gate /* something unexpected */ 80957c478bd9Sstevel@tonic-gate } else { 80967c478bd9Sstevel@tonic-gate free(st); 80977c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 80987c478bd9Sstevel@tonic-gate gettext("Params/filter/class clause expected " 80997c478bd9Sstevel@tonic-gate "line %u.\n"), lineno); 81007c478bd9Sstevel@tonic-gate goto fail; 81017c478bd9Sstevel@tonic-gate } 81027c478bd9Sstevel@tonic-gate } 81037c478bd9Sstevel@tonic-gate 81047c478bd9Sstevel@tonic-gate (void) fclose(tfp); 81057c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 81067c478bd9Sstevel@tonic-gate 81077c478bd9Sstevel@tonic-gate fail: 81087c478bd9Sstevel@tonic-gate if (tfp) 81097c478bd9Sstevel@tonic-gate (void) fclose(tfp); 81107c478bd9Sstevel@tonic-gate if (*action) { 81117c478bd9Sstevel@tonic-gate free_actions(*action); 81127c478bd9Sstevel@tonic-gate *action = NULL; 81137c478bd9Sstevel@tonic-gate } 81147c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 81157c478bd9Sstevel@tonic-gate } 81167c478bd9Sstevel@tonic-gate 81177c478bd9Sstevel@tonic-gate /* 81187c478bd9Sstevel@tonic-gate * check that each of the actions in actions is uniquely named. If one isn't 81197c478bd9Sstevel@tonic-gate * set *name to point at the name of the duplicate action. 81207c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if a non-unique action, else IPQOS_CONF_SUCCESS. 81217c478bd9Sstevel@tonic-gate */ 81227c478bd9Sstevel@tonic-gate static int 81237c478bd9Sstevel@tonic-gate actions_unique(ipqos_conf_action_t *actions, char **name) 81247c478bd9Sstevel@tonic-gate { 81257c478bd9Sstevel@tonic-gate 81267c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In actions_unique.\n"); 81277c478bd9Sstevel@tonic-gate 81287c478bd9Sstevel@tonic-gate while (actions) { 81297c478bd9Sstevel@tonic-gate if (actionexist(actions->name, actions->next)) { 81307c478bd9Sstevel@tonic-gate *name = actions->name; 81317c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 81327c478bd9Sstevel@tonic-gate } 81337c478bd9Sstevel@tonic-gate actions = actions->next; 81347c478bd9Sstevel@tonic-gate } 81357c478bd9Sstevel@tonic-gate 81367c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 81377c478bd9Sstevel@tonic-gate } 81387c478bd9Sstevel@tonic-gate 81397c478bd9Sstevel@tonic-gate /* 81407c478bd9Sstevel@tonic-gate * checks whether the action parameter is involved in an action cycle. 81417c478bd9Sstevel@tonic-gate * RETURNS: 1 if involved in a cycle, 0 otherwise. 81427c478bd9Sstevel@tonic-gate */ 81437c478bd9Sstevel@tonic-gate static int 81447c478bd9Sstevel@tonic-gate in_cycle( 81457c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action) 81467c478bd9Sstevel@tonic-gate { 81477c478bd9Sstevel@tonic-gate 81487c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *aref; 81497c478bd9Sstevel@tonic-gate ipqos_conf_class_t *c; 81507c478bd9Sstevel@tonic-gate 81517c478bd9Sstevel@tonic-gate IPQOSCDBG1(L0, "in_cycle: visiting action %s\n", action->name); 81527c478bd9Sstevel@tonic-gate 81537c478bd9Sstevel@tonic-gate 81547c478bd9Sstevel@tonic-gate /* have we visited this action before? */ 81557c478bd9Sstevel@tonic-gate 81567c478bd9Sstevel@tonic-gate if (action->visited == INCYCLE_VISITED) { 81577c478bd9Sstevel@tonic-gate action->visited = 0; 81587c478bd9Sstevel@tonic-gate return (1); 81597c478bd9Sstevel@tonic-gate } 81607c478bd9Sstevel@tonic-gate action->visited = INCYCLE_VISITED; 81617c478bd9Sstevel@tonic-gate 81627c478bd9Sstevel@tonic-gate /* 81637c478bd9Sstevel@tonic-gate * recurse down the child actions of this action through the 81647c478bd9Sstevel@tonic-gate * classes next action and parameter actions. 81657c478bd9Sstevel@tonic-gate */ 81667c478bd9Sstevel@tonic-gate 81677c478bd9Sstevel@tonic-gate for (aref = action->params->actions; aref != NULL; aref = aref->next) { 81687c478bd9Sstevel@tonic-gate 81697c478bd9Sstevel@tonic-gate /* skip virtual actions - they can't be in a cycle */ 81707c478bd9Sstevel@tonic-gate 81717c478bd9Sstevel@tonic-gate if (virtual_action(aref->name)) { 81727c478bd9Sstevel@tonic-gate continue; 81737c478bd9Sstevel@tonic-gate } 81747c478bd9Sstevel@tonic-gate 81757c478bd9Sstevel@tonic-gate if (in_cycle(aref->action)) { 81767c478bd9Sstevel@tonic-gate action->visited = 0; 81777c478bd9Sstevel@tonic-gate return (1); 81787c478bd9Sstevel@tonic-gate } 81797c478bd9Sstevel@tonic-gate } 81807c478bd9Sstevel@tonic-gate 81817c478bd9Sstevel@tonic-gate for (c = action->classes; c != NULL; c = c->next) { 81827c478bd9Sstevel@tonic-gate aref = c->alist; 81837c478bd9Sstevel@tonic-gate 81847c478bd9Sstevel@tonic-gate if (virtual_action(aref->name)) { 81857c478bd9Sstevel@tonic-gate continue; 81867c478bd9Sstevel@tonic-gate } 81877c478bd9Sstevel@tonic-gate 81887c478bd9Sstevel@tonic-gate if (in_cycle(aref->action)) { 81897c478bd9Sstevel@tonic-gate action->visited = 0; 81907c478bd9Sstevel@tonic-gate return (1); 81917c478bd9Sstevel@tonic-gate } 81927c478bd9Sstevel@tonic-gate } 81937c478bd9Sstevel@tonic-gate 81947c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in_cycle: return\n"); 81957c478bd9Sstevel@tonic-gate action->visited = 0; 81967c478bd9Sstevel@tonic-gate return (0); 81977c478bd9Sstevel@tonic-gate } 81987c478bd9Sstevel@tonic-gate 81997c478bd9Sstevel@tonic-gate /* 82007c478bd9Sstevel@tonic-gate * checks that the configuration in actions is a valid whole, that 82017c478bd9Sstevel@tonic-gate * all actions are unique, all filters and classes are unique within 82027c478bd9Sstevel@tonic-gate * their action, that classes referenced by filters exist and actions 82037c478bd9Sstevel@tonic-gate * referenced by classes and params exist. Also checks that there are no root 82047c478bd9Sstevel@tonic-gate * actions but ipgpc and that no actions are involved in cycles. As 82057c478bd9Sstevel@tonic-gate * a consequence of checking that the actions exist two way pointers 82067c478bd9Sstevel@tonic-gate * are created between the dependee and dependant actions. 82077c478bd9Sstevel@tonic-gate * 82087c478bd9Sstevel@tonic-gate * In the case the the userconf flag is zero only this link creation is 82097c478bd9Sstevel@tonic-gate * set as we trust the kernel to return a valid configuration. 82107c478bd9Sstevel@tonic-gate * 82117c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if config isn't valid, else IPQOS_CONF_SUCCESS. 82127c478bd9Sstevel@tonic-gate * 82137c478bd9Sstevel@tonic-gate */ 82147c478bd9Sstevel@tonic-gate 82157c478bd9Sstevel@tonic-gate static int 82167c478bd9Sstevel@tonic-gate validconf( 82177c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions, 82187c478bd9Sstevel@tonic-gate int userconf) /* are we checking a conf file ? */ 82197c478bd9Sstevel@tonic-gate { 82207c478bd9Sstevel@tonic-gate char *name; 82217c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 82227c478bd9Sstevel@tonic-gate int res; 82237c478bd9Sstevel@tonic-gate ipqos_conf_action_t *dact; 82247c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 82257c478bd9Sstevel@tonic-gate ipqos_conf_class_t *cls; 82267c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params; 82277c478bd9Sstevel@tonic-gate ipqos_conf_act_ref_t *aref; 82287c478bd9Sstevel@tonic-gate 82297c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In validconf\n"); 82307c478bd9Sstevel@tonic-gate 82317c478bd9Sstevel@tonic-gate /* check actions are unique */ 82327c478bd9Sstevel@tonic-gate 82337c478bd9Sstevel@tonic-gate if (userconf && actions_unique(actions, &name) != IPQOS_CONF_SUCCESS) { 82347c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Duplicate named action %s.\n"), 82357c478bd9Sstevel@tonic-gate name); 82367c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 82377c478bd9Sstevel@tonic-gate } 82387c478bd9Sstevel@tonic-gate 82397c478bd9Sstevel@tonic-gate for (act = actions; act; act = act->next) { 82407c478bd9Sstevel@tonic-gate 82417c478bd9Sstevel@tonic-gate /* 82427c478bd9Sstevel@tonic-gate * check filters (for user land configs only). 82437c478bd9Sstevel@tonic-gate * check they are unique in this action and their class exists. 82447c478bd9Sstevel@tonic-gate */ 82457c478bd9Sstevel@tonic-gate if (userconf) { 82467c478bd9Sstevel@tonic-gate for (flt = act->filters; flt; flt = flt->next) { 82477c478bd9Sstevel@tonic-gate 82487c478bd9Sstevel@tonic-gate /* check unique name */ 82497c478bd9Sstevel@tonic-gate 82507c478bd9Sstevel@tonic-gate if (filterexist(flt->name, flt->instance, 82517c478bd9Sstevel@tonic-gate flt->next)) { 82527c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 82537c478bd9Sstevel@tonic-gate gettext("Duplicate named filter " 82547c478bd9Sstevel@tonic-gate "%s in action %s.\n"), flt->name, 82557c478bd9Sstevel@tonic-gate act->name); 82567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 82577c478bd9Sstevel@tonic-gate } 82587c478bd9Sstevel@tonic-gate 82597c478bd9Sstevel@tonic-gate /* 82607c478bd9Sstevel@tonic-gate * check existence of class and error if 82617c478bd9Sstevel@tonic-gate * class doesn't exist and not a perm class 82627c478bd9Sstevel@tonic-gate */ 82637c478bd9Sstevel@tonic-gate 82647c478bd9Sstevel@tonic-gate if (!classexist(flt->class_name, 82657c478bd9Sstevel@tonic-gate act->classes)) { 82667c478bd9Sstevel@tonic-gate if (!in_string_table(act->perm_classes, 82677c478bd9Sstevel@tonic-gate act->num_perm_classes, 82687c478bd9Sstevel@tonic-gate flt->class_name)) { 82697c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 82707c478bd9Sstevel@tonic-gate gettext("Undefined " 82717c478bd9Sstevel@tonic-gate "class in filter %s, " 82727c478bd9Sstevel@tonic-gate "action %s.\n"), flt->name, 82737c478bd9Sstevel@tonic-gate act->name); 82747c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 82757c478bd9Sstevel@tonic-gate } 82767c478bd9Sstevel@tonic-gate } 82777c478bd9Sstevel@tonic-gate } 82787c478bd9Sstevel@tonic-gate } 82797c478bd9Sstevel@tonic-gate 82807c478bd9Sstevel@tonic-gate /* check classes */ 82817c478bd9Sstevel@tonic-gate 82827c478bd9Sstevel@tonic-gate for (cls = act->classes; cls; cls = cls->next) { 82837c478bd9Sstevel@tonic-gate 82847c478bd9Sstevel@tonic-gate /* check if class name unique (userland only) */ 82857c478bd9Sstevel@tonic-gate 82867c478bd9Sstevel@tonic-gate if (userconf && classexist(cls->name, cls->next)) { 82877c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 82887c478bd9Sstevel@tonic-gate gettext("Duplicate named class %s in " 82897c478bd9Sstevel@tonic-gate "action %s.\n"), cls->name, act->name); 82907c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 82917c478bd9Sstevel@tonic-gate } 82927c478bd9Sstevel@tonic-gate 82937c478bd9Sstevel@tonic-gate /* 82947c478bd9Sstevel@tonic-gate * virtual actions always exist so don't check for next 82957c478bd9Sstevel@tonic-gate * action. 82967c478bd9Sstevel@tonic-gate */ 82977c478bd9Sstevel@tonic-gate if (virtual_action(cls->alist->name)) { 82987c478bd9Sstevel@tonic-gate continue; 82997c478bd9Sstevel@tonic-gate } 83007c478bd9Sstevel@tonic-gate 83017c478bd9Sstevel@tonic-gate /* 83027c478bd9Sstevel@tonic-gate * check existance of next action and create link to 83037c478bd9Sstevel@tonic-gate * it. 83047c478bd9Sstevel@tonic-gate */ 83057c478bd9Sstevel@tonic-gate if ((cls->alist->action = 83067c478bd9Sstevel@tonic-gate actionexist(cls->alist->name, actions)) == NULL) { 83077c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 83087c478bd9Sstevel@tonic-gate gettext("Undefined action in class %s, " 83097c478bd9Sstevel@tonic-gate "action %s.\n"), cls->name, act->name); 83107c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83117c478bd9Sstevel@tonic-gate } 83127c478bd9Sstevel@tonic-gate 83137c478bd9Sstevel@tonic-gate /* create backwards link - used for deletions */ 83147c478bd9Sstevel@tonic-gate 83157c478bd9Sstevel@tonic-gate dact = cls->alist->action; 83167c478bd9Sstevel@tonic-gate res = add_aref(&dact->dependencies, NULL, act->name); 83177c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 83187c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83197c478bd9Sstevel@tonic-gate } 83207c478bd9Sstevel@tonic-gate dact->dependencies->action = act; 83217c478bd9Sstevel@tonic-gate } 83227c478bd9Sstevel@tonic-gate 83237c478bd9Sstevel@tonic-gate 83247c478bd9Sstevel@tonic-gate /* check actions exist for action type parameters */ 83257c478bd9Sstevel@tonic-gate 83267c478bd9Sstevel@tonic-gate params = act->params; 83277c478bd9Sstevel@tonic-gate for (aref = params->actions; aref; aref = aref->next) { 83287c478bd9Sstevel@tonic-gate 83297c478bd9Sstevel@tonic-gate /* skip virtuals */ 83307c478bd9Sstevel@tonic-gate 83317c478bd9Sstevel@tonic-gate if (virtual_action(aref->name)) { 83327c478bd9Sstevel@tonic-gate continue; 83337c478bd9Sstevel@tonic-gate } 83347c478bd9Sstevel@tonic-gate 83357c478bd9Sstevel@tonic-gate /* 83367c478bd9Sstevel@tonic-gate * check existance of action in this ref 83377c478bd9Sstevel@tonic-gate * and if present create a ptr to it. 83387c478bd9Sstevel@tonic-gate */ 83397c478bd9Sstevel@tonic-gate aref->action = actionexist(aref->name, actions); 83407c478bd9Sstevel@tonic-gate if (aref->action == NULL) { 83417c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 83427c478bd9Sstevel@tonic-gate gettext("Undefined action in parameter " 83437c478bd9Sstevel@tonic-gate "%s, action %s.\n"), 83447c478bd9Sstevel@tonic-gate SHORT_NAME(aref->field), act->name); 83457c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83467c478bd9Sstevel@tonic-gate } 83477c478bd9Sstevel@tonic-gate 83487c478bd9Sstevel@tonic-gate /* create backwards link */ 83497c478bd9Sstevel@tonic-gate 83507c478bd9Sstevel@tonic-gate dact = aref->action; 83517c478bd9Sstevel@tonic-gate res = add_aref(&dact->dependencies, NULL, 83527c478bd9Sstevel@tonic-gate act->name); 83537c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 83547c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83557c478bd9Sstevel@tonic-gate } 83567c478bd9Sstevel@tonic-gate dact->dependencies->action = act; 83577c478bd9Sstevel@tonic-gate } 83587c478bd9Sstevel@tonic-gate } 83597c478bd9Sstevel@tonic-gate 83607c478bd9Sstevel@tonic-gate /* for kernel retrieved configs we don't do the following checks. */ 83617c478bd9Sstevel@tonic-gate if (!userconf) { 83627c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 83637c478bd9Sstevel@tonic-gate } 83647c478bd9Sstevel@tonic-gate 83657c478bd9Sstevel@tonic-gate /* check for cycles in config and orphaned actions other than ipgpc */ 83667c478bd9Sstevel@tonic-gate 83677c478bd9Sstevel@tonic-gate for (act = actions; act; act = act->next) { 83687c478bd9Sstevel@tonic-gate 83697c478bd9Sstevel@tonic-gate /* check if involved in cycle */ 83707c478bd9Sstevel@tonic-gate 83717c478bd9Sstevel@tonic-gate if (in_cycle(act)) { 83727c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 83737c478bd9Sstevel@tonic-gate gettext("Action %s involved in cycle.\n"), 83747c478bd9Sstevel@tonic-gate act->name); 83757c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83767c478bd9Sstevel@tonic-gate } 83777c478bd9Sstevel@tonic-gate 83787c478bd9Sstevel@tonic-gate /* check that this action has a parent (except ipgpc) */ 83797c478bd9Sstevel@tonic-gate 83807c478bd9Sstevel@tonic-gate if (act->dependencies == NULL && 83817c478bd9Sstevel@tonic-gate strcmp(act->name, IPGPC_CLASSIFY) != 0) { 83827c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Action %s isn't " 83837c478bd9Sstevel@tonic-gate "referenced by any other actions.\n"), act->name); 83847c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 83857c478bd9Sstevel@tonic-gate } 83867c478bd9Sstevel@tonic-gate } 83877c478bd9Sstevel@tonic-gate 83887c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 83897c478bd9Sstevel@tonic-gate } 83907c478bd9Sstevel@tonic-gate 83917c478bd9Sstevel@tonic-gate /* 83927c478bd9Sstevel@tonic-gate * Read the version from the config file with stream cfp with 83937c478bd9Sstevel@tonic-gate * the tag version_tag. The tag-value pair should be the first tokens 83947c478bd9Sstevel@tonic-gate * encountered. 83957c478bd9Sstevel@tonic-gate * 83967c478bd9Sstevel@tonic-gate * RETURNS: -1 if a missing or invalid version or a read error, 83977c478bd9Sstevel@tonic-gate * else an integer encoding of the version. 83987c478bd9Sstevel@tonic-gate */ 83997c478bd9Sstevel@tonic-gate static int 84007c478bd9Sstevel@tonic-gate read_cfile_ver( 84017c478bd9Sstevel@tonic-gate FILE *cfp, 84027c478bd9Sstevel@tonic-gate char *version_tag) 84037c478bd9Sstevel@tonic-gate { 84047c478bd9Sstevel@tonic-gate char *sp = NULL; 84057c478bd9Sstevel@tonic-gate int res; 84067c478bd9Sstevel@tonic-gate int version; 84077c478bd9Sstevel@tonic-gate 84087c478bd9Sstevel@tonic-gate IPQOSCDBG0(L1, "In read_cfile_ver:\n"); 84097c478bd9Sstevel@tonic-gate 84107c478bd9Sstevel@tonic-gate /* 84117c478bd9Sstevel@tonic-gate * read version tag string. 84127c478bd9Sstevel@tonic-gate */ 84137c478bd9Sstevel@tonic-gate res = readtoken(cfp, &sp); 84147c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 84157c478bd9Sstevel@tonic-gate goto fail; 84167c478bd9Sstevel@tonic-gate } else if (strcasecmp(sp, version_tag) != 0) { 84177c478bd9Sstevel@tonic-gate goto fail; 84187c478bd9Sstevel@tonic-gate } 84197c478bd9Sstevel@tonic-gate free(sp); 84207c478bd9Sstevel@tonic-gate sp = NULL; 84217c478bd9Sstevel@tonic-gate 84227c478bd9Sstevel@tonic-gate /* 84237c478bd9Sstevel@tonic-gate * read version number string. 84247c478bd9Sstevel@tonic-gate */ 84257c478bd9Sstevel@tonic-gate res = readtoken(cfp, &sp); 84267c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 84277c478bd9Sstevel@tonic-gate goto fail; 84287c478bd9Sstevel@tonic-gate } 84297c478bd9Sstevel@tonic-gate 84307c478bd9Sstevel@tonic-gate /* 84317c478bd9Sstevel@tonic-gate * encode version into int. 84327c478bd9Sstevel@tonic-gate */ 84337c478bd9Sstevel@tonic-gate if ((version = ver_str_to_int(sp)) == -1) { 84347c478bd9Sstevel@tonic-gate goto fail; 84357c478bd9Sstevel@tonic-gate } 84367c478bd9Sstevel@tonic-gate free(sp); 84377c478bd9Sstevel@tonic-gate 84387c478bd9Sstevel@tonic-gate return (version); 84397c478bd9Sstevel@tonic-gate fail: 84407c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 84417c478bd9Sstevel@tonic-gate gettext("Missing/Invalid config file %s.\n"), version_tag); 84427c478bd9Sstevel@tonic-gate if (sp != NULL) 84437c478bd9Sstevel@tonic-gate free(sp); 84447c478bd9Sstevel@tonic-gate return (-1); 84457c478bd9Sstevel@tonic-gate } 84467c478bd9Sstevel@tonic-gate 84477c478bd9Sstevel@tonic-gate /* 84487c478bd9Sstevel@tonic-gate * read the set of actions definitions from the stream cfp and store 84497c478bd9Sstevel@tonic-gate * them in a list pointed to by conf. 84507c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if any errors, else IPQOS_CONF_SUCCESS. 84517c478bd9Sstevel@tonic-gate */ 84527c478bd9Sstevel@tonic-gate static int 84537c478bd9Sstevel@tonic-gate readconf( 84547c478bd9Sstevel@tonic-gate FILE *cfp, 84557c478bd9Sstevel@tonic-gate ipqos_conf_action_t **conf) 84567c478bd9Sstevel@tonic-gate { 84577c478bd9Sstevel@tonic-gate 84587c478bd9Sstevel@tonic-gate int res; 84597c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action; 84607c478bd9Sstevel@tonic-gate boolean_t ipgpc_action = B_FALSE; 84617c478bd9Sstevel@tonic-gate int fmt_ver; 84627c478bd9Sstevel@tonic-gate 84637c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In readconf\n"); 84647c478bd9Sstevel@tonic-gate 84657c478bd9Sstevel@tonic-gate *conf = NULL; 84667c478bd9Sstevel@tonic-gate 84677c478bd9Sstevel@tonic-gate /* 84687c478bd9Sstevel@tonic-gate * get config file format version. 84697c478bd9Sstevel@tonic-gate */ 84707c478bd9Sstevel@tonic-gate fmt_ver = read_cfile_ver(cfp, IPQOS_FMT_VERSION_STR); 84717c478bd9Sstevel@tonic-gate if (fmt_ver == -1) { 84727c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 84737c478bd9Sstevel@tonic-gate } else { 84747c478bd9Sstevel@tonic-gate /* 84757c478bd9Sstevel@tonic-gate * check version is valid 84767c478bd9Sstevel@tonic-gate */ 84777c478bd9Sstevel@tonic-gate if ((IPP_MAJOR_MODULE_VER(fmt_ver) > 1) || 84787c478bd9Sstevel@tonic-gate (IPP_MINOR_MODULE_VER(fmt_ver) > 0)) { 84797c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Unsupported config file " 84807c478bd9Sstevel@tonic-gate "format version.\n")); 84817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 84827c478bd9Sstevel@tonic-gate } 84837c478bd9Sstevel@tonic-gate } 84847c478bd9Sstevel@tonic-gate 84857c478bd9Sstevel@tonic-gate /* loop reading actions adding to conf till EOF */ 84867c478bd9Sstevel@tonic-gate 84877c478bd9Sstevel@tonic-gate for (;;) { 84887c478bd9Sstevel@tonic-gate action = NULL; 84897c478bd9Sstevel@tonic-gate 84907c478bd9Sstevel@tonic-gate /* readaction */ 84917c478bd9Sstevel@tonic-gate 84927c478bd9Sstevel@tonic-gate res = readaction(cfp, &action); 84937c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_ERR) { 84947c478bd9Sstevel@tonic-gate goto fail; 84957c478bd9Sstevel@tonic-gate } 84967c478bd9Sstevel@tonic-gate 84977c478bd9Sstevel@tonic-gate /* reached eof, finish */ 84987c478bd9Sstevel@tonic-gate 84997c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_EOF) { 85007c478bd9Sstevel@tonic-gate break; 85017c478bd9Sstevel@tonic-gate } 85027c478bd9Sstevel@tonic-gate 85037c478bd9Sstevel@tonic-gate ADD_TO_LIST(conf, action); 85047c478bd9Sstevel@tonic-gate 85057c478bd9Sstevel@tonic-gate /* check if we just read an ipgpc action */ 85067c478bd9Sstevel@tonic-gate 85077c478bd9Sstevel@tonic-gate if (strcmp(action->name, IPGPC_CLASSIFY) == 0) 85087c478bd9Sstevel@tonic-gate ipgpc_action = B_TRUE; 85097c478bd9Sstevel@tonic-gate } 85107c478bd9Sstevel@tonic-gate 85117c478bd9Sstevel@tonic-gate /* check that there is one or more actions and that one is ipgpc */ 85127c478bd9Sstevel@tonic-gate 85137c478bd9Sstevel@tonic-gate if (ipgpc_action == B_FALSE) { 85147c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("No %s action defined.\n"), 85157c478bd9Sstevel@tonic-gate IPGPC_NAME); 85167c478bd9Sstevel@tonic-gate goto fail; 85177c478bd9Sstevel@tonic-gate } 85187c478bd9Sstevel@tonic-gate 85197c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 85207c478bd9Sstevel@tonic-gate fail: 85217c478bd9Sstevel@tonic-gate free_actions(*conf); 85227c478bd9Sstevel@tonic-gate *conf = NULL; 85237c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 85247c478bd9Sstevel@tonic-gate } 85257c478bd9Sstevel@tonic-gate 85267c478bd9Sstevel@tonic-gate /* ************************ kernel config retrieval ************************ */ 85277c478bd9Sstevel@tonic-gate 85287c478bd9Sstevel@tonic-gate 85297c478bd9Sstevel@tonic-gate /* 85307c478bd9Sstevel@tonic-gate * read the current configuration from the kernel and make *conf a ptr to it. 85317c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 85327c478bd9Sstevel@tonic-gate */ 85337c478bd9Sstevel@tonic-gate static int 85347c478bd9Sstevel@tonic-gate readkconf(ipqos_conf_action_t **conf) 85357c478bd9Sstevel@tonic-gate { 85367c478bd9Sstevel@tonic-gate 85377c478bd9Sstevel@tonic-gate int res; 85387c478bd9Sstevel@tonic-gate char **modnames = NULL; 85397c478bd9Sstevel@tonic-gate int nmods; 85407c478bd9Sstevel@tonic-gate char **actnames = NULL; 85417c478bd9Sstevel@tonic-gate int nacts; 85427c478bd9Sstevel@tonic-gate int x, y; 85437c478bd9Sstevel@tonic-gate FILE *tfp; 85447c478bd9Sstevel@tonic-gate int openerr; 85457c478bd9Sstevel@tonic-gate ipqos_actinfo_prm_t ai_prm; 85467c478bd9Sstevel@tonic-gate 85477c478bd9Sstevel@tonic-gate 85487c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In readkconf\n"); 85497c478bd9Sstevel@tonic-gate 85507c478bd9Sstevel@tonic-gate /* initialise conf to NULL */ 85517c478bd9Sstevel@tonic-gate *conf = NULL; 85527c478bd9Sstevel@tonic-gate 85537c478bd9Sstevel@tonic-gate /* get list of modules currently loaded */ 85547c478bd9Sstevel@tonic-gate 85557c478bd9Sstevel@tonic-gate res = ipp_list_mods(&modnames, &nmods); 85567c478bd9Sstevel@tonic-gate if (res != 0) { 85577c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "ipp_list_mods"); 85587c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 85597c478bd9Sstevel@tonic-gate } 85607c478bd9Sstevel@tonic-gate 85617c478bd9Sstevel@tonic-gate /* 85627c478bd9Sstevel@tonic-gate * iterate through all loaded modules retrieving their list of actions 85637c478bd9Sstevel@tonic-gate * and then retrieving the configuration of each of these 85647c478bd9Sstevel@tonic-gate * and attatching it to conf. 85657c478bd9Sstevel@tonic-gate */ 85667c478bd9Sstevel@tonic-gate for (x = 0; x < nmods; x++) { 85677c478bd9Sstevel@tonic-gate 85687c478bd9Sstevel@tonic-gate /* skip actions of modules that we can't open types file of */ 85697c478bd9Sstevel@tonic-gate 85707c478bd9Sstevel@tonic-gate if ((tfp = validmod(modnames[x], &openerr)) == NULL) { 85717c478bd9Sstevel@tonic-gate 85727c478bd9Sstevel@tonic-gate /* mem error */ 85737c478bd9Sstevel@tonic-gate 85747c478bd9Sstevel@tonic-gate if (!openerr) { 85757c478bd9Sstevel@tonic-gate goto fail; 85767c478bd9Sstevel@tonic-gate 85777c478bd9Sstevel@tonic-gate /* 85787c478bd9Sstevel@tonic-gate * fopen fail - if we failed because the file didn't 85797c478bd9Sstevel@tonic-gate * exist we assume this is an unknown module and 85807c478bd9Sstevel@tonic-gate * ignore this module, otherwise error. 85817c478bd9Sstevel@tonic-gate */ 85827c478bd9Sstevel@tonic-gate } else { 85837c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 85847c478bd9Sstevel@tonic-gate continue; 85857c478bd9Sstevel@tonic-gate } else { 85867c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 85877c478bd9Sstevel@tonic-gate goto fail; 85887c478bd9Sstevel@tonic-gate } 85897c478bd9Sstevel@tonic-gate } 85907c478bd9Sstevel@tonic-gate } 85917c478bd9Sstevel@tonic-gate (void) fclose(tfp); 85927c478bd9Sstevel@tonic-gate 85937c478bd9Sstevel@tonic-gate /* get action list for this module */ 85947c478bd9Sstevel@tonic-gate 85957c478bd9Sstevel@tonic-gate res = ipp_mod_list_actions(modnames[x], &actnames, &nacts); 85967c478bd9Sstevel@tonic-gate if (res != 0) { 85977c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "ipp_mod_list_actions"); 85987c478bd9Sstevel@tonic-gate goto fail; 85997c478bd9Sstevel@tonic-gate } 86007c478bd9Sstevel@tonic-gate 86017c478bd9Sstevel@tonic-gate /* read config of each action of this module */ 86027c478bd9Sstevel@tonic-gate 86037c478bd9Sstevel@tonic-gate for (y = 0; y < nacts; y++) { 86047c478bd9Sstevel@tonic-gate ai_prm.action = alloc_action(); 86057c478bd9Sstevel@tonic-gate if (ai_prm.action == NULL) { 86067c478bd9Sstevel@tonic-gate goto fail; 86077c478bd9Sstevel@tonic-gate } 86087c478bd9Sstevel@tonic-gate 86097c478bd9Sstevel@tonic-gate /* copy action name into action struct */ 86107c478bd9Sstevel@tonic-gate 86117c478bd9Sstevel@tonic-gate (void) strlcpy(ai_prm.action->name, actnames[y], 86127c478bd9Sstevel@tonic-gate IPQOS_CONF_NAME_LEN); 86137c478bd9Sstevel@tonic-gate 86147c478bd9Sstevel@tonic-gate /* copy module name into action struct */ 86157c478bd9Sstevel@tonic-gate 86167c478bd9Sstevel@tonic-gate (void) strlcpy(ai_prm.action->module, modnames[x], 86177c478bd9Sstevel@tonic-gate IPQOS_CONF_NAME_LEN); 86187c478bd9Sstevel@tonic-gate 86197c478bd9Sstevel@tonic-gate /* get action info */ 86207c478bd9Sstevel@tonic-gate 86217c478bd9Sstevel@tonic-gate res = ipp_action_info(actnames[y], 86227c478bd9Sstevel@tonic-gate (int (*)(nvlist_t *, void *))parse_kaction, 86237c478bd9Sstevel@tonic-gate (void *)&ai_prm, 0); 86247c478bd9Sstevel@tonic-gate if (res != 0) { 86257c478bd9Sstevel@tonic-gate /* was this an ipp error */ 86267c478bd9Sstevel@tonic-gate if (ai_prm.intl_ret == IPQOS_CONF_SUCCESS) { 86277c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 86287c478bd9Sstevel@tonic-gate "ipp_action_info"); 86297c478bd9Sstevel@tonic-gate } 86307c478bd9Sstevel@tonic-gate goto fail; 86317c478bd9Sstevel@tonic-gate } 86327c478bd9Sstevel@tonic-gate 86337c478bd9Sstevel@tonic-gate ADD_TO_LIST(conf, ai_prm.action); 86347c478bd9Sstevel@tonic-gate } 86357c478bd9Sstevel@tonic-gate 86367c478bd9Sstevel@tonic-gate cleanup_string_table(actnames, nacts); 86377c478bd9Sstevel@tonic-gate } 86387c478bd9Sstevel@tonic-gate 86397c478bd9Sstevel@tonic-gate cleanup_string_table(modnames, nmods); 86407c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 86417c478bd9Sstevel@tonic-gate fail: 86427c478bd9Sstevel@tonic-gate free_actions(*conf); 86437c478bd9Sstevel@tonic-gate *conf = NULL; 86447c478bd9Sstevel@tonic-gate cleanup_string_table(modnames, nmods); 86457c478bd9Sstevel@tonic-gate cleanup_string_table(actnames, nacts); 86467c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 86477c478bd9Sstevel@tonic-gate } 86487c478bd9Sstevel@tonic-gate 86497c478bd9Sstevel@tonic-gate /* 86507c478bd9Sstevel@tonic-gate * This is passed as a parameter to ipp_action_info() in readkaction and 86517c478bd9Sstevel@tonic-gate * is called back one for each configuration element within the action 86527c478bd9Sstevel@tonic-gate * specified. This results in filters and classes being created and chained 86537c478bd9Sstevel@tonic-gate * off of action, and action having its params set. 86547c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCESS. 86557c478bd9Sstevel@tonic-gate */ 86567c478bd9Sstevel@tonic-gate static int 86577c478bd9Sstevel@tonic-gate parse_kaction( 86587c478bd9Sstevel@tonic-gate nvlist_t *nvl, 86597c478bd9Sstevel@tonic-gate ipqos_actinfo_prm_t *ai_prm) 86607c478bd9Sstevel@tonic-gate { 86617c478bd9Sstevel@tonic-gate 86627c478bd9Sstevel@tonic-gate int ret; 86637c478bd9Sstevel@tonic-gate uint8_t cfgtype; 86647c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter = NULL; 86657c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class = NULL; 86667c478bd9Sstevel@tonic-gate ipqos_conf_action_t *action = ai_prm->action; 86677c478bd9Sstevel@tonic-gate 86687c478bd9Sstevel@tonic-gate 86697c478bd9Sstevel@tonic-gate IPQOSCDBG1(KRET, "In parse_kaction: action_name: %s\n", action->name); 86707c478bd9Sstevel@tonic-gate 86717c478bd9Sstevel@tonic-gate /* get config type */ 86727c478bd9Sstevel@tonic-gate 86737c478bd9Sstevel@tonic-gate (void) nvlist_lookup_byte(nvl, IPP_CONFIG_TYPE, &cfgtype); 86747c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvl, IPP_CONFIG_TYPE); 86757c478bd9Sstevel@tonic-gate 86767c478bd9Sstevel@tonic-gate switch (cfgtype) { 86777c478bd9Sstevel@tonic-gate case CLASSIFIER_ADD_FILTER: { 86787c478bd9Sstevel@tonic-gate /* 86797c478bd9Sstevel@tonic-gate * parse the passed filter nvlist 86807c478bd9Sstevel@tonic-gate * and add result to action's filter list. 86817c478bd9Sstevel@tonic-gate */ 86827c478bd9Sstevel@tonic-gate filter = alloc_filter(); 86837c478bd9Sstevel@tonic-gate if (filter == NULL) { 86847c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_ERR; 86857c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 86867c478bd9Sstevel@tonic-gate } 86877c478bd9Sstevel@tonic-gate 86887c478bd9Sstevel@tonic-gate ret = parse_kfilter(filter, nvl); 86897c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 86907c478bd9Sstevel@tonic-gate free_filter(filter); 86917c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_ERR; 86927c478bd9Sstevel@tonic-gate return (ret); 86937c478bd9Sstevel@tonic-gate } 86947c478bd9Sstevel@tonic-gate 86957c478bd9Sstevel@tonic-gate ADD_TO_LIST(&action->filters, filter); 86967c478bd9Sstevel@tonic-gate break; 86977c478bd9Sstevel@tonic-gate } 86987c478bd9Sstevel@tonic-gate case CLASSIFIER_ADD_CLASS: 86997c478bd9Sstevel@tonic-gate case CLASSIFIER_MODIFY_CLASS: { 87007c478bd9Sstevel@tonic-gate /* 87017c478bd9Sstevel@tonic-gate * parse the passed class nvlist 87027c478bd9Sstevel@tonic-gate * and add result to action's class list. 87037c478bd9Sstevel@tonic-gate */ 87047c478bd9Sstevel@tonic-gate class = alloc_class(); 87057c478bd9Sstevel@tonic-gate if (class == NULL) { 87067c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_ERR; 87077c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 87087c478bd9Sstevel@tonic-gate } 87097c478bd9Sstevel@tonic-gate 87107c478bd9Sstevel@tonic-gate ret = parse_kclass(class, nvl); 87117c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 87127c478bd9Sstevel@tonic-gate free_class(class); 87137c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_ERR; 87147c478bd9Sstevel@tonic-gate return (ret); 87157c478bd9Sstevel@tonic-gate } 87167c478bd9Sstevel@tonic-gate 87177c478bd9Sstevel@tonic-gate ADD_TO_LIST(&action->classes, class); 87187c478bd9Sstevel@tonic-gate break; 87197c478bd9Sstevel@tonic-gate } 87207c478bd9Sstevel@tonic-gate case IPP_SET: { 87217c478bd9Sstevel@tonic-gate /* 87227c478bd9Sstevel@tonic-gate * we don't alloc a params struct as it is created 87237c478bd9Sstevel@tonic-gate * as part of an action. 87247c478bd9Sstevel@tonic-gate */ 87257c478bd9Sstevel@tonic-gate 87267c478bd9Sstevel@tonic-gate /* parse the passed params nvlist */ 87277c478bd9Sstevel@tonic-gate 87287c478bd9Sstevel@tonic-gate ret = parse_kparams(action->module, action->params, 87297c478bd9Sstevel@tonic-gate nvl); 87307c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 87317c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_ERR; 87327c478bd9Sstevel@tonic-gate return (ret); 87337c478bd9Sstevel@tonic-gate } 87347c478bd9Sstevel@tonic-gate } 87357c478bd9Sstevel@tonic-gate } 87367c478bd9Sstevel@tonic-gate 87377c478bd9Sstevel@tonic-gate ai_prm->intl_ret = IPQOS_CONF_SUCCESS; 87387c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 87397c478bd9Sstevel@tonic-gate } 87407c478bd9Sstevel@tonic-gate 87417c478bd9Sstevel@tonic-gate /* 87427c478bd9Sstevel@tonic-gate * parses a params nvlist returned from the kernel. 87437c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 87447c478bd9Sstevel@tonic-gate */ 87457c478bd9Sstevel@tonic-gate int 87467c478bd9Sstevel@tonic-gate parse_kparams( 87477c478bd9Sstevel@tonic-gate char *module, 87487c478bd9Sstevel@tonic-gate ipqos_conf_params_t *params, 87497c478bd9Sstevel@tonic-gate nvlist_t *nvl) { 87507c478bd9Sstevel@tonic-gate 87517c478bd9Sstevel@tonic-gate int ret; 87527c478bd9Sstevel@tonic-gate ipqos_nvtype_t type; 87537c478bd9Sstevel@tonic-gate str_val_nd_t *tmp; 87547c478bd9Sstevel@tonic-gate char *act; 87557c478bd9Sstevel@tonic-gate uint32_t u32; 87567c478bd9Sstevel@tonic-gate nvpair_t *nvp; 87577c478bd9Sstevel@tonic-gate FILE *tfp; 87587c478bd9Sstevel@tonic-gate char dfltst[IPQOS_VALST_MAXLEN]; 87597c478bd9Sstevel@tonic-gate char *param; 87607c478bd9Sstevel@tonic-gate nvlist_t *nvlcp; 87617c478bd9Sstevel@tonic-gate int openerr; 87627c478bd9Sstevel@tonic-gate place_t place; 87637c478bd9Sstevel@tonic-gate 87647c478bd9Sstevel@tonic-gate IPQOSCDBG0(KRET, "In parse_kparams:\n"); 87657c478bd9Sstevel@tonic-gate 87667c478bd9Sstevel@tonic-gate /* get stream to module types file */ 87677c478bd9Sstevel@tonic-gate 87687c478bd9Sstevel@tonic-gate tfp = validmod(module, &openerr); 87697c478bd9Sstevel@tonic-gate if (tfp == NULL) { 87707c478bd9Sstevel@tonic-gate if (openerr) { 87717c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 87727c478bd9Sstevel@tonic-gate } 87737c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 87747c478bd9Sstevel@tonic-gate } 87757c478bd9Sstevel@tonic-gate 87767c478bd9Sstevel@tonic-gate /* make copy of passed in nvlist as it is freed by the caller */ 87777c478bd9Sstevel@tonic-gate 87787c478bd9Sstevel@tonic-gate ret = nvlist_dup(nvl, &nvlcp, 0); 87797c478bd9Sstevel@tonic-gate if (ret != 0) { 87807c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 87817c478bd9Sstevel@tonic-gate } 87827c478bd9Sstevel@tonic-gate 87837c478bd9Sstevel@tonic-gate /* 87847c478bd9Sstevel@tonic-gate * get config originator and remove from nvlist. If no owner we 87857c478bd9Sstevel@tonic-gate * assume ownership. 87867c478bd9Sstevel@tonic-gate */ 87877c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32(nvlcp, IPP_CONFIG_ORIGINATOR, &u32); 87887c478bd9Sstevel@tonic-gate if (ret == 0) { 87897c478bd9Sstevel@tonic-gate params->originator = u32; 87907c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPP_CONFIG_ORIGINATOR); 87917c478bd9Sstevel@tonic-gate } else { 87927c478bd9Sstevel@tonic-gate params->originator = IPP_CONFIG_IPQOSCONF; 87937c478bd9Sstevel@tonic-gate } 87947c478bd9Sstevel@tonic-gate 87957c478bd9Sstevel@tonic-gate /* get action stats and remove from nvlist */ 87967c478bd9Sstevel@tonic-gate 87977c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32(nvlcp, IPP_ACTION_STATS_ENABLE, &u32); 87987c478bd9Sstevel@tonic-gate if (ret == 0) { 87997c478bd9Sstevel@tonic-gate params->stats_enable = *(boolean_t *)&u32; 88007c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPP_ACTION_STATS_ENABLE); 88017c478bd9Sstevel@tonic-gate } 88027c478bd9Sstevel@tonic-gate 88037c478bd9Sstevel@tonic-gate /* 88047c478bd9Sstevel@tonic-gate * loop throught nvlist elements and for those that are actions create 88057c478bd9Sstevel@tonic-gate * action ref entrys for them. 88067c478bd9Sstevel@tonic-gate */ 88077c478bd9Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvlcp, NULL); 88087c478bd9Sstevel@tonic-gate while (nvp != NULL) { 88097c478bd9Sstevel@tonic-gate param = SHORT_NAME(nvpair_name(nvp)); 88107c478bd9Sstevel@tonic-gate place = PL_ANY; 88117c478bd9Sstevel@tonic-gate ret = readtype(tfp, module, param, &type, &tmp, dfltst, 88127c478bd9Sstevel@tonic-gate B_FALSE, &place); 88137c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 88147c478bd9Sstevel@tonic-gate goto fail; 88157c478bd9Sstevel@tonic-gate } 88167c478bd9Sstevel@tonic-gate 88177c478bd9Sstevel@tonic-gate if ((place == PL_PARAMS) && /* avoid map entries */ 88187c478bd9Sstevel@tonic-gate (type == IPQOS_DATA_TYPE_ACTION)) { 88197c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &act); 88207c478bd9Sstevel@tonic-gate ret = add_aref(¶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 88487c478bd9Sstevel@tonic-gate parse_kclass( 88497c478bd9Sstevel@tonic-gate ipqos_conf_class_t *class, 88507c478bd9Sstevel@tonic-gate nvlist_t *nvl) 88517c478bd9Sstevel@tonic-gate { 88527c478bd9Sstevel@tonic-gate 88537c478bd9Sstevel@tonic-gate int ret; 88547c478bd9Sstevel@tonic-gate uint32_t u32; 88557c478bd9Sstevel@tonic-gate char *str; 88567c478bd9Sstevel@tonic-gate 88577c478bd9Sstevel@tonic-gate IPQOSCDBG0(KRET, "In parse_kclass:\n"); 88587c478bd9Sstevel@tonic-gate 88597c478bd9Sstevel@tonic-gate /* lookup object originator */ 88607c478bd9Sstevel@tonic-gate 88617c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32(nvl, IPP_CONFIG_ORIGINATOR, &u32); 88627c478bd9Sstevel@tonic-gate if (ret == 0) { 88637c478bd9Sstevel@tonic-gate class->originator = u32; 88647c478bd9Sstevel@tonic-gate } else { 88657c478bd9Sstevel@tonic-gate class->originator = IPP_CONFIG_IPQOSCONF; 88667c478bd9Sstevel@tonic-gate } 88677c478bd9Sstevel@tonic-gate 88687c478bd9Sstevel@tonic-gate /* lookup name */ 88697c478bd9Sstevel@tonic-gate 88707c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvl, CLASSIFIER_CLASS_NAME, &str); 88717c478bd9Sstevel@tonic-gate (void) strlcpy(class->name, str, IPQOS_CONF_NAME_LEN); 88727c478bd9Sstevel@tonic-gate IPQOSCDBG1(KRET, "reading class %s\n", class->name); 88737c478bd9Sstevel@tonic-gate 88747c478bd9Sstevel@tonic-gate /* lookup next action */ 88757c478bd9Sstevel@tonic-gate 88767c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvl, CLASSIFIER_NEXT_ACTION, &str); 88777c478bd9Sstevel@tonic-gate ret = add_aref(&class->alist, NULL, str); 88787c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 88797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 88807c478bd9Sstevel@tonic-gate } 88817c478bd9Sstevel@tonic-gate 88827c478bd9Sstevel@tonic-gate /* lookup stats enable */ 88837c478bd9Sstevel@tonic-gate 88847c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32(nvl, CLASSIFIER_CLASS_STATS_ENABLE, &u32); 88857c478bd9Sstevel@tonic-gate if (ret == 0) { 88867c478bd9Sstevel@tonic-gate class->stats_enable = *(boolean_t *)&u32; 88877c478bd9Sstevel@tonic-gate } 88887c478bd9Sstevel@tonic-gate 88897c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 88907c478bd9Sstevel@tonic-gate } 88917c478bd9Sstevel@tonic-gate 88927c478bd9Sstevel@tonic-gate /* 88937c478bd9Sstevel@tonic-gate * parses a filters nvlist returned from the kernel. 88947c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 88957c478bd9Sstevel@tonic-gate */ 88967c478bd9Sstevel@tonic-gate static int 88977c478bd9Sstevel@tonic-gate parse_kfilter( 88987c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *filter, 88997c478bd9Sstevel@tonic-gate nvlist_t *nvl) 89007c478bd9Sstevel@tonic-gate { 89017c478bd9Sstevel@tonic-gate 89027c478bd9Sstevel@tonic-gate int ret; 89037c478bd9Sstevel@tonic-gate char *str; 89047c478bd9Sstevel@tonic-gate uint32_t u32; 89057c478bd9Sstevel@tonic-gate nvlist_t *nvlcp; 89067c478bd9Sstevel@tonic-gate char *end; 89077c478bd9Sstevel@tonic-gate 89087c478bd9Sstevel@tonic-gate IPQOSCDBG0(KRET, "In parse_kfilter:\n"); 89097c478bd9Sstevel@tonic-gate 89107c478bd9Sstevel@tonic-gate /* make copy of passed in nvlist as it is freed by the caller */ 89117c478bd9Sstevel@tonic-gate 89127c478bd9Sstevel@tonic-gate ret = nvlist_dup(nvl, &nvlcp, 0); 89137c478bd9Sstevel@tonic-gate if (ret != 0) { 89147c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 89157c478bd9Sstevel@tonic-gate } 89167c478bd9Sstevel@tonic-gate 89177c478bd9Sstevel@tonic-gate /* lookup originator */ 89187c478bd9Sstevel@tonic-gate 89197c478bd9Sstevel@tonic-gate ret = nvlist_lookup_uint32(nvlcp, IPP_CONFIG_ORIGINATOR, &u32); 89207c478bd9Sstevel@tonic-gate if (ret == 0) { 89217c478bd9Sstevel@tonic-gate filter->originator = u32; 89227c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPP_CONFIG_ORIGINATOR); 89237c478bd9Sstevel@tonic-gate } else { 89247c478bd9Sstevel@tonic-gate filter->originator = IPP_CONFIG_IPQOSCONF; 89257c478bd9Sstevel@tonic-gate } 89267c478bd9Sstevel@tonic-gate 89277c478bd9Sstevel@tonic-gate /* lookup filter name */ 89287c478bd9Sstevel@tonic-gate 89297c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvlcp, CLASSIFIER_FILTER_NAME, &str); 89307c478bd9Sstevel@tonic-gate (void) strlcpy(filter->name, str, IPQOS_CONF_NAME_LEN); 89317c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, CLASSIFIER_FILTER_NAME); 89327c478bd9Sstevel@tonic-gate 89337c478bd9Sstevel@tonic-gate /* lookup class name */ 89347c478bd9Sstevel@tonic-gate 89357c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvlcp, CLASSIFIER_CLASS_NAME, &str); 89367c478bd9Sstevel@tonic-gate (void) strlcpy(filter->class_name, str, IPQOS_CONF_NAME_LEN); 89377c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, CLASSIFIER_CLASS_NAME); 89387c478bd9Sstevel@tonic-gate 89397c478bd9Sstevel@tonic-gate /* lookup src and dst host names if present */ 89407c478bd9Sstevel@tonic-gate 89417c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(nvlcp, IPGPC_SADDR_HOSTNAME, &str) == 0) { 89427c478bd9Sstevel@tonic-gate filter->src_nd_name = malloc(strlen(str) + 1); 89437c478bd9Sstevel@tonic-gate if (filter->src_nd_name) { 89447c478bd9Sstevel@tonic-gate (void) strcpy(filter->src_nd_name, str); 89457c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPGPC_SADDR_HOSTNAME); 89467c478bd9Sstevel@tonic-gate } else { 89477c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 89487c478bd9Sstevel@tonic-gate nvlist_free(nvlcp); 89497c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 89507c478bd9Sstevel@tonic-gate } 89517c478bd9Sstevel@tonic-gate } 89527c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(nvlcp, IPGPC_DADDR_HOSTNAME, &str) == 0) { 89537c478bd9Sstevel@tonic-gate filter->dst_nd_name = malloc(strlen(str) + 1); 89547c478bd9Sstevel@tonic-gate if (filter->dst_nd_name) { 89557c478bd9Sstevel@tonic-gate (void) strcpy(filter->dst_nd_name, str); 89567c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPGPC_DADDR_HOSTNAME); 89577c478bd9Sstevel@tonic-gate } else { 89587c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 89597c478bd9Sstevel@tonic-gate nvlist_free(nvlcp); 89607c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 89617c478bd9Sstevel@tonic-gate } 89627c478bd9Sstevel@tonic-gate } 89637c478bd9Sstevel@tonic-gate 89647c478bd9Sstevel@tonic-gate /* lookup ip_version if present */ 89657c478bd9Sstevel@tonic-gate 89667c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(nvlcp, IPGPC_FILTER_PRIVATE, &str) == 0) { 89677c478bd9Sstevel@tonic-gate filter->ip_versions = (uint32_t)strtol(str, &end, 0); 89687c478bd9Sstevel@tonic-gate if (end != str) { 89697c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPGPC_FILTER_PRIVATE); 89707c478bd9Sstevel@tonic-gate } else { 89717c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 89727c478bd9Sstevel@tonic-gate gettext("Corrupted ip_version returned from " 89737c478bd9Sstevel@tonic-gate "kernel.\n")); 89747c478bd9Sstevel@tonic-gate nvlist_free(nvlcp); 89757c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 89767c478bd9Sstevel@tonic-gate } 89777c478bd9Sstevel@tonic-gate } 89787c478bd9Sstevel@tonic-gate 89797c478bd9Sstevel@tonic-gate /* lookup filter instance if present */ 89807c478bd9Sstevel@tonic-gate 89817c478bd9Sstevel@tonic-gate ret = nvlist_lookup_int32(nvlcp, IPGPC_FILTER_INSTANCE, 89827c478bd9Sstevel@tonic-gate &filter->instance); 89837c478bd9Sstevel@tonic-gate if (ret != 0) { 89847c478bd9Sstevel@tonic-gate filter->instance = -1; 89857c478bd9Sstevel@tonic-gate } else { 89867c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlcp, IPGPC_FILTER_INSTANCE); 89877c478bd9Sstevel@tonic-gate } 89887c478bd9Sstevel@tonic-gate 89897c478bd9Sstevel@tonic-gate /* attach new trimmed nvlist to filter */ 89907c478bd9Sstevel@tonic-gate filter->nvlist = nvlcp; 89917c478bd9Sstevel@tonic-gate 89927c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 89937c478bd9Sstevel@tonic-gate } 89947c478bd9Sstevel@tonic-gate 89957c478bd9Sstevel@tonic-gate 89967c478bd9Sstevel@tonic-gate /* 89977c478bd9Sstevel@tonic-gate * determines whether action_name is a virtual action name. 89987c478bd9Sstevel@tonic-gate * RETURNS: if virtual action 1, else 0. 89997c478bd9Sstevel@tonic-gate */ 90007c478bd9Sstevel@tonic-gate static int 90017c478bd9Sstevel@tonic-gate virtual_action(char *action_name) 90027c478bd9Sstevel@tonic-gate { 90037c478bd9Sstevel@tonic-gate 90047c478bd9Sstevel@tonic-gate if (strcmp(action_name, IPP_ANAME_CONT) == 0 || 90057c478bd9Sstevel@tonic-gate strcmp(action_name, IPP_ANAME_DEFER) == 0 || 90067c478bd9Sstevel@tonic-gate strcmp(action_name, IPP_ANAME_DROP) == 0) { 90077c478bd9Sstevel@tonic-gate return (1); 90087c478bd9Sstevel@tonic-gate } 90097c478bd9Sstevel@tonic-gate 90107c478bd9Sstevel@tonic-gate return (0); 90117c478bd9Sstevel@tonic-gate } 90127c478bd9Sstevel@tonic-gate 90137c478bd9Sstevel@tonic-gate /* 90147c478bd9Sstevel@tonic-gate * remove all the actions within the kernel. If there is a failure 90157c478bd9Sstevel@tonic-gate * modified is set to represent whether the attempt to flush modified 90167c478bd9Sstevel@tonic-gate * the configuration in any way. 90177c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if the ipp_* functions return any errors, 90187c478bd9Sstevel@tonic-gate * else IPQOS_CONF_SUCCESS. 90197c478bd9Sstevel@tonic-gate */ 90207c478bd9Sstevel@tonic-gate static int 90217c478bd9Sstevel@tonic-gate flush( 90227c478bd9Sstevel@tonic-gate boolean_t *modified) 90237c478bd9Sstevel@tonic-gate { 90247c478bd9Sstevel@tonic-gate 90257c478bd9Sstevel@tonic-gate int res; 90267c478bd9Sstevel@tonic-gate char **modnames = NULL; 90277c478bd9Sstevel@tonic-gate int nmods; 90287c478bd9Sstevel@tonic-gate char **actnames = NULL; 90297c478bd9Sstevel@tonic-gate int nacts; 90307c478bd9Sstevel@tonic-gate int x, y; 90317c478bd9Sstevel@tonic-gate 90327c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In flush\n"); 90337c478bd9Sstevel@tonic-gate 90347c478bd9Sstevel@tonic-gate *modified = B_FALSE; 90357c478bd9Sstevel@tonic-gate 90367c478bd9Sstevel@tonic-gate /* 90377c478bd9Sstevel@tonic-gate * get list of modules currently loaded. 90387c478bd9Sstevel@tonic-gate */ 90397c478bd9Sstevel@tonic-gate res = ipp_list_mods(&modnames, &nmods); 90407c478bd9Sstevel@tonic-gate if (res != 0) { 90417c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "ipp_list_mods"); 90427c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 90437c478bd9Sstevel@tonic-gate } 90447c478bd9Sstevel@tonic-gate 90457c478bd9Sstevel@tonic-gate /* 90467c478bd9Sstevel@tonic-gate * iterate through all the modules listing their actions and 90477c478bd9Sstevel@tonic-gate * deleting all of them. 90487c478bd9Sstevel@tonic-gate */ 90497c478bd9Sstevel@tonic-gate for (x = 0; x < nmods; x++) { 90507c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "Getting actions of module %s.\n", 90517c478bd9Sstevel@tonic-gate modnames[x]); 90527c478bd9Sstevel@tonic-gate res = ipp_mod_list_actions(modnames[x], &actnames, &nacts); 90537c478bd9Sstevel@tonic-gate if (res != 0) { 90547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "ipp_mod_list_actions"); 90557c478bd9Sstevel@tonic-gate cleanup_string_table(modnames, nmods); 90567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 90577c478bd9Sstevel@tonic-gate } 90587c478bd9Sstevel@tonic-gate 90597c478bd9Sstevel@tonic-gate for (y = 0; y < nacts; y++) { 90607c478bd9Sstevel@tonic-gate IPQOSCDBG1(APPLY, "deleting action %s\n", actnames[y]); 90617c478bd9Sstevel@tonic-gate res = ipp_action_destroy(actnames[y], IPP_DESTROY_REF); 90627c478bd9Sstevel@tonic-gate /* 90637c478bd9Sstevel@tonic-gate * if fails for reason other than action doesn't 90647c478bd9Sstevel@tonic-gate * exist or action has dependency. 90657c478bd9Sstevel@tonic-gate */ 90667c478bd9Sstevel@tonic-gate if (res != 0 && errno != ENOENT && errno != EBUSY) { 90677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "ipp_action_destroy"); 90687c478bd9Sstevel@tonic-gate cleanup_string_table(modnames, nmods); 90697c478bd9Sstevel@tonic-gate cleanup_string_table(actnames, nacts); 90707c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 90717c478bd9Sstevel@tonic-gate } 90727c478bd9Sstevel@tonic-gate 90737c478bd9Sstevel@tonic-gate if (res == 0) 90747c478bd9Sstevel@tonic-gate *modified = B_TRUE; 90757c478bd9Sstevel@tonic-gate } 90767c478bd9Sstevel@tonic-gate cleanup_string_table(actnames, nacts); 90777c478bd9Sstevel@tonic-gate } 90787c478bd9Sstevel@tonic-gate cleanup_string_table(modnames, nmods); 90797c478bd9Sstevel@tonic-gate 90807c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 90817c478bd9Sstevel@tonic-gate } 90827c478bd9Sstevel@tonic-gate 90837c478bd9Sstevel@tonic-gate /* 90847c478bd9Sstevel@tonic-gate * Trys to flush the configuration. If it fails and nothing has been modified 90857c478bd9Sstevel@tonic-gate * and force_flush is false just return an error, otherwise persist trying to 90867c478bd9Sstevel@tonic-gate * completion. 90877c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if flush attempt failed without modifying anything 90887c478bd9Sstevel@tonic-gate * and force_flush was set to false, otherwise IPQOS_CONF_SUCCESS. 90897c478bd9Sstevel@tonic-gate */ 90907c478bd9Sstevel@tonic-gate static int 90917c478bd9Sstevel@tonic-gate atomic_flush( 90927c478bd9Sstevel@tonic-gate boolean_t force_flush) 90937c478bd9Sstevel@tonic-gate { 90947c478bd9Sstevel@tonic-gate int x = 0; 90957c478bd9Sstevel@tonic-gate int res; 90967c478bd9Sstevel@tonic-gate boolean_t modified = B_FALSE; 90977c478bd9Sstevel@tonic-gate 90987c478bd9Sstevel@tonic-gate /* 90997c478bd9Sstevel@tonic-gate * attempt first flush of config. 91007c478bd9Sstevel@tonic-gate */ 91017c478bd9Sstevel@tonic-gate res = flush(&modified); 91027c478bd9Sstevel@tonic-gate if ((force_flush == B_FALSE) && (res != IPQOS_CONF_SUCCESS) && 91037c478bd9Sstevel@tonic-gate (modified == B_FALSE)) { 91047c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 91057c478bd9Sstevel@tonic-gate } else if (res == IPQOS_CONF_SUCCESS) { 91067c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 91077c478bd9Sstevel@tonic-gate } 91087c478bd9Sstevel@tonic-gate 91097c478bd9Sstevel@tonic-gate /* 91107c478bd9Sstevel@tonic-gate * failed flush that modified config, or force flush set; loop till 91117c478bd9Sstevel@tonic-gate * successful flush. 91127c478bd9Sstevel@tonic-gate */ 91137c478bd9Sstevel@tonic-gate while (res != IPQOS_CONF_SUCCESS) { 91147c478bd9Sstevel@tonic-gate if (x == 5) { /* 10 secs since start/last message. */ 91157c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 91167c478bd9Sstevel@tonic-gate gettext("Retrying configuration flush.\n")); 91177c478bd9Sstevel@tonic-gate x = 0; 91187c478bd9Sstevel@tonic-gate } 91197c478bd9Sstevel@tonic-gate (void) sleep(2); 91207c478bd9Sstevel@tonic-gate x++; 91217c478bd9Sstevel@tonic-gate res = flush(&modified); 91227c478bd9Sstevel@tonic-gate } 91237c478bd9Sstevel@tonic-gate 91247c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 91257c478bd9Sstevel@tonic-gate } 91267c478bd9Sstevel@tonic-gate 91277c478bd9Sstevel@tonic-gate /* 91287c478bd9Sstevel@tonic-gate * Performs a flush of the configuration within a signal blocking region 91297c478bd9Sstevel@tonic-gate * so that there's minimal chance of it being killed and the flush only 91307c478bd9Sstevel@tonic-gate * partially completing. 91317c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_SUCCESS (for symmetry with the other main functions). 91327c478bd9Sstevel@tonic-gate */ 91337c478bd9Sstevel@tonic-gate static int 91347c478bd9Sstevel@tonic-gate flushconf() 91357c478bd9Sstevel@tonic-gate { 91367c478bd9Sstevel@tonic-gate int res; 91377c478bd9Sstevel@tonic-gate 91387c478bd9Sstevel@tonic-gate /* 91397c478bd9Sstevel@tonic-gate * make sure that flush is as atomic as possible. 91407c478bd9Sstevel@tonic-gate */ 91417c478bd9Sstevel@tonic-gate if ((res = block_all_signals()) == -1) 91427c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 91437c478bd9Sstevel@tonic-gate 91447c478bd9Sstevel@tonic-gate res = atomic_flush(B_FALSE); 91457c478bd9Sstevel@tonic-gate 91467c478bd9Sstevel@tonic-gate /* 91477c478bd9Sstevel@tonic-gate * restore signals. 91487c478bd9Sstevel@tonic-gate */ 91497c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 91507c478bd9Sstevel@tonic-gate 91517c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_SUCCESS) { 91527c478bd9Sstevel@tonic-gate ipqos_msg(MT_LOG, gettext("Configuration flushed.\n")); 91537c478bd9Sstevel@tonic-gate } else { 91547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "atomic_flush"); 91557c478bd9Sstevel@tonic-gate } 91567c478bd9Sstevel@tonic-gate 91577c478bd9Sstevel@tonic-gate return (res); 91587c478bd9Sstevel@tonic-gate } 91597c478bd9Sstevel@tonic-gate 91607c478bd9Sstevel@tonic-gate static int 91617c478bd9Sstevel@tonic-gate in_string_table(char *stable[], int size, char *string) 91627c478bd9Sstevel@tonic-gate { 91637c478bd9Sstevel@tonic-gate 91647c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "In in_string_table: search string %s\n", string); 91657c478bd9Sstevel@tonic-gate 91667c478bd9Sstevel@tonic-gate for (--size; size >= 0; size--) { 91677c478bd9Sstevel@tonic-gate if (strcmp(stable[size], string) == 0) { 91687c478bd9Sstevel@tonic-gate IPQOSCDBG1(L1, "Found %s in string table\n", string); 91697c478bd9Sstevel@tonic-gate return (1); 91707c478bd9Sstevel@tonic-gate } 91717c478bd9Sstevel@tonic-gate } 91727c478bd9Sstevel@tonic-gate 91737c478bd9Sstevel@tonic-gate return (0); 91747c478bd9Sstevel@tonic-gate } 91757c478bd9Sstevel@tonic-gate 91767c478bd9Sstevel@tonic-gate /* free the memory occupied by the string table ctable and its contents. */ 91777c478bd9Sstevel@tonic-gate static void 91787c478bd9Sstevel@tonic-gate cleanup_string_table(char *ctable[], int size) 91797c478bd9Sstevel@tonic-gate { 91807c478bd9Sstevel@tonic-gate 91817c478bd9Sstevel@tonic-gate int x; 91827c478bd9Sstevel@tonic-gate 91837c478bd9Sstevel@tonic-gate if (ctable) { 91847c478bd9Sstevel@tonic-gate for (x = 0; x < size; x++) { 91857c478bd9Sstevel@tonic-gate free(ctable[x]); 91867c478bd9Sstevel@tonic-gate } 91877c478bd9Sstevel@tonic-gate free(ctable); 91887c478bd9Sstevel@tonic-gate } 91897c478bd9Sstevel@tonic-gate } 91907c478bd9Sstevel@tonic-gate 91917c478bd9Sstevel@tonic-gate #if 0 91927c478bd9Sstevel@tonic-gate 91937c478bd9Sstevel@tonic-gate /* 91947c478bd9Sstevel@tonic-gate * makes a copy of a string table and returns a ptr to it. 91957c478bd9Sstevel@tonic-gate * RETURNS: NULL on error or if size was 0, else ptr to copied table. 91967c478bd9Sstevel@tonic-gate */ 91977c478bd9Sstevel@tonic-gate static char ** 91987c478bd9Sstevel@tonic-gate copy_string_table(char *stable1[], int size) 91997c478bd9Sstevel@tonic-gate { 92007c478bd9Sstevel@tonic-gate 92017c478bd9Sstevel@tonic-gate char **st = NULL; 92027c478bd9Sstevel@tonic-gate int pos; 92037c478bd9Sstevel@tonic-gate 92047c478bd9Sstevel@tonic-gate /* create char ptr array */ 92057c478bd9Sstevel@tonic-gate 92067c478bd9Sstevel@tonic-gate st = malloc(size * sizeof (char *)); 92077c478bd9Sstevel@tonic-gate if (st == NULL) { 92087c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 92097c478bd9Sstevel@tonic-gate return (st); 92107c478bd9Sstevel@tonic-gate } 92117c478bd9Sstevel@tonic-gate 92127c478bd9Sstevel@tonic-gate /* create copy of each string from stable1 in array */ 92137c478bd9Sstevel@tonic-gate 92147c478bd9Sstevel@tonic-gate for (pos = size - 1; pos >= 0; pos--) { 92157c478bd9Sstevel@tonic-gate st[pos] = malloc(strlen(stable1[pos] + 1)); 92167c478bd9Sstevel@tonic-gate if (st[pos] == NULL) { 92177c478bd9Sstevel@tonic-gate for (pos++; pos < size; pos++) 92187c478bd9Sstevel@tonic-gate free(st[pos]); 92197c478bd9Sstevel@tonic-gate free(st); 92207c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 92217c478bd9Sstevel@tonic-gate return (NULL); 92227c478bd9Sstevel@tonic-gate } 92237c478bd9Sstevel@tonic-gate 92247c478bd9Sstevel@tonic-gate (void) strcpy(st[pos], stable1[pos]); 92257c478bd9Sstevel@tonic-gate } 92267c478bd9Sstevel@tonic-gate 92277c478bd9Sstevel@tonic-gate return (st); 92287c478bd9Sstevel@tonic-gate } 92297c478bd9Sstevel@tonic-gate #endif /* 0 */ 92307c478bd9Sstevel@tonic-gate 92317c478bd9Sstevel@tonic-gate /* 92327c478bd9Sstevel@tonic-gate * retry lookups on filters that soft failed a previous lookup and 92337c478bd9Sstevel@tonic-gate * were put on the retry list. 92347c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on any errors, else IPQOS_CONF_SUCCESS. 92357c478bd9Sstevel@tonic-gate */ 92367c478bd9Sstevel@tonic-gate static int 92377c478bd9Sstevel@tonic-gate retry_name_lookups( 92387c478bd9Sstevel@tonic-gate ipqos_conf_action_t *actions) 92397c478bd9Sstevel@tonic-gate { 92407c478bd9Sstevel@tonic-gate 92417c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 92427c478bd9Sstevel@tonic-gate ipqos_conf_filter_t **new_filters; 92437c478bd9Sstevel@tonic-gate ipqos_conf_filter_t *flt; 92447c478bd9Sstevel@tonic-gate 92457c478bd9Sstevel@tonic-gate IPQOSCDBG0(APPLY, "In retry_name_lookups:\n"); 92467c478bd9Sstevel@tonic-gate 92477c478bd9Sstevel@tonic-gate for (act = actions; act != NULL; act = act->next) { 92487c478bd9Sstevel@tonic-gate 92497c478bd9Sstevel@tonic-gate /* store start of new resolved filters */ 9250*85280f08SToomas Soome GET_LIST_END(&act->filters, &new_filters); 92517c478bd9Sstevel@tonic-gate 92527c478bd9Sstevel@tonic-gate /* 92537c478bd9Sstevel@tonic-gate * do name resolution on retry list adding resolved filters 92547c478bd9Sstevel@tonic-gate * to end of actions filters. 92557c478bd9Sstevel@tonic-gate */ 92567c478bd9Sstevel@tonic-gate for (flt = act->retry_filters; flt != NULL; flt = flt->next) { 92577c478bd9Sstevel@tonic-gate 92587c478bd9Sstevel@tonic-gate if (domultihome(flt, new_filters, B_TRUE) != 92597c478bd9Sstevel@tonic-gate IPQOS_CONF_SUCCESS) { 92607c478bd9Sstevel@tonic-gate 92617c478bd9Sstevel@tonic-gate /* if resource failure */ 92627c478bd9Sstevel@tonic-gate 92637c478bd9Sstevel@tonic-gate if (flt->nlerr == 0) { 92647c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 92657c478bd9Sstevel@tonic-gate } 92667c478bd9Sstevel@tonic-gate } 92677c478bd9Sstevel@tonic-gate } 92687c478bd9Sstevel@tonic-gate 92697c478bd9Sstevel@tonic-gate /* add the newly resolved filters to the kernel action */ 92707c478bd9Sstevel@tonic-gate 92717c478bd9Sstevel@tonic-gate for (flt = *new_filters; flt != NULL; flt = flt->next) { 92727c478bd9Sstevel@tonic-gate if (add_filter(act->name, flt, act->module_version) != 92737c478bd9Sstevel@tonic-gate IPQOS_CONF_SUCCESS) { 92747c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 92757c478bd9Sstevel@tonic-gate } 92767c478bd9Sstevel@tonic-gate } 92777c478bd9Sstevel@tonic-gate } 92787c478bd9Sstevel@tonic-gate 92797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 92807c478bd9Sstevel@tonic-gate } 92817c478bd9Sstevel@tonic-gate 92827c478bd9Sstevel@tonic-gate /* 92837c478bd9Sstevel@tonic-gate * write the configuration in conf to the file given in dstpath. This 92847c478bd9Sstevel@tonic-gate * is done by writing first to a temporary file and then renaming that 92857c478bd9Sstevel@tonic-gate * file to dstpath. This assures an atomic write. 92867c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on any errors, else IPQOS_CONF_SUCCESS. 92877c478bd9Sstevel@tonic-gate */ 92887c478bd9Sstevel@tonic-gate static int 92897c478bd9Sstevel@tonic-gate writeconf( 92907c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf, 92917c478bd9Sstevel@tonic-gate char *dstpath) 92927c478bd9Sstevel@tonic-gate { 92937c478bd9Sstevel@tonic-gate 92947c478bd9Sstevel@tonic-gate FILE *tmpfp; 92957c478bd9Sstevel@tonic-gate char *tmppath; 92967c478bd9Sstevel@tonic-gate char *pathend; 92977c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 92987c478bd9Sstevel@tonic-gate int res; 92997c478bd9Sstevel@tonic-gate 93007c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "in writeconf\n"); 93017c478bd9Sstevel@tonic-gate 93027c478bd9Sstevel@tonic-gate /* construct tmp file path so we can use rename() */ 93037c478bd9Sstevel@tonic-gate 93047c478bd9Sstevel@tonic-gate pathend = strrchr(dstpath, '/'); 93057c478bd9Sstevel@tonic-gate 93067c478bd9Sstevel@tonic-gate /* dstpath in current dir */ 93077c478bd9Sstevel@tonic-gate 93087c478bd9Sstevel@tonic-gate if (pathend == NULL) { 93097c478bd9Sstevel@tonic-gate tmppath = malloc(strlen("ipqosconf.tmp") + 1); 93107c478bd9Sstevel@tonic-gate if (tmppath == NULL) { 93117c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 93127c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 93137c478bd9Sstevel@tonic-gate } 93147c478bd9Sstevel@tonic-gate (void) strcpy(tmppath, "ipqosconf.tmp"); 93157c478bd9Sstevel@tonic-gate 93167c478bd9Sstevel@tonic-gate /* dstpath in root dir */ 93177c478bd9Sstevel@tonic-gate 93187c478bd9Sstevel@tonic-gate } else if (pathend == dstpath) { 93197c478bd9Sstevel@tonic-gate tmppath = malloc(strlen("/ipqosconf.tmp") + 1); 93207c478bd9Sstevel@tonic-gate if (tmppath == NULL) { 93217c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 93227c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 93237c478bd9Sstevel@tonic-gate } 93247c478bd9Sstevel@tonic-gate (void) strcpy(tmppath, "/ipqosconf.tmp"); 93257c478bd9Sstevel@tonic-gate 93267c478bd9Sstevel@tonic-gate /* not pwd or root */ 93277c478bd9Sstevel@tonic-gate 93287c478bd9Sstevel@tonic-gate } else { 93297c478bd9Sstevel@tonic-gate *pathend = NULL; 93307c478bd9Sstevel@tonic-gate tmppath = malloc(strlen(dstpath) + strlen("/ipqosconf.tmp") + 93317c478bd9Sstevel@tonic-gate 1); 93327c478bd9Sstevel@tonic-gate if (tmppath == NULL) { 93337c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "malloc"); 93347c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 93357c478bd9Sstevel@tonic-gate } 93367c478bd9Sstevel@tonic-gate (void) strcpy(tmppath, dstpath); 93377c478bd9Sstevel@tonic-gate (void) strcat(tmppath, "/ipqosconf.tmp"); 93387c478bd9Sstevel@tonic-gate *pathend = '/'; 93397c478bd9Sstevel@tonic-gate } 93407c478bd9Sstevel@tonic-gate 93417c478bd9Sstevel@tonic-gate 93427c478bd9Sstevel@tonic-gate /* open tmp file */ 93437c478bd9Sstevel@tonic-gate 93447c478bd9Sstevel@tonic-gate tmpfp = fopen(tmppath, "w"); 93457c478bd9Sstevel@tonic-gate if (tmpfp == NULL) { 93467c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "fopen"); 93477c478bd9Sstevel@tonic-gate free(tmppath); 93487c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 93497c478bd9Sstevel@tonic-gate } 93507c478bd9Sstevel@tonic-gate 93517c478bd9Sstevel@tonic-gate /* write out format version */ 93527c478bd9Sstevel@tonic-gate 93537c478bd9Sstevel@tonic-gate (void) fprintf(tmpfp, "%s %d.%d\n\n", IPQOS_FMT_VERSION_STR, 93547c478bd9Sstevel@tonic-gate IPQOS_CUR_FMT_MAJOR_VER, IPQOS_CUR_FMT_MINOR_VER); 93557c478bd9Sstevel@tonic-gate 93567c478bd9Sstevel@tonic-gate /* 93577c478bd9Sstevel@tonic-gate * loop through actions in list writing ipqosconf originated 93587c478bd9Sstevel@tonic-gate * ones out to the tmp file. 93597c478bd9Sstevel@tonic-gate */ 93607c478bd9Sstevel@tonic-gate for (act = conf; act != NULL; act = act->next) { 93617c478bd9Sstevel@tonic-gate if (act->params->originator == IPP_CONFIG_IPQOSCONF) { 93627c478bd9Sstevel@tonic-gate res = printaction(tmpfp, act, 0, 0); 93637c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 93647c478bd9Sstevel@tonic-gate free(tmppath); 93657c478bd9Sstevel@tonic-gate (void) fclose(tmpfp); 93667c478bd9Sstevel@tonic-gate return (res); 93677c478bd9Sstevel@tonic-gate } 93687c478bd9Sstevel@tonic-gate } 93697c478bd9Sstevel@tonic-gate } 93707c478bd9Sstevel@tonic-gate (void) fclose(tmpfp); 93717c478bd9Sstevel@tonic-gate 93727c478bd9Sstevel@tonic-gate /* rename tmp file to dst file */ 93737c478bd9Sstevel@tonic-gate 93747c478bd9Sstevel@tonic-gate if (rename(tmppath, dstpath) != 0) { 93757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "rename"); 93767c478bd9Sstevel@tonic-gate free(tmppath); 93777c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 93787c478bd9Sstevel@tonic-gate } 93797c478bd9Sstevel@tonic-gate free(tmppath); 93807c478bd9Sstevel@tonic-gate 93817c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 93827c478bd9Sstevel@tonic-gate } 93837c478bd9Sstevel@tonic-gate 93847c478bd9Sstevel@tonic-gate /* 93857c478bd9Sstevel@tonic-gate * read the configuration back from the kernel and then write each of the 93867c478bd9Sstevel@tonic-gate * actions read to IPQOS_CONF_INIT_PATH. 93877c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if error, else IPQOS_CONF_SUCCESS. 93887c478bd9Sstevel@tonic-gate */ 93897c478bd9Sstevel@tonic-gate static int 93907c478bd9Sstevel@tonic-gate commitconf() 93917c478bd9Sstevel@tonic-gate { 93927c478bd9Sstevel@tonic-gate 93937c478bd9Sstevel@tonic-gate int ret; 93947c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf; 93957c478bd9Sstevel@tonic-gate 93967c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In commitconf\n"); 93977c478bd9Sstevel@tonic-gate 93987c478bd9Sstevel@tonic-gate /* read the configuration from the kernel */ 93997c478bd9Sstevel@tonic-gate 94007c478bd9Sstevel@tonic-gate ret = readkconf(&conf); 94017c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 94027c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 94037c478bd9Sstevel@tonic-gate } 94047c478bd9Sstevel@tonic-gate 94057c478bd9Sstevel@tonic-gate /* dissallow a null config to be stored (we can't read one in) */ 94067c478bd9Sstevel@tonic-gate 94077c478bd9Sstevel@tonic-gate if (conf == NULL) { 94087c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 94097c478bd9Sstevel@tonic-gate gettext("Can't commit a null configuration.\n")); 94107c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 94117c478bd9Sstevel@tonic-gate } 94127c478bd9Sstevel@tonic-gate 94137c478bd9Sstevel@tonic-gate /* make sure if we create file that perms are 644 */ 94147c478bd9Sstevel@tonic-gate 94157c478bd9Sstevel@tonic-gate (void) umask(S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH); 94167c478bd9Sstevel@tonic-gate 94177c478bd9Sstevel@tonic-gate /* write the configuration to the init file */ 94187c478bd9Sstevel@tonic-gate 94197c478bd9Sstevel@tonic-gate ret = writeconf(conf, IPQOS_CONF_INIT_PATH); 94207c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 94217c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 94227c478bd9Sstevel@tonic-gate } 94237c478bd9Sstevel@tonic-gate 94247c478bd9Sstevel@tonic-gate ipqos_msg(MT_LOG, 94257c478bd9Sstevel@tonic-gate gettext("Current configuration saved to init file.\n")); 94267c478bd9Sstevel@tonic-gate 94277c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 94287c478bd9Sstevel@tonic-gate } 94297c478bd9Sstevel@tonic-gate 94307c478bd9Sstevel@tonic-gate /* 94317c478bd9Sstevel@tonic-gate * Called in the event of a failed rollback. It first flushes the 94327c478bd9Sstevel@tonic-gate * current configuration, then attempts to apply the oconf (the old 94337c478bd9Sstevel@tonic-gate * one), and if that fails flushes again. 94347c478bd9Sstevel@tonic-gate * 94357c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR if the application of old config fails, 94367c478bd9Sstevel@tonic-gate * else IPQOS_CONF_SUCCESS. 94377c478bd9Sstevel@tonic-gate */ 94387c478bd9Sstevel@tonic-gate static int 94397c478bd9Sstevel@tonic-gate rollback_recover( 94407c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oconf) 94417c478bd9Sstevel@tonic-gate { 94427c478bd9Sstevel@tonic-gate int res; 94437c478bd9Sstevel@tonic-gate 94447c478bd9Sstevel@tonic-gate IPQOSCDBG0(RBK, "In rollback_recover\n"); 94457c478bd9Sstevel@tonic-gate 94467c478bd9Sstevel@tonic-gate /* 94477c478bd9Sstevel@tonic-gate * flush configuration. 94487c478bd9Sstevel@tonic-gate */ 94497c478bd9Sstevel@tonic-gate (void) atomic_flush(B_TRUE); 94507c478bd9Sstevel@tonic-gate 94517c478bd9Sstevel@tonic-gate /* 94527c478bd9Sstevel@tonic-gate * mark all elements of old config for application. 94537c478bd9Sstevel@tonic-gate */ 94547c478bd9Sstevel@tonic-gate mark_config_new(oconf); 94557c478bd9Sstevel@tonic-gate 94567c478bd9Sstevel@tonic-gate /* 94577c478bd9Sstevel@tonic-gate * attempt to apply old config. 94587c478bd9Sstevel@tonic-gate */ 94597c478bd9Sstevel@tonic-gate res = applydiff(oconf, NULL); 94607c478bd9Sstevel@tonic-gate /* 94617c478bd9Sstevel@tonic-gate * if failed force flush of config. 94627c478bd9Sstevel@tonic-gate */ 94637c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 94647c478bd9Sstevel@tonic-gate (void) atomic_flush(B_TRUE); 94657c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 94667c478bd9Sstevel@tonic-gate } 94677c478bd9Sstevel@tonic-gate 94687c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 94697c478bd9Sstevel@tonic-gate } 94707c478bd9Sstevel@tonic-gate 94717c478bd9Sstevel@tonic-gate /* 94727c478bd9Sstevel@tonic-gate * read and apply the configuration contained if file ifile to the kernel. 94737c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 94747c478bd9Sstevel@tonic-gate */ 94757c478bd9Sstevel@tonic-gate static int 94767c478bd9Sstevel@tonic-gate applyconf(char *ifile) 94777c478bd9Sstevel@tonic-gate { 94787c478bd9Sstevel@tonic-gate 94797c478bd9Sstevel@tonic-gate FILE *ifp; 94807c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf = NULL; 94817c478bd9Sstevel@tonic-gate ipqos_conf_action_t *oconf = NULL; 94827c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act, *oact; 94837c478bd9Sstevel@tonic-gate int res; 94847c478bd9Sstevel@tonic-gate 94857c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In applyconf:\n"); 94867c478bd9Sstevel@tonic-gate 94877c478bd9Sstevel@tonic-gate 94887c478bd9Sstevel@tonic-gate /* if filename '-' read from stdin */ 94897c478bd9Sstevel@tonic-gate 94907c478bd9Sstevel@tonic-gate if (strcmp(ifile, "-") == 0) { 94917c478bd9Sstevel@tonic-gate ifp = stdin; 94927c478bd9Sstevel@tonic-gate } else { 94937c478bd9Sstevel@tonic-gate ifp = fopen(ifile, "r"); 94947c478bd9Sstevel@tonic-gate if (ifp == NULL) { 94957c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 94967c478bd9Sstevel@tonic-gate gettext("Opening file %s for read: %s.\n"), 94977c478bd9Sstevel@tonic-gate ifile, strerror(errno)); 94987c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 94997c478bd9Sstevel@tonic-gate } 95007c478bd9Sstevel@tonic-gate } 95017c478bd9Sstevel@tonic-gate 95027c478bd9Sstevel@tonic-gate /* read in new configuration */ 95037c478bd9Sstevel@tonic-gate 95047c478bd9Sstevel@tonic-gate res = readconf(ifp, &conf); 95057c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95067c478bd9Sstevel@tonic-gate goto fail; 95077c478bd9Sstevel@tonic-gate } 95087c478bd9Sstevel@tonic-gate 95097c478bd9Sstevel@tonic-gate /* check configuration is valid */ 95107c478bd9Sstevel@tonic-gate 95117c478bd9Sstevel@tonic-gate res = validconf(conf, 1); 95127c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95137c478bd9Sstevel@tonic-gate goto fail; 95147c478bd9Sstevel@tonic-gate } 95157c478bd9Sstevel@tonic-gate 95167c478bd9Sstevel@tonic-gate /* read in kernel configuration */ 95177c478bd9Sstevel@tonic-gate 95187c478bd9Sstevel@tonic-gate res = readkconf(&oconf); 95197c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95207c478bd9Sstevel@tonic-gate goto fail; 95217c478bd9Sstevel@tonic-gate } 95227c478bd9Sstevel@tonic-gate 95237c478bd9Sstevel@tonic-gate /* 95247c478bd9Sstevel@tonic-gate * check there are no same named actions in both config file and the 95257c478bd9Sstevel@tonic-gate * the kernel that are for a different module. The application 95267c478bd9Sstevel@tonic-gate * system can't handle these as we would try to add the new 95277c478bd9Sstevel@tonic-gate * action before we deleted the old one and because actions 95287c478bd9Sstevel@tonic-gate * in the kernel are indexed solely on their name (their module 95297c478bd9Sstevel@tonic-gate * isn't included) the kernel would return an error. We want 95307c478bd9Sstevel@tonic-gate * to avoid this error and the resulting rollback. 95317c478bd9Sstevel@tonic-gate */ 95327c478bd9Sstevel@tonic-gate for (act = conf; act != NULL; act = act->next) { 95337c478bd9Sstevel@tonic-gate for (oact = oconf; oact != NULL; oact = oact->next) { 95347c478bd9Sstevel@tonic-gate /* found action */ 95357c478bd9Sstevel@tonic-gate if (strcmp(act->name, oact->name) == 0) { 95367c478bd9Sstevel@tonic-gate /* different module */ 95377c478bd9Sstevel@tonic-gate if (strcmp(act->module, oact->module) != 0) { 95387c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 95397c478bd9Sstevel@tonic-gate gettext("Action at line %u has " 95407c478bd9Sstevel@tonic-gate "same name as currently " 95417c478bd9Sstevel@tonic-gate "installed action, but is for a " 95427c478bd9Sstevel@tonic-gate "different module.\n"), 95437c478bd9Sstevel@tonic-gate act->lineno); 95447c478bd9Sstevel@tonic-gate goto fail; 95457c478bd9Sstevel@tonic-gate /* same module - stop search */ 95467c478bd9Sstevel@tonic-gate } else { 95477c478bd9Sstevel@tonic-gate break; 95487c478bd9Sstevel@tonic-gate } 95497c478bd9Sstevel@tonic-gate } 95507c478bd9Sstevel@tonic-gate } 95517c478bd9Sstevel@tonic-gate } 95527c478bd9Sstevel@tonic-gate 95537c478bd9Sstevel@tonic-gate 95547c478bd9Sstevel@tonic-gate /* create links between actions for use with deletions etc.. */ 95557c478bd9Sstevel@tonic-gate 95567c478bd9Sstevel@tonic-gate res = validconf(oconf, 0); 95577c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95587c478bd9Sstevel@tonic-gate goto fail; 95597c478bd9Sstevel@tonic-gate } 95607c478bd9Sstevel@tonic-gate 95617c478bd9Sstevel@tonic-gate /* diff conf file against kernel */ 95627c478bd9Sstevel@tonic-gate 95637c478bd9Sstevel@tonic-gate res = diffconf(oconf, conf); 95647c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95657c478bd9Sstevel@tonic-gate goto fail; 95667c478bd9Sstevel@tonic-gate } 95677c478bd9Sstevel@tonic-gate 95687c478bd9Sstevel@tonic-gate /* make kernel mods as atomic as possible */ 95697c478bd9Sstevel@tonic-gate 95707c478bd9Sstevel@tonic-gate if ((res = block_all_signals()) == -1) { 95717c478bd9Sstevel@tonic-gate res = IPQOS_CONF_ERR; 95727c478bd9Sstevel@tonic-gate goto fail; 95737c478bd9Sstevel@tonic-gate } 95747c478bd9Sstevel@tonic-gate 95757c478bd9Sstevel@tonic-gate /* apply difference to kernel */ 95767c478bd9Sstevel@tonic-gate 95777c478bd9Sstevel@tonic-gate res = applydiff(conf, oconf); 95787c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 95797c478bd9Sstevel@tonic-gate if (force_rback || res != IPQOS_CONF_SUCCESS) { 95807c478bd9Sstevel@tonic-gate #else 95817c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95827c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 95837c478bd9Sstevel@tonic-gate 95847c478bd9Sstevel@tonic-gate res = rollback(conf, oconf); 95857c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95867c478bd9Sstevel@tonic-gate res = rollback_recover(oconf); 95877c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 95887c478bd9Sstevel@tonic-gate /* system left flushed */ 95897c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 95907c478bd9Sstevel@tonic-gate gettext("Failed to rollback from failed " 95917c478bd9Sstevel@tonic-gate "configuration, configuration flushed.\n")); 95927c478bd9Sstevel@tonic-gate res = IPQOS_CONF_RECOVER_ERR; 95937c478bd9Sstevel@tonic-gate } else { /* old config re-applied */ 95947c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 95957c478bd9Sstevel@tonic-gate gettext("Configuration failed, system " 95967c478bd9Sstevel@tonic-gate "state unchanged.\n")); 95977c478bd9Sstevel@tonic-gate res = IPQOS_CONF_ERR; 95987c478bd9Sstevel@tonic-gate } 95997c478bd9Sstevel@tonic-gate } else { 96007c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 96017c478bd9Sstevel@tonic-gate gettext("Configuration failed, system " 96027c478bd9Sstevel@tonic-gate "state unchanged.\n")); 96037c478bd9Sstevel@tonic-gate res = IPQOS_CONF_ERR; 96047c478bd9Sstevel@tonic-gate } 96057c478bd9Sstevel@tonic-gate goto fail; 96067c478bd9Sstevel@tonic-gate } 96077c478bd9Sstevel@tonic-gate 96087c478bd9Sstevel@tonic-gate /* retry any soft name lookup failures */ 96097c478bd9Sstevel@tonic-gate 96107c478bd9Sstevel@tonic-gate res = retry_name_lookups(conf); 96117c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 96127c478bd9Sstevel@tonic-gate res = rollback(conf, oconf); 96137c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 96147c478bd9Sstevel@tonic-gate res = rollback_recover(oconf); 96157c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 96167c478bd9Sstevel@tonic-gate /* system left flushed */ 96177c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 96187c478bd9Sstevel@tonic-gate gettext("Failed to rollback from failed " 96197c478bd9Sstevel@tonic-gate "configuration, configuration flushed.\n")); 96207c478bd9Sstevel@tonic-gate res = IPQOS_CONF_RECOVER_ERR; 96217c478bd9Sstevel@tonic-gate } else { /* old config re-applied */ 96227c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 96237c478bd9Sstevel@tonic-gate gettext("Configuration failed, system " 96247c478bd9Sstevel@tonic-gate "state unchanged.\n")); 96257c478bd9Sstevel@tonic-gate res = IPQOS_CONF_ERR; 96267c478bd9Sstevel@tonic-gate } 96277c478bd9Sstevel@tonic-gate } else { 96287c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, 96297c478bd9Sstevel@tonic-gate gettext("Configuration failed, system " 96307c478bd9Sstevel@tonic-gate "state unchanged.\n")); 96317c478bd9Sstevel@tonic-gate res = IPQOS_CONF_ERR; 96327c478bd9Sstevel@tonic-gate } 96337c478bd9Sstevel@tonic-gate goto fail; 96347c478bd9Sstevel@tonic-gate 96357c478bd9Sstevel@tonic-gate } 96367c478bd9Sstevel@tonic-gate 96377c478bd9Sstevel@tonic-gate ipqos_msg(MT_LOG, gettext("IPQoS configuration applied.\n")); 96387c478bd9Sstevel@tonic-gate 96397c478bd9Sstevel@tonic-gate /* re-enable signals */ 96407c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 96417c478bd9Sstevel@tonic-gate 96427c478bd9Sstevel@tonic-gate (void) fclose(ifp); 96437c478bd9Sstevel@tonic-gate free_actions(conf); 96447c478bd9Sstevel@tonic-gate free_actions(oconf); 96457c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 96467c478bd9Sstevel@tonic-gate fail: 96477c478bd9Sstevel@tonic-gate (void) fclose(ifp); 96487c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 96497c478bd9Sstevel@tonic-gate if (conf) 96507c478bd9Sstevel@tonic-gate free_actions(conf); 96517c478bd9Sstevel@tonic-gate if (oconf) 96527c478bd9Sstevel@tonic-gate free_actions(oconf); 96537c478bd9Sstevel@tonic-gate if (res == IPQOS_CONF_RECOVER_ERR) 96547c478bd9Sstevel@tonic-gate ipqos_msg(MT_LOG, gettext("Configuration flushed.\n")); 96557c478bd9Sstevel@tonic-gate return (res); 96567c478bd9Sstevel@tonic-gate } 96577c478bd9Sstevel@tonic-gate 96587c478bd9Sstevel@tonic-gate static sigset_t set, oset; 96597c478bd9Sstevel@tonic-gate 96607c478bd9Sstevel@tonic-gate static int 96617c478bd9Sstevel@tonic-gate block_all_signals() 96627c478bd9Sstevel@tonic-gate { 96637c478bd9Sstevel@tonic-gate if (sigfillset(&set) == -1) { 96647c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "sigfillset"); 96657c478bd9Sstevel@tonic-gate return (-1); 96667c478bd9Sstevel@tonic-gate } 96677c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) { 96687c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "sigprocmask"); 96697c478bd9Sstevel@tonic-gate return (-1); 96707c478bd9Sstevel@tonic-gate } 96717c478bd9Sstevel@tonic-gate return (0); 96727c478bd9Sstevel@tonic-gate } 96737c478bd9Sstevel@tonic-gate 96747c478bd9Sstevel@tonic-gate static int 96757c478bd9Sstevel@tonic-gate restore_all_signals() 96767c478bd9Sstevel@tonic-gate { 96777c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { 96787c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "sigprocmask"); 96797c478bd9Sstevel@tonic-gate return (-1); 96807c478bd9Sstevel@tonic-gate } 96817c478bd9Sstevel@tonic-gate return (0); 96827c478bd9Sstevel@tonic-gate } 96837c478bd9Sstevel@tonic-gate 96847c478bd9Sstevel@tonic-gate static int 96857c478bd9Sstevel@tonic-gate unlock(int fd) 96867c478bd9Sstevel@tonic-gate { 96877c478bd9Sstevel@tonic-gate if (lockf(fd, F_ULOCK, 0) == -1) { 96887c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "lockf"); 96897c478bd9Sstevel@tonic-gate return (-1); 96907c478bd9Sstevel@tonic-gate } 96917c478bd9Sstevel@tonic-gate return (0); 96927c478bd9Sstevel@tonic-gate } 96937c478bd9Sstevel@tonic-gate 96947c478bd9Sstevel@tonic-gate static int 96957c478bd9Sstevel@tonic-gate lock() 96967c478bd9Sstevel@tonic-gate { 96977c478bd9Sstevel@tonic-gate int fd; 96987c478bd9Sstevel@tonic-gate struct stat sbuf1; 96997c478bd9Sstevel@tonic-gate struct stat sbuf2; 97007c478bd9Sstevel@tonic-gate 97017c478bd9Sstevel@tonic-gate /* 97027c478bd9Sstevel@tonic-gate * Open the file with O_CREAT|O_EXCL. If it exists already, it 97037c478bd9Sstevel@tonic-gate * will fail. If it already exists, check whether it looks like 97047c478bd9Sstevel@tonic-gate * the one we created. 97057c478bd9Sstevel@tonic-gate */ 97067c478bd9Sstevel@tonic-gate (void) umask(0077); 97077c478bd9Sstevel@tonic-gate if ((fd = open(IPQOS_CONF_LOCK_FILE, O_EXCL|O_CREAT|O_RDWR, 97087c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR)) == -1) { 97097c478bd9Sstevel@tonic-gate if (errno != EEXIST) { 97107c478bd9Sstevel@tonic-gate /* Some other problem. */ 97117c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 97127c478bd9Sstevel@tonic-gate gettext("Cannot open lock file %s"), 97137c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97147c478bd9Sstevel@tonic-gate return (-1); 97157c478bd9Sstevel@tonic-gate } 97167c478bd9Sstevel@tonic-gate 97177c478bd9Sstevel@tonic-gate /* 97187c478bd9Sstevel@tonic-gate * open() returned an EEXIST error. We don't fail yet 97197c478bd9Sstevel@tonic-gate * as it could be a residual from a previous 97207c478bd9Sstevel@tonic-gate * execution. However, we need to clear errno here. 97217c478bd9Sstevel@tonic-gate * If we don't and print_cmd_buf() is later invoked 97227c478bd9Sstevel@tonic-gate * as the result of a parsing error, it 97237c478bd9Sstevel@tonic-gate * will assume that the current error is EEXIST and 97247c478bd9Sstevel@tonic-gate * that a corresponding error message has already been 97257c478bd9Sstevel@tonic-gate * printed, which results in an incomplete error 97267c478bd9Sstevel@tonic-gate * message. If errno is zero, print_cmd_buf() will 97277c478bd9Sstevel@tonic-gate * assume that it is called as a result of a 97287c478bd9Sstevel@tonic-gate * parsing error and will print the appropriate 97297c478bd9Sstevel@tonic-gate * error message. 97307c478bd9Sstevel@tonic-gate */ 97317c478bd9Sstevel@tonic-gate errno = 0; 97327c478bd9Sstevel@tonic-gate 97337c478bd9Sstevel@tonic-gate /* 97347c478bd9Sstevel@tonic-gate * File exists. make sure it is OK. We need to lstat() 97357c478bd9Sstevel@tonic-gate * as fstat() stats the file pointed to by the symbolic 97367c478bd9Sstevel@tonic-gate * link. 97377c478bd9Sstevel@tonic-gate */ 97387c478bd9Sstevel@tonic-gate if (lstat(IPQOS_CONF_LOCK_FILE, &sbuf1) == -1) { 97397c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 97407c478bd9Sstevel@tonic-gate gettext("Cannot lstat lock file %s\n"), 97417c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97427c478bd9Sstevel@tonic-gate return (-1); 97437c478bd9Sstevel@tonic-gate } 97447c478bd9Sstevel@tonic-gate /* 97457c478bd9Sstevel@tonic-gate * Check whether it is a regular file and not a symbolic 97467c478bd9Sstevel@tonic-gate * link. Its link count should be 1. The owner should be 97477c478bd9Sstevel@tonic-gate * root and the file should be empty. 97487c478bd9Sstevel@tonic-gate */ 97494bc0a2efScasper if (!S_ISREG(sbuf1.st_mode) || 97507c478bd9Sstevel@tonic-gate sbuf1.st_nlink != 1 || 97517c478bd9Sstevel@tonic-gate sbuf1.st_uid != 0 || 97527c478bd9Sstevel@tonic-gate sbuf1.st_size != 0) { 97537c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Bad lock file %s.\n"), 97547c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97557c478bd9Sstevel@tonic-gate return (-1); 97567c478bd9Sstevel@tonic-gate } 97577c478bd9Sstevel@tonic-gate if ((fd = open(IPQOS_CONF_LOCK_FILE, O_CREAT|O_RDWR, 97587c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR)) == -1) { 97597c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 97607c478bd9Sstevel@tonic-gate gettext("Cannot open lock file %s"), 97617c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97627c478bd9Sstevel@tonic-gate return (-1); 97637c478bd9Sstevel@tonic-gate } 97647c478bd9Sstevel@tonic-gate 97657c478bd9Sstevel@tonic-gate /* Check whether we opened the file that we lstat()ed. */ 97667c478bd9Sstevel@tonic-gate if (fstat(fd, &sbuf2) == -1) { 97677c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, 97687c478bd9Sstevel@tonic-gate gettext("Cannot fstat lock file %s\n"), 97697c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97707c478bd9Sstevel@tonic-gate return (-1); 97717c478bd9Sstevel@tonic-gate } 97727c478bd9Sstevel@tonic-gate if (sbuf1.st_dev != sbuf2.st_dev || 97737c478bd9Sstevel@tonic-gate sbuf1.st_ino != sbuf2.st_ino) { 97747c478bd9Sstevel@tonic-gate /* File changed after we did the lstat() above */ 97757c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Bad lock file %s.\n"), 97767c478bd9Sstevel@tonic-gate IPQOS_CONF_LOCK_FILE); 97777c478bd9Sstevel@tonic-gate return (-1); 97787c478bd9Sstevel@tonic-gate } 97797c478bd9Sstevel@tonic-gate } 97807c478bd9Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) == -1) { 97817c478bd9Sstevel@tonic-gate ipqos_msg(MT_ENOSTR, "lockf"); 97827c478bd9Sstevel@tonic-gate return (-1); 97837c478bd9Sstevel@tonic-gate } 97847c478bd9Sstevel@tonic-gate return (fd); 97857c478bd9Sstevel@tonic-gate } 97867c478bd9Sstevel@tonic-gate 97877c478bd9Sstevel@tonic-gate /* 97887c478bd9Sstevel@tonic-gate * print the current kernel configuration out to stdout. If viewall 97897c478bd9Sstevel@tonic-gate * is set this causes more verbose configuration listing including 97907c478bd9Sstevel@tonic-gate * showing objects we didn't create, each instance of a mhome filter, 97917c478bd9Sstevel@tonic-gate * etc.. see printaction(). 97927c478bd9Sstevel@tonic-gate * RETURNS: IPQOS_CONF_ERR on error, else IPQOS_CONF_SUCCES. 97937c478bd9Sstevel@tonic-gate */ 97947c478bd9Sstevel@tonic-gate 97957c478bd9Sstevel@tonic-gate static int 97967c478bd9Sstevel@tonic-gate viewconf(int viewall) 97977c478bd9Sstevel@tonic-gate { 97987c478bd9Sstevel@tonic-gate 97997c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf = NULL; 98007c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 98017c478bd9Sstevel@tonic-gate int ret; 98027c478bd9Sstevel@tonic-gate 98037c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In viewconf\n"); 98047c478bd9Sstevel@tonic-gate 98057c478bd9Sstevel@tonic-gate /* get kernel configuration */ 98067c478bd9Sstevel@tonic-gate 98077c478bd9Sstevel@tonic-gate ret = readkconf(&conf); 98087c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 98097c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 98107c478bd9Sstevel@tonic-gate } 98117c478bd9Sstevel@tonic-gate 98127c478bd9Sstevel@tonic-gate /* write out format version */ 98137c478bd9Sstevel@tonic-gate 98147c478bd9Sstevel@tonic-gate if (conf != NULL) { 98157c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s %d.%d\n\n", IPQOS_FMT_VERSION_STR, 98167c478bd9Sstevel@tonic-gate IPQOS_CUR_FMT_MAJOR_VER, IPQOS_CUR_FMT_MINOR_VER); 98177c478bd9Sstevel@tonic-gate } 98187c478bd9Sstevel@tonic-gate 98197c478bd9Sstevel@tonic-gate /* print each of the actions in the kernel config to stdout */ 98207c478bd9Sstevel@tonic-gate 98217c478bd9Sstevel@tonic-gate for (act = conf; act != NULL; act = act->next) { 98227c478bd9Sstevel@tonic-gate ret = printaction(stdout, act, viewall, 0); 98237c478bd9Sstevel@tonic-gate if (ret != IPQOS_CONF_SUCCESS) { 98247c478bd9Sstevel@tonic-gate free_actions(conf); 98257c478bd9Sstevel@tonic-gate return (ret); 98267c478bd9Sstevel@tonic-gate } 98277c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 98287c478bd9Sstevel@tonic-gate } 98297c478bd9Sstevel@tonic-gate 98307c478bd9Sstevel@tonic-gate free_actions(conf); 98317c478bd9Sstevel@tonic-gate 98327c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 98337c478bd9Sstevel@tonic-gate } 98347c478bd9Sstevel@tonic-gate 98357c478bd9Sstevel@tonic-gate 98367c478bd9Sstevel@tonic-gate /* 98377c478bd9Sstevel@tonic-gate * debug function that reads the config file and prints it out after 98387c478bd9Sstevel@tonic-gate * interpreting to stdout. 98397c478bd9Sstevel@tonic-gate */ 98407c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 98417c478bd9Sstevel@tonic-gate static int 98427c478bd9Sstevel@tonic-gate viewcfile(char *cfile) 98437c478bd9Sstevel@tonic-gate { 98447c478bd9Sstevel@tonic-gate 98457c478bd9Sstevel@tonic-gate ipqos_conf_action_t *conf; 98467c478bd9Sstevel@tonic-gate ipqos_conf_action_t *act; 98477c478bd9Sstevel@tonic-gate int res; 98487c478bd9Sstevel@tonic-gate FILE *ifp; 98497c478bd9Sstevel@tonic-gate int viewall = 1; 98507c478bd9Sstevel@tonic-gate 98517c478bd9Sstevel@tonic-gate IPQOSCDBG0(L0, "In viewcfile\n"); 98527c478bd9Sstevel@tonic-gate ifp = fopen(cfile, "r"); 98537c478bd9Sstevel@tonic-gate if (ifp == NULL) { 98547c478bd9Sstevel@tonic-gate ipqos_msg(MT_ERROR, gettext("Opening file %s for read: %s.\n"), 98557c478bd9Sstevel@tonic-gate cfile, strerror(errno)); 98567c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 98577c478bd9Sstevel@tonic-gate } 98587c478bd9Sstevel@tonic-gate 98597c478bd9Sstevel@tonic-gate res = readconf(ifp, &conf); 98607c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 98617c478bd9Sstevel@tonic-gate free(ifp); 98627c478bd9Sstevel@tonic-gate return (IPQOS_CONF_ERR); 98637c478bd9Sstevel@tonic-gate } 98647c478bd9Sstevel@tonic-gate 98657c478bd9Sstevel@tonic-gate /* print each of the actions in the kernel config to stdout */ 98667c478bd9Sstevel@tonic-gate for (act = conf; act != NULL; act = act->next) { 98677c478bd9Sstevel@tonic-gate res = printaction(stdout, act, viewall, 0); 98687c478bd9Sstevel@tonic-gate if (res != IPQOS_CONF_SUCCESS) { 98697c478bd9Sstevel@tonic-gate free(ifp); 98707c478bd9Sstevel@tonic-gate return (res); 98717c478bd9Sstevel@tonic-gate } 98727c478bd9Sstevel@tonic-gate 98737c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 98747c478bd9Sstevel@tonic-gate } 98757c478bd9Sstevel@tonic-gate 98767c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 98777c478bd9Sstevel@tonic-gate 98787c478bd9Sstevel@tonic-gate 98797c478bd9Sstevel@tonic-gate return (IPQOS_CONF_SUCCESS); 98807c478bd9Sstevel@tonic-gate } 98817c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 98827c478bd9Sstevel@tonic-gate 98837c478bd9Sstevel@tonic-gate static void 98847c478bd9Sstevel@tonic-gate usage(void) 98857c478bd9Sstevel@tonic-gate { 98867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage:\n" 98877c478bd9Sstevel@tonic-gate "\tipqosconf [-sv] -a file|-\n" 98887c478bd9Sstevel@tonic-gate "\tipqosconf -c\n" 98897c478bd9Sstevel@tonic-gate "\tipqosconf -l\n" 98907c478bd9Sstevel@tonic-gate "\tipqosconf -L\n" 98917c478bd9Sstevel@tonic-gate "\tipqosconf -f\n")); 98927c478bd9Sstevel@tonic-gate } 98937c478bd9Sstevel@tonic-gate 98947c478bd9Sstevel@tonic-gate int 98957c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 98967c478bd9Sstevel@tonic-gate { 98977c478bd9Sstevel@tonic-gate 98987c478bd9Sstevel@tonic-gate int c; 98997c478bd9Sstevel@tonic-gate char *ifile = NULL; 99007c478bd9Sstevel@tonic-gate int args; 99017c478bd9Sstevel@tonic-gate int ret; 99027c478bd9Sstevel@tonic-gate int cmd; 99037c478bd9Sstevel@tonic-gate int viewall = 0; 99047c478bd9Sstevel@tonic-gate int lfp; 99057c478bd9Sstevel@tonic-gate 99067c478bd9Sstevel@tonic-gate /* init global flags */ 99077c478bd9Sstevel@tonic-gate use_syslog = verbose = 0; 99087c478bd9Sstevel@tonic-gate 99097c478bd9Sstevel@tonic-gate /* init current line number */ 99107c478bd9Sstevel@tonic-gate lineno = 0; 99117c478bd9Sstevel@tonic-gate 99127c478bd9Sstevel@tonic-gate /* setup internationalisation */ 99137c478bd9Sstevel@tonic-gate 99147c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 99157c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 99167c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 99177c478bd9Sstevel@tonic-gate #endif 99187c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 99197c478bd9Sstevel@tonic-gate 99207c478bd9Sstevel@tonic-gate /* setup syslog parameters */ 99217c478bd9Sstevel@tonic-gate openlog("ipqosconf", 0, LOG_USER); 99227c478bd9Sstevel@tonic-gate 99237c478bd9Sstevel@tonic-gate args = 0; 99247c478bd9Sstevel@tonic-gate 99257c478bd9Sstevel@tonic-gate /* enable debug options */ 99267c478bd9Sstevel@tonic-gate 99277c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 99287c478bd9Sstevel@tonic-gate #define DBGOPTS "rz:" 99297c478bd9Sstevel@tonic-gate #else 99307c478bd9Sstevel@tonic-gate #define DBGOPTS 99317c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 99327c478bd9Sstevel@tonic-gate 99337c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "sca:vflL" DBGOPTS)) != EOF) { 99347c478bd9Sstevel@tonic-gate switch (c) { 99357c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 99367c478bd9Sstevel@tonic-gate case 'z': 99377c478bd9Sstevel@tonic-gate cmd = -1; 99387c478bd9Sstevel@tonic-gate ifile = optarg; 99397c478bd9Sstevel@tonic-gate if (*ifile == '\0') { 99407c478bd9Sstevel@tonic-gate usage(); 99417c478bd9Sstevel@tonic-gate exit(1); 99427c478bd9Sstevel@tonic-gate } 99437c478bd9Sstevel@tonic-gate args++; 99447c478bd9Sstevel@tonic-gate break; 99457c478bd9Sstevel@tonic-gate case 'r': 99467c478bd9Sstevel@tonic-gate force_rback++; 99477c478bd9Sstevel@tonic-gate break; 99487c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 99497c478bd9Sstevel@tonic-gate case 'c': 99507c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_COMMIT; 99517c478bd9Sstevel@tonic-gate args++; 99527c478bd9Sstevel@tonic-gate break; 99537c478bd9Sstevel@tonic-gate case 'a': 99547c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_APPLY; 99557c478bd9Sstevel@tonic-gate ifile = optarg; 99567c478bd9Sstevel@tonic-gate if (*ifile == '\0') { 99577c478bd9Sstevel@tonic-gate usage(); 99587c478bd9Sstevel@tonic-gate exit(1); 99597c478bd9Sstevel@tonic-gate } 99607c478bd9Sstevel@tonic-gate args++; 99617c478bd9Sstevel@tonic-gate break; 99627c478bd9Sstevel@tonic-gate case 'f': 99637c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_FLUSH; 99647c478bd9Sstevel@tonic-gate args++; 99657c478bd9Sstevel@tonic-gate break; 99667c478bd9Sstevel@tonic-gate case 'l': 99677c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_VIEW; 99687c478bd9Sstevel@tonic-gate args++; 99697c478bd9Sstevel@tonic-gate break; 99707c478bd9Sstevel@tonic-gate case 'L': 99717c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_VIEW; 99727c478bd9Sstevel@tonic-gate viewall++; 99737c478bd9Sstevel@tonic-gate args++; 99747c478bd9Sstevel@tonic-gate break; 99757c478bd9Sstevel@tonic-gate case 'v': 99767c478bd9Sstevel@tonic-gate verbose++; 99777c478bd9Sstevel@tonic-gate break; 99787c478bd9Sstevel@tonic-gate case 's': 99797c478bd9Sstevel@tonic-gate use_syslog++; 99807c478bd9Sstevel@tonic-gate break; 99817c478bd9Sstevel@tonic-gate case '?': 99827c478bd9Sstevel@tonic-gate usage(); 99837c478bd9Sstevel@tonic-gate return (1); 99847c478bd9Sstevel@tonic-gate } 99857c478bd9Sstevel@tonic-gate } 99867c478bd9Sstevel@tonic-gate 99877c478bd9Sstevel@tonic-gate /* 99887c478bd9Sstevel@tonic-gate * dissallow non-option args, > 1 cmd args and syslog/verbose flags set 99897c478bd9Sstevel@tonic-gate * for anything but apply. 99907c478bd9Sstevel@tonic-gate */ 99917c478bd9Sstevel@tonic-gate if (optind != argc || args > 1 || 99927c478bd9Sstevel@tonic-gate use_syslog && cmd != IPQOS_CONF_APPLY || 99937c478bd9Sstevel@tonic-gate verbose && cmd != IPQOS_CONF_APPLY) { 99947c478bd9Sstevel@tonic-gate usage(); 99957c478bd9Sstevel@tonic-gate exit(1); 99967c478bd9Sstevel@tonic-gate } 99977c478bd9Sstevel@tonic-gate 99987c478bd9Sstevel@tonic-gate /* if no cmd option then show config */ 99997c478bd9Sstevel@tonic-gate 100007c478bd9Sstevel@tonic-gate if (args == 0) { 100017c478bd9Sstevel@tonic-gate cmd = IPQOS_CONF_VIEW; 100027c478bd9Sstevel@tonic-gate } 100037c478bd9Sstevel@tonic-gate 100047c478bd9Sstevel@tonic-gate /* stop concurrent ipqosconf invocations */ 100057c478bd9Sstevel@tonic-gate lfp = lock(); 100067c478bd9Sstevel@tonic-gate if (lfp == -1) { 100077c478bd9Sstevel@tonic-gate exit(1); 100087c478bd9Sstevel@tonic-gate } 100097c478bd9Sstevel@tonic-gate 100107c478bd9Sstevel@tonic-gate switch (cmd) { 100117c478bd9Sstevel@tonic-gate #ifdef _IPQOS_CONF_DEBUG 100127c478bd9Sstevel@tonic-gate case -1: 100137c478bd9Sstevel@tonic-gate ret = viewcfile(ifile); 100147c478bd9Sstevel@tonic-gate break; 100157c478bd9Sstevel@tonic-gate #endif /* _IPQOS_CONF_DEBUG */ 100167c478bd9Sstevel@tonic-gate case IPQOS_CONF_APPLY: 100177c478bd9Sstevel@tonic-gate ret = applyconf(ifile); 100187c478bd9Sstevel@tonic-gate break; 100197c478bd9Sstevel@tonic-gate case IPQOS_CONF_COMMIT: 100207c478bd9Sstevel@tonic-gate ret = commitconf(); 100217c478bd9Sstevel@tonic-gate break; 100227c478bd9Sstevel@tonic-gate case IPQOS_CONF_VIEW: 100237c478bd9Sstevel@tonic-gate ret = viewconf(viewall); 100247c478bd9Sstevel@tonic-gate break; 100257c478bd9Sstevel@tonic-gate case IPQOS_CONF_FLUSH: 100267c478bd9Sstevel@tonic-gate ret = flushconf(); 100277c478bd9Sstevel@tonic-gate break; 100287c478bd9Sstevel@tonic-gate } 100297c478bd9Sstevel@tonic-gate 100307c478bd9Sstevel@tonic-gate (void) unlock(lfp); 100317c478bd9Sstevel@tonic-gate 100327c478bd9Sstevel@tonic-gate return (ret); 100337c478bd9Sstevel@tonic-gate 100347c478bd9Sstevel@tonic-gate } 10035