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

« back to all changes in this revision

Viewing changes to 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
 
 
74
 
static struct logdata *logcur, *logdatas;
75
 
 
76
 
static struct numlist *numlist = NULL;
77
 
static struct stringlist *stringlist = NULL;
78
 
 
79
 
void yyerror(char *c);
80
 
int yylex();
81
 
static int bind_ports();
82
 
static void service_copy(struct service *to, struct service *from);
83
 
static void service_free(struct service *s); 
84
 
static struct service *service_new();
85
 
#ifndef HAVE_GETADDRINFO
86
 
static int getservport(char *str, char *proto);
87
 
#endif
88
 
static struct logdata *logdata_get(char *name);
89
 
static struct logdata *logdata_new();
90
 
static void pidtab_fixup();
91
 
static void validate_service(struct service *s);
92
 
static void add_directory(char *dir, char *match, char *ignore);
93
 
static int chargen_buffer();
94
 
 
95
 
void freebufs(); /* from parse.l */
96
 
 
97
 
%}
98
 
 
99
 
%union {
100
 
        long num;
101
 
        char *cp;
102
 
        struct passwd *uid;
103
 
        struct group *gid;
104
 
        struct opmetalist *opml;
105
 
        struct opmeta *opm;
106
 
        rlim_t rl;
107
 
}
108
 
 
109
 
%token T_SERVICE T_PORT T_EXEC T_PROTO T_UDP T_TCP T_UID T_GID T_BACKLOG
110
 
%token T_INSTANCES T_WAIT T_DEFAULT T_NICE T_INTERFACE T_FISH T_CHROOT T_SERVER
111
 
%token T_DIR T_RPC T_VERSION T_NAME T_WRAP T_CAPS T_FAMILY T_IPV4 T_IPV6
112
 
%token T_INITGROUPS T_BANNER T_ECHO T_DISCARD T_FILTER T_CHARGEN T_LOOPBACK
113
 
 
114
 
%token T_RLIMIT T_LIM_CPU T_LIM_FSIZE T_LIM_DATA T_LIM_STACK T_LIM_CORE
115
 
%token T_LIM_RSS T_LIM_NPROC T_LIM_NOFILE T_LIM_MEMLOCK T_LIM_INFINITY
116
 
%token T_SOFT T_HARD
117
 
%token T_YES T_NO
118
 
 
119
 
%token T_LOG T_PIPE T_SYSLOG T_PATH T_MODE
120
 
 
121
 
%token T_ACCEPT T_DENY T_CLOSE T_EXIT
122
 
 
123
 
%token <num> T_NUMERIC
124
 
%token <cp> T_QSTRING T_IPADDR
125
 
 
126
 
%type <gid> groupid;
127
 
%type <uid> userid;
128
 
%type <num> limittype limit protocol;
129
 
%type <opm> opcode_element
130
 
%type <opml> service_elements complex_opcode_element opcode_block
131
 
%type <rl> limitvalue
132
 
%type <cp> optionalstring
133
 
%type <num> signed_numeric
134
 
%type <num> boolean
135
 
 
136
 
%%
137
 
 
138
 
tles:   tle
139
 
        |       tles tle
140
 
        ;
141
 
 
142
 
tle:    service
143
 
        |       default
144
 
        |       log
145
 
        |       directory
146
 
        ;
147
 
 
148
 
directory:      T_DIR T_QSTRING ';'
149
 
        {       add_directory($2, NULL, NULL);  }
150
 
        |       T_DIR T_QSTRING T_QSTRING ';'
151
 
        {       add_directory($2, $3, NULL);    }
152
 
        |       T_DIR T_QSTRING T_QSTRING T_QSTRING ';'
153
 
        {       add_directory($2, $3, $4);      }
154
 
        ;
155
 
 
156
 
log:    T_LOG T_QSTRING '{' log_element '}'
157
 
        {
158
 
                if(logdata_get($2)) {
159
 
                        RL_PWARN("duplicate declaration of log %s, ignoring", $2);
160
 
                        free($2);
161
 
                } else {
162
 
                        logcur->name = $2;
163
 
                        logcur->next = logdatas;
164
 
                        logdatas = logcur;
165
 
                        logcur = logdata_new();
166
 
                }
167
 
                clearuserdata(&userdata);
168
 
        }
169
 
        ;
170
 
 
171
 
log_element: file_elements
172
 
        {
173
 
                if(!logcur->path) {
174
 
                        RL_PWARN("No path defined for log %s", logcur->name);
175
 
                } else {
176
 
                        if((logcur->index = open(logcur->path, O_CREAT|O_APPEND|O_WRONLY, logcur->mode)) < 0) {
177
 
                                RL_PWARN("open(\"%s\", O_CREAT|O_APPEND|O_WRONLY, 0%o) failed (%s)",
178
 
                                                                logcur->path, logcur->mode, strerror(errno));
179
 
                        } else {
180
 
 
181
 
                                if(fchmod(logcur->index, logcur->mode)) {
182
 
                                        RL_PWARN("fchmod(\"%s\", 0%o) failed (%s)",
183
 
                                                                        logcur->path, logcur->mode, 
184
 
                                                                        strerror(errno));
185
 
                                }
186
 
 
187
 
                                if(fchown(logcur->index, logcur->uid, logcur->gid)) {
188
 
                                        RL_PWARN("fchown(\"%s\", %d, %d) failed for log %s (%s)",
189
 
                                                                        logcur->path, logcur->uid, logcur->gid, logcur->name,
190
 
                                                                        strerror(errno));
191
 
                                }
192
 
                        }
193
 
                }
194
 
        }
195
 
        ;
196
 
 
197
 
file_elements:  file_element
198
 
        |       file_elements file_element
199
 
        ;
200
 
 
201
 
file_element:   ';'
202
 
        |       T_PATH T_QSTRING ';'
203
 
        {
204
 
                if(logcur->path) {
205
 
                        RL_PWARN("duplicate path declaration (%s) "
206
 
                                "in log directive %s, ignoring", $2, 
207
 
                                logcur->name);
208
 
                        free($2);
209
 
                } else {
210
 
                        logcur->path = $2;
211
 
                }
212
 
        }
213
 
        |       T_UID userid ';'
214
 
        {
215
 
                if (logcur->uid > -1) { /* FIXME */
216
 
                        RL_PWARN("duplicate user declaration "
217
 
                                "in log directive %s, ignoring", logcur->name);
218
 
                }
219
 
                else if ($2) {
220
 
                        logcur->uid = $2->pw_uid;
221
 
                } else {
222
 
                        RL_PWARN("unknown username");
223
 
                }
224
 
        }
225
 
        |       T_GID groupid ';'
