~ubuntu-branches/debian/sid/rlinetd/sid

« back to all changes in this revision

Viewing changes to src/grammar.y

  • Committer: Bazaar Package Importer
  • Author(s): Robert Luberda
  • Date: 2010-03-20 18:03:45 UTC
  • mfrom: (2.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100320180345-x1srfbe2tg00ezsf
Tags: 0.7-1
* New upstream version.
* Recommend rsyslog instead of sysklogd (closes: #526922).
* update-inetd:
  + add support for enabling, disabling and removing entries;
  + use ucf for managing generated files;
  + ignore ucf files in rlinetd.conf;
  + make appropriate changes in  postinst and postrm scripts.
* Set debhelper compat level to 7
* Standards-Version: 3.8.4 (no changes). 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%{
 
2
 
 
3
 
 
4
#include <errno.h>
 
5
#include <fcntl.h>
 
6
#include <grp.h>
 
7
#include <netdb.h>
 
8
#include <netinet/in.h>
 
9
#include <arpa/inet.h>
 
10
#include <pwd.h>
 
11
#include <rpc/rpc.h>
 
12
#include <rpc/pmap_clnt.h>
 
13
#include <stdlib.h>
 
14
#include <stdio.h>
 
15
#include <string.h>
 
16
#include <sysexits.h>
 
17
#include <syslog.h>
 
18
#include <sys/socket.h>
 
19
#include <sys/stat.h>
 
20
#include <sys/types.h>
 
21
#include <unistd.h>
 
22
#include <regex.h>
 
23
        
 
24
#include "config.h"
 
25
#include <installpaths.h>       
 
26
#include <port/port.h>
 
27
 
 
28
#if HAVE_DIRENT_H
 
29
# include <dirent.h>
 
30
# define NAMLEN(dirent) strlen((dirent)->d_name)
 
31
#else
 
32
# define dirent direct
 
33
# define NAMLEN(dirent) (dirent)->d_namlen
 
34
# if HAVE_SYS_NDIR_H
 
35
#  include <sys/ndir.h>
 
36
# endif
 
37
# if HAVE_SYS_DIR_H
 
38
#  include <sys/dir.h>
 
39
# endif
 
40
# if HAVE_NDIR_H
 
41
#  include <ndir.h>
 
42
# endif
 
43
#endif
 
44
 
 
45
#ifdef HAVE_NET_BPF_H
 
46
#include <net/bpf.h>
 
47
#endif
 
48
        
 
49
#include "assemble.h"
 
50
#include "bytecode.h"
 
51
#include "data.h"
 
52
#include "db.h"
 
53
#include "error.h"
 
54
#include "parse.h"
 
55
#include "rlinetd.h"
 
56
#include "signals.h"
 
57
#include "util.h"       
 
58
 
 
59
#define RL_PWARN(x...)                  rl_pwarn(curfile_name, curfile_line, x)
 
60
#define RL_PFATAL(x,y...)               rl_pfatal(x, curfile_name, curfile_line, y)
 
61
 
 
62
struct userdata *userdata;
 
63
 
 
64
static struct service *current_service;
 
65
extern FILE *yyin;
 
66
extern char *rl_config; 
 
67
char **files = NULL;
 
68
static int curfile = -1, numfiles = 0; 
 
69
char *curfile_name = NULL;  /* name of the current file */
 
70
int curfile_line = 1;                                    /* line */
 
71
 
 
72
static struct service *defaults;
 
73
static struct opmetalist *opml_defaults;
 
74
 
 
75
static struct logdata *logcur, *logdatas;
 
76
 
 
77
static struct numlist *numlist = NULL;
 
78
static struct stringlist *stringlist = NULL;
 
79
 
 
80
void yyerror(char *c);
 
81
int yylex();
 
82
static int bind_ports();
 
83
static int add_user_group(const struct service* current_service, struct opmetalist * l);
 
84
static void service_copy(struct service *to, struct service *from);
 
85
static void service_free(struct service *s); 
 
86
static struct service *service_new();
 
87
#ifndef HAVE_GETADDRINFO
 
88
static int getservport(char *str, char *proto);
 
89
#endif
 
90
static struct logdata *logdata_get(char *name);
 
91
static struct logdata *logdata_new();
 
92
static void pidtab_fixup();
 
93
static void validate_service(struct service *s);
 
94
static void add_directory(char *dir, char *match, char *ignore);
 
95
static int chargen_buffer();
 
96
 
 
97
void freebufs(); /* from parse.l */
 
98
 
 
99
%}
 
100
 
 
101
%union {
 
102
        long num;
 
103
        char *cp;
 
104
        struct passwd *uid;
 
105
        struct group *gid;
 
106
        struct opmetalist *opml;
 
107
        struct opmeta *opm;
 
108
        rlim_t rl;
 
109
}
 
110
 
 
111
%token T_SERVICE T_PORT T_EXEC T_PROTO T_UDP T_TCP T_UID T_GID T_BACKLOG
 
112
%token T_INSTANCES T_WAIT T_DEFAULT T_NICE T_INTERFACE T_FISH T_CHROOT T_SERVER
 
113
%token T_DIR T_RPC T_VERSION T_NAME T_WRAP T_CAPS T_FAMILY T_IPV4 T_IPV6
 
114
%token T_INITGROUPS T_BANNER T_ECHO T_DISCARD T_FILTER T_CHARGEN T_LOOPBACK
 
115
%token T_ENABLED
 
116
 
 
117
%token T_RLIMIT T_LIM_CPU T_LIM_FSIZE T_LIM_DATA T_LIM_STACK T_LIM_CORE
 
118
%token T_LIM_RSS T_LIM_NPROC T_LIM_NOFILE T_LIM_MEMLOCK T_LIM_INFINITY
 
119
%token T_SOFT T_HARD
 
120
%token T_YES T_NO
 
121
 
 
122
%token T_LOG T_PIPE T_SYSLOG T_PATH T_MODE
 
123
 
 
124
%token T_ACCEPT T_DENY T_CLOSE T_EXIT
 
125
 
 
126
%token <num> T_NUMERIC
 
127
%token <cp> T_QSTRING T_IPADDR
 
128
 
 
129
%type <gid> groupid;
 
130
%type <uid> userid;
 
131
%type <num> limittype limit protocol;
 
132
%type <opm> opcode_element
 
133
%type <opml> service_elements complex_opcode_element opcode_block
 
134
%type <rl> limitvalue
 
135
%type <cp> optionalstring
 
136
%type <num> signed_numeric
 
137
%type <num> boolean
 
138
 
 
139
%%
 
140
 
 
141
tles:   tle
 
142
        |       tles tle
 
143
        ;
 
144
 
 
145
tle:    service
 
146
        |       default
 
147
        |       log
 
148
        |       directory
 
149
        ;
 
150
 
 
151
directory:      T_DIR T_QSTRING ';'
 
152
        {       add_directory($2, NULL, NULL);  }
 
153
        |       T_DIR T_QSTRING T_QSTRING ';'
 
154
        {       add_directory($2, $3, NULL);    }
 
155
        |       T_DIR T_QSTRING T_QSTRING T_QSTRING ';'
 
156
        {       add_directory($2, $3, $4);      }
 
157
        ;
 
158
 
 
159
log:    T_LOG T_QSTRING '{' log_element '}'
 
160
        {
 
161
                if(logdata_get($2)) {
 
162
                        RL_PWARN("duplicate declaration of log %s, ignoring", $2);
 
163
                        free($2);
 
164
                } else {
 
165
                        logcur->name = $2;
 
166
                        logcur->next = logdatas;
 
167
                        logdatas = logcur;
 
168
                        logcur = logdata_new();
 
169
                }
 
170
                clearuserdata(&userdata);
 
171
        }
 
172
        ;
 
173
 
 
174
log_element: file_elements
 
175
        {
 
176
                if(!logcur->path) {
 
177
                        RL_PWARN(_("No path defined for log %s"), logcur->name);
 
178
                } else {
 
179
                        if((logcur->index = open(logcur->path, O_CREAT|O_APPEND|O_WRONLY, logcur->mode)) < 0) {
 
180
                                RL_PWARN(_("open(\"%s\", O_CREAT|O_APPEND|O_WRONLY, 0%o) failed (%s)"),
 
181
                                                                logcur->path, logcur->mode, strerror(errno));
 
182
                        } else {
 
183
 
 
184
                                if(fchmod(logcur->index, logcur->mode)) {
 
185
                                        RL_PWARN(_("fchmod(\"%s\", 0%o) failed (%s)"),
 
186
                                                                        logcur->path, logcur->mode, 
 
187
                                                                        strerror(errno));
 
188
                                }
 
189
 
 
190
                                if(fchown(logcur->index, logcur->uid, logcur->gid)) {
 
191
                                        RL_PWARN(_("fchown(\"%s\", %d, %d) failed for log %s (%s)"),
 
192
                                                                        logcur->path, logcur->uid, logcur->gid, logcur->name,
 
193
                                                                        strerror(errno));
 
194
                                }
 
195
                        }
 
196
                }
 
197
        }
 
198
        ;
 
199
 
 
200
file_elements:  file_element
 
201
        |       file_elements file_element
 
202
        ;
 
203
 
 
204
file_element:   ';'
 
205
        |       T_PATH T_QSTRING ';'
 
206
        {
 
207
                if(logcur->path) {
 
208
                        RL_PWARN(_("duplicate path declaration (%s) "
 
209
                                "in log directive %s, ignoring"), $2, 
 
210
                                logcur->name);
 
211
                        free($2);
 
212
                } else {
 
213
                        logcur->path = $2;
 
214
                }
 
215
        }
 
216
        |       T_UID userid ';'
 
217
        {
 
218
                if ($2) {
 
219
                        logcur->uid = $2->pw_uid;
 
220
                } else {
 
221
                        RL_PWARN("unknown username");
 
222
                }
 
223
        }
 
224
        |       T_GID groupid ';'
 
225
        {
 
226
                if ($2) {
 
227
                        logcur->gid = $2->gr_gid;
 
228
                } else {
 
229
                        RL_PWARN("unknown groupname");
 
230
                }
 
231
        }
 
232
        |       T_MODE T_NUMERIC ';'
 
233
        {
 
234
                if ($2 > 07777)  {
 
235
                        RL_PWARN(_("invalid mode declaration "
 
236
                                "in log directive %s, ignoring"), logcur->name);
 
237
                } else {
 
238
                        logcur->mode = $2;
 
239
                }
 
240
        }
 
241
        ;
 
242
 
 
243
default:        T_DEFAULT '{' service_elements '}'
 
244
        {
 
245
                /* swich pointers to current_service and defaults */
 
246
                struct service * saved_defaults = defaults;
 
247
                defaults = current_service;
 
248
                current_service = saved_defaults;
 
249
 
 
250
                /* copy new defaults to current_service */
 
251
                service_free(current_service);
 
252
                service_copy(current_service, defaults);
 
253
 
 
254
                /* save default opmetalist */
 
255
                opmetalist_free(opml_defaults);
 
256
                free(opml_defaults);
 
257
                opml_defaults = $3;
 
258
        }
 
259
        ;
 
260
 
 
261
service:        T_SERVICE T_QSTRING '{' service_elements '}'
 
262
        {
 
263
                struct opmetalist *parent;
 
264
                struct opmetalist *onexit;
 
265
                struct oplist *ops;
 
266
                int i, bound;
 
267
                int fds;
 
268
                fd_set *fdst;
 
269
 
 
270
                parent = opmetalist_new();
 
271
                onexit = opmetalist_new();
 
272
 
 
273
                current_service->name = $2;
 
274
                current_service->opfixups[ofp_iname] = stringtab_add($2);
 
275
 
 
276
                do { /* avoid goto */   
 
277
                        
 
278
                        if (current_service->disabled)
 
279
                                break;
 
280
                        
 
281
                        if(current_service->socktype == SOCK_STREAM && !current_service->wait) {
 
282
                                if(opmetalist_add($4, opmeta_make(2, OP_ACCEPT, 200))) { /* !200 */
 
283
                                        RL_PWARN(_("opcode resolving problem"));
 
284
                                        current_service->disabled++;
 
285
                                        break;
 
286
                                }
 
287
                                opmetalist_add(parent, opmeta_make(1, OP_CLOSE));
 
288
 
 
289
                                if (current_service->internal) 
 
290
                                        opmetalist_add(onexit, opmeta_make(1, OP_CLOSE));
 
291
                                else
 
292
                                        opmetalist_add(onexit, opmeta_make(1, OP_RET));
 
293
 
 
294
                        } else {
 
295
                                opmetalist_add(parent, opmeta_make(1, OP_RET));
 
296
                                opmetalist_add(onexit, opmeta_make(1, OP_RET));
 
297
                        }
 
298
                        validate_service(current_service);
 
299
 
 
300
 
 
301
                        if (current_service->disabled)
 
302
                                break;
 
303
 
 
304
                        if (!add_user_group(current_service, $4))
 
305
                        {
 
306
                                ++current_service->disabled;
 
307
                          break;
 
308
                  }
 
309
                        
 
310
 
 
311
                        fds = bind_ports();
 
312
                        
 
313
 
 
314
                        if(current_service->limit) {
 
315
                                struct opmetalist *o;
 
316
                                struct oplist *l;
 
317
                                int match, under;
 
318
        
 
319
                                o = opmetalist_new();
 
320
                                opmetalist_add(o, opmeta_make(2, OP_LCLR, fds));
 
321
                                opmetalist_add(o, opmeta_make(1, OP_RET));
 
322
                                l = opmetalist_resolve(o, current_service->opfixups);
 
323
                                match = oplisttab_add(l);
 
324
                                opmetalist_free(o);
 
325
                                free(o);
 
326
                                oplist_free(l);
 
327
                                free(l);
 
328
                                
 
329
                                o = opmetalist_new();
 
330
                                opmetalist_add(o, opmeta_make(2, OP_LSET, fds));
 
331
                                opmetalist_add(o, opmeta_make(1, OP_RET));
 
332
                                l = opmetalist_resolve(o, current_service->opfixups);
 
333
                                under = oplisttab_add(l);
 
334
                                opmetalist_free(o);
 
335
                                free(o);
 
336
                                oplist_free(l);
 
337
                                free(l);
 
338
                                
 
339
                                i = semaphore_add(current_service->limit, match, under);
 
340
                                opmetalist_add($4, opmeta_make(2, OP_DOWN, i));
 
341
                                opmetalist_add(onexit, opmeta_make(2, OP_UP, i));
 
342
                        }
 
343
                        ops = opmetalist_resolve(onexit, current_service->opfixups);
 
344
                        current_service->opfixups[ofp_onexit] = oplisttab_add(ops);
 
345
                        opmetalist_free(onexit);
 
346
                        free(onexit);
 
347
                        oplist_free(ops);
 
348
                        free(ops);
 
349
                        
 
350
                        ops = opmetalist_resolve(parent, current_service->opfixups);
 
351
                        current_service->opfixups[ofp_parent] = oplisttab_add(ops);
 
352
                        opmetalist_free(parent);
 
353
                        free(parent);
 
354
                        oplist_free(ops);
 
355
                        free(ops);
 
356
 
 
357
                        opmetalist_merge($4, opml_defaults);
 
358
 
 
359
                        opmetalist_add($4, opmeta_make(2, OP_JUMP, current_service->opfixups[ofp_onexit]));
 
360
                        ops = opmetalist_resolve($4, current_service->opfixups);
 
361
                
 
362
                        current_service->run = oplisttab_add(ops);
 
363
                        opmetalist_free($4);
 
364
                        free($4);
 
365
                        oplist_free(ops);
 
366
                        free(ops);
 
367
        
 
368
                        fdst = fdsettab_get(fds);
 
369
                        bound = getdtablesize();
 
370
                        for(i = 0; i < bound; i++)
 
371
                                if(FD_ISSET(i, fdst))
 
372
                                        read_hook(i, oplisttab_get(current_service->run), NULL);
 
373
 
 
374
                } while (0);    
 
375
 
 
376
                if (current_service->disabled) {
 
377
                                        rl_warn(_("service %s DISABLED"), current_service->name);
 
378
                } else {
 
379
                        rl_note(_("service %s enabled"), current_service->name);
 
380
                        if (rl_debug > 1)
 
381
                                rl_note(_("+-> uid=%d, sgid=%d, supgid=%d fl=%d"), current_service->opfixups[ofp_setuid],
 
382
                                        current_service->opfixups[ofp_setgid], current_service->opfixups[ofp_supgid], current_service->sflags);
 
383
                        
 
384
                }
 
385
 
 
386
                service_free(current_service);
 
387
                service_copy(current_service, defaults);
 
388
        }
 
389
        ;
 
390
 
 
391
service_elements:       service_element
 
392
        {
 
393
                $$ = opmetalist_new();
 
394
        }
 
395
        | service_elements service_element
 
396
        {
 
397
                $$ = $1;
 
398
        }
 
399
        | opcode_element
 
400
        {
 
401
                struct opmetalist *l;
 
402
 
 
403
                l = opmetalist_new();
 
404
                if(opmetalist_add(l, $1)) {
 
405
                        RL_PWARN(_("opcode resolving problem"));
 
406
                        current_service->disabled++;
 
407
                }
 
408
                $$ = l;
 
409
        }
 
410
        | service_elements opcode_element
 
411
        {
 
412
                if(opmetalist_add($1, $2)) {
 
413
                        RL_PWARN(_("opcode resolving problem"));
 
414
                        current_service->disabled++;
 
415
                }
 
416
                $$ = $1;
 
417
        }
 
418
        | service_elements complex_opcode_element
 
419
        {
 
420
                $$ = opmetalist_join($1, $2);
 
421
                if(!$$) {
 
422
                        RL_PWARN(_("opcode resolving problem"));
 
423
                        current_service->disabled++;
 
424
                }
 
425
        }
 
426
        | complex_opcode_element
 
427
        {
 
428
                $$ = $1;
 
429
        }
 
430
        ;
 
431
 
 
432
opcode_block: complex_opcode_element
 
433
        {
 
434
                $$ = $1;
 
435
        }
 
436
        |       opcode_element
 
437
        {
 
438
                struct opmetalist *l;
 
439
 
 
440
                l = opmetalist_new();
 
441
                if(opmetalist_add(l, $1)) {
 
442
                        RL_PWARN(_("opcode resolving problem"));
 
443
                        current_service->disabled++;
 
444
                }
 
445
                $$ = l;
 
446
        }
 
447
        | opcode_block opcode_element
 
448
        {
 
449
                if(opmetalist_add($1, $2)) {
 
450
                        RL_PWARN(_("opcode resolving problem"));
 
451
                        current_service->disabled++;
 
452
                }
 
453
                $$ = $1;
 
454
        }
 
455
        | opcode_block complex_opcode_element
 
456
        {
 
457
                $$ = opmetalist_join($1, $2);
 
458
                if(!$$) {
 
459
                        RL_PWARN(_("opcode resolving problem"));
 
460
                        current_service->disabled++;
 
461
                }
 
462
        }
 
463
        ;
 
464
 
 
465
complex_opcode_element: T_EXEC T_QSTRING ';'
 
466
        {
 
467
                struct opmetalist *l;
 
468
                struct opmeta *o;
 
469
                
 
470
                l = opmetalist_new();
 
471
                o = opmeta_make(3, OP_EXEC, 666, argvtab_add($2, 1));
 
472
                opmeta_fixup(o, 1, ofp_exec);
 
473
                if(opmetalist_add(l, o)) {
 
474
                        RL_PWARN(_("opcode resolving problem"));
 
475
                        current_service->disabled++;
 
476
                }
 
477
                o = opmeta_make(3, OP_FORK, 666, 666);
 
478
                opmeta_fixup(o, 1, ofp_parent);
 
479
                opmeta_fixup(o, 2, ofp_onexit);
 
480
                if(opmetalist_add(l, o)) {
 
481
                        RL_PWARN(_("opcode resolving problem"));
 
482
                        current_service->disabled++;
 
483
                }
 
484
                $$ = l;
 
485
        }
 
486
        |       T_UID userid ';'
 
487
        {
 
488
                if($2) {
 
489
 
 
490
                        current_service->opfixups[ofp_iuser] = stringtab_add($2->pw_name);
 
491
                        current_service->opfixups[ofp_setuid] = $2->pw_uid;
 
492
                  current_service->opfixups[ofp_supgid] = $2->pw_gid;
 
493
 
 
494
                        set_flag(current_service, FLAG_USER);
 
495
 
 
496
                        if(!has_flag(current_service, FLAG_GROUP)) {
 
497
                    current_service->opfixups[ofp_setgid] = $2->pw_gid;
 
498
                        }
 
499
                        
 
500
                        $$ = NULL;
 
501
                } else {
 
502
                        RL_PWARN("unknown username");
 
503
                        current_service->disabled++;
 
504
                        $$ = NULL;
 
505
                }
 
506
        }
 
507
        | T_INITGROUPS ';'
 
508
        {
 
509
                set_flag(current_service, FLAG_INITGROUPS);
 
510
 
 
511
                $$ = NULL;
 
512
 
 
513
        }
 
514
        | T_INITGROUPS boolean ';'
 
515
        {
 
516
    if ($2)
 
517
                  set_flag(current_service, FLAG_INITGROUPS)
 
518
    else 
 
519
                  reset_flag(current_service, FLAG_INITGROUPS)
 
520
                $$ = NULL;
 
521
        }       
 
522
        ;
 
523
 
 
524
opcode_element: T_NICE signed_numeric ';'
 
525
        {
 
526
                $$ = opmeta_make(2, OP_NICE, $2);
 
527
        }
 
528
        |       T_FISH ';'
 
529
        {
 
530
                $$ = opmeta_make(1, OP_FISH);
 
531
        }
 
532
        |       T_RLIMIT limittype limit
 
533
        {
 
534
                $$ = opmeta_make(3, OP_RLIMIT, $2, $3);
 
535
        }
 
536
        |       T_LOG T_SYSLOG T_QSTRING ';'
 
537
        {
 
538
                int i;
 
539
 
 
540
                i = logtab_add(-1, $3);
 
541
                $$ = opmeta_make(2, OP_LOG, i);
 
542
                free($3);
 
543
        }
 
544
        |       T_BANNER T_QSTRING ';'
 
545
        {
 
546
                int ret;
 
547
 
 
548
                ret = buftab_addfile($2);
 
549
                if(ret == -1)
 
550
                        current_service->disabled++;
 
551
                $$ = opmeta_make(16, OP_ZERO, OP_BUFCLONE, ret, OP_WHOOK, 0, OP_WUNHOOK,
 
552
                                                                                 OP_DUP, OP_BUFCOPY, OP_DUP, OP_BZNEG, 3, OP_ADD,
 
553
                                                                                 OP_WHOOK, -9, OP_POP, OP_BUFFREE);
 
554
                free($2);
 
555
        }
 
556
        |       T_CHARGEN optionalstring ';'
 
557
        {
 
558
                int i;
 
559
 
 
560
                if($2) {
 
561
                        i = buftab_addfile($2);
 
562
                        if(i < 0)
 
563
                                current_service->disabled++;
 
564
                } else {
 
565
                        i = chargen_buffer();
 
566
                }
 
567
                $$ = opmeta_make(25, OP_ZERO, OP_DUP, OP_BUFCLONE, i, OP_POP,
 
568
                                                                                 OP_POP, OP_ZERO, OP_WHOOK, 0, OP_WUNHOOK, OP_DUP,
 
569
                                                                                 OP_BUFCOPY, OP_DUP, OP_BZ, -11, OP_DUP, OP_BZNEG, 3,
 
570
                                                                                 OP_ADD, OP_WHOOK, -12, OP_POP, OP_BUFFREE, OP_JUMP, 666);
 
571
                opmeta_fixup($$, 24, ofp_onexit);
 
572
                current_service->internal = 1;
 
573
                if($2)
 
574
                        free($2);
 
575
        }
 
576
        |       T_LOG T_QSTRING T_QSTRING ';'
 
577
        {
 
578
                struct logdata *ld = logdata_get($2);
 
579
 
 
580
                if(!ld) {
 
581
                        RL_PWARN(_("unknown log %s"), $2);
 
582
                        current_service->disabled++;
 
583
                } else {
 
584
                        int i = logtab_add(ld->index, $3);
 
585
                        $$ = opmeta_make(2, OP_LOG, i);
 
586
                }
 
587
                free($2);
 
588
                free($3);
 
589
        }
 
590
        |       T_GID groupid ';'
 
591
        {
 
592
                if(!$2) {
 
593
                        RL_PWARN(_("unknown group"));
 
594
                        current_service->disabled++;
 
595
                        $$ = NULL;
 
596
     } else {
 
597
 
 
598
                        current_service->opfixups[ofp_setgid] = $2->gr_gid;
 
599
                        set_flag(current_service, FLAG_GROUP);
 
600
 
 
601
                        $$ = NULL;
 
602
    }
 
603
        }
 
604
        |       T_CHROOT T_QSTRING ';'
 
605
        {
 
606
                $$ = opmeta_make(2, OP_CHROOT, argvtab_add($2, 1));
 
607
        }
 
608
        |       T_CAPS T_QSTRING ';'
 
609
        {
 
610
#ifdef HAVE_CAPABILITIES
 
611
                cap_t caps = cap_from_text($2);
 
612
                if(caps) {
 
613
                        $$ = opmeta_make(2, OP_SETCAP, captab_add(caps));
 
614
                } else {
 
615
                        RL_PWARN(_("failed to parse capability string \"%s\"\n"), $2);
 
616
                        current_service->disabled++;
 
617
                }
 
618
                free($2);
 
619
#else
 
620
                RL_PFATAL(EX_DATAERR, _("ABORT - support for capabilities not compiled in"));
 
621
#endif
 
622
        }
 
623
        | T_WRAP T_QSTRING '{' opcode_block '}'
 
624
        {
 
625
                int i;
 
626
                struct oplist *op;
 
627
 
 
628
                opmetalist_add($4, opmeta_make(1, OP_RET));
 
629
                op = opmetalist_resolve($4,current_service->opfixups);
 
630
                i = oplisttab_add(op);
 
631
                $$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
 
632
                free($2);
 
633
                oplist_free(op);
 
634
                free(op);
 
635
                opmetalist_free($4);
 
636
                free($4);
 
637
        }
 
638
        | T_WRAP '{' opcode_block '}'
 
639
        {
 
640
                struct opmeta *o;
 
641
                int i;
 
642
                struct oplist *op;
 
643
 
 
644
                opmetalist_add($3, opmeta_make(1, OP_RET));
 
645
                op = opmetalist_resolve($3, current_service->opfixups);
 
646
                i = oplisttab_add(op);
 
647
                o = opmeta_make(3, OP_WRAP, 666, i);
 
648
                opmeta_fixup(o, 1, ofp_iname);
 
649
                $$ = o;
 
650
                oplist_free(op);
 
651
                free(op);
 
652
                opmetalist_free($3);
 
653
                free($3);
 
654
        }
 
655
        |       T_WRAP T_QSTRING ';'
 
656
        {
 
657
                struct opmetalist *l;
 
658
                int i;
 
659
                struct oplist *op;
 
660
 
 
661
                l = opmetalist_new();
 
662
                opmetalist_add(l, opmeta_make(1, OP_EXIT));
 
663
                op = opmetalist_resolve(l, current_service->opfixups);
 
664
                i = oplisttab_add(op);
 
665
                $$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
 
666
                free($2);
 
667
                oplist_free(op);
 
668
                free(op);
 
669
                opmetalist_free(l);
 
670
                free(l);
 
671
        }
 
672
        |       T_WRAP ';'
 
673
        {
 
674
                struct opmetalist *l;
 
675
                struct opmeta *o;
 
676
                int i;
 
677
                struct oplist *op;
 
678
 
 
679
                l = opmetalist_new();
 
680
                opmetalist_add(l, opmeta_make(1, OP_EXIT));
 
681
                op = opmetalist_resolve(l,current_service->opfixups);
 
682
                i = oplisttab_add(op);
 
683
                o = opmeta_make(3, OP_WRAP, 666, i);
 
684
                opmeta_fixup(o, 1, ofp_iname);
 
685
                $$ = o;
 
686
                oplist_free(op);
 
687
                free(op);
 
688
                opmetalist_free(l);
 
689
                free(l);
 
690
        }
 
691
        | T_CLOSE ';'
 
692
        {
 
693
                $$ = opmeta_make(1, OP_CLOSE);
 
694
        }
 
695
        | T_EXIT ';'
 
696
        {
 
697
                $$ = opmeta_make(1, OP_EXIT);
 
698
        }
 
699
        | T_ECHO T_QSTRING ';'
 
700
        {
 
701
                $$ = opmeta_make(2, OP_ECHO, argvtab_add($2, 0));
 
702
        }
 
703
        | T_LOOPBACK ';'
 
704
        {
 
705
                $$ = opmeta_make(29, OP_ZERO, OP_BUFINIT, 11, OP_RHOOK, 0, OP_BUFREAD,
 
706
                                                                                 OP_RUNHOOK, OP_DUP, OP_BZNEG, 17, OP_ADD, OP_WHOOK, 0,
 
707
                                                                                 OP_BUFWRITE, OP_WUNHOOK, OP_DUP, OP_BZ, 6, OP_DUP,
 
708
                                                                                 OP_BZNEG, 6, OP_SUB, OP_WHOOK, -11, OP_POP, OP_RHOOK, -22,
 
709
                                                                                 OP_JUMP, 666);
 
710
                opmeta_fixup($$, 28, ofp_onexit);
 
711
                current_service->internal = 1;
 
712
        }
 
713
        | T_DISCARD ';'
 
714
        {
 
715
                $$ = opmeta_make(13, OP_ZERO, OP_RHOOK, 0, OP_RUNHOOK, OP_BUFINIT, 1024,
 
716
                                                                                 OP_BUFREAD, OP_BZNEG, 2, OP_RHOOK, -8, OP_JUMP, 666);
 
717
                opmeta_fixup($$, 12, ofp_onexit);
 
718
                current_service->internal = 1;
 
719
        }
 
720
        ;
 
721
 
 
722
optionalstring:
 
723
        {       $$ = NULL;      }
 
724
        |       T_QSTRING
 
725
        ;
 
726
 
 
727
service_element:        ';'
 
728
        |       T_PORT portlists ';'
 
729
        {
 
730
                if(current_service->port)
 
731
                        stringlist_free(current_service->port);
 
732
                current_service->port = stringlist;
 
733
                stringlist = NULL;
 
734
        }
 
735
        |       T_PROTO protocol ';'
 
736
        {
 
737
                current_service->socktype = $2;
 
738
        }
 
739
        |       T_BACKLOG T_NUMERIC ';'
 
740
        {
 
741
                current_service->backlog = $2;
 
742
        }
 
743
        |       T_INSTANCES T_NUMERIC ';'
 
744
        {
 
745
                current_service->limit = $2;
 
746
        }
 
747
        | T_WAIT boolean ';'
 
748
        {
 
749
                current_service->wait  = $2;
 
750
        }       
 
751
        | T_ENABLED boolean ';'
 
752
        {
 
753
                current_service->disabled  = ! $2;
 
754
        }       
 
755
        |       T_INTERFACE ipaddrlists ';'
 
756
        {
 
757
                if(current_service->interface)
 
758
                        stringlist_free(current_service->interface);
 
759
                current_service->interface = stringlist;
 
760
                stringlist = NULL;
 
761
        }
 
762
        |       T_SERVER T_QSTRING ';'
 
763
        {
 
764
                current_service->opfixups[ofp_exec] = stringtab_add($2);
 
765
                free($2);
 
766
        }
 
767
        |       T_RPC '{' rpcents '}'
 
768
        | T_FAMILY family ';'
 
769
        | T_FILTER T_QSTRING ';'
 
770
        {
 
771
#ifdef HAVE_NET_BPF_H
 
772
                if(current_service->filter)
 
773
                        free(current_service->filter);
 
774
                if(rl_readfile($2, &current_service->filter, &current_service->filterlen))
 
775
                        current_service->disabled++;
 
776
                free($2);
 
777
#else
 
778
                RL_PFATAL(EX_DATAERR, _("ABORT - support for socket filter not compiled in"));
 
779
#endif
 
780
        }
 
781
                
 
782
        ;
 
783
 
 
784
rpcents:        rpcent
 
785
        |       rpcents rpcent
 
786
        ;
 
787
 
 
788
rpcent: T_NAME T_QSTRING ';'
 
789
        {
 
790
                current_service->rpcname = $2;
 
791
        }
 
792
        |       T_VERSION numrangelist ';'
 
793
        {
 
794
                current_service->rpcvers = numlist;
 
795
                numlist = NULL;
 
796
        }
 
797
        ;
 
798
 
 
799
numrangelist:   numrange
 
800
        |       numrangelist ',' numrange
 
801
        ;
 
802
 
 
803
numrange:       T_NUMERIC
 
804
        {
 
805
                numlist_add(&numlist, $1);
 
806
        }
 
807
        |       T_NUMERIC '-' T_NUMERIC
 
808
        {
 
809
                int i;
 
810
 
 
811
                if($3 >= $1)
 
812
                        for(i = $1; i <= $3; i++)
 
813
                                numlist_add(&numlist, i);
 
814
        }
 
815
        ;
 
816
 
 
817
limitents:      limitent
 
818
        |       limitents limitent
 
819
        ;
 
820
 
 
821
limitent:       T_SOFT limitvalue ';'
 
822
        {
 
823
                current_service->r.rlim_cur = $2;
 
824
        }
 
825
        |       T_HARD limitvalue ';'
 
826
        {
 
827
                current_service->r.rlim_max = $2;
 
828
        }
 
829
        ;
 
830
 
 
831
ipaddrlists:    ipaddrlist
 
832
        |       ipaddrlists ',' ipaddrlist
 
833
        ;
 
834
 
 
835
ipaddrlist:     T_IPADDR
 
836
        {
 
837
                stringlist_add(&stringlist, $1);
 
838
        }
 
839
        ;
 
840
 
 
841
portlists:      portlist
 
842
        |       portlists ',' portlist
 
843
        ;
 
844
 
 
845
portlist:       T_QSTRING
 
846
        {
 
847
                stringlist_add(&stringlist, $1);
 
848
        }
 
849
        | T_NUMERIC
 
850
        {
 
851
                char tmp[20];
 
852
 
 
853
                snprintf(tmp, 19, "%ld", $1);
 
854
                tmp[19] = '\0';
 
855
                stringlist_add(&stringlist, strdup(tmp));
 
856
        }
 
857
        ;
 
858
 
 
859
limit:  limitvalue ';'
 
860
        {
 
861
                $$ = rlimittab_add($1, $1);
 
862
        }
 
863
        |       '{' limitents '}'
 
864
        {
 
865
                if((current_service->r.rlim_max != RLIM_INFINITY) &&
 
866
                         (current_service->r.rlim_cur > current_service->r.rlim_max)) {
 
867
                        RL_PWARN(_("invalid resource limit"));
 
868
                }
 
869
                $$ = rlimittab_add(current_service->r.rlim_cur, current_service->r.rlim_max);
 
870
                current_service->r.rlim_cur = current_service->r.rlim_max = RLIM_INFINITY;
 
871
        }
 
872
        ;
 
873
 
 
874
limitvalue:     T_NUMERIC
 
875
        { $$ = (rlim_t)$1; }
 
876
        |       T_LIM_INFINITY
 
877
        { $$ = RLIM_INFINITY; }
 
878
        ;
 
879
 
 
880
limittype:      T_LIM_CPU
 
881
        { $$ = RLIMIT_CPU; }
 
882
        |       T_LIM_FSIZE
 
883
        { $$ = RLIMIT_FSIZE; }
 
884
        |       T_LIM_DATA
 
885
        { $$ = RLIMIT_DATA; }
 
886
        |       T_LIM_STACK
 
887
        { $$ = RLIMIT_STACK; }
 
888
        |       T_LIM_CORE
 
889
        { $$ = RLIMIT_CORE; }
 
890
        |       T_LIM_RSS
 
891
        { $$ = RLIMIT_RSS; }
 
892
        |       T_LIM_NPROC
 
893
        {
 
894
#ifdef RLIMIT_NPROC
 
895
                $$ = RLIMIT_NPROC;
 
896
#else
 
897
                RL_PFATAL(EX_DATAERR, _("%s limit not available on this system"), "nproc");
 
898
#endif
 
899
        }
 
900
        |       T_LIM_NOFILE
 
901
        {
 
902
#ifdef RLIMIT_NOFILE
 
903
                $$ = RLIMIT_NOFILE;
 
904
#else
 
905
                RL_PFATAL(EX_DATAERR, _("%s limit not available on this system"), "nofile");
 
906
#endif
 
907
        }
 
908
        |       T_LIM_MEMLOCK
 
909
        {
 
910
#ifdef RLIMIT_MEMLOCK
 
911
                $$ = RLIMIT_MEMLOCK;
 
912
#else
 
913
                RL_PFATAL(EX_DATAERR, _("%s limit not available on this system"), "memlock");
 
914
#endif          
 
915
        }
 
916
        ;
 
917
 
 
918
userid:         T_NUMERIC
 
919
        {
 
920
                $$ = getpwuid($1);
 
921
                endpwent();
 
922
        }
 
923
        |       T_QSTRING
 
924
        {
 
925
                $$ = getpwnam($1);
 
926
                free($1);
 
927
                endpwent();
 
928
        }
 
929
        ;
 
930
 
 
931
groupid:        T_NUMERIC
 
932
        {
 
933
                $$ = getgrgid($1);
 
934
                endgrent();
 
935
        }
 
936
        |       T_QSTRING
 
937
        {
 
938
                $$ = getgrnam($1);
 
939
                free($1);
 
940
                endgrent();
 
941
        }
 
942
        ;
 
943
 
 
944
protocol:       T_TCP
 
945
        {
 
946
                $$ = SOCK_STREAM;
 
947
                current_service->protoname = "tcp";
 
948
                current_service->proto = IPPROTO_TCP;
 
949
        }
 
950
        |       T_UDP
 
951
        {
 
952
                $$ = SOCK_DGRAM;
 
953
                current_service->protoname = "udp";
 
954
                current_service->proto = IPPROTO_UDP;
 
955
        }
 
956
        ;
 
957
 
 
958
family: T_IPV4
 
959
        {
 
960
                current_service->family = PF_INET;
 
961
        }
 
962
        | T_IPV6
 
963
        {
 
964
#ifdef HAVE_SOCKADDR_IN6                
 
965
                current_service->family = PF_INET6;
 
966
#else           
 
967
                RL_PWARN(_("ipv6 support is not compiled in"));
 
968
                current_service->family = PF_INET;
 
969
#endif
 
970
        }
 
971
        ;
 
972
 
 
973
signed_numeric: T_NUMERIC 
 
974
  {
 
975
                $$ = $1;
 
976
        }
 
977
        | '-' T_NUMERIC
 
978
        {
 
979
                $$ = (-$2);
 
980
        }       
 
981
        ;
 
982
 
 
983
boolean: T_YES
 
984
        {
 
985
                $$ = 1;
 
986
        }       
 
987
        | T_NO
 
988
        {
 
989
                $$ = 0;
 
990
        }
 
991
        ;
 
992
%%
 
993
 
 
994
void yyerror(char *str) {
 
995
        RL_PFATAL(EX_DATAERR, _("ABORT - %s"), str);
 
996
}
 
997
 
 
998
int yywrap() {
 
999
        fclose(yyin);
 
1000
        if(numfiles) {
 
1001
                while(++curfile < numfiles) {
 
1002
                        if((yyin = fopen(files[curfile], "r"))) {
 
1003
                                curfile_name = files[curfile];
 
1004
                                curfile_line = 1;
 
1005
                                return 0;
 
1006
                        } else {
 
1007
                                curfile_name = NULL;
 
1008
                                RL_PWARN(_("cannot open file %s (%s)"), files[curfile],
 
1009
                                                strerror(errno));
 
1010
                        }
 
1011
                }
 
1012
        }
 
1013
        return 1;
 
1014
}
 
1015
 
 
1016
static struct service *service_new() {
 
1017
        struct service *p = (struct service *)malloc(sizeof(*p));
 
1018
 
 
1019
        if (!p)
 
1020
                rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1021
        memset(p, 0, sizeof(*p));
 
1022
        return p;
 
1023
}
 
1024
 
 
1025
void services_free() {
 
1026
        if(rl_cleanups) {
 
1027
                rlp_cleanup(rl_cleanups);
 
1028
                rl_cleanups = NULL;
 
1029
        }
 
1030
}
 
1031
 
 
1032
static void validate_service(struct service *s) {
 
1033
        if(!s->name) {
 
1034
                RL_PWARN(_("service without name"));
 
1035
                s->disabled++;
 
1036
                return;
 
1037
        }
 
1038
 
 
1039
 if (!has_flag(s, FLAG_USER)) {
 
1040
                RL_PWARN(_("user is not set for service %s"), s->name);
 
1041
                s->disabled++;
 
1042
                return;
 
1043
 }
 
1044
        
 
1045
        if (s->wait && s->limit != 1) {
 
1046
                if (s->limit != defaults->limit)
 
1047
                        RL_PWARN(_("ignoring `instances %d' directive for service %s, because `wait' was also given"), 
 
1048
                                                                                s->limit, s->name);
 
1049
                s->limit = 1;
 
1050
        }       
 
1051
        
 
1052
        if(s->rpcvers) {
 
1053
                char *rpcname = s->name;
 
1054
                struct rpcent *rep;
 
1055
 
 
1056
                if(s->rpcname)
 
1057
                        rpcname = s->rpcname;
 
1058
                rep = getrpcbyname(rpcname);
 
1059
                if(!rep) {
 
1060
                        RL_PWARN(_("can't find rpc service %s for service %s"),
 
1061
                                                        rpcname, s->name);
 
1062
                        s->disabled++;
 
1063
                } else {
 
1064
                        s->rpcnum = rep->r_number;
 
1065
                }
 
1066
                endrpcent();
 
1067
        }
 
1068
}
 
1069
                 
 
1070
static int bind_ports() {
 
1071
        int fd;
 
1072
        long opt = 1;
 
1073
        struct stringlist *portp;
 
1074
        struct stringlist *ifp;
 
1075
#ifdef HAVE_GETADDRINFO
 
1076
        struct addrinfo hints;
 
1077
        struct addrinfo *results = NULL, *ai;
 
1078
        int ret;
 
1079
#else
 
1080
        void *addrbuf;
 
1081
        int portnum;
 
1082
        char *ctmp;
 
1083
#endif  
 
1084
        char *port, *addr;
 
1085
        char *lasterror, *errfunc = NULL;
 
1086
        int succeeded;
 
1087
        fd_set fds;
 
1088
        int n_fds;
 
1089
 
 
1090
        int family, socktype, protocol;
 
1091
        socklen_t saddrlen;
 
1092
        struct sockaddr *saddr = NULL;
 
1093
        
 
1094
        FD_ZERO(&fds);
 
1095
        n_fds = 0;
 
1096
        ifp = current_service->interface;
 
1097
        do {
 
1098
                struct stringlist fallback = { !current_service->rpcnum ? current_service->name : "0" , NULL };
 
1099
 
 
1100
                addr = ifp ? ifp->str : NULL;
 
1101
                portp = current_service->port;
 
1102
                if(!portp)
 
1103
                        portp = &fallback;
 
1104
                do {
 
1105
                        lasterror = NULL;
 
1106
                        succeeded = 0;
 
1107
                                
 
1108
                        port = portp->str;
 
1109
#ifdef HAVE_GETADDRINFO
 
1110
                        memset(&hints, 0, sizeof(hints));
 
1111
                        hints.ai_flags = AI_PASSIVE;
 
1112
                        hints.ai_family = current_service->family;
 
1113
                        hints.ai_socktype = current_service->socktype;
 
1114
                        hints.ai_protocol = current_service->proto;
 
1115
                        if(results)
 
1116
                                freeaddrinfo(results);
 
1117
                        results = NULL;
 
1118
                        if((ret = getaddrinfo(addr, port, &hints, &results))) {
 
1119
#ifdef HAVE_GAI_STRERROR
 
1120
                                RL_PWARN(_("getaddrinfo(%s, %s) failed: %s"), addr, port,
 
1121
                                                                gai_strerror(ret));
 
1122
#else
 
1123
                                RL_PWARN(_("getaddrinfo(%s, %s) failed: %s"), addr, port,
 
1124
                                                                _("for reasons unknown") );
 
1125
#endif                                                                  
 
1126
                                continue;
 
1127
                        }
 
1128
                        ai = results;
 
1129
                        do {
 
1130
                                family = ai->ai_family;
 
1131
                                socktype = ai->ai_socktype;
 
1132
                                protocol = ai->ai_protocol;
 
1133
                                saddr = ai->ai_addr;
 
1134
                                saddrlen = ai->ai_addrlen;
 
1135
#else
 
1136
                                portnum = strtoul(port, &ctmp, 10);
 
1137
                                if(*ctmp) {
 
1138
                                        portnum = getservport(port, current_service->protoname);
 
1139
                                        if(portnum == -1) {
 
1140
                                                RL_PWARN(_("Failed to resolve %s, protocol %s"),
 
1141
                                                                                current_service->proto, port);
 
1142
                                                continue;
 
1143
                                        }
 
1144
                                }
 
1145
                                family = current_service->family;
 
1146
                                socktype = current_service->socktype;
 
1147
                                protocol = current_service->proto;
 
1148
                                if(saddr) {
 
1149
                                        free(saddr);
 
1150
                                        saddr = NULL;
 
1151
                                }
 
1152
                                switch(family) {
 
1153
                                        struct sockaddr_in *sin;
 
1154
#ifdef HAVE_SOCKADDR_IN6
 
1155
                                        struct sockaddr_in6 *sin6;
 
1156
#endif
 
1157
                                                
 
1158
                                        case PF_INET:
 
1159
                                                saddrlen = sizeof(struct sockaddr_in);
 
1160
                                                sin = (struct sockaddr_in *)malloc(saddrlen);
 
1161
                                                if (!sin)
 
1162
                                                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1163
                                                addrbuf = &sin->sin_addr.s_addr;
 
1164
                                                sin->sin_family = current_service->family;
 
1165
                                                sin->sin_port = htons(portnum);
 
1166
                                                sin->sin_addr.s_addr = INADDR_ANY;
 
1167
                                                saddr = (struct sockaddr *)sin;
 
1168
                                                break;
 
1169
#ifdef HAVE_SOCKADDR_IN6
 
1170
                                        case PF_INET6:
 
1171
                                                saddrlen = sizeof(struct sockaddr_in6);
 
1172
                                                sin6 = (struct sockaddr_in6 *)malloc(saddrlen);
 
1173
                                                if (!sin6)
 
1174
                                                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1175
                                                addrbuf = &sin6->sin_addr.s_addr;
 
1176
                                                sin6->sin6_family = current_service->family;
 
1177
                                                sin6->sin6_port = htons(portnum);
 
1178
                                                sin6->sin6_addr = IN6ADDR_ANY_INIT;
 
1179
                                                saddr = (struct sockaddr *)sin6;
 
1180
                                                break;
 
1181
#endif                                                  
 
1182
                                        default:
 
1183
                                                RL_PFATAL(EX_SOFTWARE, _("funky family in service"));
 
1184
                                }
 
1185
                                if(addr) {
 
1186
                                        if(
 
1187
#ifdef HAVE_INET_PTON
 
1188
                                                 inet_pton(family, addr, addrbuf)
 
1189
#else                                           
 
1190
                                                                                                                                /* this cast is a pain */
 
1191
                                                 (*(unsigned int *)addrbuf = inet_addr(addr)) == -1
 
1192
#endif
 
1193
                                                 ) {
 
1194
                                                RL_PWARN(_("bad address %s in service %s"), addr,
 
1195
                                                                                current_service->name);
 
1196
                                                free(saddr);
 
1197
                                                saddr = NULL;
 
1198
                                                continue;
 
1199
                                        }
 
1200
                                }
 
1201
#endif                          
 
1202
                                if((fd = socket(family, socktype, protocol)) < 0) {
 
1203
                                        lasterror = strerror(errno);
 
1204
                                        errfunc = "socket()";
 
1205
                                        goto out;
 
1206
                                }
 
1207
                                if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
 
1208
                                        RL_PWARN(_("setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, 1) failed for service %s (%s)"),
 
1209
                                                                        fd, current_service->name, strerror(errno));
 
1210
                                }
 
1211
#ifdef HAVE_NET_BPF_H
 
1212
                                if(current_service->filter) {
 
1213
                                        struct bpf_program bp;
 
1214
 
 
1215
                                        bp.bf_len = current_service->filterlen / sizeof(struct bpf_insn);
 
1216
                                        bp.bf_insns = current_service->filter;
 
1217
                                        if(setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bp, sizeof(bp))) {
 
1218
                                                lasterror = strerror(errno);
 
1219
                                                close(fd);
 
1220
                                                errfunc = "setsockopt(..., SO_ATTACH_FILTER)";
 
1221
                                                goto out;
 
1222
                                        }
 
1223
                                }
 
1224
#endif                          
 
1225
                                if(bind(fd, saddr, saddrlen) < 0) {
 
1226
                                        lasterror = strerror(errno);
 
1227
                                        close(fd);
 
1228
                                        errfunc = "bind()";
 
1229
                                        goto out;
 
1230
                                }
 
1231
                                if(current_service->rpcnum) {
 
1232
                                        struct numlist *vers = current_service->rpcvers;
 
1233
                                        struct rl_cleanup *p;
 
1234
                                        struct sockaddr saddr2;
 
1235
 
 
1236
                                        if (getsockname(fd, &saddr2, &saddrlen) == -1) {
 
1237
                                                RL_PWARN(_("getsockname(%d) failed for service %s"), fd, current_service->name);
 
1238
                                                memcpy(&saddr2, saddr, sizeof(struct sockaddr));
 
1239
                                        }
 
1240
 
 
1241
                                        do {
 
1242
                                                if(!pmap_set(current_service->rpcnum, vers->num,
 
1243
                                                                                                 protocol,
 
1244
                                                                                                 ntohs(((struct sockaddr_in *)&saddr2)->sin_port)))
 
1245
                                                        RL_PWARN(_("pmap_set(%d, %d, %d, %d) failed for service %s"),
 
1246
                                                                                        current_service->rpcnum, vers->num,
 
1247
                                                                                        protocol, ntohs(((struct sockaddr_in *)&saddr2)->sin_port),
 
1248
                                                                                        current_service->name);
 
1249
                                        } while((vers = vers->next));
 
1250
                                        p = (struct rl_cleanup *)malloc(sizeof(struct rl_cleanup));
 
1251
                                        if (!p)
 
1252
                                                rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1253
                                        p->next = rl_cleanups;
 
1254
                                        p->data =       (struct rlc_unrpc *)malloc(sizeof(struct rlc_unrpc));
 
1255
                                        if (!p->data)
 
1256
                                                rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1257
                                        p->type = RLC_UNRPC;
 
1258
                                        ((struct rlc_unrpc *)p->data)->vers = NULL;
 
1259
                                        numlist_copy(&(((struct rlc_unrpc *)p->data)->vers), current_service->rpcvers);
 
1260
                                        ((struct rlc_unrpc *)p->data)->prog =   current_service->rpcnum;
 
1261
                                        /* current_service->rpcvers = NULL;*/ /* caused segfault in the next iteration
 
1262
                                                                                                                                                                                                         of do...while(ai=ai->ai_next) loop */
 
1263
                                        rl_cleanups = p;
 
1264
                                }
 
1265
                                FD_SET(fd, &fds);
 
1266
                                if(socktype == SOCK_STREAM) {
 
1267
                                        if(listen(fd, current_service->backlog)) {
 
1268
                                                lasterror = strerror(errno);
 
1269
                                                close(fd);
 
1270
                                                errfunc = "listen(fd)";
 
1271
                                                goto out;
 
1272
                                        }
 
1273
                                }
 
1274
                                if(fcntl(fd, F_SETFD, 1)) {
 
1275
                                        lasterror = strerror(errno);
 
1276
                                        errfunc = "fcntl(fd, F_SETFD, 1)";
 
1277
                                        close(fd);
 
1278
                                        goto out;
 
1279
                                }
 
1280
                                if(fcntl(fd, F_SETFL, O_NDELAY)) {
 
1281
                                        lasterror = strerror(errno);
 
1282
                                        close(fd);
 
1283
                                        errfunc = "fcntl(fd, F_SETFL, O_NDELAY)";
 
1284
                                        goto out;
 
1285
                                }
 
1286
                                n_fds++;
 
1287
                                succeeded++;
 
1288
                        out:
 
1289
#ifdef HAVE_GETADDRINFO
 
1290
                                continue;
 
1291
                        } while((ai = ai->ai_next));
 
1292
#endif
 
1293
                        if(!succeeded && lasterror)
 
1294
                                RL_PWARN(_("%s failed for service %s: %s"),
 
1295
                                                                errfunc, current_service->name, lasterror);
 
1296
                } while(portp && (portp = portp->next));
 
1297
        } while(ifp && (ifp = ifp->next));
 
1298
        stringlist_free(current_service->port);
 
1299
        current_service->port = NULL;
 
1300
        stringlist_free(current_service->interface);
 
1301
        current_service->interface = NULL;
 
1302
        numlist_free(current_service->rpcvers);
 
1303
        current_service->rpcvers = NULL;
 
1304
#ifdef HAVE_GETADDRINFO
 
1305
        if(results) {
 
1306
                freeaddrinfo(results);
 
1307
                results = NULL;
 
1308
        }
 
1309
#else
 
1310
        if(saddr) {
 
1311
                free(saddr);
 
1312
                saddr = NULL;
 
1313
        }
 
1314
#endif  
 
1315
        if (!n_fds)
 
1316
                current_service->disabled++;
 
1317
        return fdsettab_add(&fds);
 
1318
}
 
