Changeset View
Standalone View
usr.sbin/inetd/inetd.c
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||||||||
* #ifdef IPSEC | * #ifdef IPSEC | ||||||||||
* Comment lines that start with "#@" denote IPsec policy string, as described | * Comment lines that start with "#@" denote IPsec policy string, as described | ||||||||||
* in ipsec_set_policy(3). This will affect all the following items in | * in ipsec_set_policy(3). This will affect all the following items in | ||||||||||
* inetd.conf(8). To reset the policy, just use "#@" line. By default, | * inetd.conf(8). To reset the policy, just use "#@" line. By default, | ||||||||||
* there's no IPsec policy. | * there's no IPsec policy. | ||||||||||
* #endif | * #endif | ||||||||||
*/ | */ | ||||||||||
#include <sys/param.h> | #include <sys/param.h> | ||||||||||
#include <sys/capsicum.h> | |||||||||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||||||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||||||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||||||||
#include <sys/time.h> | #include <sys/time.h> | ||||||||||
#include <sys/resource.h> | #include <sys/resource.h> | ||||||||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||||||||
#include <sys/un.h> | #include <sys/un.h> | ||||||||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||||||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||||||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||||||||
#include <rpc/rpc.h> | #include <rpc/rpc.h> | ||||||||||
#include <rpc/pmap_clnt.h> | #include <rpc/pmap_clnt.h> | ||||||||||
#include <capsicum_helpers.h> | |||||||||||
#include <ctype.h> | #include <ctype.h> | ||||||||||
#include <errno.h> | #include <errno.h> | ||||||||||
#include <err.h> | #include <err.h> | ||||||||||
#include <fcntl.h> | #include <fcntl.h> | ||||||||||
#include <grp.h> | #include <grp.h> | ||||||||||
#include <libutil.h> | #include <libutil.h> | ||||||||||
#include <limits.h> | #include <limits.h> | ||||||||||
#include <netdb.h> | #include <netdb.h> | ||||||||||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | |||||||||||
static const char *CONFIG = _PATH_INETDCONF; | static const char *CONFIG = _PATH_INETDCONF; | ||||||||||
static const char *pid_file = _PATH_INETDPID; | static const char *pid_file = _PATH_INETDPID; | ||||||||||
static struct pidfh *pfh = NULL; | static struct pidfh *pfh = NULL; | ||||||||||
static struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; | static struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; | ||||||||||
static LIST_HEAD(, procinfo) proctable[PERIPSIZE]; | static LIST_HEAD(, procinfo) proctable[PERIPSIZE]; | ||||||||||
static cap_rights_t ctrl_rights, dgram_svc_rights, svc_rights; | |||||||||||
static unsigned long *ctrl_cmds, nctrl_cmds; | |||||||||||
markj: `ctrl_ioctls` seems like a slightly clearer name. | |||||||||||
static int | static int | ||||||||||
getvalue(const char *arg, int *value, const char *whine) | getvalue(const char *arg, int *value, const char *whine) | ||||||||||
{ | { | ||||||||||
int tmp; | int tmp; | ||||||||||
char *p; | char *p; | ||||||||||
tmp = strtol(arg, &p, 0); | tmp = strtol(arg, &p, 0); | ||||||||||
if (tmp < 0 || *p) { | if (tmp < 0 || *p) { | ||||||||||
Show All 17 Lines | #ifdef INET6 | ||||||||||
if (sa->sa_family == AF_INET6 && | if (sa->sa_family == AF_INET6 && | ||||||||||
IN6_IS_ADDR_V4MAPPED(&satosin6(sa)->sin6_addr)) | IN6_IS_ADDR_V4MAPPED(&satosin6(sa)->sin6_addr)) | ||||||||||
return AF_INET; | return AF_INET; | ||||||||||
#endif | #endif | ||||||||||
return sa->sa_family; | return sa->sa_family; | ||||||||||
} | } | ||||||||||
#endif | #endif | ||||||||||
static void | |||||||||||
setup_sigpipe(void) | |||||||||||
{ | |||||||||||
const unsigned long sigpipe_cmds[] = { FIONREAD }; | |||||||||||
cap_rights_t sigrxpipe_rights, sigtxpipe_rights; | |||||||||||
cap_rights_init(&sigtxpipe_rights, CAP_WRITE); | |||||||||||
cap_rights_init(&sigrxpipe_rights, CAP_READ, CAP_IOCTL, CAP_EVENT); | |||||||||||
if (pipe2(signalpipe, O_CLOEXEC) != 0) { | |||||||||||
syslog(LOG_ERR, "pipe: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
if (caph_rights_limit(signalpipe[1], &sigtxpipe_rights) == -1) { | |||||||||||
oshogboUnsubmitted Not Done Inline ActionsUp to you: but this can be writen shorten: oshogbo: Up to you: but this can be writen shorten:
caph_rights_limit(signalpipe[1], cap_rights_init… | |||||||||||
syslog(LOG_ERR, "failed to limit tx signalpipe: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
if (caph_rights_limit(signalpipe[0], &sigrxpipe_rights) == -1 || | |||||||||||
caph_ioctls_limit(signalpipe[0], sigpipe_cmds, | |||||||||||
nitems(sigpipe_cmds)) == -1) { | |||||||||||
syslog(LOG_ERR, "failed to limit rx signalpipe: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
} | |||||||||||
static void | |||||||||||
prepare_ctrl_caps(void) | |||||||||||
{ | |||||||||||
const unsigned long std_ctrl_cmds[] = { FIONBIO, FIONREAD }; | |||||||||||
size_t i, j; | |||||||||||
/* | |||||||||||
* The rights we're imposing on these sockets will be passed down to | |||||||||||
* inetd services as stdio, so we need to both be somewhat respectful of | |||||||||||
* what they may reasonably attempt to do and we need to make sure we | |||||||||||
* apply a superset of the standard rights we grant to stdio. | |||||||||||
*/ | |||||||||||
caph_stream_rights(&ctrl_rights, CAPH_READ | CAPH_WRITE); | |||||||||||
caph_stream_rights(&svc_rights, CAPH_READ | CAPH_WRITE); | |||||||||||
/* Control rights need to be a superset of service rights. */ | |||||||||||
cap_rights_set(&ctrl_rights, CAP_ACCEPT, CAP_BIND, CAP_CONNECT, | |||||||||||
CAP_LISTEN, CAP_SETSOCKOPT, CAP_GETSOCKNAME); | |||||||||||
cap_rights_set(&svc_rights, CAP_SETSOCKOPT, CAP_GETSOCKNAME); | |||||||||||
oshogboUnsubmitted Not Done Inline ActionsThis is my private preference, so it's up to you what you will do with it: oshogbo: This is my private preference, so it's up to you what you will do with it:
I just prefer to… | |||||||||||
kevansAuthorUnsubmitted Done Inline ActionsSo, the problem is that I don't want to be duplicating the caph_stream_rights() because then that would need to be maintained, but I need them since the invoked program may attempt to caph_limit_stdio(). kevans: So, the problem is that I don't want to be duplicating the caph_stream_rights() because then… | |||||||||||
#ifdef LIBWRAP | |||||||||||
cap_rights_set(&ctrl_rights, CAP_GETPEERNAME); | |||||||||||
cap_rights_set(&svc_rights, CAP_GETPEERNAME); | |||||||||||
#endif | |||||||||||
/* Now build dgram_svc_rights as based on svc_rights + CAP_CONNECT. */ | |||||||||||
cap_rights_init(&dgram_svc_rights); | |||||||||||
cap_rights_merge(&dgram_svc_rights, &svc_rights); | |||||||||||
cap_rights_set(&dgram_svc_rights, CAP_CONNECT); | |||||||||||
nctrl_cmds = nitems(caph_stream_cmds) + nitems(std_ctrl_cmds); | |||||||||||
ctrl_cmds = reallocarray(NULL, nctrl_cmds, sizeof(*ctrl_cmds)); | |||||||||||
Not Done Inline ActionsCan this just be calloc()? markj: Can this just be calloc()? | |||||||||||
if (ctrl_cmds == NULL) { | |||||||||||
syslog(LOG_ERR, "reallocarray: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
for (i = 0, j = 0; i < nitems(caph_stream_cmds); ++i, ++j) | |||||||||||
ctrl_cmds[j] = caph_stream_cmds[i]; | |||||||||||
for (i = 0; i < nitems(std_ctrl_cmds); ++i, ++j) | |||||||||||
ctrl_cmds[j] = std_ctrl_cmds[i]; | |||||||||||
} | |||||||||||
/* | |||||||||||
* Both service and control capabilities are handled through here, to simplify | |||||||||||
* paths needed to read to understand what can be done. Service sockets are | |||||||||||
Not Done Inline ActionsI don't quite understand this reasoning. markj: I don't quite understand this reasoning. | |||||||||||
Done Inline ActionsIt might have made more sense to chop off the first sentence entirely, maybe something more like: Service sockets are created via accept(2), thus inheriting the rights of the control socket. Therefore, control caps must be a superset of those needed by the services. Apply rights here for both service sockets and control socket to make it easier to audit that this is happening. kevans: It might have made more sense to chop off the first sentence entirely, maybe something more… | |||||||||||
Not Done Inline ActionsOk, that seems fine to me. markj: Ok, that seems fine to me. | |||||||||||
* created via accept(2), thus inheriting the rights of the control socket. | |||||||||||
* Therefore, control caps must be a superset of those needed by the services. | |||||||||||
*/ | |||||||||||
static void | |||||||||||
setup_ctrl_caps(int fd, struct servtab *sep) | |||||||||||
{ | |||||||||||
cap_rights_t *rights; | |||||||||||
if (sep != NULL && sep->se_socktype == SOCK_DGRAM) | |||||||||||
rights = &dgram_svc_rights; | |||||||||||
else if (sep != NULL) | |||||||||||
rights = &svc_rights; | |||||||||||
else | |||||||||||
rights = &ctrl_rights; | |||||||||||
if (caph_rights_limit(fd, rights) == -1) { | |||||||||||
syslog(LOG_ERR, "failed to limit %s sock: %m", | |||||||||||
sep != NULL ? "service" : "control"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
if (sep == NULL && caph_ioctls_limit(fd, ctrl_cmds, nctrl_cmds) == -1) { | |||||||||||
oshogboUnsubmitted Done Inline ActionsWhy don't lmit it in the first if? oshogbo: Why don't lmit it in the first if? | |||||||||||
kevansAuthorUnsubmitted Done Inline ActionsWill do kevans: Will do | |||||||||||
syslog(LOG_ERR, "failed to limit control ioctls: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
} | |||||||||||
int | int | ||||||||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||||||||
{ | { | ||||||||||
struct servtab *sep; | struct servtab *sep; | ||||||||||
struct passwd *pwd; | struct passwd *pwd; | ||||||||||
struct group *grp; | struct group *grp; | ||||||||||
struct sigaction sa, saalrm, sachld, sahup, sapipe; | struct sigaction sa, saalrm, sachld, sahup, sapipe; | ||||||||||
int ch, dofork; | int ch; | ||||||||||
pid_t pid; | pid_t pid; | ||||||||||
char buf[50]; | char buf[50]; | ||||||||||
#ifdef LOGIN_CAP | #ifdef LOGIN_CAP | ||||||||||
login_cap_t *lc = NULL; | login_cap_t *lc = NULL; | ||||||||||
#endif | #endif | ||||||||||
#ifdef LIBWRAP | #ifdef LIBWRAP | ||||||||||
struct request_info req; | struct request_info req; | ||||||||||
int denied; | int denied; | ||||||||||
char *service = NULL; | char *service = NULL; | ||||||||||
#endif | #endif | ||||||||||
struct sockaddr_storage peer; | struct sockaddr_storage peer; | ||||||||||
int i; | int i; | ||||||||||
struct addrinfo hints, *res; | struct addrinfo hints, *res; | ||||||||||
const char *servname; | const char *servname; | ||||||||||
int error; | int error; | ||||||||||
struct conninfo *conn; | struct conninfo *conn; | ||||||||||
bool dofork; | |||||||||||
openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON); | openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON); | ||||||||||
/* Relies on syslog(3). */ | |||||||||||
prepare_ctrl_caps(); | |||||||||||
if (caph_limit_stdio() == -1) { | |||||||||||
syslog(LOG_ERR, "caph_limit_stdio: %m"); | |||||||||||
exit(1); | |||||||||||
Done Inline Actions
markj: | |||||||||||
} | |||||||||||
while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1) | while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1) | ||||||||||
switch(ch) { | switch(ch) { | ||||||||||
case 'd': | case 'd': | ||||||||||
debug = 1; | debug = 1; | ||||||||||
options |= SO_DEBUG; | options |= SO_DEBUG; | ||||||||||
break; | break; | ||||||||||
case 'l': | case 'l': | ||||||||||
dolog = 1; | dolog = 1; | ||||||||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | |||||||||||
#define DUMMYSIZE 100 | #define DUMMYSIZE 100 | ||||||||||
char dummy[DUMMYSIZE]; | char dummy[DUMMYSIZE]; | ||||||||||
(void)memset(dummy, 'x', DUMMYSIZE - 1); | (void)memset(dummy, 'x', DUMMYSIZE - 1); | ||||||||||
dummy[DUMMYSIZE - 1] = '\0'; | dummy[DUMMYSIZE - 1] = '\0'; | ||||||||||
(void)setenv("inetd_dummy", dummy, 1); | (void)setenv("inetd_dummy", dummy, 1); | ||||||||||
} | } | ||||||||||
if (pipe2(signalpipe, O_CLOEXEC) != 0) { | setup_sigpipe(); | ||||||||||
syslog(LOG_ERR, "pipe: %m"); | |||||||||||
exit(EX_OSERR); | |||||||||||
} | |||||||||||
FD_SET(signalpipe[0], &allsock); | FD_SET(signalpipe[0], &allsock); | ||||||||||
#ifdef SANITY_CHECK | #ifdef SANITY_CHECK | ||||||||||
nsock++; | nsock++; | ||||||||||
#endif | #endif | ||||||||||
maxsock = MAX(MAX(maxsock, signalpipe[0]), signalpipe[1]); | maxsock = MAX(MAX(maxsock, signalpipe[0]), signalpipe[1]); | ||||||||||
for (;;) { | for (;;) { | ||||||||||
int n, ctrl; | int n, ctrl; | ||||||||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | while (--nsig >= 0) { | ||||||||||
syslog(LOG_WARNING, | syslog(LOG_WARNING, | ||||||||||
"accept (for %s): %m", | "accept (for %s): %m", | ||||||||||
sep->se_service); | sep->se_service); | ||||||||||
if (sep->se_accept && | if (sep->se_accept && | ||||||||||
sep->se_socktype == SOCK_STREAM) | sep->se_socktype == SOCK_STREAM) | ||||||||||
close(ctrl); | close(ctrl); | ||||||||||
continue; | continue; | ||||||||||
} | } | ||||||||||
/* | |||||||||||
* This will limit the service effectively to | |||||||||||
* read/write/select for all spawned processes, both | |||||||||||
* builtin and external. | |||||||||||
*/ | |||||||||||
setup_ctrl_caps(ctrl, sep); | |||||||||||
i = 0; | i = 0; | ||||||||||
if (ioctl(sep->se_fd, FIONBIO, &i) < 0) | if (ioctl(sep->se_fd, FIONBIO, &i) < 0) | ||||||||||
syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m"); | syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m"); | ||||||||||
if (ioctl(ctrl, FIONBIO, &i) < 0) | if (ioctl(ctrl, FIONBIO, &i) < 0) | ||||||||||
syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m"); | syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m"); | ||||||||||
if (cpmip(sep, ctrl) < 0) { | if (cpmip(sep, ctrl) < 0) { | ||||||||||
close(ctrl); | close(ctrl); | ||||||||||
continue; | continue; | ||||||||||
} | } | ||||||||||
if (dofork && | if (dofork && | ||||||||||
(conn = search_conn(sep, ctrl)) != NULL && | (conn = search_conn(sep, ctrl)) != NULL && | ||||||||||
!room_conn(sep, conn)) { | !room_conn(sep, conn)) { | ||||||||||
close(ctrl); | close(ctrl); | ||||||||||
continue; | continue; | ||||||||||
} | } | ||||||||||
} else | } else | ||||||||||
ctrl = sep->se_fd; | ctrl = sep->se_fd; | ||||||||||
if (sep->se_socktype == SOCK_DGRAM) | |||||||||||
setup_ctrl_caps(ctrl, sep); | |||||||||||
Not Done Inline ActionsAre we limiting rights on the same socket each time the service is invoked? markj: Are we limiting rights on the same socket each time the service is invoked? | |||||||||||
Done Inline ActionsReading it again, yeah... this would seem to boil down to setup_ctrl_caps(sep->se_fd, sep); kevans: Reading it again, yeah... this would seem to boil down to `setup_ctrl_caps(sep->se_fd, sep);` | |||||||||||
Not Done Inline ActionsNot the end of the world I guess, but worth an XXX comment or so if you prefer to keep it as is for now. markj: Not the end of the world I guess, but worth an XXX comment or so if you prefer to keep it as is… | |||||||||||
if (dolog && !ISWRAP(sep)) { | if (dolog && !ISWRAP(sep)) { | ||||||||||
char pname[NI_MAXHOST] = "unknown"; | char pname[NI_MAXHOST] = "unknown"; | ||||||||||
socklen_t sl; | socklen_t sl; | ||||||||||
sl = sizeof(peer); | sl = sizeof(peer); | ||||||||||
if (getpeername(ctrl, (struct sockaddr *) | if (getpeername(ctrl, (struct sockaddr *) | ||||||||||
&peer, &sl)) { | &peer, &sl)) { | ||||||||||
sl = sizeof(peer); | sl = sizeof(peer); | ||||||||||
if (recvfrom(ctrl, buf, sizeof(buf), | if (recvfrom(ctrl, buf, sizeof(buf), | ||||||||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | while (--nsig >= 0) { | ||||||||||
if (sep->se_bi && | if (sep->se_bi && | ||||||||||
sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) { | sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) { | ||||||||||
sep = tcpmux(ctrl); | sep = tcpmux(ctrl); | ||||||||||
if (sep == NULL) { | if (sep == NULL) { | ||||||||||
close(ctrl); | close(ctrl); | ||||||||||
_exit(0); | _exit(0); | ||||||||||
} | } | ||||||||||
} | } | ||||||||||
#ifdef LIBWRAP | #ifdef LIBWRAP | ||||||||||
if (ISWRAP(sep)) { | if (ISWRAP(sep)) { | ||||||||||
inetd_setproctitle("wrapping", ctrl); | inetd_setproctitle("wrapping", ctrl); | ||||||||||
service = sep->se_server_name ? | service = sep->se_server_name ? | ||||||||||
sep->se_server_name : sep->se_service; | sep->se_server_name : sep->se_service; | ||||||||||
request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, 0); | request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, 0); | ||||||||||
fromhost(&req); | fromhost(&req); | ||||||||||
deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; | deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; | ||||||||||
Show All 14 Lines | #ifdef LIBWRAP | ||||||||||
if (dolog) { | if (dolog) { | ||||||||||
syslog(allow_severity, | syslog(allow_severity, | ||||||||||
"connection from %.500s, service %s (%s%s)", | "connection from %.500s, service %s (%s%s)", | ||||||||||
eval_client(&req), service, sep->se_proto, | eval_client(&req), service, sep->se_proto, | ||||||||||
(whichaf(&req) == AF_INET6) ? "6" : ""); | (whichaf(&req) == AF_INET6) ? "6" : ""); | ||||||||||
} | } | ||||||||||
} | } | ||||||||||
#endif | #endif | ||||||||||
if (dofork && sep->se_bi != NULL && | |||||||||||
sep->se_bi->bi_capenter && caph_enter() == -1) { | |||||||||||
syslog(LOG_ERR, "cap_enter: %m"); | |||||||||||
_exit(0); | |||||||||||
} | |||||||||||
markjUnsubmitted Done Inline ActionsThis could be collapsed into the following if-statement (for now). You are duplicating the sep->se_bi != NULL test. markj: This could be collapsed into the following if-statement (for now). You are duplicating the sep… | |||||||||||
if (sep->se_bi) { | if (sep->se_bi) { | ||||||||||
(*sep->se_bi->bi_fn)(ctrl, sep); | (*sep->se_bi->bi_fn)(ctrl, sep); | ||||||||||
} else { | } else { | ||||||||||
if (debug) | if (debug) | ||||||||||
warnx("%d execl %s", | warnx("%d execl %s", | ||||||||||
oshogboUnsubmitted Done Inline ActionsWe don't need a caph_cache_catpages ? oshogbo: We don't need a caph_cache_catpages ? | |||||||||||
getpid(), sep->se_server); | getpid(), sep->se_server); | ||||||||||
/* Clear close-on-exec. */ | /* Clear close-on-exec. */ | ||||||||||
if (fcntl(ctrl, F_SETFD, 0) < 0) { | if (fcntl(ctrl, F_SETFD, 0) < 0) { | ||||||||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||||||||
oshogboUnsubmitted Done Inline ActionsShould we use casper service here for the syslog? oshogbo: Should we use casper service here for the syslog? | |||||||||||
kevansAuthorUnsubmitted Done Inline ActionsThis branch doesn't get hit in the caph_enter() path, but both are things we'll need to consider going forward (that I hadn't previously) when we allow inetd.conf specifying that a service should be capsicumized. kevans: This branch doesn't get hit in the caph_enter() path, but both are things we'll need to… | |||||||||||
"%s/%s: fcntl (F_SETFD, 0): %m", | "%s/%s: fcntl (F_SETFD, 0): %m", | ||||||||||
sep->se_service, sep->se_proto); | sep->se_service, sep->se_proto); | ||||||||||
_exit(EX_OSERR); | _exit(EX_OSERR); | ||||||||||
} | } | ||||||||||
if (ctrl != 0) { | if (ctrl != 0) { | ||||||||||
dup2(ctrl, 0); | dup2(ctrl, 0); | ||||||||||
close(ctrl); | close(ctrl); | ||||||||||
} | } | ||||||||||
▲ Show 20 Lines • Show All 457 Lines • ▼ Show 20 Lines | if ((sep->se_fd = socket(sep->se_family, | ||||||||||
sep->se_socktype | SOCK_CLOEXEC, 0)) < 0) { | sep->se_socktype | SOCK_CLOEXEC, 0)) < 0) { | ||||||||||
if (debug) | if (debug) | ||||||||||
warn("socket failed on %s/%s", | warn("socket failed on %s/%s", | ||||||||||
sep->se_service, sep->se_proto); | sep->se_service, sep->se_proto); | ||||||||||
syslog(LOG_ERR, "%s/%s: socket: %m", | syslog(LOG_ERR, "%s/%s: socket: %m", | ||||||||||
sep->se_service, sep->se_proto); | sep->se_service, sep->se_proto); | ||||||||||
return; | return; | ||||||||||
} | } | ||||||||||
setup_ctrl_caps(sep->se_fd, NULL); | |||||||||||
#define turnon(fd, opt) \ | #define turnon(fd, opt) \ | ||||||||||
setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) | setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) | ||||||||||
if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && | if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && | ||||||||||
turnon(sep->se_fd, SO_DEBUG) < 0) | turnon(sep->se_fd, SO_DEBUG) < 0) | ||||||||||
syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); | syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); | ||||||||||
if (turnon(sep->se_fd, SO_REUSEADDR) < 0) | if (turnon(sep->se_fd, SO_REUSEADDR) < 0) | ||||||||||
syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); | syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); | ||||||||||
#ifdef SO_PRIVSTATE | #ifdef SO_PRIVSTATE | ||||||||||
▲ Show 20 Lines • Show All 1,289 Lines • Show Last 20 Lines |
ctrl_ioctls seems like a slightly clearer name.