226
 
        {
227
 
                if (logcur->gid > -1) { /* FIXME */
228
 
                        RL_PWARN("duplicate group declaration "
229
 
                                "in log directive %s, ignoring", logcur->name);
230
 
                }
231
 
                else if ($2) {
232
 
                        logcur->gid = $2->gr_gid;
233
 
                } else {
234
 
                        RL_PWARN("unknown groupname");
235
 
                }
236
 
        }
237
 
        |       T_MODE T_NUMERIC ';'
238
 
        {
239
 
                if (logcur->mode > -1) { /* FIXME */
240
 
                        RL_PWARN("duplicate mode declaration "
241
 
                                "in log directive, ignoring");
242
 
                } else if ($2 > 07777)  {
243
 
                        RL_PWARN("invalid mode declaration "
244
 
                                "in log directive, ignoring");
245
 
                } else {
246
 
                        logcur->mode = $2;
247
 
                }
248
 
        }
249
 
        ;
250
 
 
251
 
default:        T_DEFAULT '{' service_elements '}'
252
 
        {
253
 
                service_free(defaults);
254
 
                service_copy(defaults, current_service);
255
 
                opmetalist_free($3);
256
 
                free($3);
257
 
        }
258
 
        ;
259
 
 
260
 
service:        T_SERVICE T_QSTRING '{' service_elements '}'
261
 
        {
262
 
                struct opmetalist *parent;
263
 
                struct opmetalist *onexit;
264
 
                struct oplist *ops;
265
 
                int i, bound;
266
 
                int fds;
267
 
                fd_set *fdst;
268
 
 
269
 
                parent = opmetalist_new();
270
 
                onexit = opmetalist_new();
271
 
 
272
 
                current_service->name = $2;
273
 
                current_service->iname = stringtab_add($2);
274
 
 
275
 
                do { /* avoid goto */   
276
 
                        
277
 
                        if (current_service->disabled)
278
 
                                break;
279
 
                        
280
 
                        if(current_service->socktype == SOCK_STREAM && !current_service->wait) {
281
 
                                if(opmetalist_add($4, opmeta_make(2, OP_ACCEPT, 200))) { /* !200 */
282
 
                                        RL_PWARN("opcode resolving problem");
283
 
                                        current_service->disabled++;
284
 
                                        break;
285
 
                                }
286
 
                                opmetalist_add(parent, opmeta_make(1, OP_CLOSE));
287
 
 
288
 
                                if (current_service->internal) 
289
 
                                        opmetalist_add(onexit, opmeta_make(1, OP_CLOSE));
290
 
                                else
291
 
                                        opmetalist_add(onexit, opmeta_make(1, OP_RET));
292
 
 
293
 
                        } else {
294
 
                                opmetalist_add(parent, opmeta_make(1, OP_RET));
295
 
                                opmetalist_add(onexit, opmeta_make(1, OP_RET));
296
 
                        }
297
 
                        validate_service(current_service);
298
 
 
299
 
                        if (current_service->disabled)
300
 
                                break;
301
 
 
302
 
                        fds = bind_ports();
303
 
                        
304
 
                        if(current_service->limit) {
305
 
                                struct opmetalist *o;
306
 
                                struct oplist *l;
307
 
                                int match, under;
308
 
        
309
 
                                o = opmetalist_new();
310
 
                                opmetalist_add(o, opmeta_make(2, OP_LCLR, fds));
311
 
                                opmetalist_add(o, opmeta_make(1, OP_RET));
312
 
                                l = opmetalist_resolve(o);
313
 
                                match = oplisttab_add(l);
314
 
                                opmetalist_free(o);
315
 
                                free(o);
316
 
                                oplist_free(l);
317
 
                                free(l);
318
 
                                
319
 
                                o = opmetalist_new();
320
 
                                opmetalist_add(o, opmeta_make(2, OP_LSET, fds));
321
 
                                opmetalist_add(o, opmeta_make(1, OP_RET));
322
 
                                l = opmetalist_resolve(o);
323
 
                                under = oplisttab_add(l);
324
 
                                opmetalist_free(o);
325
 
                                free(o);
326
 
                                oplist_free(l);
327
 
                                free(l);
328
 
                                
329
 
                                i = semaphore_add(current_service->limit, match, under);
330
 
                                opmetalist_add($4, opmeta_make(2, OP_DOWN, i));
331
 
                                opmetalist_add(onexit, opmeta_make(2, OP_UP, i));
332
 
                        }
333
 
                        ops = opmetalist_resolve(onexit);
334
 
                        current_service->onexit = oplisttab_add(ops);
335
 
                        opmetalist_free(onexit);
336
 
                        free(onexit);
337
 
                        oplist_free(ops);
338
 
                        free(ops);
339
 
                        
340
 
                        ops = opmetalist_resolve(parent);
341
 
                        current_service->parent = oplisttab_add(ops);
342
 
                        opmetalist_free(parent);
343
 
                        free(parent);
344
 
                        oplist_free(ops);
345
 
                        free(ops);
346
 
        
347
 
                        opmetalist_add($4, opmeta_make(2, OP_JUMP, current_service->onexit));
348
 
                        ops = opmetalist_resolve($4);
349
 
                        current_service->run = oplisttab_add(ops);
350
 
                        opmetalist_free($4);
351
 
                        free($4);
352
 
                        oplist_free(ops);
353
 
                        free(ops);
354
 
        
355
 
                        fdst = fdsettab_get(fds);
356
 
                        bound = getdtablesize();
357
 
                        for(i = 0; i < bound; i++)
358
 
                                if(FD_ISSET(i, fdst))
359
 
                                        read_hook(i, oplisttab_get(current_service->run), NULL);
360
 
 
361
 
                } while (0);    
362
 
 
363
 
                if (current_service->disabled) {
364
 
                rl_warn("service %s DISABLED", current_service->name);
365
 
                } else {
366
 
                        rl_note("service %s enabled", current_service->name);
367
 
                        if (rl_debug > 1)
368
 
                                rl_note("+-> uid=%d, sgid=%d, supgid=%d", current_service->setuid,
369
 
                                        current_service->setgid, current_service->supgid);
370
 
                        
371
 
                }
372
 
 
373
 
                service_free(current_service);
374
 
                service_copy(current_service, defaults);
375
 
        }
376
 
        ;
377
 
 
378
 
service_elements:       service_element
379
 
        {
380
 
                $$ = opmetalist_new();
381
 
        }
382
 
        | service_elements service_element
383
 
        {
384
 
                $$ = $1;
385
 
        }
386
 
        | opcode_element
387
 
        {
388
 
                struct opmetalist *l;
389
 
 
390
 
                l = opmetalist_new();
391
 
                if(opmetalist_add(l, $1)) {
392
 
                        RL_PWARN("opcode resolving problem");
393
 
                        current_service->disabled++;
394
 
                }
395
 
                $$ = l;
396
 
        }