1319
 
 
1320
static int add_user_group(const struct service* s, struct opmetalist * l)
 
1321
{
 
1322
        struct opmeta *o = NULL;
 
1323
        if (has_flag(s, FLAG_USER))
 
1324
        {
 
1325
                o = opmeta_make(2, OP_SUID, 666);
 
1326
                opmeta_fixup(o, 1, ofp_setuid);
 
1327
                if(opmetalist_add(l, o)) {
 
1328
                                RL_PWARN(_("opcode resolving problem"));
 
1329
                                return 0;
 
1330
                }
 
1331
  }
 
1332
 
 
1333
        if (has_flag(s, FLAG_USER) || (has_flag(s, FLAG_GROUP)))
 
1334
        {
 
1335
                                o = opmeta_make(2, OP_SGID, 666);
 
1336
                                opmeta_fixup(o, 1, ofp_setgid);
 
1337
                                if(opmetalist_add(l, o)) {
 
1338
                                        RL_PWARN(_("opcode resolving problem"));
 
1339
                                  return 0;
 
1340
                                }
 
1341
  }
 
1342
 
 
1343
        if (has_flag(s, FLAG_USER) && has_flag(s, FLAG_INITGROUPS))
 
1344
  {
 
1345
                        o = opmeta_make(3, OP_INITGR, 666, 666);
 
1346
                        opmeta_fixup(o, 1, ofp_iuser);
 
1347
                        opmeta_fixup(o, 2, ofp_supgid);
 
1348
                        if(opmetalist_add(l, o)) {
 
1349
                                RL_PWARN(_("opcode resolving problem"));
 
1350
                         return 0;
 
1351
                }
 
1352
        }
 
1353
  return 1;
 
1354
}
 
