1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl /* 220dfdd7f3Smichen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #ifndef _NSCD_SWITCH_H 27cb5caa98Sdjl #define _NSCD_SWITCH_H 28cb5caa98Sdjl 29cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 30cb5caa98Sdjl 31cb5caa98Sdjl #ifdef __cplusplus 32cb5caa98Sdjl extern "C" { 33cb5caa98Sdjl #endif 34cb5caa98Sdjl 35cb5caa98Sdjl #include <nss_dbdefs.h> 36cb5caa98Sdjl #include <thread.h> 37cb5caa98Sdjl #include <libscf.h> 38cb5caa98Sdjl #define __NSS_PRIVATE_INTERFACE 39cb5caa98Sdjl #include "nsswitch_priv.h" 40cb5caa98Sdjl #undef __NSS_PRIVATE_INTERFACE 41cb5caa98Sdjl #include "nscd_db.h" 42cb5caa98Sdjl #include "nscd_config.h" 43cb5caa98Sdjl 44cb5caa98Sdjl /* 45cb5caa98Sdjl * max. length of e.g. "passwd: files ldap" 46cb5caa98Sdjl */ 47cb5caa98Sdjl #define MAX_NSSWITCH_CONFIG_STRING_SZ 256 48cb5caa98Sdjl 49cb5caa98Sdjl /* 50cb5caa98Sdjl * max. length of the name of a NSS database 51cb5caa98Sdjl */ 52cb5caa98Sdjl #define MAX_NSSWITCH_CONFIG_DB_NAME_SZ 256 53cb5caa98Sdjl 54cb5caa98Sdjl /* 55cb5caa98Sdjl * nscd_nsw_config_t is an abstraction of the configuration 56cb5caa98Sdjl * for a NSS database 57cb5caa98Sdjl */ 58cb5caa98Sdjl typedef struct { 59cb5caa98Sdjl char *db_name; 60cb5caa98Sdjl char *nsw_cfg_str; 61cb5caa98Sdjl nss_db_params_t fe_params; 62cb5caa98Sdjl struct __nsw_switchconfig_v1 *nsw_config; 63cb5caa98Sdjl int max_src; 64cb5caa98Sdjl int *src_idx; /* ptr to array of */ 65cb5caa98Sdjl /* src index */ 66cb5caa98Sdjl int nobase; /* not shared */ 67cb5caa98Sdjl } nscd_nsw_config_t; 68cb5caa98Sdjl 69cb5caa98Sdjl /* 70cb5caa98Sdjl * nscd_be_info_t is an abstraction of a NSS backend 71cb5caa98Sdjl */ 72cb5caa98Sdjl typedef struct { 73cb5caa98Sdjl nss_backend_constr_t be_constr; 74cb5caa98Sdjl nss_backend_finder_t *finder; 75cb5caa98Sdjl void *finder_priv; 76cb5caa98Sdjl } nscd_be_info_t; 77cb5caa98Sdjl 78cb5caa98Sdjl /* 79cb5caa98Sdjl * nscd_state_ctrl_t is used to control a nscd_nsw_state pool 80cb5caa98Sdjl */ 81cb5caa98Sdjl typedef struct { 82cb5caa98Sdjl int max; 83cb5caa98Sdjl int allocated; 84cb5caa98Sdjl int free; 85cb5caa98Sdjl int waiter; 86cb5caa98Sdjl struct nscd_nsw_state *first; 87cb5caa98Sdjl } nscd_state_ctrl_t; 88cb5caa98Sdjl 89cb5caa98Sdjl /* 90cb5caa98Sdjl * nscd_nsw_state_base_t represents the nscd_nsw_state pool 91cb5caa98Sdjl * for a NSS database 92cb5caa98Sdjl */ 93cb5caa98Sdjl typedef struct nscd_nsw_state_base { 94cb5caa98Sdjl int dbi; /* which database? */ 95cb5caa98Sdjl nscd_state_ctrl_t nsw_state; 96cb5caa98Sdjl nscd_state_ctrl_t nsw_state_thr; 97cb5caa98Sdjl int used_by_thr; 98cb5caa98Sdjl thread_t tid; 99cb5caa98Sdjl cond_t thr_cond; 100cb5caa98Sdjl } nscd_nsw_state_base_t; 101cb5caa98Sdjl 102cb5caa98Sdjl /* 103cb5caa98Sdjl * nscd_nsw_state_t is an abstraction of all the data needed 104cb5caa98Sdjl * to do lookup of NSS database (e.g. "passwd" or "hosts") 105cb5caa98Sdjl */ 106cb5caa98Sdjl typedef struct nscd_nsw_state { 107cb5caa98Sdjl int dbi; /* which database? */ 108cb5caa98Sdjl int max_src; /* is == config->num_lookups */ 109cb5caa98Sdjl int getent; /* used by getent */ 110bf1e3beeSmichen nscd_bool_t recheck_be; /* if set, check/init be */ 111cb5caa98Sdjl nss_db_params_t p; 112cb5caa98Sdjl struct __nsw_switchconfig_v1 *config; 113cb5caa98Sdjl nscd_nsw_config_t **nsw_cfg_p; 114cb5caa98Sdjl nscd_nsw_state_base_t *base; 115cb5caa98Sdjl nss_backend_t **be; /* array of backends */ 116bf1e3beeSmichen nss_backend_constr_t *be_constr; /* be constructor array */ 117cb5caa98Sdjl nscd_db_t ***be_db_pp; 118cb5caa98Sdjl struct nscd_nsw_state *next; 119cb5caa98Sdjl } nscd_nsw_state_t; 120cb5caa98Sdjl 121cb5caa98Sdjl /* 122cb5caa98Sdjl * nscd_getent_ctx_base_t represents the nscd_getent_ctx_base_t pool 123cb5caa98Sdjl * for a NSS database 124cb5caa98Sdjl */ 125cb5caa98Sdjl typedef struct nscd_getent_ctx_base { 126cb5caa98Sdjl int dbi; /* which database? */ 127cb5caa98Sdjl int deattached; /* not associated with */ 128cb5caa98Sdjl /* current config */ 129cb5caa98Sdjl int max_getent_ctx; 130cb5caa98Sdjl int num_getent_ctx; 131cb5caa98Sdjl int num_waiter; 132cb5caa98Sdjl struct nscd_getent_context *first; 133cb5caa98Sdjl } nscd_getent_ctx_base_t; 134cb5caa98Sdjl 135cb5caa98Sdjl /* 136cb5caa98Sdjl * nscd_getent_context_t is an abstraction of all the data needed 137cb5caa98Sdjl * to enumerate a NSS database (e.g. "passwd" or "hosts") 138cb5caa98Sdjl */ 139cb5caa98Sdjl typedef struct nscd_getent_context { 140cb5caa98Sdjl int dbi; 141cb5caa98Sdjl nscd_seq_num_t seq_num; 142e37190e5Smichen nscd_cookie_num_t cookie_num; 143cb5caa98Sdjl pid_t pid; /* door client's pid */ 144cb5caa98Sdjl int n_src; /* >=max_src: end of sequence */ 145cb5caa98Sdjl nscd_nsw_state_t *nsw_state; 146cb5caa98Sdjl nss_backend_t *be; 147cb5caa98Sdjl nscd_getent_ctx_base_t *base; 148cb5caa98Sdjl struct nscd_getent_context *next; 149cb5caa98Sdjl } nscd_getent_context_t; 150cb5caa98Sdjl 151cb5caa98Sdjl /* 152cb5caa98Sdjl * nscd_smf_state_t is used to keep track of the state of the smf 153cb5caa98Sdjl * service associated with a NSS source (e.g. "passwd" or "hosts") 154cb5caa98Sdjl */ 155cb5caa98Sdjl typedef struct { 156cb5caa98Sdjl char *src_name; 157cb5caa98Sdjl int src_state; 158cb5caa98Sdjl } nscd_smf_state_t; 159cb5caa98Sdjl 160cb5caa98Sdjl /* 161cb5caa98Sdjl * nscd_smf_state_t is used to keep track of the state of the smf 162cb5caa98Sdjl * service associated with a NSS source (e.g. "passwd" or "hosts") 163cb5caa98Sdjl */ 164cb5caa98Sdjl typedef struct { 165cb5caa98Sdjl int dbi; /* database index */ 166cb5caa98Sdjl /* 167cb5caa98Sdjl * index of the database of which the switch policy 168cb5caa98Sdjl * should be used 169cb5caa98Sdjl */ 170cb5caa98Sdjl int cfgdbi; 171cb5caa98Sdjl /* 172cb5caa98Sdjl * index of the pseudo database that the NSS backend 173cb5caa98Sdjl * does search on 174cb5caa98Sdjl */ 175cb5caa98Sdjl int compati; 176cb5caa98Sdjl /* 177cb5caa98Sdjl * ptr to ptr to the siwtch config structure 178cb5caa98Sdjl */ 179cb5caa98Sdjl nscd_nsw_config_t **nswcfg; 180cb5caa98Sdjl /* 181cb5caa98Sdjl * frontend params passed to nss_search or nss_*ent 182cb5caa98Sdjl */ 183cb5caa98Sdjl struct nss_db_params p; 184cb5caa98Sdjl /* 185cb5caa98Sdjl * set to 1 if database is "hosts", else 2 if "ipnodes" 186cb5caa98Sdjl */ 187cb5caa98Sdjl int8_t dnsi; 188cb5caa98Sdjl /* 189cb5caa98Sdjl * set to 1 if require privilege to look up the database 190cb5caa98Sdjl */ 191cb5caa98Sdjl uint8_t privdb; 192cb5caa98Sdjl } nscd_nsw_params_t; 193cb5caa98Sdjl 194cb5caa98Sdjl /* 195cb5caa98Sdjl * additional info returned by the switch engine 196cb5caa98Sdjl */ 197cb5caa98Sdjl typedef struct { 198cb5caa98Sdjl void *pbuf; /* ptr to packed buffer */ 199cb5caa98Sdjl size_t pbufsiz; /* length of the packed buffer */ 200cb5caa98Sdjl int srci; /* last source searched */ 201cb5caa98Sdjl int errnum; /* errno from the backend */ 202cb5caa98Sdjl int noarg; /* if set, backend does not use the arg structure */ 203cb5caa98Sdjl int fallback; /* if set, may need to fall back to main nscd */ 204*4b22b933Srs200217 int datalen; /* pbuf->data_len (backend may change it) */ 205cb5caa98Sdjl } nscd_sw_return_t; 206cb5caa98Sdjl 207cb5caa98Sdjl /* 208e37190e5Smichen * nscd cookies used for setent/getent/endent 209e37190e5Smichen * - p0 cookie: returned by nscd to indicate 210e37190e5Smichen * the start of the enumeration position 211e37190e5Smichen * - p1 cookie: returned/updated by nscd to indicate 212e37190e5Smichen * the current enumeration position 213e37190e5Smichen */ 214e37190e5Smichen #define NSCD_P0_COOKIE_SEQNUM -1 215e37190e5Smichen typedef struct { 216e37190e5Smichen pid_t p0_pid; 217e37190e5Smichen time_t p0_time; 218e37190e5Smichen nscd_seq_num_t p0_seqnum; 219e37190e5Smichen } nscd_getent_p0_cookie_t; 220e37190e5Smichen 221e37190e5Smichen typedef struct { 222e37190e5Smichen nscd_cookie_num_t p1_cookie_num; 223e37190e5Smichen nscd_seq_num_t p1_seqnum; 224e37190e5Smichen } nscd_getent_p1_cookie_t; 225e37190e5Smichen 226e37190e5Smichen /* 227cb5caa98Sdjl * static tables or global data defined in other files 228cb5caa98Sdjl */ 229cb5caa98Sdjl extern int _nscd_cfg_num_nsw_src; 230cb5caa98Sdjl extern int _nscd_cfg_num_nsw_src_all; 231cb5caa98Sdjl extern int _nscd_cfg_num_nsw_db; 232cb5caa98Sdjl extern int _nscd_cfg_num_nsw_db_all; 233cb5caa98Sdjl extern int _nscd_cfg_num_smf_services; 234cb5caa98Sdjl extern nscd_cfg_id_t _nscd_cfg_nsw_src[]; 235cb5caa98Sdjl extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all; 236cb5caa98Sdjl extern nscd_cfg_id_t _nscd_cfg_nsw_db[]; 237cb5caa98Sdjl extern nss_db_initf_t nscd_nss_db_initf[]; 238cb5caa98Sdjl extern nscd_cfg_id_t _nscd_cfg_smf_services[]; 239cb5caa98Sdjl extern nscd_smf_state_t *nscd_smf_service_state; 240cb5caa98Sdjl extern nscd_db_t ***nscd_src_backend_db; 241cb5caa98Sdjl extern nscd_nsw_config_t ***nscd_nsw_config; 242cb5caa98Sdjl extern nscd_nsw_state_base_t **nscd_nsw_state_base; 243cb5caa98Sdjl extern nscd_getent_ctx_base_t **nscd_getent_ctx_base; 244cb5caa98Sdjl extern nscd_cfg_global_switch_t nscd_switch_cfg_g; 245cb5caa98Sdjl extern nscd_cfg_switch_t *nscd_switch_cfg; 246cb5caa98Sdjl extern nscd_cfg_stat_global_switch_t nscd_switch_stats_g; 247cb5caa98Sdjl extern nscd_cfg_stat_switch_t *nscd_switch_stats; 248cb5caa98Sdjl 249cb5caa98Sdjl #define NSCD_NUM_SRC _nscd_cfg_num_nsw_src_all 250cb5caa98Sdjl #define NSCD_NUM_DB _nscd_cfg_num_nsw_db_all 251cb5caa98Sdjl #define NSCD_NUM_SMF_FMRI _nscd_cfg_num_smf_services 252cb5caa98Sdjl #define NSCD_NSW_SRC_NAME(i) (_nscd_cfg_nsw_src_all + i)->name 253cb5caa98Sdjl #define NSCD_NSW_DB_NAME(i) _nscd_cfg_nsw_db[i].name 254cb5caa98Sdjl #define NSCD_SMF_SVC_FMRI(i) _nscd_cfg_smf_services[i].name 255cb5caa98Sdjl #define NSCD_SMF_SVC_INDEX(i) _nscd_cfg_smf_services[i].index 256cb5caa98Sdjl #define NSCD_SMF_SVC_STATE(i) nscd_smf_service_state[i].src_state 257cb5caa98Sdjl #define NSCD_SW_CFG_G nscd_switch_cfg_g 258cb5caa98Sdjl #define NSCD_SW_CFG(i) nscd_switch_cfg[i] 259cb5caa98Sdjl #define NSCD_SW_STATS_G nscd_switch_stats_g 260cb5caa98Sdjl #define NSCD_SW_STATS(i) nscd_switch_stats[i] 261cb5caa98Sdjl 262cb5caa98Sdjl /* 263cb5caa98Sdjl * special service states used by the switch engine 264cb5caa98Sdjl */ 265cb5caa98Sdjl #define NSCD_SVC_STATE_UNINITED -1 266cb5caa98Sdjl #define NSCD_SVC_STATE_UNKNOWN_SRC -2 267cb5caa98Sdjl 268cb5caa98Sdjl /* 269cb5caa98Sdjl * prototypes 270cb5caa98Sdjl */ 271cb5caa98Sdjl 272cb5caa98Sdjl void 273cb5caa98Sdjl _nscd_put_nsw_state( 274cb5caa98Sdjl nscd_nsw_state_t *s); 275cb5caa98Sdjl 276cb5caa98Sdjl void 277cb5caa98Sdjl _nscd_put_nsw_state_thread( 278cb5caa98Sdjl nscd_nsw_state_t *s); 279cb5caa98Sdjl 280cb5caa98Sdjl nscd_rc_t 281cb5caa98Sdjl _nscd_get_nsw_state( 282cb5caa98Sdjl nss_db_root_t *rootp, 283cb5caa98Sdjl nscd_nsw_params_t *params); 284cb5caa98Sdjl 285cb5caa98Sdjl nscd_rc_t 286cb5caa98Sdjl _nscd_get_nsw_state_thread( 287cb5caa98Sdjl nss_db_root_t *rootp, 288cb5caa98Sdjl nscd_nsw_params_t *params); 289cb5caa98Sdjl 290cb5caa98Sdjl nscd_rc_t 291cb5caa98Sdjl _nscd_init_all_nsw_state_base(); 292cb5caa98Sdjl 293cb5caa98Sdjl nscd_rc_t 294cb5caa98Sdjl _nscd_init_nsw_state_base( 295cb5caa98Sdjl int dbi, 296ad0e80f7Smichen int compat_basei, 297cb5caa98Sdjl int lock); 298cb5caa98Sdjl 299cb5caa98Sdjl nscd_rc_t 300cb5caa98Sdjl _nscd_init_all_getent_ctx(); 301cb5caa98Sdjl 302cb5caa98Sdjl nscd_rc_t 303cb5caa98Sdjl _nscd_init_getent_ctx_base( 304cb5caa98Sdjl int dbi, 305cb5caa98Sdjl int lock); 306cb5caa98Sdjl 307cb5caa98Sdjl nscd_db_t 308cb5caa98Sdjl *_nscd_create_getent_ctxaddrDB(); 309cb5caa98Sdjl 310cb5caa98Sdjl nscd_rc_t 311cb5caa98Sdjl _nscd_get_getent_ctx( 312cb5caa98Sdjl nss_getent_t *contextpp, 313cb5caa98Sdjl nscd_nsw_params_t *params); 314cb5caa98Sdjl 315cb5caa98Sdjl void 316cb5caa98Sdjl _nscd_put_getent_ctx( 317cb5caa98Sdjl nscd_getent_context_t *ctx); 318cb5caa98Sdjl 319cb5caa98Sdjl nscd_rc_t 320cb5caa98Sdjl _nscd_init_all_nsw_config(); 321cb5caa98Sdjl 322cb5caa98Sdjl nscd_rc_t 323cb5caa98Sdjl _nscd_init_all_nsw_be_info_db(); 324cb5caa98Sdjl 325cb5caa98Sdjl #ifdef NSCD_NSSWITCH_CONF_FROM_SMF_PROP 326cb5caa98Sdjl nscd_rc_t 327cb5caa98Sdjl _nscd_get_new_nsw_config( 328cb5caa98Sdjl scf_handle_t *hndl, 329cb5caa98Sdjl const char *fmri, 330cb5caa98Sdjl scf_propertygroup_t *pg); 331cb5caa98Sdjl #endif 332cb5caa98Sdjl 333cb5caa98Sdjl nscd_rc_t 334cb5caa98Sdjl _nscd_get_new_service_state( 335cb5caa98Sdjl int index, 336cb5caa98Sdjl scf_handle_t *hndl, 337cb5caa98Sdjl scf_property_t *prop); 338cb5caa98Sdjl 339cb5caa98Sdjl nscd_getent_context_t * 340cb5caa98Sdjl _nscd_is_getent_ctx( 341e37190e5Smichen nscd_cookie_num_t cookie_num); 342cb5caa98Sdjl 343cb5caa98Sdjl nscd_rc_t 344cb5caa98Sdjl _nscd_create_sw_struct( 345cb5caa98Sdjl int dbi, 346ad0e80f7Smichen int compat_basei, 347cb5caa98Sdjl const char *dbn, 348cb5caa98Sdjl const char *cfgstr, 349cb5caa98Sdjl void *swcfgv1, 350cb5caa98Sdjl nscd_nsw_params_t *params); 351cb5caa98Sdjl 352cb5caa98Sdjl nscd_rc_t 353cb5caa98Sdjl _nscd_create_new_config( 354cb5caa98Sdjl nscd_nsw_params_t *params); 355cb5caa98Sdjl 356cb5caa98Sdjl void 357cb5caa98Sdjl _nscd_free_nsw_config( 358cb5caa98Sdjl nscd_nsw_config_t *nswcfg); 359cb5caa98Sdjl 360cb5caa98Sdjl nscd_rc_t 361cb5caa98Sdjl _nscd_init_smf_monitor(); 362cb5caa98Sdjl 363cb5caa98Sdjl nscd_rc_t 364cb5caa98Sdjl _nscd_alloc_nsw_config(); 365cb5caa98Sdjl 366cb5caa98Sdjl nscd_rc_t 367cb5caa98Sdjl _nscd_alloc_service_state_table(); 368cb5caa98Sdjl 369cb5caa98Sdjl nscd_rc_t 370cb5caa98Sdjl _nscd_alloc_nsw_state_base(); 371cb5caa98Sdjl 372cb5caa98Sdjl nscd_rc_t 373cb5caa98Sdjl _nscd_alloc_nsw_be_info_db(); 374cb5caa98Sdjl 375cb5caa98Sdjl nscd_rc_t 376cb5caa98Sdjl _nscd_alloc_getent_ctx_base(); 377cb5caa98Sdjl 378cb5caa98Sdjl void 379cb5caa98Sdjl _nscd_free_all_nsw_state_base(); 380cb5caa98Sdjl 381cb5caa98Sdjl void 382cb5caa98Sdjl _nscd_free_all_getent_ctx_base(); 383cb5caa98Sdjl 384cb5caa98Sdjl void 385cb5caa98Sdjl _nscd_free_all_nsw_config(); 386cb5caa98Sdjl 387cb5caa98Sdjl void 388cb5caa98Sdjl _nscd_free_all_nsw_backend_info_db(); 389cb5caa98Sdjl 390cb5caa98Sdjl struct __nsw_switchconfig_v1 * 391cb5caa98Sdjl _nsw_getoneconfig_v1( 392cb5caa98Sdjl const char *name, 393cb5caa98Sdjl char *linep, 394cb5caa98Sdjl enum __nsw_parse_err *errp); 395cb5caa98Sdjl int 396cb5caa98Sdjl __nsw_freeconfig_v1( 397cb5caa98Sdjl struct __nsw_switchconfig_v1 *conf); 398cb5caa98Sdjl 399cb5caa98Sdjl int 400cb5caa98Sdjl _nscd_get_smf_state(int srci, int dbi, int recheck); 401cb5caa98Sdjl 402cb5caa98Sdjl void 403cb5caa98Sdjl nss_psearch(void *buffer, size_t length); 404cb5caa98Sdjl void 405cb5caa98Sdjl nss_psetent(void *buffer, size_t length, pid_t pid); 406cb5caa98Sdjl void 407cb5caa98Sdjl nss_pgetent(void *buffer, size_t length); 408cb5caa98Sdjl void 409cb5caa98Sdjl nss_pendent(void *buffer, size_t length); 410cb5caa98Sdjl void 411cb5caa98Sdjl nss_pdelete(void *buffer, size_t length); 412cb5caa98Sdjl 413cb5caa98Sdjl nscd_rc_t _nscd_alloc_switch_cfg(); 414cb5caa98Sdjl nscd_rc_t _nscd_alloc_switch_stats(); 415cb5caa98Sdjl nscd_db_t *_nscd_create_getent_ctx_addrDB(); 416cb5caa98Sdjl nscd_db_t *_nscd_create_getent_ctxDB(); 417cb5caa98Sdjl 418cb5caa98Sdjl #ifdef __cplusplus 419cb5caa98Sdjl } 420cb5caa98Sdjl #endif 421cb5caa98Sdjl 422cb5caa98Sdjl #endif /* _NSCD_SWITCH_H */ 423