397
 
        | service_elements opcode_element
398
 
        {
399
 
                if(opmetalist_add($1, $2)) {
400
 
                        RL_PWARN("opcode resolving problem");
401
 
                        current_service->disabled++;
402
 
                }
403
 
                $$ = $1;
404
 
        }
405
 
        | service_elements complex_opcode_element
406
 
        {
407
 
                $$ = opmetalist_join($1, $2);
408
 
                if(!$$) {
409
 
                        RL_PWARN("opcode resolving problem");
410
 
                        current_service->disabled++;
411
 
                }
412
 
        }
413
 
        | complex_opcode_element
414
 
        {
415
 
                $$ = $1;
416
 
        }
417
 
        ;
418
 
 
419
 
opcode_block: complex_opcode_element
420
 
        {
421
 
                $$ = $1;
422
 
        }
423
 
        |       opcode_element
424
 
        {
425
 
                struct opmetalist *l;
426
 
 
427
 
                l = opmetalist_new();
428
 
                if(opmetalist_add(l, $1)) {
429
 
                        RL_PWARN("opcode resolving problem");
430
 
                        current_service->disabled++;
431
 
                }
432
 
                $$ = l;
433
 
        }
434
 
        | opcode_block opcode_element
435
 
        {
436
 
                if(opmetalist_add($1, $2)) {
437
 
                        RL_PWARN("opcode resolving problem");
438
 
                        current_service->disabled++;
439
 
                }
440
 
                $$ = $1;
441
 
        }
442
 
        | opcode_block complex_opcode_element
443
 
        {
444
 
                $$ = opmetalist_join($1, $2);
445
 
                if(!$$) {
446
 
                        RL_PWARN("opcode resolving problem");
447
 
                        current_service->disabled++;
448
 
                }
449
 
        }
450
 
        ;
451
 
 
452
 
complex_opcode_element: T_EXEC T_QSTRING ';'
453
 
        {
454
 
                struct opmetalist *l;
455
 
                struct opmeta *o;
456
 
                
457
 
                l = opmetalist_new();
458
 
                o = opmeta_make(3, OP_EXEC, 666, argvtab_add($2, 1));
459
 
                opmeta_fixup(o, 1, &current_service->exec);
460
 
                if(opmetalist_add(l, o)) {
461
 
                        RL_PWARN("opcode resolving problem");
462
 
                        current_service->disabled++;
463
 
                }
464
 
                o = opmeta_make(3, OP_FORK, 666, 666);
465
 
                opmeta_fixup(o, 1, &current_service->parent);
466
 
                opmeta_fixup(o, 2, &current_service->onexit);
467
 
                if(opmetalist_add(l, o)) {
468
 
                        RL_PWARN("opcode resolving problem");
469
 
                        current_service->disabled++;
470
 
                }
471
 
                $$ = l;
472
 
        }
473
 
        | T_INITGROUPS ';'
474
 
        {
475
 
                struct opmetalist *l;
476
 
                struct opmeta *o;
477
 
 
478
 
                l = opmetalist_new();
479
 
                o = opmeta_make(3, OP_INITGR, 666, 666);
480
 
                opmeta_fixup(o, 1, &current_service->iuser);
481
 
                opmeta_fixup(o, 2, &current_service->supgid);
482
 
                if(opmetalist_add(l, o)) {
483
 
                        RL_PWARN("opcode resolving problem");
484
 
                        current_service->disabled++;
485
 
                }
486
 
                if(!current_service->sgid) {
487
 
                        o = opmeta_make(2, OP_SGID, 666);
488
 
                        opmeta_fixup(o, 1, &current_service->setgid);
489
 
                        current_service->sgid = 1;
490
 
                        if(opmetalist_add(l, o)) {
491
 
                                RL_PWARN("opcode resolving problem");
492
 
                                current_service->disabled++;
493
 
                        }
494
 
                }
495
 
                        
496
 
                $$ = l;
497
 
        }
498
 
        ;
499
 
 
500
 
opcode_element: T_NICE signed_numeric ';'
501
 
        {
502
 
                $$ = opmeta_make(2, OP_NICE, $2);
503
 
        }
504
 
        |       T_FISH ';'
505
 
        {
506
 
                $$ = opmeta_make(1, OP_FISH);
507
 
        }
508
 
        |       T_RLIMIT limittype limit
509
 
        {
510
 
                $$ = opmeta_make(3, OP_RLIMIT, $2, $3);
511
 
        }
512
 
        |       T_LOG T_SYSLOG T_QSTRING ';'
513
 
        {
514
 
                int i;
515
 
 
516
 
                i = logtab_add(-1, $3);
517
 
                $$ = opmeta_make(2, OP_LOG, i);
518
 
                free($3);
519
 
        }
520
 
        |       T_UID userid ';'
521
 
        {
522
 
                if($2) {
523
 
                        struct opmeta *o = NULL;
524
 
 
525
 
                        current_service->iuser = stringtab_add($2->pw_name);
526
 
                        current_service->setuid = $2->pw_uid;
527
 
                        if(current_service->sgid == -1) {
528
 
                                current_service->setgid = $2->pw_gid;
529
 
                        }
530
 
                        current_service->supgid = $2->pw_gid;
531
 
 
532
 
                        o = opmeta_make(4, OP_SGID, 666, OP_SUID, 666);
533
 
                        opmeta_fixup(o, 1, &current_service->setgid);
534
 
                        opmeta_fixup(o, 3, &current_service->setuid);
535
 
                        $$ = o;
536
 
                } else {
537
 
                        RL_PWARN("unknown username");
538
 
                        current_service->disabled++;
539
 
                        $$ = NULL;
540
 
                }
541
 
        }
542
 
        |       T_BANNER T_QSTRING ';'
543
 
        {
544
 
                int ret;
545
 
 
546
 
                ret = buftab_addfile($2);
547
 
                if(ret == -1)
548
 
                        current_service->disabled++;
549
 
                $$ = opmeta_make(16, OP_ZERO, OP_BUFCLONE, ret, OP_WHOOK, 0, OP_WUNHOOK,
550
 
                                                                                 OP_DUP, OP_BUFCOPY, OP_DUP, OP_BZNEG, 3, OP_ADD,
551
 
                                                                                 OP_WHOOK, -9, OP_POP, OP_BUFFREE);
552
 
                free($2);
553
 
        }
554
 
        |       T_CHARGEN optionalstring ';'