1355
 
 
1356
static void service_free(struct service *s) {
 
1357
        if(s->name) {
 
1358
                free(s->name);
 
1359
                s->name = NULL;
 
1360
        }
 
1361
        stringlist_free(s->port);
 
1362
        s->port = NULL;
 
1363
        stringlist_free(s->interface);
 
1364
        s->interface = NULL;
 
1365
        if(s->rpcname) {
 
1366
                free(s->rpcname);
 
1367
                s->rpcname = NULL;
 
1368
        }
 
1369
        if(s->rpcvers) {
 
1370
                numlist_free(s->rpcvers);
 
1371
                s->rpcvers = NULL;
 
1372
        }
 
1373
#ifdef HAVE_CAPABILITIES
 
1374
        if(s->caps) {
 
1375
                cap_free(&s->caps);
 
1376
                s->caps = NULL;
 
1377
        }
 
1378
#endif  
 
1379
#ifdef HAVE_NET_BPF_H
 
1380
        if(s->filter) {
 
1381
                free(s->filter);
 
1382
                s->filter = NULL;
 
1383
                s->filterlen = 0;
 
1384
        }
 
1385
#endif  
 
1386
}
 
1387
 
 
1388
static void service_copy(struct service *to, struct service *from) {
 
1389
        memcpy(to, from, sizeof(*to));
 
1390
        to->name = NULL;
 
1391
        to->port = NULL;
 
1392
        to->interface = NULL;
 
1393
        stringlist_copy(&to->port, from->port);
 
1394
        stringlist_copy(&to->interface, from->interface);
 
1395
        to->rpcname = from->rpcname ? strdup(from->rpcname) : NULL;
 
1396
        to->rpcvers = NULL;
 
1397
        numlist_copy(&to->rpcvers, from->rpcvers);
 
1398
#ifdef HAVE_LIBCAP
 
1399
        to->caps = from->caps ? cap_dup(from->caps) : NULL;
 
1400
#endif
 
1401
#ifdef HAVE_NET_BPF_H
 
1402
        if(from->filter) {
 
1403
                to->filter = malloc(from->filterlen);
 
1404
                if (!to->filter)
 
1405
                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1406
                memcpy(to->filter, from->filter, from->filterlen);
 
1407
        }
 
1408
#endif  
 
1409
}
 
