1 #ifndef OPT_SERV_H
2 #define OPT_SERV_H
3 
4 #include "opt.h"
5 #include "conf.h"
6 #include "evnt.h"
7 
8 #define OPT_SERV_CONF_BUF_SZ (128 - sizeof(Vstr_node_buf))
9 #define OPT_SERV_CONF_MEM_PREALLOC_MAX (128 * 1024)
10 
11 #define OPT_SERV_CONF_USE_DAEMON FALSE
12 #define OPT_SERV_CONF_USE_DROP_PRIVS FALSE
13 #define OPT_SERV_CONF_USE_PDEATHSIG FALSE
14 #define OPT_SERV_CONF_DEF_RLIM_CORE_CALL FALSE
15 #define OPT_SERV_CONF_DEF_RLIM_FILE_CALL FALSE
16 #define OPT_SERV_CONF_DEF_TCP_DEFER_ACCEPT 8 /* HC usage txt */
17 #define OPT_SERV_CONF_DEF_PRIV_UID 60001
18 #define OPT_SERV_CONF_DEF_PRIV_GID 60001
19 #define OPT_SERV_CONF_DEF_NUM_PROCS 1
20 #define OPT_SERV_CONF_DEF_IDLE_TIMEOUT (2 * 60)
21 #define OPT_SERV_CONF_DEF_Q_LISTEN_LEN 128
22 #define OPT_SERV_CONF_DEF_MAX_CONNECTIONS 0
23 #define OPT_SERV_CONF_DEF_RLIM_CORE_NUM 0
24 #define OPT_SERV_CONF_DEF_RLIM_FILE_NUM 0
25 
26 typedef struct Opt_serv_policy_opts
27 {
28  Vstr_ref *ref;
29  struct Opt_serv_policy_opts *next;
30  struct Opt_serv_opts *beg;
31 
32  Vstr_base *policy_name;
33 
34  unsigned int idle_timeout;
35  unsigned int max_connections;
36 } Opt_serv_policy_opts;
37 
38 typedef struct Opt_serv_addr_opts
39 {
40  struct Opt_serv_addr_opts *next;
41  Vstr_base *acpt_filter_file;
42  Vstr_base *ipv4_address;
43  unsigned short tcp_port;
44  unsigned int defer_accept;
45  unsigned int q_listen_len;
46  unsigned int max_connections;
47 } Opt_serv_addr_opts;
48 
49 typedef struct Opt_serv_opts
50 {
51  Opt_serv_policy_opts *def_policy;
52 
53  Opt_serv_policy_opts *(*make_policy)(struct Opt_serv_opts *);
54  int                   (*copy_policy)(struct Opt_serv_policy_opts *,
55                                       const struct Opt_serv_policy_opts *);
56 
57  const char  *vers_cstr;
58  const size_t vers_len;
59 
60  const char  *name_cstr;
61        size_t name_len;
62 
63  unsigned int become_daemon : 1;
64  unsigned int drop_privs : 1;
65  unsigned int use_pdeathsig : 1;
66  unsigned int no_conf_listen : 1;
67  unsigned int rlim_core_call : 1;
68  unsigned int rlim_file_call : 1;
69 
70  Vstr_base *pid_file;
71  Vstr_base *cntl_file;
72  Vstr_base *chroot_dir;
73 
74  Vstr_base *vpriv_uid;
75  uid_t priv_uid;
76  Vstr_base *vpriv_gid;
77  gid_t priv_gid;
78  unsigned int num_procs;
79 
80  unsigned int rlim_core_num;
81  unsigned int rlim_file_num;
82 
83  unsigned int max_spare_bases;
84 
85  unsigned int max_spare_buf_nodes;
86  unsigned int max_spare_ptr_nodes;
87  unsigned int max_spare_ref_nodes;
88 
89  Opt_serv_addr_opts *addr_beg;
90 } Opt_serv_opts;
91 
92 /* uid/gid default to NFS nobody */
93 #define OPT_SERV_CONF_INIT_OPTS(x, y)                                   \
94     NULL,                                                               \
95     opt_policy_make,                                                    \
96     opt_policy_copy,                                                    \
97     x,                                                                  \
98     sizeof(x) - 1,                                                      \
99     y,                                                                  \
100     sizeof(y) - 1,                                                      \
101     OPT_SERV_CONF_USE_DAEMON,                                           \
102     OPT_SERV_CONF_USE_DROP_PRIVS,                                       \
103     OPT_SERV_CONF_USE_PDEATHSIG,                                        \
104     FALSE,                                                              \
105     OPT_SERV_CONF_DEF_RLIM_CORE_CALL,                                   \
106     OPT_SERV_CONF_DEF_RLIM_FILE_CALL,                                   \
107     NULL, NULL, NULL,                                                   \
108     NULL, OPT_SERV_CONF_DEF_PRIV_UID,                                   \
109     NULL, OPT_SERV_CONF_DEF_PRIV_GID,                                   \
110     OPT_SERV_CONF_DEF_NUM_PROCS,                                        \
111     OPT_SERV_CONF_DEF_RLIM_CORE_NUM,                                    \
112     OPT_SERV_CONF_DEF_RLIM_FILE_NUM,                                    \
113     4,                                                                  \
114     (OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ),            \
115     (OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ),            \
116     (OPT_SERV_CONF_MEM_PREALLOC_MAX / OPT_SERV_CONF_BUF_SZ),            \
117     NULL
118 
119 #define OPT_SERV_CONF_DECL_OPTS(N, x, y)                \
120     Opt_serv_opts N[1] = {{OPT_SERV_CONF_INIT_OPTS(x, y)}}
121 
122 extern void opt_serv_conf_free(Opt_serv_opts *);
123 extern int  opt_serv_conf_init(Opt_serv_opts *);
124 
125 extern Opt_serv_addr_opts *opt_serv_make_addr(Opt_serv_opts *);
126 
127 extern int opt_serv_conf(Opt_serv_opts *, Conf_parse *, Conf_token *);
128 extern int opt_serv_conf_parse_cstr(Vstr_base *, Opt_serv_opts *, const char *);
129 extern int opt_serv_conf_parse_file(Vstr_base *, Opt_serv_opts *, const char *);
130 
131 extern void opt_serv_logger(Vlg *);
132 
133 extern int opt_serv_sc_tst(Conf_parse *, Conf_token *, int *,
134                            int (*tst_func)(Conf_parse *, Conf_token *,
135                                            int *, void *), void *);
136 
137 extern int opt_serv_match_init(struct Opt_serv_opts *,
138                                Conf_parse *, Conf_token *, int *);
139 
140 extern void opt_serv_sc_drop_privs(Opt_serv_opts *);
141 extern void opt_serv_sc_rlim_file_num(unsigned int);
142 extern void opt_serv_sc_rlim_core_num(unsigned int);
143 extern int  opt_serv_sc_acpt_end(const Opt_serv_policy_opts *,
144                                  struct Evnt *, struct Evnt *);
145 extern void opt_serv_sc_free_beg(struct Evnt *, struct Vstr_ref *);
146 extern void opt_serv_sc_signals(void);
147 extern void opt_serv_sc_check_children(void);
148 extern void opt_serv_sc_cntl_resources(const Opt_serv_opts *);
149 extern int opt_serv_sc_append_hostname(Vstr_base *, size_t);
150 extern int opt_serv_sc_append_cwd(Vstr_base *, size_t);
151 extern int opt_serv_sc_make_static_path(struct Opt_serv_opts *,
152                                         Conf_parse *, Conf_token *,
153                                         Vstr_base *);
154 
155 
156 #define OPT_SERV_DECL_GETOPTS()                         \
157    {"help", no_argument, NULL, 'h'},                    \
158    {"daemon", optional_argument, NULL, 1},              \
159    {"chroot", required_argument, NULL, 2},              \
160    {"drop-privs", optional_argument, NULL, 3},          \
161    {"priv-uid", required_argument, NULL, 4},            \
162    {"priv-gid", required_argument, NULL, 5},            \
163    {"pid-file", required_argument, NULL, 6},            \
164    {"cntl-file", required_argument, NULL, 7},           \
165    {"acpt-filter-file", required_argument, NULL, 8},    \
166    {"accept-filter-file", required_argument, NULL, 8},  \
167    {"processes", required_argument, NULL, 9},           \
168    {"procs", required_argument, NULL, 9},               \
169    {"debug", no_argument, NULL, 'd'},                   \
170    {"host", required_argument, NULL, 'H'},              \
171    {"port", required_argument, NULL, 'P'},              \
172    {"nagle", optional_argument, NULL, 'n'},             \
173    {"max-connections", required_argument, NULL, 'M'},   \
174    {"idle-timeout", required_argument, NULL, 't'},      \
175    {"defer-accept", required_argument, NULL, 10},       \
176    {"version", no_argument, NULL, 'V'}
177 
178 #define OPT_SERV_GETOPTS(opts)                                          \
179     case 't': opts->def_policy->idle_timeout = atoi(optarg);        break; \
180     case 'H': OPT_VSTR_ARG(opts->addr_beg->ipv4_address);           break; \
181     case 'M': OPT_NUM_NR_ARG(opts->addr_beg->max_connections,           \
182                              "max connections");                        \
183     opts->def_policy->max_connections = opts->addr_beg->max_connections; \
184     break;                                                              \
185     case 'P': OPT_NUM_ARG(opts->addr_beg->tcp_port, "tcp port",         \
186                           0, 65535, "");                                \
187     opts->no_conf_listen = FALSE; break;                                \
188     case 'd': vlg_debug(vlg);                                       break; \
189                                                                         \
190     case 'n': OPT_TOGGLE_ARG(evnt_opt_nagle);                       break; \
191                                                                         \
192     case 1: OPT_TOGGLE_ARG(opts->become_daemon);                    break; \
193     case 2: OPT_VSTR_ARG(opts->chroot_dir);                         break; \
194     case 3: OPT_TOGGLE_ARG(opts->drop_privs);                       break; \
195     case 4: OPT_VSTR_ARG(opts->vpriv_uid);                          break; \
196     case 5: OPT_VSTR_ARG(opts->vpriv_gid);                          break; \
197     case 6: OPT_VSTR_ARG(opts->pid_file);                           break; \
198     case 7: OPT_VSTR_ARG(opts->cntl_file);                          break; \
199     case 8: OPT_VSTR_ARG(opts->addr_beg->acpt_filter_file);         break; \
200     case 9: OPT_NUM_ARG(opts->num_procs, "number of processes",         \
201                         1, 255, "");                                break; \
202     case 10: OPT_NUM_ARG(opts->addr_beg->defer_accept,                  \
203                          "seconds to defer connections",                \
204                          0, 4906, " (1 hour 8 minutes)");           break
205 
206 
207 
208 /* simple typer for EQ */
209 #define OPT_SERV_SYM_EQ(x)                      \
210     conf_token_cmp_sym_cstr_eq(conf, token, x)
211 
212 /* eXport data from configuration file to structs... */
213 #define OPT_SERV_X_TOGGLE(x) do {                               \
214       int opt__val = (x);                                       \
215                                                                 \
216       if (conf_sc_token_parse_toggle(conf, token, &opt__val))   \
217         return (FALSE);                                         \
218       (x) = opt__val;                                           \
219     } while (FALSE)
220 
221 #define OPT_SERV_X_UINT(x) do {                                 \
222       unsigned int opt__val = 0;                                \
223                                                                 \
224       if (conf_sc_token_parse_uint(conf, token, &opt__val))     \
225         return (FALSE);                                         \
226       (x) = opt__val;                                           \
227     } while (FALSE)
228 
229 #define OPT_SERV_X__ESC_VSTR(x, p, l) do {                              \
230       if ((token->type == CONF_TOKEN_TYPE_QUOTE_ESC_D) ||               \
231           (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_DDD) ||             \
232           (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_S) ||               \
233           (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_SSS) ||             \
234           FALSE)                                                        \
235         if (!conf_sc_conv_unesc((x), p, l, NULL))                       \
236           return (FALSE);                                               \
237     } while (FALSE)
238 
239 #define OPT_SERV_X__VSTR(x, p, l) do {                                  \
240       if (conf_sc_token_sub_vstr(conf, token, x, p, l))                 \
241         return (FALSE);                                                 \
242                                                                         \
243       if ((x)->conf->malloc_bad)                                        \
244         return (FALSE);                                                 \
245       OPT_SERV_X__ESC_VSTR(x, p, token->u.node->len);                   \
246     } while (FALSE)
247 
248 #define OPT_SERV_X_VSTR(x) OPT_SERV_X__VSTR(x, 1, (x)->len)
249 
250 #define OPT_SERV_SC_MATCH_INIT(x, y) do {                               \
251       unsigned int match_init__depth = token->depth_num;                \
252       int match_init__matches = TRUE;                                   \
253                                                                         \
254       if (!opt_serv_match_init(x, conf, token, &match_init__matches))   \
255         return (FALSE);                                                 \
256                                                                         \
257       if (!match_init__matches)                                         \
258         conf_parse_end_token(conf, token, match_init__depth);           \
259                                                                         \
260       while (conf_token_list_num(token, match_init__depth))             \
261       {                                                                 \
262         CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, match_init__depth, FALSE); \
263         CONF_SC_TOGGLE_CLIST_VAR(clist);                                \
264         if (!(y))                                                       \
265           return (FALSE);                                               \
266       }                                                                 \
267     } while (FALSE)
268 
269 #endif
270