555
 
        {
556
 
                int i;
557
 
 
558
 
                if($2) {
559
 
                        i = buftab_addfile($2);
560
 
                        if(i < 0)
561
 
                                current_service->disabled++;
562
 
                } else {
563
 
                        i = chargen_buffer();
564
 
                }
565
 
                $$ = opmeta_make(25, OP_ZERO, OP_DUP, OP_BUFCLONE, i, OP_POP,
566
 
                                                                                 OP_POP, OP_ZERO, OP_WHOOK, 0, OP_WUNHOOK, OP_DUP,
567
 
                                                                                 OP_BUFCOPY, OP_DUP, OP_BZ, -11, OP_DUP, OP_BZNEG, 3,
568
 
                                                                                 OP_ADD, OP_WHOOK, -12, OP_POP, OP_BUFFREE, OP_JUMP, 666);
569
 
                opmeta_fixup($$, 24, &current_service->onexit);
570
 
                current_service->internal = 1;
571
 
                if($2)
572
 
                        free($2);
573
 
        }
574
 
        |       T_LOG T_QSTRING T_QSTRING ';'
575
 
        {
576
 
                struct logdata *ld = logdata_get($2);
577
 
 
578
 
                if(!ld) {
579
 
                        RL_PWARN("unknown log %s", $2);
580
 
                        current_service->disabled++;
581
 
                } else {
582
 
                        int i = logtab_add(ld->index, $3);
583
 
                        $$ = opmeta_make(2, OP_LOG, i);
584
 
                }
585
 
                free($2);
586
 
                free($3);
587
 
        }
588
 
        |       T_GID groupid ';'
589
 
        {
590
 
                if($2) {
591
 
                        struct opmeta *o = NULL;
592
 
 
593
 
                        if(!current_service->sgid) {
594
 
                                o = opmeta_make(2, OP_SGID, 666);
595
 
                                opmeta_fixup(o, 1, &current_service->setgid);
596
 
                                current_service->sgid = 1;
597
 
                        }
598
 
                        if (current_service->supgid == -1)
599
 
                                current_service->supgid = $2->gr_gid;
600
 
                        current_service->setgid = $2->gr_gid;
601
 
                        $$ = o;
602
 
                } else {
603
 
                        RL_PWARN("unknown group");
604
 
                        current_service->disabled++;
605
 
                        $$ = NULL;
606
 
                }
607
 
        }
608
 
        |       T_CHROOT T_QSTRING ';'
609
 
        {
610
 
                $$ = opmeta_make(2, OP_CHROOT, argvtab_add($2, 1));
611
 
        }
612
 
        |       T_CAPS T_QSTRING ';'
613
 
        {
614
 
#ifdef HAVE_CAPABILITIES
615
 
                cap_t caps = cap_from_text($2);
616
 
                if(caps) {
617
 
                        $$ = opmeta_make(2, OP_SETCAP, captab_add(caps));
618
 
                } else {
619
 
                        RL_PWARN("failed to parse capability string \"%s\"\n", $2);
620
 
                        current_service->disabled++;
621
 
                }
622
 
                free($2);
623
 
#else
624
 
                RL_PFATAL(EX_DATAERR, "ABORT - support for capabilities not compiled in");
625
 
#endif
626
 
        }
627
 
        | T_WRAP T_QSTRING '{' opcode_block '}'
628
 
        {
629
 
                int i;
630
 
                struct oplist *op;
631
 
 
632
 
                opmetalist_add($4, opmeta_make(1, OP_RET));
633
 
                op = opmetalist_resolve($4);
634
 
                i = oplisttab_add(op);
635
 
                $$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
636
 
                free($2);
637
 
                oplist_free(op);
638
 
                free(op);
639
 
                opmetalist_free($4);
640
 
                free($4);
641
 
        }
642
 
        | T_WRAP '{' opcode_block '}'
643
 
        {
644
 
                struct opmeta *o;
645
 
                int i;
646
 
                struct oplist *op;
647
 
 
648
 
                opmetalist_add($3, opmeta_make(1, OP_RET));
649
 
                op = opmetalist_resolve($3);
650
 
                i = oplisttab_add(op);
651
 
                o = opmeta_make(3, OP_WRAP, 666, i);
652
 
                opmeta_fixup(o, 1, &current_service->iname);
653
 
                $$ = o;
654
 
                oplist_free(op);
655
 
                free(op);
656
 
                opmetalist_free($3);
657
 
                free($3);
658
 
        }
659
 
        |       T_WRAP T_QSTRING ';'
660
 
        {
661
 
                struct opmetalist *l;
662
 
                int i;
663
 
                struct oplist *op;
664
 
 
665
 
                l = opmetalist_new();
666
 
                opmetalist_add(l, opmeta_make(1, OP_EXIT));
667
 
                op = opmetalist_resolve(l);
668
 
                i = oplisttab_add(op);
669
 
                $$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
670
 
                free($2);
671
 
                oplist_free(op);
672
 
                free(op);
673
 
                opmetalist_free(l);
674
 
                free(l);
675
 
        }
676
 
        |       T_WRAP ';'
677
 
        {
678
 
                struct opmetalist *l;
679
 
                struct opmeta *o;
680
 
                int i;
681
 
                struct oplist *op;
682
 
 
683
 
                l = opmetalist_new();
684
 
                opmetalist_add(l, opmeta_make(1, OP_EXIT));
685
 
                op = opmetalist_resolve(l);
686
 
                i = oplisttab_add(op);
687
 
                o = opmeta_make(3, OP_WRAP, 666, i);
688
 
                opmeta_fixup(o, 1, &current_service->iname);
689
 
                $$ = o;
690
 
                oplist_free(op);
691
 
                free(op);
692
 
                opmetalist_free(l);
693
 
                free(l);
694
 
        }
695
 
        | T_CLOSE ';'
696
 
        {
697
 
                $$ = opmeta_make(1, OP_CLOSE);
698
 
        }
699
 
        | T_EXIT ';'
700
 
        {
701
 
                $$ = opmeta_make(1, OP_EXIT);
702
 
        }
703
 
        | T_ECHO T_QSTRING ';'
704
 
        {
705
 
                $$ = opmeta_make(2, OP_ECHO, argvtab_add($2, 0));
706
 
        }
707
 
        | T_LOOPBACK ';'
708
 
        {
709
 
                $$ = opmeta_make(29, OP_ZERO, OP_BUFINIT, 11, OP_RHOOK, 0, OP_BUFREAD,
710
 
                                                                                 OP_RUNHOOK, OP_DUP, OP_BZNEG, 17, OP_ADD, OP_WHOOK, 0,
711
 
                                                                                 OP_BUFWRITE, OP_WUNHOOK, OP_DUP, OP_BZ, 6, OP_DUP,
712
 
                                                                                 OP_BZNEG, 6, OP_SUB, OP_WHOOK, -11, OP_POP, OP_RHOOK, -22,
713
 
                                                                                 OP_JUMP, 666);
714
 
                opmeta_fixup($$, 28, &current_service->onexit);
715
 
                current_service->internal = 1;
716
 
        }