1410
 
 
1411
static struct logdata *logdata_get(char *name) {
 
1412
        struct logdata *ptr = logdatas;
 
1413
 
 
1414
        if(!ptr)
 
1415
                return NULL;
 
1416
        do {
 
1417
                if(!strcmp(name, ptr->name))
 
1418
                        return ptr;
 
1419
        } while((ptr = ptr->next));
 
1420
        return NULL;
 
1421
}
 
1422
 
 
1423
static void logdatas_free() {
 
1424
        struct logdata *p, *q;
 
1425
 
 
1426
        p = logdatas;
 
1427
        while(p) {
 
1428
                q = p->next;
 
1429
                if(p->name)
 
1430
                        free(p->name);
 
1431
                if(p->path)
 
1432
                        free(p->path);
 
1433
                free(p);
 
1434
                p = q;
 
1435
        }
 
1436
        logdatas = NULL;
 
1437
}
 
1438
 
 
1439
static struct logdata *logdata_new() {
 
1440
        struct logdata *ptr = (struct logdata *)malloc(sizeof(*ptr));
 
1441
 
 
1442
        if (!ptr)
 
1443
                rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1444
 
 
1445
        memset(ptr, 0, sizeof(*ptr));
 
1446
        ptr->index = -1;
 
1447
        ptr->mode =
 
1448
#ifdef S_IRUSR
 
1449
                S_IRUSR|S_IWUSR|S_IRGRP
 
1450
#else
 
1451
                0640
 
1452
#endif
 
1453
                ;
 
1454
        ptr->uid = -1;
 
1455
        ptr->gid = -1;
 
1456
        return ptr;
 
1457
}
 
