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;
73
static struct opmetalist *opml_defaults;
75
static struct logdata *logcur, *logdatas;
77
static struct numlist *numlist = NULL;
78
static struct stringlist *stringlist = NULL;
80
void yyerror(char *c);
82
static int bind_ports();
83
static int add_user_group(const struct service* current_service, struct opmetalist * l);
84
static void service_copy(struct service *to, struct service *from);
85
static void service_free(struct service *s);
86
static struct service *service_new();
87
#ifndef HAVE_GETADDRINFO
88
static int getservport(char *str, char *proto);
90
static struct logdata *logdata_get(char *name);
91
static struct logdata *logdata_new();
92
static void pidtab_fixup();
93
static void validate_service(struct service *s);
94
static void add_directory(char *dir, char *match, char *ignore);
95
static int chargen_buffer();
97
void freebufs(); /* from parse.l */
106
struct opmetalist *opml;
111
%token T_SERVICE T_PORT T_EXEC T_PROTO T_UDP T_TCP T_UID T_GID T_BACKLOG
112
%token T_INSTANCES T_WAIT T_DEFAULT T_NICE T_INTERFACE T_FISH T_CHROOT T_SERVER
113
%token T_DIR T_RPC T_VERSION T_NAME T_WRAP T_CAPS T_FAMILY T_IPV4 T_IPV6
114
%token T_INITGROUPS T_BANNER T_ECHO T_DISCARD T_FILTER T_CHARGEN T_LOOPBACK
117
%token T_RLIMIT T_LIM_CPU T_LIM_FSIZE T_LIM_DATA T_LIM_STACK T_LIM_CORE
118
%token T_LIM_RSS T_LIM_NPROC T_LIM_NOFILE T_LIM_MEMLOCK T_LIM_INFINITY
122
%token T_LOG T_PIPE T_SYSLOG T_PATH T_MODE
124
%token T_ACCEPT T_DENY T_CLOSE T_EXIT
126
%token <num> T_NUMERIC
127
%token <cp> T_QSTRING T_IPADDR
131
%type <num> limittype limit protocol;
132
%type <opm> opcode_element
133
%type <opml> service_elements complex_opcode_element opcode_block
134
%type <rl> limitvalue
135
%type <cp> optionalstring
136
%type <num> signed_numeric
151
directory: T_DIR T_QSTRING ';'
152
{ add_directory($2, NULL, NULL); }
153
| T_DIR T_QSTRING T_QSTRING ';'
154
{ add_directory($2, $3, NULL); }
155
| T_DIR T_QSTRING T_QSTRING T_QSTRING ';'
156
{ add_directory($2, $3, $4); }
159
log: T_LOG T_QSTRING '{' log_element '}'
161
if(logdata_get($2)) {
162
RL_PWARN("duplicate declaration of log %s, ignoring", $2);
166
logcur->next = logdatas;
168
logcur = logdata_new();
170
clearuserdata(&userdata);
174
log_element: file_elements
177
RL_PWARN(_("No path defined for log %s"), logcur->name);
179
if((logcur->index = open(logcur->path, O_CREAT|O_APPEND|O_WRONLY, logcur->mode)) < 0) {
180
RL_PWARN(_("open(\"%s\", O_CREAT|O_APPEND|O_WRONLY, 0%o) failed (%s)"),
181
logcur->path, logcur->mode, strerror(errno));
184
if(fchmod(logcur->index, logcur->mode)) {
185
RL_PWARN(_("fchmod(\"%s\", 0%o) failed (%s)"),
186
logcur->path, logcur->mode,
190
if(fchown(logcur->index, logcur->uid, logcur->gid)) {
191
RL_PWARN(_("fchown(\"%s\", %d, %d) failed for log %s (%s)"),
192
logcur->path, logcur->uid, logcur->gid, logcur->name,
200
file_elements: file_element
201
| file_elements file_element
205
| T_PATH T_QSTRING ';'
208
RL_PWARN(_("duplicate path declaration (%s) "
209
"in log directive %s, ignoring"), $2,
219
logcur->uid = $2->pw_uid;
221
RL_PWARN("unknown username");
227
logcur->gid = $2->gr_gid;
229
RL_PWARN("unknown groupname");
232
| T_MODE T_NUMERIC ';'
235
RL_PWARN(_("invalid mode declaration "
236
"in log directive %s, ignoring"), logcur->name);
243
default: T_DEFAULT '{' service_elements '}'
245
/* swich pointers to current_service and defaults */
246
struct service * saved_defaults = defaults;
247
defaults = current_service;
248
current_service = saved_defaults;
250
/* copy new defaults to current_service */
251
service_free(current_service);
252
service_copy(current_service, defaults);
254
/* save default opmetalist */
255
opmetalist_free(opml_defaults);
261
service: T_SERVICE T_QSTRING '{' service_elements '}'
263
struct opmetalist *parent;
264
struct opmetalist *onexit;
270
parent = opmetalist_new();
271
onexit = opmetalist_new();
273
current_service->name = $2;
274
current_service->opfixups[ofp_iname] = stringtab_add($2);
276
do { /* avoid goto */
278
if (current_service->disabled)
281
if(current_service->socktype == SOCK_STREAM && !current_service->wait) {
282
if(opmetalist_add($4, opmeta_make(2, OP_ACCEPT, 200))) { /* !200 */
283
RL_PWARN(_("opcode resolving problem"));
284
current_service->disabled++;
287
opmetalist_add(parent, opmeta_make(1, OP_CLOSE));
289
if (current_service->internal)
290
opmetalist_add(onexit, opmeta_make(1, OP_CLOSE));
292
opmetalist_add(onexit, opmeta_make(1, OP_RET));
295
opmetalist_add(parent, opmeta_make(1, OP_RET));
296
opmetalist_add(onexit, opmeta_make(1, OP_RET));
298
validate_service(current_service);
301
if (current_service->disabled)
304
if (!add_user_group(current_service, $4))
306
++current_service->disabled;
314
if(current_service->limit) {
315
struct opmetalist *o;
319
o = opmetalist_new();
320
opmetalist_add(o, opmeta_make(2, OP_LCLR, fds));
321
opmetalist_add(o, opmeta_make(1, OP_RET));
322
l = opmetalist_resolve(o, current_service->opfixups);
323
match = oplisttab_add(l);
329
o = opmetalist_new();
330
opmetalist_add(o, opmeta_make(2, OP_LSET, fds));
331
opmetalist_add(o, opmeta_make(1, OP_RET));
332
l = opmetalist_resolve(o, current_service->opfixups);
333
under = oplisttab_add(l);
339
i = semaphore_add(current_service->limit, match, under);
340
opmetalist_add($4, opmeta_make(2, OP_DOWN, i));
341
opmetalist_add(onexit, opmeta_make(2, OP_UP, i));
343
ops = opmetalist_resolve(onexit, current_service->opfixups);
344
current_service->opfixups[ofp_onexit] = oplisttab_add(ops);
345
opmetalist_free(onexit);
350
ops = opmetalist_resolve(parent, current_service->opfixups);
351
current_service->opfixups[ofp_parent] = oplisttab_add(ops);
352
opmetalist_free(parent);
357
opmetalist_merge($4, opml_defaults);
359
opmetalist_add($4, opmeta_make(2, OP_JUMP, current_service->opfixups[ofp_onexit]));
360
ops = opmetalist_resolve($4, current_service->opfixups);
362
current_service->run = oplisttab_add(ops);
368
fdst = fdsettab_get(fds);
369
bound = getdtablesize();
370
for(i = 0; i < bound; i++)
371
if(FD_ISSET(i, fdst))
372
read_hook(i, oplisttab_get(current_service->run), NULL);
376
if (current_service->disabled) {
377
rl_warn(_("service %s DISABLED"), current_service->name);
379
rl_note(_("service %s enabled"), current_service->name);
381
rl_note(_("+-> uid=%d, sgid=%d, supgid=%d fl=%d"), current_service->opfixups[ofp_setuid],
382
current_service->opfixups[ofp_setgid], current_service->opfixups[ofp_supgid], current_service->sflags);
386
service_free(current_service);
387
service_copy(current_service, defaults);
391
service_elements: service_element
393
$$ = opmetalist_new();
395
| service_elements service_element
401
struct opmetalist *l;
403
l = opmetalist_new();
404
if(opmetalist_add(l, $1)) {
405
RL_PWARN(_("opcode resolving problem"));
406
current_service->disabled++;
410
| service_elements opcode_element
412
if(opmetalist_add($1, $2)) {
413
RL_PWARN(_("opcode resolving problem"));
414
current_service->disabled++;
418
| service_elements complex_opcode_element
420
$$ = opmetalist_join($1, $2);
422
RL_PWARN(_("opcode resolving problem"));
423
current_service->disabled++;
426
| complex_opcode_element
432
opcode_block: complex_opcode_element
438
struct opmetalist *l;
440
l = opmetalist_new();
441
if(opmetalist_add(l, $1)) {
442
RL_PWARN(_("opcode resolving problem"));
443
current_service->disabled++;
447
| opcode_block opcode_element
449
if(opmetalist_add($1, $2)) {
450
RL_PWARN(_("opcode resolving problem"));
451
current_service->disabled++;
455
| opcode_block complex_opcode_element
457
$$ = opmetalist_join($1, $2);
459
RL_PWARN(_("opcode resolving problem"));
460
current_service->disabled++;
465
complex_opcode_element: T_EXEC T_QSTRING ';'
467
struct opmetalist *l;
470
l = opmetalist_new();
471
o = opmeta_make(3, OP_EXEC, 666, argvtab_add($2, 1));
472
opmeta_fixup(o, 1, ofp_exec);
473
if(opmetalist_add(l, o)) {
474
RL_PWARN(_("opcode resolving problem"));
475
current_service->disabled++;
477
o = opmeta_make(3, OP_FORK, 666, 666);
478
opmeta_fixup(o, 1, ofp_parent);
479
opmeta_fixup(o, 2, ofp_onexit);
480
if(opmetalist_add(l, o)) {
481
RL_PWARN(_("opcode resolving problem"));
482
current_service->disabled++;
490
current_service->opfixups[ofp_iuser] = stringtab_add($2->pw_name);
491
current_service->opfixups[ofp_setuid] = $2->pw_uid;
492
current_service->opfixups[ofp_supgid] = $2->pw_gid;
494
set_flag(current_service, FLAG_USER);
496
if(!has_flag(current_service, FLAG_GROUP)) {
497
current_service->opfixups[ofp_setgid] = $2->pw_gid;
502
RL_PWARN("unknown username");
503
current_service->disabled++;
509
set_flag(current_service, FLAG_INITGROUPS);
514
| T_INITGROUPS boolean ';'
517
set_flag(current_service, FLAG_INITGROUPS)
519
reset_flag(current_service, FLAG_INITGROUPS)
524
opcode_element: T_NICE signed_numeric ';'
526
$$ = opmeta_make(2, OP_NICE, $2);
530
$$ = opmeta_make(1, OP_FISH);
532
| T_RLIMIT limittype limit
534
$$ = opmeta_make(3, OP_RLIMIT, $2, $3);
536
| T_LOG T_SYSLOG T_QSTRING ';'
540
i = logtab_add(-1, $3);
541
$$ = opmeta_make(2, OP_LOG, i);
544
| T_BANNER T_QSTRING ';'
548
ret = buftab_addfile($2);
550
current_service->disabled++;
551
$$ = opmeta_make(16, OP_ZERO, OP_BUFCLONE, ret, OP_WHOOK, 0, OP_WUNHOOK,
552
OP_DUP, OP_BUFCOPY, OP_DUP, OP_BZNEG, 3, OP_ADD,
553
OP_WHOOK, -9, OP_POP, OP_BUFFREE);
556
| T_CHARGEN optionalstring ';'
561
i = buftab_addfile($2);
563
current_service->disabled++;
565
i = chargen_buffer();
567
$$ = opmeta_make(25, OP_ZERO, OP_DUP, OP_BUFCLONE, i, OP_POP,
568
OP_POP, OP_ZERO, OP_WHOOK, 0, OP_WUNHOOK, OP_DUP,
569
OP_BUFCOPY, OP_DUP, OP_BZ, -11, OP_DUP, OP_BZNEG, 3,
570
OP_ADD, OP_WHOOK, -12, OP_POP, OP_BUFFREE, OP_JUMP, 666);
571
opmeta_fixup($$, 24, ofp_onexit);
572
current_service->internal = 1;
576
| T_LOG T_QSTRING T_QSTRING ';'
578
struct logdata *ld = logdata_get($2);
581
RL_PWARN(_("unknown log %s"), $2);
582
current_service->disabled++;
584
int i = logtab_add(ld->index, $3);
585
$$ = opmeta_make(2, OP_LOG, i);
593
RL_PWARN(_("unknown group"));
594
current_service->disabled++;
598
current_service->opfixups[ofp_setgid] = $2->gr_gid;
599
set_flag(current_service, FLAG_GROUP);
604
| T_CHROOT T_QSTRING ';'
606
$$ = opmeta_make(2, OP_CHROOT, argvtab_add($2, 1));
608
| T_CAPS T_QSTRING ';'
610
#ifdef HAVE_CAPABILITIES
611
cap_t caps = cap_from_text($2);
613
$$ = opmeta_make(2, OP_SETCAP, captab_add(caps));
615
RL_PWARN(_("failed to parse capability string \"%s\"\n"), $2);
616
current_service->disabled++;
620
RL_PFATAL(EX_DATAERR, _("ABORT - support for capabilities not compiled in"));
623
| T_WRAP T_QSTRING '{' opcode_block '}'
628
opmetalist_add($4, opmeta_make(1, OP_RET));
629
op = opmetalist_resolve($4,current_service->opfixups);
630
i = oplisttab_add(op);
631
$$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
638
| T_WRAP '{' opcode_block '}'
644
opmetalist_add($3, opmeta_make(1, OP_RET));
645
op = opmetalist_resolve($3, current_service->opfixups);
646
i = oplisttab_add(op);
647
o = opmeta_make(3, OP_WRAP, 666, i);
648
opmeta_fixup(o, 1, ofp_iname);
655
| T_WRAP T_QSTRING ';'
657
struct opmetalist *l;
661
l = opmetalist_new();
662
opmetalist_add(l, opmeta_make(1, OP_EXIT));
663
op = opmetalist_resolve(l, current_service->opfixups);
664
i = oplisttab_add(op);
665
$$ = opmeta_make(3, OP_WRAP, stringtab_add($2), i);
674
struct opmetalist *l;
679
l = opmetalist_new();
680
opmetalist_add(l, opmeta_make(1, OP_EXIT));
681
op = opmetalist_resolve(l,current_service->opfixups);
682
i = oplisttab_add(op);
683
o = opmeta_make(3, OP_WRAP, 666, i);
684
opmeta_fixup(o, 1, ofp_iname);
693
$$ = opmeta_make(1, OP_CLOSE);
697
$$ = opmeta_make(1, OP_EXIT);
699
| T_ECHO T_QSTRING ';'
701
$$ = opmeta_make(2, OP_ECHO, argvtab_add($2, 0));
705
$$ = opmeta_make(29, OP_ZERO, OP_BUFINIT, 11, OP_RHOOK, 0, OP_BUFREAD,
706
OP_RUNHOOK, OP_DUP, OP_BZNEG, 17, OP_ADD, OP_WHOOK, 0,
707
OP_BUFWRITE, OP_WUNHOOK, OP_DUP, OP_BZ, 6, OP_DUP,
708
OP_BZNEG, 6, OP_SUB, OP_WHOOK, -11, OP_POP, OP_RHOOK, -22,
710
opmeta_fixup($$, 28, ofp_onexit);
711
current_service->internal = 1;
715
$$ = opmeta_make(13, OP_ZERO, OP_RHOOK, 0, OP_RUNHOOK, OP_BUFINIT, 1024,
716
OP_BUFREAD, OP_BZNEG, 2, OP_RHOOK, -8, OP_JUMP, 666);
717
opmeta_fixup($$, 12, ofp_onexit);
718
current_service->internal = 1;
728
| T_PORT portlists ';'
730
if(current_service->port)
731
stringlist_free(current_service->port);
732
current_service->port = stringlist;
735
| T_PROTO protocol ';'
737
current_service->socktype = $2;
739
| T_BACKLOG T_NUMERIC ';'
741
current_service->backlog = $2;
743
| T_INSTANCES T_NUMERIC ';'
745
current_service->limit = $2;
749
current_service->wait = $2;
751
| T_ENABLED boolean ';'
753
current_service->disabled = ! $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->opfixups[ofp_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, _("%s limit not available on this system"), "nproc");
905
RL_PFATAL(EX_DATAERR, _("%s limit not available on this system"), "nofile");
910
#ifdef RLIMIT_MEMLOCK
913
RL_PFATAL(EX_DATAERR, _("%s limit not available on this system"), "memlock");
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(_("ipv6 support is not compiled in"));
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 (!has_flag(s, FLAG_USER)) {
1040
RL_PWARN(_("user is not set for service %s"), s->name);
1045
if (s->wait && s->limit != 1) {
1046
if (s->limit != defaults->limit)
1047
RL_PWARN(_("ignoring `instances %d' directive for service %s, because `wait' was also given"),
1053
char *rpcname = s->name;
1057
rpcname = s->rpcname;
1058
rep = getrpcbyname(rpcname);
1060
RL_PWARN(_("can't find rpc service %s for service %s"),
1064
s->rpcnum = rep->r_number;
1070
static int bind_ports() {
1073
struct stringlist *portp;
1074
struct stringlist *ifp;
1075
#ifdef HAVE_GETADDRINFO
1076
struct addrinfo hints;
1077
struct addrinfo *results = NULL, *ai;
1085
char *lasterror, *errfunc = NULL;
1090
int family, socktype, protocol;
1092
struct sockaddr *saddr = NULL;
1096
ifp = current_service->interface;
1098
struct stringlist fallback = { !current_service->rpcnum ? current_service->name : "0" , NULL };
1100
addr = ifp ? ifp->str : NULL;
1101
portp = current_service->port;
1109
#ifdef HAVE_GETADDRINFO
1110
memset(&hints, 0, sizeof(hints));
1111
hints.ai_flags = AI_PASSIVE;
1112
hints.ai_family = current_service->family;
1113
hints.ai_socktype = current_service->socktype;
1114
hints.ai_protocol = current_service->proto;
1116
freeaddrinfo(results);
1118
if((ret = getaddrinfo(addr, port, &hints, &results))) {
1119
#ifdef HAVE_GAI_STRERROR
1120
RL_PWARN(_("getaddrinfo(%s, %s) failed: %s"), addr, port,
1123
RL_PWARN(_("getaddrinfo(%s, %s) failed: %s"), addr, port,
1124
_("for reasons unknown") );
1130
family = ai->ai_family;
1131
socktype = ai->ai_socktype;
1132
protocol = ai->ai_protocol;
1133
saddr = ai->ai_addr;
1134
saddrlen = ai->ai_addrlen;
1136
portnum = strtoul(port, &ctmp, 10);
1138
portnum = getservport(port, current_service->protoname);
1140
RL_PWARN(_("Failed to resolve %s, protocol %s"),
1141
current_service->proto, port);
1145
family = current_service->family;
1146
socktype = current_service->socktype;
1147
protocol = current_service->proto;
1153
struct sockaddr_in *sin;
1154
#ifdef HAVE_SOCKADDR_IN6
1155
struct sockaddr_in6 *sin6;
1159
saddrlen = sizeof(struct sockaddr_in);
1160
sin = (struct sockaddr_in *)malloc(saddrlen);
1162
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1163
addrbuf = &sin->sin_addr.s_addr;
1164
sin->sin_family = current_service->family;
1165
sin->sin_port = htons(portnum);
1166
sin->sin_addr.s_addr = INADDR_ANY;
1167
saddr = (struct sockaddr *)sin;
1169
#ifdef HAVE_SOCKADDR_IN6
1171
saddrlen = sizeof(struct sockaddr_in6);
1172
sin6 = (struct sockaddr_in6 *)malloc(saddrlen);
1174
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1175
addrbuf = &sin6->sin_addr.s_addr;
1176
sin6->sin6_family = current_service->family;
1177
sin6->sin6_port = htons(portnum);
1178
sin6->sin6_addr = IN6ADDR_ANY_INIT;
1179
saddr = (struct sockaddr *)sin6;
1183
RL_PFATAL(EX_SOFTWARE, _("funky family in service"));
1187
#ifdef HAVE_INET_PTON
1188
inet_pton(family, addr, addrbuf)
1190
/* this cast is a pain */
1191
(*(unsigned int *)addrbuf = inet_addr(addr)) == -1
1194
RL_PWARN(_("bad address %s in service %s"), addr,
1195
current_service->name);
1202
if((fd = socket(family, socktype, protocol)) < 0) {
1203
lasterror = strerror(errno);
1204
errfunc = "socket()";
1207
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
1208
RL_PWARN(_("setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, 1) failed for service %s (%s)"),
1209
fd, current_service->name, strerror(errno));
1211
#ifdef HAVE_NET_BPF_H
1212
if(current_service->filter) {
1213
struct bpf_program bp;
1215
bp.bf_len = current_service->filterlen / sizeof(struct bpf_insn);
1216
bp.bf_insns = current_service->filter;
1217
if(setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bp, sizeof(bp))) {
1218
lasterror = strerror(errno);
1220
errfunc = "setsockopt(..., SO_ATTACH_FILTER)";
1225
if(bind(fd, saddr, saddrlen) < 0) {
1226
lasterror = strerror(errno);
1231
if(current_service->rpcnum) {
1232
struct numlist *vers = current_service->rpcvers;
1233
struct rl_cleanup *p;
1234
struct sockaddr saddr2;
1236
if (getsockname(fd, &saddr2, &saddrlen) == -1) {
1237
RL_PWARN(_("getsockname(%d) failed for service %s"), fd, current_service->name);
1238
memcpy(&saddr2, saddr, sizeof(struct sockaddr));
1242
if(!pmap_set(current_service->rpcnum, vers->num,
1244
ntohs(((struct sockaddr_in *)&saddr2)->sin_port)))
1245
RL_PWARN(_("pmap_set(%d, %d, %d, %d) failed for service %s"),
1246
current_service->rpcnum, vers->num,
1247
protocol, ntohs(((struct sockaddr_in *)&saddr2)->sin_port),
1248
current_service->name);
1249
} while((vers = vers->next));
1250
p = (struct rl_cleanup *)malloc(sizeof(struct rl_cleanup));
1252
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1253
p->next = rl_cleanups;
1254
p->data = (struct rlc_unrpc *)malloc(sizeof(struct rlc_unrpc));
1256
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1257
p->type = RLC_UNRPC;
1258
((struct rlc_unrpc *)p->data)->vers = NULL;
1259
numlist_copy(&(((struct rlc_unrpc *)p->data)->vers), current_service->rpcvers);
1260
((struct rlc_unrpc *)p->data)->prog = current_service->rpcnum;
1261
/* current_service->rpcvers = NULL;*/ /* caused segfault in the next iteration
1262
of do...while(ai=ai->ai_next) loop */
1266
if(socktype == SOCK_STREAM) {
1267
if(listen(fd, current_service->backlog)) {
1268
lasterror = strerror(errno);
1270
errfunc = "listen(fd)";
1274
if(fcntl(fd, F_SETFD, 1)) {
1275
lasterror = strerror(errno);
1276
errfunc = "fcntl(fd, F_SETFD, 1)";
1280
if(fcntl(fd, F_SETFL, O_NDELAY)) {
1281
lasterror = strerror(errno);
1283
errfunc = "fcntl(fd, F_SETFL, O_NDELAY)";
1289
#ifdef HAVE_GETADDRINFO
1291
} while((ai = ai->ai_next));
1293
if(!succeeded && lasterror)
1294
RL_PWARN(_("%s failed for service %s: %s"),
1295
errfunc, current_service->name, lasterror);
1296
} while(portp && (portp = portp->next));
1297
} while(ifp && (ifp = ifp->next));
1298
stringlist_free(current_service->port);
1299
current_service->port = NULL;
1300
stringlist_free(current_service->interface);
1301
current_service->interface = NULL;
1302
numlist_free(current_service->rpcvers);
1303
current_service->rpcvers = NULL;
1304
#ifdef HAVE_GETADDRINFO
1306
freeaddrinfo(results);
1316
current_service->disabled++;
1317
return fdsettab_add(&fds);
1320
static int add_user_group(const struct service* s, struct opmetalist * l)
1322
struct opmeta *o = NULL;
1323
if (has_flag(s, FLAG_USER))
1325
o = opmeta_make(2, OP_SUID, 666);
1326
opmeta_fixup(o, 1, ofp_setuid);
1327
if(opmetalist_add(l, o)) {
1328
RL_PWARN(_("opcode resolving problem"));
1333
if (has_flag(s, FLAG_USER) || (has_flag(s, FLAG_GROUP)))
1335
o = opmeta_make(2, OP_SGID, 666);
1336
opmeta_fixup(o, 1, ofp_setgid);
1337
if(opmetalist_add(l, o)) {
1338
RL_PWARN(_("opcode resolving problem"));
1343
if (has_flag(s, FLAG_USER) && has_flag(s, FLAG_INITGROUPS))
1345
o = opmeta_make(3, OP_INITGR, 666, 666);
1346
opmeta_fixup(o, 1, ofp_iuser);
1347
opmeta_fixup(o, 2, ofp_supgid);
1348
if(opmetalist_add(l, o)) {
1349
RL_PWARN(_("opcode resolving problem"));
1356
static void service_free(struct service *s) {
1361
stringlist_free(s->port);
1363
stringlist_free(s->interface);
1364
s->interface = NULL;
1370
numlist_free(s->rpcvers);
1373
#ifdef HAVE_CAPABILITIES
1379
#ifdef HAVE_NET_BPF_H
1388
static void service_copy(struct service *to, struct service *from) {
1389
memcpy(to, from, sizeof(*to));
1392
to->interface = NULL;
1393
stringlist_copy(&to->port, from->port);
1394
stringlist_copy(&to->interface, from->interface);
1395
to->rpcname = from->rpcname ? strdup(from->rpcname) : NULL;
1397
numlist_copy(&to->rpcvers, from->rpcvers);
1399
to->caps = from->caps ? cap_dup(from->caps) : NULL;
1401
#ifdef HAVE_NET_BPF_H
1403
to->filter = malloc(from->filterlen);
1405
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1406
memcpy(to->filter, from->filter, from->filterlen);
1411
static struct logdata *logdata_get(char *name) {
1412
struct logdata *ptr = logdatas;
1417
if(!strcmp(name, ptr->name))
1419
} while((ptr = ptr->next));
1423
static void logdatas_free() {
1424
struct logdata *p, *q;
1439
static struct logdata *logdata_new() {
1440
struct logdata *ptr = (struct logdata *)malloc(sizeof(*ptr));
1443
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1445
memset(ptr, 0, sizeof(*ptr));
1449
S_IRUSR|S_IWUSR|S_IRGRP
1464
newuserdata(&userdata);
1474
#ifdef HAVE_CAPABILITIES
1479
if(strcmp(rl_config, "-") || !rl_debug) {
1480
if(!(yyin = fopen(rl_config, "r"))) {
1481
RL_PFATAL(EX_NOINPUT, _("fopen(%s) failed, aborting"), rl_config);
1483
curfile_name = rl_config;
1488
logcur = logdata_new();
1489
current_service = service_new();
1490
defaults = service_new();
1491
#ifdef HAVE_GETADDRINFO
1492
defaults->family = PF_UNSPEC;
1494
defaults->family = PF_INET;
1496
defaults->socktype = SOCK_STREAM;
1497
defaults->protoname = "tcp";
1498
defaults->proto = IPPROTO_TCP;
1499
defaults->backlog = 5;
1500
defaults->limit = 40;
1501
defaults->r.rlim_cur = RLIM_INFINITY;
1502
defaults->r.rlim_max = RLIM_INFINITY;
1506
defaults->opfixups[ofp_exec] = -1;
1508
defaults->opfixups[ofp_iname] = -1;
1509
defaults->opfixups[ofp_parent] = -1;
1510
defaults->opfixups[ofp_iuser] = -1;
1511
defaults->sflags = 0;
1512
defaults->opfixups[ofp_supgid] = -1;
1513
defaults->opfixups[ofp_setgid] = -1;
1514
defaults->opfixups[ofp_setuid] = -1;
1515
service_copy(current_service, defaults);
1516
opml_defaults = opmetalist_new();
1519
service_free(defaults);
1525
service_free(current_service);
1526
free(current_service);
1527
current_service = NULL;
1528
for(curfile = 0; curfile < numfiles; curfile++) {
1529
free(files[curfile]);
1530
files[curfile] = NULL;
1534
clearuserdata(&userdata);
1538
static void pidtab_fixup() {
1542
for(i = 0; i < 8; i++) {
1543
p = pidtabs[i].next;
1553
#ifndef HAVE_GETADDRINFO
1554
static int getservport(char *str, char *proto) {
1555
struct servent *foo;
1558
foo = getservbyname(str, proto);
1560
ret = ntohs(foo->s_port);
1566
static void add_directory(char *dir, char *match, char *ignore) {
1569
regex_t rmatch, rignore;
1576
if((e = regcomp(&rmatch, match, REG_EXTENDED|REG_NOSUB))) {
1577
regerror(e, &rmatch, err, 127);
1578
RL_PWARN(_("regexp compile failed for directory %s: %s"),
1582
if((e = regcomp(&rignore, ignore, REG_EXTENDED|REG_NOSUB))) {
1583
regerror(e, &rignore, err, 127);
1584
RL_PWARN(_("regexp compile failed for directory %s: %s"),
1588
if((d = opendir(dir))) {
1589
while((de = readdir(d))) {
1591
if(regexec(&rmatch, de->d_name, 0, NULL, 0))
1594
if(!regexec(&rignore, de->d_name, 0, NULL, 0))
1596
if(de->d_name[0] != '.') {
1597
file = malloc(strlen(dir) + NAMLEN(de) + 2);
1599
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1603
strcat(file, de->d_name);
1604
if(stat(file, &st) || S_ISDIR(st.st_mode)) {
1605
RL_PWARN(_("file %s does not exists or"
1606
" is a directory"), file);
1610
files = (char **)realloc(files, ++numfiles * sizeof(char *));
1612
rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
1613
files[numfiles - 1] = file;
1617
RL_PFATAL(EX_NOINPUT, _("Directory %s open failed (%s)"), dir,
1632
int chargen_buffer() {
1634
char *b = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
1637
cb = buftab_addbuf(b, strlen(b));
1642
/* vim: set ts=2: */