717
 
        | T_DISCARD ';'
718
 
        {
719
 
                $$ = opmeta_make(13, OP_ZERO, OP_RHOOK, 0, OP_RUNHOOK, OP_BUFINIT, 1024,
720
 
                                                                                 OP_BUFREAD, OP_BZNEG, 2, OP_RHOOK, -8, OP_JUMP, 666);
721
 
                opmeta_fixup($$, 12, &current_service->onexit);
722
 
                current_service->internal = 1;
723
 
        }
724
 
        ;
725
 
 
726
 
optionalstring:
727
 
        {       $$ = NULL;      }
728
 
        |       T_QSTRING
729
 
        ;
730
 
 
731
 
service_element:        ';'
732
 
        |       T_PORT portlists ';'
733
 
        {
734
 
                if(current_service->port)
735
 
                        stringlist_free(current_service->port);
736
 
                current_service->port = stringlist;
737
 
                stringlist = NULL;
738
 
        }
739
 
        |       T_PROTO protocol ';'
740
 
        {
741
 
                current_service->socktype = $2;
742
 
        }
743
 
        |       T_BACKLOG T_NUMERIC ';'
744
 
        {
745
 
                current_service->backlog = $2;
746
 
        }
747
 
        |       T_INSTANCES T_NUMERIC ';'
748
 
        {
749
 
                current_service->limit = $2;
750
 
        }
751
 
        | T_WAIT boolean ';'
752
 
        {
753
 
                current_service->wait  = $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->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, "nproc limit not available on this system");
898
 
#endif
899
 
        }
900
 
        |       T_LIM_NOFILE
901
 
        {
902
 
#ifdef RLIMIT_NOFILE
903
 
                $$ = RLIMIT_NOFILE;
904
 
#else
905
 
                RL_PFATAL(EX_DATAERR, "nofile limit not available on this system");
906
 
#endif
907
 
        }
908
 
        |       T_LIM_MEMLOCK
909
 
        {
910
 
#ifdef RLIMIT_MEMLOCK
911
 
                $$ = RLIMIT_MEMLOCK;
912
 
#else
913
 
                RL_PFATAL(EX_DATAERR, "memlock limit not available on this system");
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("you have no ipv6 support");
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 (s->wait && s->limit != 1) {
1040
 
                if (s->limit != defaults->limit)
1041
 
                        RL_PWARN("ignoring `instances %d' directive for service %s, because `wait' was also given", 
1042
 
                                                                                s->limit, s->name);
1043
 
                s->limit = 1;
1044
 
        }       
1045
 
        
1046
 
        if(s->rpcvers) {
1047
 
                char *rpcname = s->name;
1048
 
                struct rpcent *rep;
1049
 
 
1050
 
                if(s->rpcname)
1051
 
                        rpcname = s->rpcname;
1052
 
                rep = getrpcbyname(rpcname);
1053
 
                if(!rep) {
1054
 
                        RL_PWARN("can't find rpc service %s for service %s",
1055
 
                                                        rpcname, s->name);
1056
 
                        s->disabled++;
1057
 
                } else {
1058
 
                        s->rpcnum = rep->r_number;
1059
 
                }
1060
 
                endrpcent();
1061
 
        }
1062
 
}
1063
 
                 
1064
 