1458
 
 
1459
void parse() {
 
1460
        void freebufs();
 
1461
        
 
1462
        numlist = NULL;
 
1463
        userdata = NULL;
 
1464
        newuserdata(&userdata);
 
1465
        pidtab_fixup();
 
1466
        all_unhook();
 
1467
        logtabs_free();
 
1468
        argvtabs_free();
 
1469
        rlimittabs_free();
 
1470
        services_free();
 
1471
        stringtabs_free();
 
1472
        buftabs_free();
 
1473
        oplisttabs_free();
 
1474
#ifdef HAVE_CAPABILITIES
 
1475
        captabs_free();
 
1476
#endif  
 
1477
        semaphores_free();
 
1478
        fdsettabs_free();
 
1479
        if(strcmp(rl_config, "-") || !rl_debug) {
 
1480
                if(!(yyin = fopen(rl_config, "r"))) {
 
1481
                        RL_PFATAL(EX_NOINPUT, _("fopen(%s) failed, aborting"), rl_config);
 
1482
                } else {
 
1483
                        curfile_name = rl_config;
 
1484
                        curfile_line = 1;
 
1485
                }
 
1486
        }
 
1487
 
 
1488
        logcur = logdata_new();
 
1489
        current_service = service_new();
 
1490
        defaults = service_new();
 
1491
#ifdef HAVE_GETADDRINFO
 
1492
        defaults->family = PF_UNSPEC;
 
1493
#else   
 
1494
        defaults->family = PF_INET;
 
1495
#endif  
 
1496
        defaults->socktype = SOCK_STREAM;
 
1497
        defaults->protoname = "tcp";
 
1498
        defaults->proto = IPPROTO_TCP;
 
1499
        defaults->backlog = 5;
 
1500
        defaults->limit = 40;
 
1501
        defaults->r.rlim_cur = RLIM_INFINITY;
 
1502
        defaults->r.rlim_max = RLIM_INFINITY;
 
1503
        defaults->wait = 0;
 
1504
 
 
1505
 
 
1506
        defaults->opfixups[ofp_exec] = -1;
 
1507
 
 
1508
        defaults->opfixups[ofp_iname] = -1;
 
1509
        defaults->opfixups[ofp_parent] = -1;
 
1510
        defaults->opfixups[ofp_iuser]  = -1;
 
1511
        defaults->sflags =  0;
 
1512
        defaults->opfixups[ofp_supgid] = -1;
 
1513
        defaults->opfixups[ofp_setgid] = -1;
 
1514
        defaults->opfixups[ofp_setuid] = -1;
 
1515
        service_copy(current_service, defaults);
 
1516
  opml_defaults = opmetalist_new();
 
1517
        yyparse();
 
1518
        freebufs();
 
1519
        service_free(defaults);
 
1520
        free(defaults);
 
1521
        defaults = NULL;
 
1522
        logdatas_free();
 
1523
        free(logcur);
 
1524
        logcur = NULL;
 
1525
        service_free(current_service);
 
1526
        free(current_service);
 
1527
        current_service = NULL;
 
1528
        for(curfile = 0; curfile < numfiles; curfile++) {
 
1529
                free(files[curfile]);
 
1530
                files[curfile] = NULL;
 
1531
        }
 
1532
        free(files);
 
1533
        files = NULL;
 
1534
        clearuserdata(&userdata);
 
1535
        free(userdata);
 
1536
}
 
