8
#include <netinet/in.h>
12
#include <rpc/pmap_clnt.h>
18
#include <sys/socket.h>
20
#include <sys/types.h>
25
#include <installpaths.h>
26
#include <port/port.h>
30
# define NAMLEN(dirent) strlen((dirent)->d_name)
32
# define dirent direct
33
# define NAMLEN(dirent) (dirent)->d_namlen
35
# include <sys/ndir.h>
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)
62
struct userdata *userdata;
64
static struct service *current_service;
66
extern char *rl_config;
68
static int curfile = -1, numfiles = 0;
69
char *curfile_name = NULL; /* name of the current file */
70
int curfile_line = 1; /* line */
72
static struct service *defaults;
74
static struct logdata *logcur, *logdatas;
76
static struct numlist *numlist = NULL;
77
static struct stringlist *stringlist = NULL;
79
void yyerror(char *c);
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);
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();
95
void freebufs(); /* from parse.l */
104
struct opmetalist *opml;
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
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
119
%token T_LOG T_PIPE T_SYSLOG T_PATH T_MODE
121
%token T_ACCEPT T_DENY T_CLOSE T_EXIT
123
%token <num> T_NUMERIC
124
%token <cp> T_QSTRING T_IPADDR
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
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); }
156
log: T_LOG T_QSTRING '{' log_element '}'
158
if(logdata_get($2)) {
159
RL_PWARN("duplicate declaration of log %s, ignoring", $2);
163
logcur->next = logdatas;
165
logcur = logdata_new();
167
clearuserdata(&userdata);
171
log_element: file_elements
174
RL_PWARN("No path defined for log %s", logcur->name);
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));
181
if(fchmod(logcur->index, logcur->mode)) {
182
RL_PWARN("fchmod(\"%s\", 0%o) failed (%s)",
183
logcur->path, logcur->mode,
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,
197
file_elements: file_element
198
| file_elements file_element
202
| T_PATH T_QSTRING ';'
205
RL_PWARN("duplicate path declaration (%s) "
206
"in log directive %s, ignoring", $2,
215
if (logcur->uid > -1) { /* FIXME */
216
RL_PWARN("duplicate user declaration "
217
"in log directive %s, ignoring", logcur->name);
220
logcur->uid = $2->pw_uid;
222
RL_PWARN("unknown username");
227
if (logcur->gid > -1) { /* FIXME */
228
RL_PWARN("duplicate group declaration "
229
"in log directive %s, ignoring", logcur->name);
232
logcur->gid = $2->gr_gid;
234
RL_PWARN("unknown groupname");
237
| T_MODE T_NUMERIC ';'
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");
251
default: T_DEFAULT '{' service_elements '}'
253
service_free(defaults);
254
service_copy(defaults, current_service);
260
service: T_SERVICE T_QSTRING '{' service_elements '}'
262
struct opmetalist *parent;
263
struct opmetalist *onexit;
269
parent = opmetalist_new();
270
onexit = opmetalist_new();
272
current_service->name = $2;
273
current_service->iname = stringtab_add($2);
275
do { /* avoid goto */
277
if (current_service->disabled)
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++;
286
opmetalist_add(parent, opmeta_make(1, OP_CLOSE));
288
if (current_service->internal)
289
opmetalist_add(onexit, opmeta_make(1, OP_CLOSE));
291
opmetalist_add(onexit, opmeta_make(1, OP_RET));
294
opmetalist_add(parent, opmeta_make(1, OP_RET));
295
opmetalist_add(onexit, opmeta_make(1, OP_RET));
297
validate_service(current_service);
299
if (current_service->disabled)
304
if(current_service->limit) {
305
struct opmetalist *o;
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);
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);
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));
333
ops = opmetalist_resolve(onexit);
334
current_service->onexit = oplisttab_add(ops);
335
opmetalist_free(onexit);
340
ops = opmetalist_resolve(parent);
341
current_service->parent = oplisttab_add(ops);
342
opmetalist_free(parent);
347
opmetalist_add($4, opmeta_make(2, OP_JUMP, current_service->onexit));
348
ops = opmetalist_resolve($4);
349
current_service->run = oplisttab_add(ops);
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);
363
if (current_service->disabled) {
364
rl_warn("service %s DISABLED", current_service->name);
366
rl_note("service %s enabled", current_service->name);
368
rl_note("+-> uid=%d, sgid=%d, supgid=%d", current_service->setuid,
369
current_service->setgid, current_service->supgid);
373
service_free(current_service);
374
service_copy(current_service, defaults);
378
service_elements: service_element
380
$$ = opmetalist_new();
382
| service_elements service_element
388
struct opmetalist *l;
390
l = opmetalist_new();
391
if(opmetalist_add(l, $1)) {
392
RL_PWARN("opcode resolving problem");
393
current_service->disabled++;
397
| service_elements opcode_element
399
if(opmetalist_add($1, $2)) {
400
RL_PWARN("opcode resolving problem");
401
current_service->disabled++;
405
| service_elements complex_opcode_element
407
$$ = opmetalist_join($1, $2);
409
RL_PWARN("opcode resolving problem");
410
current_service->disabled++;
413
| complex_opcode_element
419
opcode_block: complex_opcode_element
425
struct opmetalist *l;
427
l = opmetalist_new();
428
if(opmetalist_add(l, $1)) {
429
RL_PWARN("opcode resolving problem");
430
current_service->disabled++;
434
| opcode_block opcode_element
436
if(opmetalist_add($1, $2)) {
437
RL_PWARN("opcode resolving problem");
438
current_service->disabled++;
442
| opcode_block complex_opcode_element
444
$$ = opmetalist_join($1, $2);
446
RL_PWARN("opcode resolving problem");
447
current_service->disabled++;
452
complex_opcode_element: T_EXEC T_QSTRING ';'
454
struct opmetalist *l;
457
l = opmetalist_new();
458
o = opmeta_make(3, OP_EXEC, 666, argvtab_add($2, 1));
459
opmeta_fixup(o, 1, ¤t_service->exec);
460
if(opmetalist_add(l, o)) {
461
RL_PWARN("opcode resolving problem");
462
current_service->disabled++;
464
o = opmeta_make(3, OP_FORK, 666, 666);
465
opmeta_fixup(o, 1, ¤t_service->parent);
466
opmeta_fixup(o, 2, ¤t_service->onexit);
467
if(opmetalist_add(l, o)) {
468
RL_PWARN("opcode resolving problem");
469
current_service->disabled++;
475
struct opmetalist *l;
478
l = opmetalist_new();
479
o = opmeta_make(3, OP_INITGR, 666, 666);
480
opmeta_fixup(o, 1, ¤t_service->iuser);
481
opmeta_fixup(o, 2, ¤t_service->supgid);
482
if(opmetalist_add(l, o)) {
483
RL_PWARN("opcode resolving problem");
484
current_service->disabled++;
486
if(!current_service->sgid) {
487
o = opmeta_make(2, OP_SGID, 666);
488
opmeta_fixup(o, 1, ¤t_service->setgid);
489
current_service->sgid = 1;
490
if(opmetalist_add(l, o)) {
491
RL_PWARN("opcode resolving problem");
492
current_service->disabled++;
500
opcode_element: T_NICE signed_numeric ';'
502
$$ = opmeta_make(2, OP_NICE, $2);
506
$$ = opmeta_make(1, OP_FISH);
508
| T_RLIMIT limittype limit
510
$$ = opmeta_make(3, OP_RLIMIT, $2, $3);
512
| T_LOG T_SYSLOG T_QSTRING ';'
516
i = logtab_add(-1, $3);
517
$$ = opmeta_make(2, OP_LOG, i);
523
struct opmeta *o = NULL;
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;
530
current_service->supgid = $2->pw_gid;
532
o = opmeta_make(4, OP_SGID, 666, OP_SUID, 666);
533
opmeta_fixup(o, 1, ¤t_service->setgid);
534
opmeta_fixup(o, 3, ¤t_service->setuid);
537
RL_PWARN("unknown username");
538
current_service->disabled++;
542
| T_BANNER T_QSTRING ';'
546
ret = buftab_addfile($2);
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);
554
| T_CHARGEN optionalstring ';'
559
i = buftab_addfile($2);
561
current_service->disabled++;
563
i = chargen_buffer();
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, ¤t_service->onexit);
570
current_service->internal = 1;
574
| T_LOG T_QSTRING T_QSTRING ';'
576
struct logdata *ld = logdata_get($2);
579
RL_PWARN("unknown log %s", $2);
580
current_service->disabled++;
582
int i = logtab_add(ld->index, $3);
583
$$ = opmeta_make(2, OP_LOG, i);
591
struct opmeta *o = NULL;
593
if(!current_service->sgid) {
594
o = opmeta_make(2, OP_SGID, 666);
595
opmeta_fixup(o, 1, ¤t_service->setgid);
596
current_service->sgid = 1;
598
if (current_service->supgid == -1)
599
current_service->supgid = $2->gr_gid;
600
current_service->setgid = $2->gr_gid;
603
RL_PWARN("unknown group");
604
current_service->disabled++;
608
| T_CHROOT T_QSTRING ';'
610
$$ = opmeta_make(2, OP_CHROOT, argvtab_add($2, 1));
612
| T_CAPS T_QSTRING ';'
614
#ifdef HAVE_CAPABILITIES
615
cap_t caps = cap_from_text($2);
617
$$ = opmeta_make(2, OP_SETCAP, captab_add(caps));
619
RL_PWARN("failed to parse capability string \"%s\"\n", $2);
620
current_service->disabled++;
624
RL_PFATAL(EX_DATAERR, "ABORT - support for capabilities not compiled in");
627
| T_WRAP T_QSTRING '{' opcode_block '}'
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);
642
| T_WRAP '{' opcode_block '}'
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, ¤t_service->iname);
659
| T_WRAP T_QSTRING ';'
661
struct opmetalist *l;
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);
678
struct opmetalist *l;
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, ¤t_service->iname);
697
$$ = opmeta_make(1, OP_CLOSE);
701
$$ = opmeta_make(1, OP_EXIT);
703
| T_ECHO T_QSTRING ';'
705
$$ = opmeta_make(2, OP_ECHO, argvtab_add($2, 0));
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,
714
opmeta_fixup($$, 28, ¤t_service->onexit);
715
current_service->internal = 1;
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, ¤t_service->onexit);
722
current_service->internal = 1;
732
| T_PORT portlists ';'
734
if(current_service->port)
735
stringlist_free(current_service->port);
736
current_service->port = stringlist;
739
| T_PROTO protocol ';'
741
current_service->socktype = $2;
743
| T_BACKLOG T_NUMERIC ';'
745
current_service->backlog = $2;
747
| T_INSTANCES T_NUMERIC ';'
749
current_service->limit = $2;
753
current_service->wait = $2;
755
| T_INTERFACE ipaddrlists ';'
757
if(current_service->interface)
758
stringlist_free(current_service->interface);
759
current_service->interface = stringlist;
762
| T_SERVER T_QSTRING ';'
764
current_service->exec = stringtab_add($2);
767
| T_RPC '{' rpcents '}'
768
| T_FAMILY family ';'
769
| T_FILTER T_QSTRING ';'
771
#ifdef HAVE_NET_BPF_H
772
if(current_service->filter)
773
free(current_service->filter);
774
if(rl_readfile($2, ¤t_service->filter, ¤t_service->filterlen))
775
current_service->disabled++;
778
RL_PFATAL(EX_DATAERR, "ABORT - support for socket filter not compiled in");
788
rpcent: T_NAME T_QSTRING ';'
790
current_service->rpcname = $2;
792
| T_VERSION numrangelist ';'
794
current_service->rpcvers = numlist;
799
numrangelist: numrange
800
| numrangelist ',' numrange
805
numlist_add(&numlist, $1);
807
| T_NUMERIC '-' T_NUMERIC
812
for(i = $1; i <= $3; i++)
813
numlist_add(&numlist, i);
821
limitent: T_SOFT limitvalue ';'
823
current_service->r.rlim_cur = $2;
825
| T_HARD limitvalue ';'
827
current_service->r.rlim_max = $2;
831
ipaddrlists: ipaddrlist
832
| ipaddrlists ',' ipaddrlist
837
stringlist_add(&stringlist, $1);
842
| portlists ',' portlist
847
stringlist_add(&stringlist, $1);
853
snprintf(tmp, 19, "%ld", $1);
855
stringlist_add(&stringlist, strdup(tmp));
859
limit: limitvalue ';'
861
$$ = rlimittab_add($1, $1);
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");
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;
874
limitvalue: T_NUMERIC
877
{ $$ = RLIM_INFINITY; }
883
{ $$ = RLIMIT_FSIZE; }
885
{ $$ = RLIMIT_DATA; }
887
{ $$ = RLIMIT_STACK; }
889
{ $$ = RLIMIT_CORE; }
897
RL_PFATAL(EX_DATAERR, "nproc limit not available on this system");
905
RL_PFATAL(EX_DATAERR, "nofile limit not available on this system");
910
#ifdef RLIMIT_MEMLOCK
913
RL_PFATAL(EX_DATAERR, "memlock limit not available on this system");
947
current_service->protoname = "tcp";
948
current_service->proto = IPPROTO_TCP;
953
current_service->protoname = "udp";
954
current_service->proto = IPPROTO_UDP;
960
current_service->family = PF_INET;
964
#ifdef HAVE_SOCKADDR_IN6
965
current_service->family = PF_INET6;
967
RL_PWARN("you have no ipv6 support");
968
current_service->family = PF_INET;
973
signed_numeric: T_NUMERIC
994
void yyerror(char *str) {
995
RL_PFATAL(EX_DATAERR, "ABORT - %s", str);
1001
while(++curfile < numfiles) {
1002
if((yyin = fopen(files[curfile], "r"))) {
1003
curfile_name = files[curfile];
1007
curfile_name = NULL;
1008
RL_PWARN("cannot open file %s (%s)", files[curfile],
1016
static struct service *service_new() {
1017
struct service *p = (struct service *)malloc(sizeof(*p));
1020
rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1021
memset(p, 0, sizeof(*p));
1025
void services_free() {
1027
rlp_cleanup(rl_cleanups);
1032
static void validate_service(struct service *s) {
1034
RL_PWARN("service without name");
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",
1047
char *rpcname = s->name;
1051
rpcname = s->rpcname;
1052
rep = getrpcbyname(rpcname);
1054
RL_PWARN("can't find rpc service %s for service %s",
1058
s->rpcnum = rep->r_number;
1064
static int bind_ports() {
1067
struct stringlist *portp;
1068
struct stringlist *ifp;
1069
#ifdef HAVE_GETADDRINFO
1070
struct addrinfo hints;
1071
struct addrinfo *results = NULL, *ai;
1079
char *lasterror, *errfunc = NULL;
1084
int family, socktype, protocol;
1086
struct sockaddr *saddr = NULL;
1090
ifp = current_service->interface;
1092
struct stringlist fallback = { !current_service->rpcnum ? current_service->name : "0" , NULL };
1094
addr = ifp ? ifp->str : NULL;
1095
portp = current_service->port;
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;
1110
freeaddrinfo(results);
1112
if((ret = getaddrinfo(addr, port, &hints, &results))) {
1113
#ifdef HAVE_GAI_STRERROR
1114
RL_PWARN("getaddrinfo(%s, %s) failed: %s", addr, port,
1117
RL_PWARN("getaddrinfo(%s, %s) failed: %s", addr, port,
1118
"for reasons unknown" );
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;
1130
portnum = strtoul(port, &ctmp, 10);
1132
portnum = getservport(port, current_service->protoname);
1134
RL_PWARN("Failed to resolve %s port %s",
1135
current_service->proto, port);
1139
family = current_service->family;
1140
socktype = current_service->socktype;
1141
protocol = current_service->proto;
1147
struct sockaddr_in *sin;
1148
#ifdef HAVE_SOCKADDR_IN6
1149
struct sockaddr_in6 *sin6;
1153
saddrlen = sizeof(struct sockaddr_in);
1154
sin = (struct sockaddr_in *)malloc(saddrlen);
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;
1163
#ifdef HAVE_SOCKADDR_IN6
1165
saddrlen = sizeof(struct sockaddr_in6);
1166
sin6 = (struct sockaddr_in6 *)malloc(saddrlen);
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;
1177
RL_PFATAL(EX_SOFTWARE, "funky family in service");
1181
#ifdef HAVE_INET_PTON
1182
inet_pton(family, addr, addrbuf)
1184
/* this cast is a pain */
1185
(*(unsigned int *)addrbuf = inet_addr(addr)) == -1
1188
RL_PWARN("bad address %s in service %s", addr,
1189
current_service->name);
1196
if((fd = socket(family, socktype, protocol)) < 0) {
1197
lasterror = strerror(errno);
1198
errfunc = "socket()";
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));
1205
#ifdef HAVE_NET_BPF_H
1206
if(current_service->filter) {
1207
struct bpf_program bp;
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);
1214
errfunc = "setsockopt(..., SO_ATTACH_FILTER)";
1219
if(bind(fd, saddr, saddrlen) < 0) {
1220
lasterror = strerror(errno);
1225
if(current_service->rpcnum) {
1226
struct numlist *vers = current_service->rpcvers;
1227
struct rl_cleanup *p;
1228
struct sockaddr saddr2;
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));
1236
if(!pmap_set(current_service->rpcnum, vers->num,
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));
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));
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 */
1260
if(socktype == SOCK_STREAM) {
1261
if(listen(fd, current_service->backlog)) {
1262
lasterror = strerror(errno);
1264
errfunc = "listen(fd)";
1268
if(fcntl(fd, F_SETFD, 1)) {
1269
lasterror = strerror(errno);
1270
errfunc = "fcntl(fd, F_SETFD, 1)";
1274
if(fcntl(fd, F_SETFL, O_NDELAY)) {
1275
lasterror = strerror(errno);
1277
errfunc = "fcntl(fd, F_SETFL, O_NDELAY)";
1283
#ifdef HAVE_GETADDRINFO
1285
} while((ai = ai->ai_next));
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
1300
freeaddrinfo(results);
1310
current_service->disabled++;
1311
return fdsettab_add(&fds);
1314
static void service_free(struct service *s) {
1319
stringlist_free(s->port);
1321
stringlist_free(s->interface);
1322
s->interface = NULL;
1328
numlist_free(s->rpcvers);
1331
#ifdef HAVE_CAPABILITIES
1337
#ifdef HAVE_NET_BPF_H
1346
static void service_copy(struct service *to, struct service *from) {
1347
memcpy(to, from, sizeof(*to));
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;
1355
numlist_copy(&to->rpcvers, from->rpcvers);
1357
to->caps = from->caps ? cap_dup(from->caps) : NULL;
1359
#ifdef HAVE_NET_BPF_H
1361
to->filter = malloc(from->filterlen);
1363
rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1364
memcpy(to->filter, from->filter, from->filterlen);
1369
static struct logdata *logdata_get(char *name) {
1370
struct logdata *ptr = logdatas;
1375
if(!strcmp(name, ptr->name))
1377
} while((ptr = ptr->next));
1381
static void logdatas_free() {
1382
struct logdata *p, *q;
1397
static struct logdata *logdata_new() {
1398
struct logdata *ptr = (struct logdata *)malloc(sizeof(*ptr));
1401
rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1403
memset(ptr, 0, sizeof(*ptr));
1407
S_IRUSR|S_IWUSR|S_IRGRP
1422
newuserdata(&userdata);
1432
#ifdef HAVE_CAPABILITIES
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);
1441
curfile_name = rl_config;
1446
logcur = logdata_new();
1447
current_service = service_new();
1448
defaults = service_new();
1449
#ifdef HAVE_GETADDRINFO
1450
defaults->family = PF_UNSPEC;
1452
defaults->family = PF_INET;
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;
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);
1474
service_free(defaults);
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;
1489
clearuserdata(&userdata);
1493
static void pidtab_fixup() {
1497
for(i = 0; i < 8; i++) {
1498
p = pidtabs[i].next;
1508
#ifndef HAVE_GETADDRINFO
1509
static int getservport(char *str, char *proto) {
1510
struct servent *foo;
1513
foo = getservbyname(str, proto);
1515
ret = ntohs(foo->s_port);
1521
static void add_directory(char *dir, char *match, char *ignore) {
1524
regex_t rmatch, rignore;
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",
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",
1543
if((d = opendir(dir))) {
1544
while((de = readdir(d))) {
1546
if(regexec(&rmatch, de->d_name, 0, NULL, 0))
1549
if(!regexec(&rignore, de->d_name, 0, NULL, 0))
1551
if(de->d_name[0] != '.') {
1552
file = malloc(strlen(dir) + NAMLEN(de) + 2);
1554
rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
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);
1565
files = (char **)realloc(files, ++numfiles * sizeof(char *));
1567
rl_fatal(EX_SOFTWARE, "ABORT - Can't allocate memory");
1568
files[numfiles - 1] = file;
1572
RL_PFATAL(EX_NOINPUT, "Directory %s open failed (%s)", dir,
1587
int chargen_buffer() {
1589
char *b = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
1592
cb = buftab_addbuf(b, strlen(b));
1596
/* vim: set ts=2: */