static int bind_ports() {
1065
 
        int fd;
1066
 
        long opt = 1;
1067
 
        struct stringlist *portp;
1068
 
        struct stringlist *ifp;
1069
 
#ifdef HAVE_GETADDRINFO
1070
 
        struct addrinfo hints;
1071
 
        struct addrinfo *results = NULL, *ai;
1072
 
        int ret;
1073
 
#else
1074
 
        void *addrbuf;
1075
 
        int portnum;
1076
 
        char *ctmp;
1077
 
#endif  
1078
 
        char *port, *addr;
1079
 
        char *lasterror, *errfunc = NULL;
1080
 
        int succeeded;
1081
 
        fd_set fds;
1082
 
        int n_fds;
1083
 
 
1084
 
        int family, socktype, protocol;
1085
 
        socklen_t saddrlen;
1086
 
        struct sockaddr *saddr = NULL;
1087
 
        
1088
 
        FD_ZERO(&fds);
1089
 
        n_fds = 0;
1090
 
        ifp = current_service->interface;
1091
 
        do {
1092
 
                struct stringlist fallback = { !current_service->rpcnum ? current_service->name : "0" , NULL };
1093
 
 
1094
 
                addr = ifp ? ifp->str : NULL;
1095
 
                portp = current_service->port;
1096
 
                if(!portp)
1097
 
                        portp = &fallback;
1098
 
                do {
1099
 
                        lasterror = NULL;
1100
 
                        succeeded = 0;
1101
 
                                
1102
 
                        port = portp->str;
1103
 
#ifdef HAVE_GETADDRINFO
1104
 
                        memset(&hints, 0, sizeof(hints));
1105
 
                        hints.ai_flags = AI_PASSIVE;
1106
 
                        hints.ai_family = current_service->family;
1107
 
                        hints.ai_socktype = current_service->socktype;
1108
 
                        hints.ai_protocol = current_service->proto;
1109
 
                        if(results)
1110
 
                                freeaddrinfo(results);
1111
 
                        results = NULL;
1112
 
                        if((ret = getaddrinfo(addr, port, &hints, &results))) {
1113
 
#ifdef HAVE_GAI_STRERROR
1114
 
                                RL_PWARN("getaddrinfo(%s, %s) failed: %s", addr, port,
1115
 
                                                                gai_strerror(ret));
1116
 
#else
1117
 
                                RL_PWARN("getaddrinfo(%s, %s) failed: %s", addr, port,
1118
 
                                                                "for reasons unknown" );
1119
 
#endif                                                                  
1120
 
                                continue;
1121
 
                        }
1122
 
                        ai = results;
1123
 
                        do {
1124
 
                                family = ai->ai_family;
1125
 
                                socktype = ai->ai_socktype;
1126
 
                                protocol = ai->ai_protocol;
1127
 
                                saddr = ai->ai_addr;
1128
 
                                saddrlen = ai->ai_addrlen;
1129
 
#else
1130
 
                                portnum = strtoul(port, &ctmp, 10);
1131
 
                                if(*ctmp) {
1132
 
                                        portnum = getservport(port, current_service->protoname);
1133
 
                                        if(portnum == -1) {
1134
 
                                                RL_PWARN("Failed to resolve %s port %s",
1135
 
                                                                                current_service->proto, port);
1136
 
                                                continue;
1137
 
                                        }
1138
 
                                }
1139
 
                                family = current_service->family;
1140
 
                                socktype = current_service->socktype;
1141
 
                                protocol = current_service->proto;
1142
 
                                if(saddr) {
1143
 
                                        free(saddr);
1144
 
                                        saddr = NULL;
1145
 
                                }
1146
 
                                switch(family) {
1147
 
                                        struct sockaddr_in *sin;
1148
 
#ifdef HAVE_SOCKADDR_IN6
1149
 
                                        struct sockaddr_in6 *sin6;
1150
 
#endif
1151
 
                                                
1152
 
                                        case PF_INET:
1153
 
                                                saddrlen = sizeof(struct sockaddr_in);
1154
 
                                                sin = (struct sockaddr_in *)malloc(saddrlen);
1155
 
                                                if (!sin)
1156
 
                                                        rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1157
 
                                                addrbuf = &sin->sin_addr.s_addr;
1158
 
                                                sin->sin_family = current_service->family;
1159
 
                                                sin->sin_port = htons(portnum);
1160
 
                                                sin->sin_addr.s_addr = INADDR_ANY;
1161
 
                                                saddr = (struct sockaddr *)sin;
1162
 
                                                break;
1163
 
#ifdef HAVE_SOCKADDR_IN6
1164
 
                                        case PF_INET6:
1165
 
                                                saddrlen = sizeof(struct sockaddr_in6);
1166
 
                                                sin6 = (struct sockaddr_in6 *)malloc(saddrlen);
1167
 
                                                if (!sin6)
1168
 
                                                        rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1169
 
                                                addrbuf = &sin6->sin_addr.s_addr;
1170
 
                                                sin6->sin6_family = current_service->family;
1171
 
                                                sin6->sin6_port = htons(portnum);
1172
 
                                                sin6->sin6_addr = IN6ADDR_ANY_INIT;
1173
 
                                                saddr = (struct sockaddr *)sin6;
1174
 
                                                break;
1175
 
#endif                                                  
1176
 
                                        default:
1177
 
                                                RL_PFATAL(EX_SOFTWARE, "funky family in service");
1178
 
                                }
1179
 
                                if(addr) {
1180
 
                                        if(
1181
 
#ifdef HAVE_INET_PTON
1182
 
                                                 inet_pton(family, addr, addrbuf)
1183
 
#else                                           
1184
 
                                                                                                                                /* this cast is a pain */
1185
 
                                                 (*(unsigned int *)addrbuf = inet_addr(addr)) == -1
1186
 
#endif
1187
 
                                                 ) {
1188
 
                                                RL_PWARN("bad address %s in service %s", addr,
1189
 
                                                                                current_service->name);
1190
 
                                                free(saddr);
1191
 
                                                saddr = NULL;
1192
 
                                                continue;
1193
 
                                        }
1194
 
                                }
1195
 
#endif                          
1196
 
                                if((fd = socket(family, socktype, protocol)) < 0) {
1197
 
                                        lasterror = strerror(errno);
1198
 
                                        errfunc = "socket()";
1199
 
                                        goto out;
1200
 
                                }
1201
 
                                if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
1202
 
                                        RL_PWARN("setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, 1) failed for service %s (%s)",
1203
 
                                                                        fd, current_service->name, strerror(errno));
1204
 
                                }
1205
 
#ifdef HAVE_NET_BPF_H
1206
 
                                if(current_service->filter) {
1207
 
                                        struct bpf_program bp;
1208
 
 
1209
 
                                        bp.bf_len = current_service->filterlen / sizeof(struct bpf_insn);
1210
 
                                        bp.bf_insns = current_service->filter;
1211
 
                                        if(setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bp, sizeof(bp))) {
1212
 
                                                lasterror = strerror(errno);
1213
 
                                                close(fd);
1214
 
                                                errfunc = "setsockopt(..., SO_ATTACH_FILTER)";
1215
 
                                                goto out;
1216
 
                                        }
1217
 
                                }
1218
 
#endif                          
1219
 
                                if(bind(fd, saddr, saddrlen) < 0) {
1220
 
                                        lasterror = strerror(errno);
1221
 
                                        close(fd);
1222
 
                                        errfunc = "bind()";
1223
 
                                        goto out;
1224
 
                                }
1225
 
                                if(current_service->rpcnum) {
1226
 
                                        struct numlist *vers = current_service->rpcvers;
1227
 
                                        struct rl_cleanup *p;
1228
 
                                        struct sockaddr saddr2;
1229
 
 
1230
 
                                        if (getsockname(fd, &saddr2, &saddrlen) == -1) {
1231
 
                                                RL_PWARN("getsockname(%d) failed for service %s", fd, current_service->name);
1232
 
                                                memcpy(&saddr2, saddr, sizeof(struct sockaddr));
1233
 
                                        }
1234
 
 
1235
 
                                        do {
1236
 
                                                if(!pmap_set(current_service->rpcnum, vers->num,
1237
 
                                                                                                 protocol,
1238
 
                                                                                                 ntohs(((struct sockaddr_in *)&saddr2)->sin_port)))
1239
 
                                                        RL_PWARN("pmap_set(%d, %d, %d, %d) failed for service %s",
1240
 
                                                                                        current_service->rpcnum, vers->num,
1241
 
                                                                                        protocol, ntohs(((struct sockaddr_in *)&saddr2)->sin_port),
1242
 
                                                                                        current_service->name);
1243
 
                                        } while((vers = vers->next));
1244
 
                                        p = (struct rl_cleanup *)malloc(sizeof(struct rl_cleanup));
1245
 
                                        if (!p)
1246
 
                                                rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1247
 
                                        p->next = rl_cleanups;
1248
 
                                        p->data =       (struct rlc_unrpc *)malloc(sizeof(struct rlc_unrpc));
1249
 
                                        if (!p->data)
1250
 
                                                rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1251
 
                                        p->type = RLC_UNRPC;
1252
 
                                        ((struct rlc_unrpc *)p->data)->vers = NULL;
1253
 
                                        numlist_copy(&(((struct rlc_unrpc *)p->data)->vers), current_service->rpcvers);
1254
 
                                        ((struct rlc_unrpc *)p->data)->prog =   current_service->rpcnum;
1255
 
                                        /* current_service->rpcvers = NULL;*/ /* caused segfault in the next iteration
1256
 
                                                                                                                                                                                                   of do...while(ai=ai->ai_next) loop */
1257
 
                                        rl_cleanups = p;
1258
 
                                }
1259
 
                                FD_SET(fd, &fds);
1260
 
                                if(socktype == SOCK_STREAM) {
1261
 
                                        if(listen(fd, current_service->backlog)) {
1262
 
                                                lasterror = strerror(errno);
1263
 
                                                close(fd);
1264
 
                                                errfunc = "listen(fd)";
1265
 
                                                goto out;
1266
 
                                        }
1267
 
                                }
1268
 
                                if(fcntl(fd, F_SETFD, 1)) {
1269
 
                                        lasterror = strerror(errno);
1270
 
                                        errfunc = "fcntl(fd, F_SETFD, 1)";
1271
 
                                        close(fd);
1272
 
                                        goto out;
1273
 
                                }
1274
 
                                if(fcntl(fd, F_SETFL, O_NDELAY)) {
1275
 
                                        lasterror = strerror(errno);
1276
 
                                        close(fd);
1277
 
                                        errfunc = "fcntl(fd, F_SETFL, O_NDELAY)";
1278
 
                                        goto out;
1279
 
                                }
1280
 
                                n_fds++;
1281
 
                                succeeded++;
1282
 
                        out:
1283
 
#ifdef HAVE_GETADDRINFO
1284
 
                                continue;
1285
 
                        } while((ai = ai->ai_next));
1286
 
#endif
1287
 
                        if(!succeeded && lasterror)
1288
 
                                RL_PWARN("%s failed for service %s: %s",
1289
 
                                                                errfunc, current_service->name, lasterror);
1290
 
                } while(portp && (portp = portp->next));