1537
 
 
1538
static void pidtab_fixup() {
 
1539
        struct pidtab *p;
 
1540
        int i;
 
1541
 
 
1542
        for(i = 0; i < 8; i++) {
 
1543
                p = pidtabs[i].next;
 
1544
                while(p) {
 
1545
                        if(p->inst)
 
1546
                                inst_free(p->inst);
 
1547
                        p->inst = NULL;
 
1548
                        p = p->next;
 
1549
                }
 
1550
        }
 
1551
}
 
1552
 
 
1553
#ifndef HAVE_GETADDRINFO
 
1554
static int getservport(char *str, char *proto) {
 
1555
        struct servent *foo;
 
1556
        int ret = -1;
 
1557
 
 
1558
        foo = getservbyname(str, proto);
 
1559
        if(foo)
 
1560
                ret = ntohs(foo->s_port);
 
1561
        endservent();
 
1562
        return ret;
 
1563
}
 
1564
#endif
 
1565
 
 
1566
static void add_directory(char *dir, char *match, char *ignore) {
 
1567
        DIR *d;
 
1568
        struct dirent *de;
 
1569
        regex_t rmatch, rignore;
 
1570
        char err[128];
 
1571
        int e;
 
1572
        struct stat st;
 
1573
        char *file;
 
1574
 
 
1575
        if(match)
 
1576
                if((e = regcomp(&rmatch, match, REG_EXTENDED|REG_NOSUB))) {
 
1577
                        regerror(e, &rmatch, err, 127);
 
1578
                        RL_PWARN(_("regexp compile failed for directory %s: %s"),
 
1579
                                                        dir, err);
 
1580
                }
 
1581
        if(ignore)
 
1582
                if((e = regcomp(&rignore, ignore, REG_EXTENDED|REG_NOSUB))) {
 
1583
                        regerror(e, &rignore, err, 127);
 
1584
                        RL_PWARN(_("regexp compile failed for directory %s: %s"),
 
1585
                                                        dir, err);
 
1586
                }
 
1587
                        
 
1588
        if((d = opendir(dir))) {
 
1589
                while((de = readdir(d))) {
 
1590
                        if(match)
 
1591
                                if(regexec(&rmatch, de->d_name, 0, NULL, 0))
 
1592
                                        continue;
 
1593
                        if(ignore)
 
1594
                                if(!regexec(&rignore, de->d_name, 0, NULL, 0))
 
1595
                                        continue;
 
1596
                        if(de->d_name[0] != '.') {
 
1597
                                file = malloc(strlen(dir) + NAMLEN(de) + 2);
 
1598
                                if (!file)
 
1599
                                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1600
                                file[0] = '\0';
 
1601
                                strcat(file, dir);
 
1602
                                strcat(file, "/");
 
1603
                                strcat(file, de->d_name);
 
1604
                                if(stat(file, &st) || S_ISDIR(st.st_mode)) {
 
1605
                                        RL_PWARN(_("file %s does not exists or"
 
1606
                                                 " is a directory"), file);     
 
1607
                                        free(file);
 
1608
                                        continue;
 
1609
                                }
 
1610
                                files = (char **)realloc(files, ++numfiles * sizeof(char *));
 
1611
                                if (!files)
 
1612
                                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
1613
                                files[numfiles - 1] = file;
 
1614
                        }
 
1615
                }
 
1616
        } else {
 
1617
                RL_PFATAL(EX_NOINPUT, _("Directory %s open failed (%s)"), dir, 
 
1618
                        strerror(errno));
 
1619
        }
 
1620
        closedir(d);
 
1621
        free(dir);
 
1622
        if(match) {
 
1623
                free(match);
 
1624
                regfree(&rmatch);
 
1625
        }
 
1626
        if(ignore) {
 
1627
                free(ignore);
 
1628
                regfree(&rignore);
 
1629
        }
 
1630
}
 
1631
 
 
1632
int chargen_buffer() {
 
1633
        static int cb = -1;
 
1634
        char *b = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
 
1635
        
 
1636
        if(cb == -1)
 
1637
                cb = buftab_addbuf(b, strlen(b));
 
1638
        return cb;
 
1639
}
 
1640
 
 
1641
 
 
1642
/* vim: set ts=2: */