Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153289442
D41364.id125717.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D41364.id125717.diff
View Options
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -187,23 +187,15 @@
#endif
/*
- * List of peers and sockets for binding.
+ * Sockets used for logging; monitored by kevent().
*/
-struct peer {
- const char *pe_name;
- const char *pe_serv;
- mode_t pe_mode;
- STAILQ_ENTRY(peer) next;
-};
-static STAILQ_HEAD(, peer) pqueue = STAILQ_HEAD_INITIALIZER(pqueue);
-
struct socklist {
+ int sl_socket;
+ const char *sl_name;
struct addrinfo sl_ai;
#define sl_sa sl_ai.ai_addr
#define sl_salen sl_ai.ai_addrlen
#define sl_family sl_ai.ai_family
- int sl_socket;
- struct peer *sl_peer;
int (*sl_recv)(struct socklist *);
STAILQ_ENTRY(socklist) next;
};
@@ -422,8 +414,7 @@
struct iovlist;
static bool allowaddr(char *);
-static int addpeer(struct peer *);
-static int addsock(struct addrinfo *, struct socklist *);
+static void addsock(const char *, const char *, mode_t);
static void cfline(const char *, const char *, const char *, const char *);
static const char *cvthname(struct sockaddr *);
static void deadq_enter(pid_t, const char *);
@@ -442,7 +433,7 @@
const char *, const char *, const char *, const char *, int);
static void log_deadchild(pid_t, int, const char *);
static void markit(void);
-static int socksetup(struct peer *);
+static struct socklist *socksetup(struct addrinfo *, const char *, mode_t);
static int socklist_recv_file(struct socklist *);
static int socklist_recv_sock(struct socklist *);
static int skip_message(const char *, const char *, int);
@@ -492,41 +483,181 @@
f->f_file = -1;
}
-static int
-addpeer(struct peer *pe0)
+static struct socklist *
+socksetup(struct addrinfo *ai, const char *name, mode_t mode)
{
- struct peer *pe;
+ struct socklist *sl;
+ int (*sl_recv)(struct socklist *);
+ int s, optval = 1;
- pe = calloc(1, sizeof(*pe));
- if (pe == NULL)
- err(1, "malloc failed");
- *pe = *pe0;
- STAILQ_INSERT_TAIL(&pqueue, pe, next);
+ if (ai->ai_family != AF_LOCAL && SecureMode > 1) {
+ /* Only AF_LOCAL in secure mode. */
+ return (NULL);
+ }
+ if (family != AF_UNSPEC && ai->ai_family != AF_LOCAL &&
+ ai->ai_family != family)
+ return (NULL);
- return (0);
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s < 0) {
+ logerror("socket");
+ return (NULL);
+ }
+ if (ai->ai_family == AF_INET6) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
+ sizeof(int)) < 0) {
+ logerror("setsockopt(IPV6_V6ONLY)");
+ close(s);
+ return (NULL);
+ }
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(int)) < 0) {
+ logerror("setsockopt(SO_REUSEADDR)");
+ close(s);
+ return (NULL);
+ }
+
+ /*
+ * Bind INET and UNIX-domain sockets.
+ *
+ * A UNIX-domain socket is always bound to a pathname
+ * regardless of -N flag.
+ *
+ * For INET sockets, RFC 3164 recommends that client
+ * side message should come from the privileged syslogd port.
+ *
+ * If the system administrator chooses not to obey
+ * this, we can skip the bind() step so that the
+ * system will choose a port for us.
+ */
+ if (ai->ai_family == AF_LOCAL)
+ unlink(name);
+ if (ai->ai_family == AF_LOCAL || NoBind == 0 || name != NULL) {
+ if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+ logerror("bind");
+ close(s);
+ return (NULL);
+ }
+ if (ai->ai_family == AF_LOCAL || SecureMode == 0)
+ increase_rcvbuf(s);
+ }
+ if (ai->ai_family == AF_LOCAL && chmod(name, mode) < 0) {
+ dprintf("chmod %s: %s\n", name, strerror(errno));
+ close(s);
+ return (NULL);
+ }
+ dprintf("new socket fd is %d\n", s);
+ if (ai->ai_socktype != SOCK_DGRAM) {
+ listen(s, 5);
+ }
+ sl_recv = socklist_recv_sock;
+ if (SecureMode && (ai->ai_family == AF_INET ||
+ ai->ai_family == AF_INET6)) {
+ dprintf("shutdown\n");
+ /* Forbid communication in secure mode. */
+ if (shutdown(s, SHUT_RD) < 0 && errno != ENOTCONN) {
+ logerror("shutdown");
+ if (!Debug)
+ die(0);
+ }
+ sl_recv = NULL;
+ } else {
+ dprintf("listening on socket\n");
+ }
+ dprintf("sending on socket\n");
+ /* Copy *ai->ai_addr to the tail of struct socklist if any. */
+ sl = calloc(1, sizeof(*sl) + ai->ai_addrlen);
+ if (sl == NULL)
+ err(1, "malloc failed");
+ sl->sl_socket = s;
+ sl->sl_name = name;
+ sl->sl_recv = sl_recv;
+ (void)memcpy(&sl->sl_ai, ai, sizeof(*ai));
+ if (ai->ai_addrlen > 0) {
+ (void)memcpy((sl + 1), ai->ai_addr, ai->ai_addrlen);
+ sl->sl_sa = (struct sockaddr *)(sl + 1);
+ } else {
+ sl->sl_sa = NULL;
+ }
+ return (sl);
}
-static int
-addsock(struct addrinfo *ai, struct socklist *sl0)
+/*
+ * We have to handle this case for backwards compatibility:
+ * If there are two (or more) colons but no '[' and ']',
+ * assume this is an inet6 address without a service.
+ */
+#define fixaddr_inet6(name, serv) \
+do { \
+ char *cp; \
+ if (name != NULL) { \
+ if (name[0] == '[' && \
+ (cp = strchr(name + 1, ']')) != NULL) { \
+ name = &name[1]; \
+ *cp = '\0'; \
+ if (cp[1] == ':' && cp[2] != '\0') \
+ serv = cp + 2; \
+ } else { \
+ cp = strchr(name, ':'); \
+ if (cp != NULL && strchr(cp + 1, ':') == NULL) {\
+ *cp = '\0'; \
+ if (cp[1] != '\0') \
+ serv = cp + 1; \
+ if (cp == name) \
+ name = NULL; \
+ } \
+ } \
+ } \
+} while (0)
+
+static void
+addsock(const char *name, const char *serv, mode_t mode)
{
+ struct addrinfo hints = { }, *res, *res0;
struct socklist *sl;
+ int error;
+ char *msgbuf;
+
+ fixaddr_inet6(name, serv);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE;
+ if (name != NULL)
+ dprintf("Trying peer: %s\n", name);
+ if (serv == NULL)
+ serv = "syslog";
+ error = getaddrinfo(name, serv, &hints, &res0);
+ if (error) {
+ asprintf(&msgbuf, "getaddrinfo failed for %s%s: %s",
+ name == NULL ? "" : name, serv,
+ gai_strerror(error));
+ errno = 0;
+ if (msgbuf == NULL)
+ logerror(gai_strerror(error));
+ else
+ logerror(msgbuf);
+ free(msgbuf);
+ die(0);
+ }
+ for (res = res0; res != NULL; res = res->ai_next) {
+ sl = socksetup(res, name, mode);
+ if (sl == NULL)
+ continue;
+ STAILQ_INSERT_TAIL(&shead, sl, next);
+ }
+ freeaddrinfo(res0);
+}
- /* Copy *ai->ai_addr to the tail of struct socklist if any. */
- sl = calloc(1, sizeof(*sl) + ((ai != NULL) ? ai->ai_addrlen : 0));
+static void
+addfile(int fd)
+{
+ struct socklist *sl = calloc(1, sizeof(*sl));
if (sl == NULL)
err(1, "malloc failed");
- *sl = *sl0;
- if (ai != NULL) {
- memcpy(&sl->sl_ai, ai, sizeof(*ai));
- if (ai->ai_addrlen > 0) {
- memcpy((sl + 1), ai->ai_addr, ai->ai_addrlen);
- sl->sl_sa = (struct sockaddr *)(sl + 1);
- } else
- sl->sl_sa = NULL;
- }
+ sl->sl_socket = fd;
+ sl->sl_recv = socklist_recv_file;
STAILQ_INSERT_TAIL(&shead, sl, next);
-
- return (0);
}
int
@@ -535,7 +666,6 @@
struct timespec ts = { }, *tsp = &ts;
struct kevent ev;
struct socklist *sl;
- struct peer *pe;
sigset_t sigset = { };
pid_t ppid = -1, spid;
int ch, kq, error;
@@ -582,18 +712,12 @@
}
if (p == NULL) {
/* A hostname or filename only. */
- addpeer(&(struct peer){
- .pe_name = optarg,
- .pe_serv = "syslog"
- });
+ addsock(optarg, "syslog", 0);
} else {
/* The case of "name:service". */
*p++ = '\0';
- addpeer(&(struct peer){
- .pe_serv = p,
- .pe_name = (strlen(optarg) == 0) ?
- NULL : optarg,
- });
+ addsock(strlen(optarg) == 0 ? NULL : optarg,
+ p, 0);
}
break;
case 'c':
@@ -651,13 +775,11 @@
} else
errx(1, "invalid mode %s, exiting",
optarg);
- } else
+ } else {
errx(1, "invalid filename %s, exiting",
optarg);
- addpeer(&(struct peer){
- .pe_name = name,
- .pe_mode = mode
- });
+ }
+ addsock(name, NULL, mode);
break;
}
case 'M': /* max length of forwarded message */
@@ -719,30 +841,17 @@
if (error < 0) {
dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
} else {
- addsock(NULL, &(struct socklist){
- .sl_socket = error,
- .sl_recv = socklist_recv_file,
- });
+ addfile(error);
}
/* Listen by default: *:514 if no -b flag. */
if (bflag == 0)
- addpeer(&(struct peer){
- .pe_serv = "syslog"
- });
+ addsock(NULL, "syslog", 0);
/* Listen by default: /var/run/log if no -p flag. */
if (pflag == 0)
- addpeer(&(struct peer){
- .pe_name = _PATH_LOG,
- .pe_mode = DEFFILEMODE,
- });
+ addsock(_PATH_LOG, NULL, DEFFILEMODE);
/* Listen by default: /var/run/logpriv if no -S flag. */
if (Sflag == 0)
- addpeer(&(struct peer){
- .pe_name = _PATH_LOG_PRIV,
- .pe_mode = S_IRUSR | S_IWUSR,
- });
- STAILQ_FOREACH(pe, &pqueue, next)
- socksetup(pe);
+ addsock(_PATH_LOG_PRIV, NULL, S_IRUSR | S_IWUSR);
pfh = pidfile_open(PidFile, 0600, &spid);
if (pfh == NULL) {
@@ -2312,7 +2421,7 @@
}
STAILQ_FOREACH(sl, &shead, next) {
if (sl->sl_sa != NULL && sl->sl_family == AF_LOCAL)
- unlink(sl->sl_peer->pe_name);
+ unlink(sl->sl_name);
}
pidfile_remove(pfh);
@@ -3677,161 +3786,6 @@
logerror(buf);
}
-static int
-socksetup(struct peer *pe)
-{
- struct addrinfo hints, *res, *res0;
- int error;
- char *cp;
- int (*sl_recv)(struct socklist *);
- /*
- * We have to handle this case for backwards compatibility:
- * If there are two (or more) colons but no '[' and ']',
- * assume this is an inet6 address without a service.
- */
- if (pe->pe_name != NULL) {
- if (pe->pe_name[0] == '[' &&
- (cp = strchr(pe->pe_name + 1, ']')) != NULL) {
- pe->pe_name = &pe->pe_name[1];
- *cp = '\0';
- if (cp[1] == ':' && cp[2] != '\0')
- pe->pe_serv = cp + 2;
- } else {
- cp = strchr(pe->pe_name, ':');
- if (cp != NULL && strchr(cp + 1, ':') == NULL) {
- *cp = '\0';
- if (cp[1] != '\0')
- pe->pe_serv = cp + 1;
- if (cp == pe->pe_name)
- pe->pe_name = NULL;
- }
- }
- }
- hints = (struct addrinfo){
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_DGRAM,
- .ai_flags = AI_PASSIVE
- };
- if (pe->pe_name != NULL)
- dprintf("Trying peer: %s\n", pe->pe_name);
- if (pe->pe_serv == NULL)
- pe->pe_serv = "syslog";
- error = getaddrinfo(pe->pe_name, pe->pe_serv, &hints, &res0);
- if (error) {
- char *msgbuf;
-
- asprintf(&msgbuf, "getaddrinfo failed for %s%s: %s",
- pe->pe_name == NULL ? "" : pe->pe_name, pe->pe_serv,
- gai_strerror(error));
- errno = 0;
- if (msgbuf == NULL)
- logerror(gai_strerror(error));
- else
- logerror(msgbuf);
- free(msgbuf);
- die(0);
- }
- for (res = res0; res != NULL; res = res->ai_next) {
- int s;
-
- if (res->ai_family != AF_LOCAL &&
- SecureMode > 1) {
- /* Only AF_LOCAL in secure mode. */
- continue;
- }
- if (family != AF_UNSPEC &&
- res->ai_family != AF_LOCAL && res->ai_family != family)
- continue;
-
- s = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol);
- if (s < 0) {
- logerror("socket");
- error++;
- continue;
- }
- if (res->ai_family == AF_INET6) {
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
- &(int){1}, sizeof(int)) < 0) {
- logerror("setsockopt(IPV6_V6ONLY)");
- close(s);
- error++;
- continue;
- }
- }
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- &(int){1}, sizeof(int)) < 0) {
- logerror("setsockopt(SO_REUSEADDR)");
- close(s);
- error++;
- continue;
- }
-
- /*
- * Bind INET and UNIX-domain sockets.
- *
- * A UNIX-domain socket is always bound to a pathname
- * regardless of -N flag.
- *
- * For INET sockets, RFC 3164 recommends that client
- * side message should come from the privileged syslogd port.
- *
- * If the system administrator chooses not to obey
- * this, we can skip the bind() step so that the
- * system will choose a port for us.
- */
- if (res->ai_family == AF_LOCAL)
- unlink(pe->pe_name);
- if (res->ai_family == AF_LOCAL ||
- NoBind == 0 || pe->pe_name != NULL) {
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
- logerror("bind");
- close(s);
- error++;
- continue;
- }
- if (res->ai_family == AF_LOCAL ||
- SecureMode == 0)
- increase_rcvbuf(s);
- }
- if (res->ai_family == AF_LOCAL &&
- chmod(pe->pe_name, pe->pe_mode) < 0) {
- dprintf("chmod %s: %s\n", pe->pe_name,
- strerror(errno));
- close(s);
- error++;
- continue;
- }
- dprintf("new socket fd is %d\n", s);
- if (res->ai_socktype != SOCK_DGRAM) {
- listen(s, 5);
- }
- sl_recv = socklist_recv_sock;
- if (SecureMode && (res->ai_family == AF_INET ||
- res->ai_family == AF_INET6)) {
- dprintf("shutdown\n");
- /* Forbid communication in secure mode. */
- if (shutdown(s, SHUT_RD) < 0 &&
- errno != ENOTCONN) {
- logerror("shutdown");
- if (!Debug)
- die(0);
- }
- sl_recv = NULL;
- } else
- dprintf("listening on socket\n");
- dprintf("sending on socket\n");
- addsock(res, &(struct socklist){
- .sl_socket = s,
- .sl_peer = pe,
- .sl_recv = sl_recv
- });
- }
- freeaddrinfo(res0);
-
- return(error);
-}
-
static void
increase_rcvbuf(int fd)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 6:53 AM (45 m, 22 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31895219
Default Alt Text
D41364.id125717.diff (12 KB)
Attached To
Mode
D41364: syslogd: Only use peerlist during flag parsing
Attached
Detach File
Event Timeline
Log In to Comment