1291
 
        } while(ifp && (ifp = ifp->next));
1292
 
        stringlist_free(current_service->port);
1293
 
        current_service->port = NULL;
1294
 
        stringlist_free(current_service->interface);
1295
 
        current_service->interface = NULL;
1296
 
        numlist_free(current_service->rpcvers);
1297
 
        current_service->rpcvers = NULL;
1298
 
#ifdef HAVE_GETADDRINFO
1299
 
        if(results) {
1300
 
                freeaddrinfo(results);
1301
 
                results = NULL;
1302
 
        }
1303
 
#else
1304
 
        if(saddr) {
1305
 
                free(saddr);
1306
 
                saddr = NULL;
1307
 
        }
1308
 
#endif  
1309
 
        if (!n_fds)
1310
 
                current_service->disabled++;
1311
 
        return fdsettab_add(&fds);
1312
 
}
1313
 
 
1314
 
static void service_free(struct service *s) {
1315
 
        if(s->name) {
1316
 
                free(s->name);
1317
 
                s->name = NULL;
1318
 
        }
1319
 
        stringlist_free(s->port);
1320
 
        s->port = NULL;
1321
 
        stringlist_free(s->interface);
1322
 
        s->interface = NULL;
1323
 
        if(s->rpcname) {
1324
 
                free(s->rpcname);
1325
 
                s->rpcname = NULL;
1326
 
        }
1327
 
        if(s->rpcvers) {
1328
 
                numlist_free(s->rpcvers);
1329
 
                s->rpcvers = NULL;
1330
 
        }
1331
 
#ifdef HAVE_CAPABILITIES
1332
 
        if(s->caps) {
1333
 
                cap_free(&s->caps);
1334
 
                s->caps = NULL;
1335
 
        }
1336
 
#endif  
1337
 
#ifdef HAVE_NET_BPF_H
1338
 
        if(s->filter) {
1339
 
                free(s->filter);
1340
 
                s->filter = NULL;
1341
 
                s->filterlen = 0;
1342
 
        }
1343
 
#endif  
1344
 
}
1345
 
 
1346
 
static void service_copy(struct service *to, struct service *from) {
1347
 
        memcpy(to, from, sizeof(*to));
1348
 
        to->name = NULL;
1349
 
        to->port = NULL;
1350
 
        to->interface = NULL;
1351
 
        stringlist_copy(&to->port, from->port);
1352
 
        stringlist_copy(&to->interface, from->interface);
1353
 
        to->rpcname = from->rpcname ? strdup(from->rpcname) : NULL;
1354
 
        to->rpcvers = NULL;
1355
 
        numlist_copy(&to->rpcvers, from->rpcvers);
1356
 
#ifdef HAVE_LIBCAP
1357
 
        to->caps = from->caps ? cap_dup(from->caps) : NULL;
1358
 
#endif
1359
 
#ifdef HAVE_NET_BPF_H
1360
 
        if(from->filter) {
1361
 
                to->filter = malloc(from->filterlen);
1362
 
                if (!to->filter)
1363
 
                        rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1364
 
                memcpy(to->filter, from->filter, from->filterlen);
1365
 
        }
1366
 
#endif  
1367
 
}
1368
 
 
1369
 
static struct logdata *logdata_get(char *name) {
1370
 
        struct logdata *ptr = logdatas;
1371
 
 
1372
 
        if(!ptr)
1373
 
                return NULL;
1374
 
        do {
1375
 
                if(!strcmp(name, ptr->name))
1376
 
                        return ptr;
1377
 
        } while((ptr = ptr->next));
1378
 
        return NULL;
1379
 
}
1380
 
 
1381
 
static void logdatas_free() {
1382
 
        struct logdata *p, *q;
1383
 
 
1384
 
        p = logdatas;
1385
 
        while(p) {
1386
 
                q = p->next;
1387
 
                if(p->name)
1388
 
                        free(p->name);
1389
 
                if(p->path)
1390
 
                        free(p->path);
1391
 
                free(p);
1392
 
                p = q;
1393
 
        }
1394
 
        logdatas = NULL;
1395
 
}
1396
 
 
1397
 
static struct logdata *logdata_new() {
1398
 
        struct logdata *ptr = (struct logdata *)malloc(sizeof(*ptr));
1399
 
 
1400
 
        if (!ptr)
1401
 
                rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1402
 
 
1403
 
        memset(ptr, 0, sizeof(*ptr));
1404
 
        ptr->index = -1;
1405
 
        ptr->mode =
1406
 
#ifdef S_IRUSR
1407
 
                S_IRUSR|S_IWUSR|S_IRGRP
1408
 
#else
1409
 
                0640
1410
 
#endif
1411
 
                ;
1412
 
        ptr->uid = -1;
1413
 
        ptr->gid = -1;
1414
 
        return ptr;
1415
 
}
1416
 
 
1417
 
void parse() {
1418
 
        void freebufs();
1419
 
        
1420
 
        numlist = NULL;
1421
 
        userdata = NULL;
1422
 
        newuserdata(&userdata);
1423
 
        pidtab_fixup();
1424
 
        all_unhook();
1425
 
        logtabs_free();
1426
 
        argvtabs_free();
1427
 
        rlimittabs_free();
1428
 
        services_free();
1429
 
        stringtabs_free();
1430
 
        buftabs_free();
1431
 
        oplisttabs_free();
1432
 
#ifdef HAVE_CAPABILITIES
1433
 
        captabs_free();
1434
 
#endif  
1435
 
        semaphores_free();
1436
 
        fdsettabs_free();
1437
 
        if(strcmp(rl_config, "-") || !rl_debug) {
1438
 
                if(!(yyin = fopen(rl_config, "r"))) {
1439
 
                        RL_PFATAL(EX_NOINPUT, "fopen(%s) failed, aborting", rl_config);
1440
 
                } else {
1441
 
                        curfile_name = rl_config;
1442
 
                        curfile_line = 1;
1443
 
                }
1444
 
        }
1445
 
 
1446
 
        logcur = logdata_new();
1447
 
        current_service = service_new();
1448
 
        defaults = service_new();
1449
 
#ifdef HAVE_GETADDRINFO
1450
 
        defaults->family = PF_UNSPEC;
1451
 
#else   
1452
 
        defaults->family = PF_INET;
1453
 
#endif  
1454
 
        defaults->socktype = SOCK_STREAM;
1455
 
        defaults->protoname = "tcp";
1456
 
        defaults->proto = IPPROTO_TCP;
1457
 
        defaults->backlog = 5;
1458
 
        defaults->limit = 40;
1459
 
        defaults->r.rlim_cur = RLIM_INFINITY;
1460
 
        defaults->r.rlim_max = RLIM_INFINITY;
1461
 
        defaults->exec = -1;
1462
 
        defaults->wait = 0;
1463
 
 
1464
 
        defaults->iname = -1;
1465
 
        defaults->parent = -1;
1466
 
        defaults->iuser  = -1;
1467
 
        defaults->sgid   = -1;
1468
 
        defaults->supgid = -1;
1469
 
        defaults->setgid = -1;
1470
 
        defaults->setuid = -1;
1471
 
        service_copy(current_service, defaults);
1472
 
        yyparse();
1473
 
        freebufs();
1474
 
        service_free(defaults);
1475
 
        free(defaults);
1476
 
        defaults = NULL;
1477
 
        logdatas_free();
1478
 
        free(logcur);
1479
 
        logcur = NULL;
1480
 
        service_free(current_service);
1481
 
        free(current_service);
1482
 
        current_service = NULL;
1483
 
        for(curfile = 0; curfile < numfiles; curfile++) {
1484
 
                free(files[curfile]);
1485
 
                files[curfile] = NULL;
1486
 
        }
1487
 
        free(files);
1488
 
        files = NULL;
1489
 
        clearuserdata(&userdata);
1490
 
        free(userdata);
1491
 
}
1492
 
 
1493
 
static void pidtab_fixup() {
1494
 
        struct pidtab *p;
1495
 
        int i;
1496
 
 
1497
 
        for(i = 0; i < 8; i++) {
1498
 
                p = pidtabs[i].next;
1499
 
                while(p) {
1500
 
                        if(p->inst)
1501
 
                                inst_free(p->inst);
1502
 
                        p->inst = NULL;
1503
 
                        p = p->next;
1504
 
                }
1505
 
        }
1506
 
}
1507
 
 
1508
 
#ifndef HAVE_GETADDRINFO
1509
 
static int getservport(char *str, char *proto) {
1510
 
        struct servent *foo;
1511
 
        int ret = -1;
1512
 
 
1513
 
        foo = getservbyname(str, proto);
1514
 
        if(foo)
1515
 
                ret = ntohs(foo->s_port);
1516
 
        endservent();
1517
 
        return ret;
1518
 
}
1519
 
#endif
1520
 
 
1521
 
static void add_directory(char *dir, char *match, char *ignore) {
1522
 
        DIR *d;
1523
 
        struct dirent *de;
1524
 
        regex_t rmatch, rignore;
1525
 
        char err[128];
1526
 
        int e;
1527
 
        struct stat st;
1528
 
        char *file;
1529
 
 
1530
 
        if(match)
1531
 
                if((e = regcomp(&rmatch, match, REG_EXTENDED|REG_NOSUB))) {
1532
 
                        regerror(e, &rmatch, err, 127);
1533
 
                        RL_PWARN("regexp compile failed for directory %s: %s",
1534
 
                                                        dir, err);
1535
 
                }
1536
 
        if(ignore)
1537
 
                if((e = regcomp(&rignore, ignore, REG_EXTENDED|REG_NOSUB))) {
1538
 
                        regerror(e, &rignore, err, 127);
1539
 
                        RL_PWARN("regexp compile failed for directory %s: %s",
1540
 
                                                        dir, err);
1541
 
                }
1542
 
                        
1543
 
        if((d = opendir(dir))) {
1544
 
                while((de = readdir(d))) {
1545
 
                        if(match)
1546
 
                                if(regexec(&rmatch, de->d_name, 0, NULL, 0))
1547
 
                                        continue;
1548
 
                        if(ignore)
1549
 
                                if(!regexec(&rignore, de->d_name, 0, NULL, 0))
1550
 
                                        continue;
1551
 
                        if(de->d_name[0] != '.') {
1552
 
                                file = malloc(strlen(dir) + NAMLEN(de) + 2);
1553
 
                                if (!file)
1554
 
                                        rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1555
 
                                file[0] = '\0';
1556
 
                                strcat(file, dir);
1557
 
                                strcat(file, "/");
1558
 
                                strcat(file, de->d_name);
1559
 
                                if(stat(file, &st) || S_ISDIR(st.st_mode)) {
1560
 
                                        RL_PWARN("file %s does not exists or"
1561
 
                                                 " is a directory", file);      
1562
 
                                        free(file);
1563
 
                                        continue;
1564
 
                                }
1565
 
                                files = (char **)realloc(files, ++numfiles * sizeof(char *));
1566
 
                                if (!files)
1567
 
                                        rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1568
 
                                files[numfiles - 1] = file;
1569
 
                        }
1570
 
                }
1571
 
        } else {
1572
 
                RL_PFATAL(EX_NOINPUT, "Directory %s open failed (%s)", dir, 
1573
 
                        strerror(errno));
1574
 
        }
1575
 
        closedir(d);
1576
 
        free(dir);
1577
 
        if(match) {
1578
 
                free(match);
1579
 
                regfree(&rmatch);
1580
 
        }
1581
 
        if(ignore) {
1582
 
                free(ignore);
1583
 
                regfree(&rignore);
1584
 
        }
1585
 
}
1586
 
 
1587
 
int chargen_buffer() {
1588
 
        static int cb = -1;
1589
 
        char *b = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
1590
 
        
1591
 
        if(cb == -1)
1592
 
                cb = buftab_addbuf(b, strlen(b));
1593
 
        return cb;
1594
 
}
1595
 
 
1596
 
/* vim: set ts=2: */