1 /* $NetBSD: syslogd.c,v 1.84 2006/11/13 20:24:00 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\n\ 35 The Regents of the University of California. All rights reserved.\n"); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94"; 41 #else 42 __RCSID("$NetBSD: syslogd.c,v 1.84 2006/11/13 20:24:00 christos Exp $"); 43 #endif 44 #endif /* not lint */ 45 46 /* 47 * syslogd -- log system messages 48 * 49 * This program implements a system log. It takes a series of lines. 50 * Each line may have a priority, signified as "<n>" as 51 * the first characters of the line. If this is 52 * not present, a default priority is used. 53 * 54 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will 55 * cause it to reread its configuration file. 56 * 57 * Defined Constants: 58 * 59 * MAXLINE -- the maximimum line length that can be handled. 60 * DEFUPRI -- the default priority for user messages 61 * DEFSPRI -- the default priority for kernel messages 62 * 63 * Author: Eric Allman 64 * extensive changes by Ralph Campbell 65 * more extensive changes by Eric Allman (again) 66 * Extension to log by program name as well as facility and priority 67 * by Peter da Silva. 68 * -U and -v by Harlan Stenn. 69 * Priority comparison code by Harlan Stenn. 70 */ 71 72 #define MAXLINE 1024 /* maximum line length */ 73 #define MAXSVLINE 120 /* maximum saved line length */ 74 #define DEFUPRI (LOG_USER|LOG_NOTICE) 75 #define DEFSPRI (LOG_KERN|LOG_NOTICE) 76 #define TIMERINTVL 30 /* interval for checking flush, mark */ 77 #define TTYMSGTIME 1 /* timeout passed to ttymsg */ 78 79 #include <sys/param.h> 80 #include <sys/socket.h> 81 #include <sys/sysctl.h> 82 #include <sys/types.h> 83 #include <sys/un.h> 84 #include <sys/wait.h> 85 #include <sys/queue.h> 86 #include <sys/event.h> 87 88 #include <netinet/in.h> 89 90 #include <assert.h> 91 #include <ctype.h> 92 #include <errno.h> 93 #include <fcntl.h> 94 #include <grp.h> 95 #include <locale.h> 96 #include <netdb.h> 97 #include <pwd.h> 98 #include <signal.h> 99 #include <stdarg.h> 100 #include <stdio.h> 101 #include <stdlib.h> 102 #include <string.h> 103 #include <unistd.h> 104 #include <util.h> 105 106 #include "utmpentry.h" 107 #include "pathnames.h" 108 109 #define SYSLOG_NAMES 110 #include <sys/syslog.h> 111 112 #ifdef LIBWRAP 113 #include <tcpd.h> 114 115 int allow_severity = LOG_AUTH|LOG_INFO; 116 int deny_severity = LOG_AUTH|LOG_WARNING; 117 #endif 118 119 char *ConfFile = _PATH_LOGCONF; 120 char ctty[] = _PATH_CONSOLE; 121 122 #define FDMASK(fd) (1 << (fd)) 123 124 #define dprintf if (Debug) printf 125 126 #define MAXUNAMES 20 /* maximum number of user names */ 127 128 /* 129 * Flags to logmsg(). 130 */ 131 132 #define IGN_CONS 0x001 /* don't print on console */ 133 #define SYNC_FILE 0x002 /* do fsync on file after printing */ 134 #define ADDDATE 0x004 /* add a date to the message */ 135 #define MARK 0x008 /* this message is a mark */ 136 #define ISKERNEL 0x010 /* kernel generated message */ 137 138 /* 139 * This structure represents the files that will have log 140 * copies printed. 141 * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY, 142 * or if f_type is F_PIPE and f_pid > 0. 143 */ 144 145 struct filed { 146 struct filed *f_next; /* next in linked list */ 147 short f_type; /* entry type, see below */ 148 short f_file; /* file descriptor */ 149 time_t f_time; /* time this was last written */ 150 char *f_host; /* host from which to record */ 151 u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ 152 u_char f_pcmp[LOG_NFACILITIES+1]; /* compare priority */ 153 #define PRI_LT 0x1 154 #define PRI_EQ 0x2 155 #define PRI_GT 0x4 156 char *f_program; /* program this applies to */ 157 union { 158 char f_uname[MAXUNAMES][UT_NAMESIZE+1]; 159 struct { 160 char f_hname[MAXHOSTNAMELEN]; 161 struct addrinfo *f_addr; 162 } f_forw; /* forwarding address */ 163 char f_fname[MAXPATHLEN]; 164 struct { 165 char f_pname[MAXPATHLEN]; 166 pid_t f_pid; 167 } f_pipe; 168 } f_un; 169 char f_prevline[MAXSVLINE]; /* last message logged */ 170 char f_lasttime[16]; /* time of last occurrence */ 171 char f_prevhost[MAXHOSTNAMELEN]; /* host from which recd. */ 172 int f_prevpri; /* pri of f_prevline */ 173 int f_prevlen; /* length of f_prevline */ 174 int f_prevcount; /* repetition cnt of prevline */ 175 int f_repeatcount; /* number of "repeated" msgs */ 176 int f_lasterror; /* last error on writev() */ 177 int f_flags; /* file-specific flags */ 178 #define FFLAG_SYNC 0x01 179 }; 180 181 /* 182 * Queue of about-to-be-dead processes we should watch out for. 183 */ 184 TAILQ_HEAD(, deadq_entry) deadq_head = TAILQ_HEAD_INITIALIZER(deadq_head); 185 186 typedef struct deadq_entry { 187 pid_t dq_pid; 188 int dq_timeout; 189 TAILQ_ENTRY(deadq_entry) dq_entries; 190 } *dq_t; 191 192 /* 193 * The timeout to apply to processes waiting on the dead queue. Unit 194 * of measure is "mark intervals", i.e. 20 minutes by default. 195 * Processes on the dead queue will be terminated after that time. 196 */ 197 #define DQ_TIMO_INIT 2 198 199 /* 200 * Intervals at which we flush out "message repeated" messages, 201 * in seconds after previous message is logged. After each flush, 202 * we move to the next interval until we reach the largest. 203 */ 204 int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ 205 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) 206 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) 207 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \ 208 (f)->f_repeatcount = MAXREPEAT; \ 209 } 210 211 /* values for f_type */ 212 #define F_UNUSED 0 /* unused entry */ 213 #define F_FILE 1 /* regular file */ 214 #define F_TTY 2 /* terminal */ 215 #define F_CONSOLE 3 /* console terminal */ 216 #define F_FORW 4 /* remote machine */ 217 #define F_USERS 5 /* list of users */ 218 #define F_WALL 6 /* everyone logged on */ 219 #define F_PIPE 7 /* pipe to program */ 220 221 char *TypeNames[8] = { 222 "UNUSED", "FILE", "TTY", "CONSOLE", 223 "FORW", "USERS", "WALL", "PIPE" 224 }; 225 226 struct filed *Files; 227 struct filed consfile; 228 229 int Debug; /* debug flag */ 230 int daemonized = 0; /* we are not daemonized yet */ 231 char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ 232 char oldLocalHostName[MAXHOSTNAMELEN];/* previous hostname */ 233 char *LocalDomain; /* our local domain name */ 234 size_t LocalDomainLen; /* length of LocalDomain */ 235 int *finet = NULL; /* Internet datagram sockets */ 236 int Initialized; /* set when we have initialized ourselves */ 237 int ShuttingDown; /* set when we die() */ 238 int MarkInterval = 20 * 60; /* interval between marks in seconds */ 239 int MarkSeq = 0; /* mark sequence number */ 240 int SecureMode = 0; /* listen only on unix domain socks */ 241 int UseNameService = 1; /* make domain name queries */ 242 int NumForwards = 0; /* number of forwarding actions in conf file */ 243 char **LogPaths; /* array of pathnames to read messages from */ 244 int NoRepeat = 0; /* disable "repeated"; log always */ 245 int RemoteAddDate = 0; /* always add date to messages from network */ 246 int SyncKernel = 0; /* write kernel messages synchronously */ 247 int UniquePriority = 0; /* only log specified priority */ 248 int LogFacPri = 0; /* put facility and priority in log messages: */ 249 /* 0=no, 1=numeric, 2=names */ 250 251 void cfline(char *, struct filed *, char *, char *); 252 char *cvthname(struct sockaddr_storage *); 253 void deadq_enter(pid_t, const char *); 254 int deadq_remove(pid_t); 255 int decode(const char *, CODE *); 256 void die(struct kevent *); /* SIGTERM kevent dispatch routine */ 257 void domark(struct kevent *);/* timer kevent dispatch routine */ 258 void fprintlog(struct filed *, int, char *); 259 int getmsgbufsize(void); 260 int* socksetup(int, const char *); 261 void init(struct kevent *); /* SIGHUP kevent dispatch routine */ 262 void logerror(const char *, ...); 263 void logmsg(int, char *, char *, int); 264 void log_deadchild(pid_t, int, const char *); 265 int matches_spec(const char *, const char *, 266 char *(*)(const char *, const char *)); 267 void printline(char *, char *, int); 268 void printsys(char *); 269 int p_open(char *, pid_t *); 270 void trim_localdomain(char *); 271 void reapchild(struct kevent *); /* SIGCHLD kevent dispatch routine */ 272 void usage(void); 273 void wallmsg(struct filed *, struct iovec *, size_t); 274 int main(int, char *[]); 275 void logpath_add(char ***, int *, int *, char *); 276 void logpath_fileadd(char ***, int *, int *, char *); 277 278 static int fkq; 279 280 static struct kevent *allocevchange(void); 281 static int wait_for_events(struct kevent *, size_t); 282 283 static void dispatch_read_klog(struct kevent *); 284 static void dispatch_read_finet(struct kevent *); 285 static void dispatch_read_funix(struct kevent *); 286 287 /* 288 * Global line buffer. Since we only process one event at a time, 289 * a global one will do. 290 */ 291 static char *linebuf; 292 static size_t linebufsize; 293 static const char *bindhostname = NULL; 294 295 #define A_CNT(x) (sizeof((x)) / sizeof((x)[0])) 296 297 int 298 main(int argc, char *argv[]) 299 { 300 int ch, *funix, j, fklog; 301 int funixsize = 0, funixmaxsize = 0; 302 struct kevent events[16]; 303 struct sockaddr_un sunx; 304 char **pp; 305 struct kevent *ev; 306 uid_t uid = 0; 307 gid_t gid = 0; 308 char *user = NULL; 309 char *group = NULL; 310 char *root = "/"; 311 char *endp; 312 struct group *gr; 313 struct passwd *pw; 314 unsigned long l; 315 316 (void)setlocale(LC_ALL, ""); 317 318 while ((ch = getopt(argc, argv, "b:dnsSf:m:p:P:ru:g:t:TUv")) != -1) 319 switch(ch) { 320 case 'b': 321 bindhostname = optarg; 322 break; 323 case 'd': /* debug */ 324 Debug++; 325 break; 326 case 'f': /* configuration file */ 327 ConfFile = optarg; 328 break; 329 case 'g': 330 group = optarg; 331 if (*group == '\0') 332 usage(); 333 break; 334 case 'm': /* mark interval */ 335 MarkInterval = atoi(optarg) * 60; 336 break; 337 case 'n': /* turn off DNS queries */ 338 UseNameService = 0; 339 break; 340 case 'p': /* path */ 341 logpath_add(&LogPaths, &funixsize, 342 &funixmaxsize, optarg); 343 break; 344 case 'P': /* file of paths */ 345 logpath_fileadd(&LogPaths, &funixsize, 346 &funixmaxsize, optarg); 347 break; 348 case 'r': /* disable "repeated" compression */ 349 NoRepeat++; 350 break; 351 case 's': /* no network listen mode */ 352 SecureMode++; 353 break; 354 case 'S': 355 SyncKernel = 1; 356 break; 357 case 't': 358 root = optarg; 359 if (*root == '\0') 360 usage(); 361 break; 362 case 'T': 363 RemoteAddDate = 1; 364 break; 365 case 'u': 366 user = optarg; 367 if (*user == '\0') 368 usage(); 369 break; 370 case 'U': /* only log specified priority */ 371 UniquePriority = 1; 372 break; 373 case 'v': /* log facility and priority */ 374 if (LogFacPri < 2) 375 LogFacPri++; 376 break; 377 default: 378 usage(); 379 } 380 if ((argc -= optind) != 0) 381 usage(); 382 383 setlinebuf(stdout); 384 385 if (user != NULL) { 386 if (isdigit((unsigned char)*user)) { 387 errno = 0; 388 endp = NULL; 389 l = strtoul(user, &endp, 0); 390 if (errno || *endp != '\0') 391 goto getuser; 392 uid = (uid_t)l; 393 if (uid != l) { 394 errno = 0; 395 logerror("UID out of range"); 396 die(NULL); 397 } 398 } else { 399 getuser: 400 if ((pw = getpwnam(user)) != NULL) { 401 uid = pw->pw_uid; 402 } else { 403 errno = 0; 404 logerror("Cannot find user `%s'", user); 405 die(NULL); 406 } 407 } 408 } 409 410 if (group != NULL) { 411 if (isdigit((unsigned char)*group)) { 412 errno = 0; 413 endp = NULL; 414 l = strtoul(group, &endp, 0); 415 if (errno || *endp != '\0') 416 goto getgroup; 417 gid = (gid_t)l; 418 if (gid != l) { 419 errno = 0; 420 logerror("GID out of range"); 421 die(NULL); 422 } 423 } else { 424 getgroup: 425 if ((gr = getgrnam(group)) != NULL) { 426 gid = gr->gr_gid; 427 } else { 428 errno = 0; 429 logerror("Cannot find group `%s'", group); 430 die(NULL); 431 } 432 } 433 } 434 435 if (access(root, F_OK | R_OK)) { 436 logerror("Cannot access `%s'", root); 437 die(NULL); 438 } 439 440 consfile.f_type = F_CONSOLE; 441 (void)strlcpy(consfile.f_un.f_fname, ctty, 442 sizeof(consfile.f_un.f_fname)); 443 linebufsize = getmsgbufsize(); 444 if (linebufsize < MAXLINE) 445 linebufsize = MAXLINE; 446 linebufsize++; 447 linebuf = malloc(linebufsize); 448 if (linebuf == NULL) { 449 logerror("Couldn't allocate line buffer"); 450 die(NULL); 451 } 452 453 #ifndef SUN_LEN 454 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) 455 #endif 456 if (funixsize == 0) 457 logpath_add(&LogPaths, &funixsize, 458 &funixmaxsize, _PATH_LOG); 459 funix = (int *)malloc(sizeof(int) * funixsize); 460 if (funix == NULL) { 461 logerror("Couldn't allocate funix descriptors"); 462 die(NULL); 463 } 464 for (j = 0, pp = LogPaths; *pp; pp++, j++) { 465 dprintf("Making unix dgram socket `%s'\n", *pp); 466 unlink(*pp); 467 memset(&sunx, 0, sizeof(sunx)); 468 sunx.sun_family = AF_LOCAL; 469 (void)strncpy(sunx.sun_path, *pp, sizeof(sunx.sun_path)); 470 funix[j] = socket(AF_LOCAL, SOCK_DGRAM, 0); 471 if (funix[j] < 0 || bind(funix[j], 472 (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 || 473 chmod(*pp, 0666) < 0) { 474 logerror("Cannot create `%s'", *pp); 475 die(NULL); 476 } 477 dprintf("Listening on unix dgram socket `%s'\n", *pp); 478 } 479 480 if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) { 481 dprintf("Can't open `%s' (%d)\n", _PATH_KLOG, errno); 482 } else { 483 dprintf("Listening on kernel log `%s'\n", _PATH_KLOG); 484 } 485 486 /* 487 * All files are open, we can drop privileges and chroot 488 */ 489 dprintf("Attempt to chroot to `%s'\n", root); 490 if (chroot(root)) { 491 logerror("Failed to chroot to `%s'", root); 492 die(NULL); 493 } 494 dprintf("Attempt to set GID/EGID to `%d'\n", gid); 495 if (setgid(gid) || setegid(gid)) { 496 logerror("Failed to set gid to `%d'", gid); 497 die(NULL); 498 } 499 dprintf("Attempt to set UID/EUID to `%d'\n", uid); 500 if (setuid(uid) || seteuid(uid)) { 501 logerror("Failed to set uid to `%d'", uid); 502 die(NULL); 503 } 504 505 /* 506 * We cannot detach from the terminal before we are sure we won't 507 * have a fatal error, because error message would not go to the 508 * terminal and would not be logged because syslogd dies. 509 * All die() calls are behind us, we can call daemon() 510 */ 511 if (!Debug) { 512 (void)daemon(0, 0); 513 daemonized = 1; 514 515 /* tuck my process id away, if i'm not in debug mode */ 516 pidfile(NULL); 517 } 518 519 /* 520 * Create the global kernel event descriptor. 521 * 522 * NOTE: We MUST do this after daemon(), bacause the kqueue() 523 * API dictates that kqueue descriptors are not inherited 524 * across forks (lame!). 525 */ 526 if ((fkq = kqueue()) < 0) { 527 logerror("Cannot create event queue"); 528 die(NULL); /* XXX This error is lost! */ 529 } 530 531 /* 532 * We must read the configuration file for the first time 533 * after the kqueue descriptor is created, because we install 534 * events during this process. 535 */ 536 init(NULL); 537 538 /* 539 * Always exit on SIGTERM. Also exit on SIGINT and SIGQUIT 540 * if we're debugging. 541 */ 542 (void)signal(SIGTERM, SIG_IGN); 543 (void)signal(SIGINT, SIG_IGN); 544 (void)signal(SIGQUIT, SIG_IGN); 545 ev = allocevchange(); 546 EV_SET(ev, SIGTERM, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 547 (intptr_t) die); 548 if (Debug) { 549 ev = allocevchange(); 550 EV_SET(ev, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 551 (intptr_t) die); 552 553 ev = allocevchange(); 554 EV_SET(ev, SIGQUIT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 555 (intptr_t) die); 556 } 557 558 ev = allocevchange(); 559 EV_SET(ev, SIGCHLD, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 560 (intptr_t) reapchild); 561 562 ev = allocevchange(); 563 EV_SET(ev, 0, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 564 TIMERINTVL * 1000 /* seconds -> ms */, (intptr_t) domark); 565 566 (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */ 567 568 /* Re-read configuration on SIGHUP. */ 569 (void) signal(SIGHUP, SIG_IGN); 570 ev = allocevchange(); 571 EV_SET(ev, SIGHUP, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 572 (intptr_t) init); 573 574 if (fklog >= 0) { 575 ev = allocevchange(); 576 EV_SET(ev, fklog, EVFILT_READ, EV_ADD | EV_ENABLE, 577 0, 0, (intptr_t) dispatch_read_klog); 578 } 579 for (j = 0, pp = LogPaths; *pp; pp++, j++) { 580 ev = allocevchange(); 581 EV_SET(ev, funix[j], EVFILT_READ, EV_ADD | EV_ENABLE, 582 0, 0, (intptr_t) dispatch_read_funix); 583 } 584 585 dprintf("Off & running....\n"); 586 587 for (;;) { 588 void (*handler)(struct kevent *); 589 int i, rv; 590 591 rv = wait_for_events(events, A_CNT(events)); 592 if (rv == 0) 593 continue; 594 if (rv < 0) { 595 if (errno != EINTR) 596 logerror("kevent() failed"); 597 continue; 598 } 599 dprintf("Got an event (%d)\n", rv); 600 for (i = 0; i < rv; i++) { 601 handler = (void *) events[i].udata; 602 (*handler)(&events[i]); 603 } 604 } 605 } 606 607 void 608 usage(void) 609 { 610 611 (void)fprintf(stderr, 612 "usage: %s [-dnrSsTUv] [-b bind_address] [-f config_file] [-g group]\n" 613 "\t[-m mark_interval] [-P file_list] [-p log_socket\n" 614 "\t[-p log_socket2 ...]] [-t chroot_dir] [-u user]\n", 615 getprogname()); 616 exit(1); 617 } 618 619 /* 620 * Dispatch routine for reading /dev/klog 621 */ 622 static void 623 dispatch_read_klog(struct kevent *ev) 624 { 625 ssize_t rv; 626 int fd = ev->ident; 627 628 dprintf("Kernel log active\n"); 629 630 rv = read(fd, linebuf, linebufsize - 1); 631 if (rv > 0) { 632 linebuf[rv] = '\0'; 633 printsys(linebuf); 634 } else if (rv < 0 && errno != EINTR) { 635 /* 636 * /dev/klog has croaked. Disable the event 637 * so it won't bother us again. 638 */ 639 struct kevent *cev = allocevchange(); 640 logerror("klog failed"); 641 EV_SET(cev, fd, EVFILT_READ, EV_DISABLE, 642 0, 0, (intptr_t) dispatch_read_klog); 643 } 644 } 645 646 /* 647 * Dispatch routine for reading Unix domain sockets. 648 */ 649 static void 650 dispatch_read_funix(struct kevent *ev) 651 { 652 struct sockaddr_un myname, fromunix; 653 ssize_t rv; 654 socklen_t sunlen; 655 int fd = ev->ident; 656 657 sunlen = sizeof(myname); 658 if (getsockname(fd, (struct sockaddr *)&myname, &sunlen) != 0) { 659 /* 660 * This should never happen, so ensure that it doesn't 661 * happen again. 662 */ 663 struct kevent *cev = allocevchange(); 664 logerror("getsockname() unix failed"); 665 EV_SET(cev, fd, EVFILT_READ, EV_DISABLE, 666 0, 0, (intptr_t) dispatch_read_funix); 667 return; 668 } 669 670 dprintf("Unix socket (%s) active\n", myname.sun_path); 671 672 sunlen = sizeof(fromunix); 673 rv = recvfrom(fd, linebuf, MAXLINE, 0, 674 (struct sockaddr *)&fromunix, &sunlen); 675 if (rv > 0) { 676 linebuf[rv] = '\0'; 677 printline(LocalHostName, linebuf, 0); 678 } else if (rv < 0 && errno != EINTR) { 679 logerror("recvfrom() unix `%s'", myname.sun_path); 680 } 681 } 682 683 /* 684 * Dispatch routine for reading Internet sockets. 685 */ 686 static void 687 dispatch_read_finet(struct kevent *ev) 688 { 689 #ifdef LIBWRAP 690 struct request_info req; 691 #endif 692 struct sockaddr_storage frominet; 693 ssize_t rv; 694 socklen_t len; 695 int fd = ev->ident; 696 int reject = 0; 697 698 dprintf("inet socket active\n"); 699 700 #ifdef LIBWRAP 701 request_init(&req, RQ_DAEMON, "syslogd", RQ_FILE, fd, NULL); 702 fromhost(&req); 703 reject = !hosts_access(&req); 704 if (reject) 705 dprintf("access denied\n"); 706 #endif 707 708 len = sizeof(frominet); 709 rv = recvfrom(fd, linebuf, MAXLINE, 0, 710 (struct sockaddr *)&frominet, &len); 711 if (rv == 0 || (rv < 0 && errno == EINTR)) 712 return; 713 else if (rv < 0) { 714 logerror("recvfrom inet"); 715 return; 716 } 717 718 linebuf[rv] = '\0'; 719 if (!reject) 720 printline(cvthname(&frominet), linebuf, 721 RemoteAddDate ? ADDDATE : 0); 722 } 723 724 /* 725 * given a pointer to an array of char *'s, a pointer to its current 726 * size and current allocated max size, and a new char * to add, add 727 * it, update everything as necessary, possibly allocating a new array 728 */ 729 void 730 logpath_add(char ***lp, int *szp, int *maxszp, char *new) 731 { 732 char **nlp; 733 int newmaxsz; 734 735 dprintf("Adding `%s' to the %p logpath list\n", new, *lp); 736 if (*szp == *maxszp) { 737 if (*maxszp == 0) { 738 newmaxsz = 4; /* start of with enough for now */ 739 *lp = NULL; 740 } else 741 newmaxsz = *maxszp * 2; 742 nlp = realloc(*lp, sizeof(char *) * (newmaxsz + 1)); 743 if (nlp == NULL) { 744 logerror("Couldn't allocate line buffer"); 745 die(NULL); 746 } 747 *lp = nlp; 748 *maxszp = newmaxsz; 749 } 750 if (((*lp)[(*szp)++] = strdup(new)) == NULL) { 751 logerror("Couldn't allocate logpath"); 752 die(NULL); 753 } 754 (*lp)[(*szp)] = NULL; /* always keep it NULL terminated */ 755 } 756 757 /* do a file of log sockets */ 758 void 759 logpath_fileadd(char ***lp, int *szp, int *maxszp, char *file) 760 { 761 FILE *fp; 762 char *line; 763 size_t len; 764 765 fp = fopen(file, "r"); 766 if (fp == NULL) { 767 logerror("Could not open socket file list `%s'", file); 768 die(NULL); 769 } 770 771 while ((line = fgetln(fp, &len))) { 772 line[len - 1] = 0; 773 logpath_add(lp, szp, maxszp, line); 774 } 775 fclose(fp); 776 } 777 778 /* 779 * Take a raw input line, decode the message, and print the message 780 * on the appropriate log files. 781 */ 782 void 783 printline(char *hname, char *msg, int flags) 784 { 785 int c, pri; 786 char *p, *q, line[MAXLINE + 1]; 787 long n; 788 789 /* test for special codes */ 790 pri = DEFUPRI; 791 p = msg; 792 if (*p == '<') { 793 errno = 0; 794 n = strtol(p + 1, &q, 10); 795 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 796 p = q + 1; 797 pri = (int)n; 798 } 799 } 800 if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) 801 pri = DEFUPRI; 802 803 /* 804 * Don't allow users to log kernel messages. 805 * NOTE: Since LOG_KERN == 0, this will also match 806 * messages with no facility specified. 807 */ 808 if ((pri & LOG_FACMASK) == LOG_KERN) 809 pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); 810 811 q = line; 812 813 while ((c = *p++) != '\0' && 814 q < &line[sizeof(line) - 2]) { 815 c &= 0177; 816 if (iscntrl(c)) 817 if (c == '\n') 818 *q++ = ' '; 819 else if (c == '\t') 820 *q++ = '\t'; 821 else { 822 *q++ = '^'; 823 *q++ = c ^ 0100; 824 } 825 else 826 *q++ = c; 827 } 828 *q = '\0'; 829 830 logmsg(pri, line, hname, flags); 831 } 832 833 /* 834 * Take a raw input line from /dev/klog, split and format similar to syslog(). 835 */ 836 void 837 printsys(char *msg) 838 { 839 int n, pri, flags, is_printf; 840 char *p, *q; 841 842 for (p = msg; *p != '\0'; ) { 843 flags = ISKERNEL | ADDDATE; 844 if (SyncKernel) 845 flags |= SYNC_FILE; 846 pri = DEFSPRI; 847 is_printf = 1; 848 if (*p == '<') { 849 errno = 0; 850 n = (int)strtol(p + 1, &q, 10); 851 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 852 p = q + 1; 853 pri = n; 854 is_printf = 0; 855 } 856 } 857 if (is_printf) { 858 /* kernel printf's come out on console */ 859 flags |= IGN_CONS; 860 } 861 if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) 862 pri = DEFSPRI; 863 for (q = p; *q != '\0' && *q != '\n'; q++) 864 /* look for end of line */; 865 if (*q != '\0') 866 *q++ = '\0'; 867 logmsg(pri, p, LocalHostName, flags); 868 p = q; 869 } 870 } 871 872 time_t now; 873 874 /* 875 * Check to see if `name' matches the provided specification, using the 876 * specified strstr function. 877 */ 878 int 879 matches_spec(const char *name, const char *spec, 880 char *(*check)(const char *, const char *)) 881 { 882 const char *s; 883 const char *cursor; 884 char prev, next; 885 size_t len; 886 887 if (name[0] == '\0') 888 return (0); 889 890 if (strchr(name, ',')) /* sanity */ 891 return (0); 892 893 len = strlen(name); 894 cursor = spec; 895 while ((s = (*check)(cursor, name)) != NULL) { 896 prev = s == spec ? ',' : *(s - 1); 897 cursor = s + len; 898 next = *cursor; 899 900 if (prev == ',' && (next == '\0' || next == ',')) 901 return (1); 902 } 903 904 return (0); 905 } 906 907 /* 908 * Log a message to the appropriate log files, users, etc. based on 909 * the priority. 910 */ 911 void 912 logmsg(int pri, char *msg, char *from, int flags) 913 { 914 struct filed *f; 915 int fac, msglen, omask, prilev, i; 916 char *timestamp; 917 char prog[NAME_MAX + 1]; 918 char buf[MAXLINE + 1]; 919 920 dprintf("logmsg: pri 0%o, flags 0x%x, from %s, msg %s\n", 921 pri, flags, from, msg); 922 923 omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); 924 925 /* 926 * Check to see if msg looks non-standard. 927 */ 928 msglen = strlen(msg); 929 if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || 930 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') 931 flags |= ADDDATE; 932 933 (void)time(&now); 934 if (flags & ADDDATE) 935 timestamp = ctime(&now) + 4; 936 else { 937 timestamp = msg; 938 msg += 16; 939 msglen -= 16; 940 } 941 942 /* skip leading whitespace */ 943 while (isspace((unsigned char)*msg)) { 944 msg++; 945 msglen--; 946 } 947 948 /* extract facility and priority level */ 949 if (flags & MARK) 950 fac = LOG_NFACILITIES; 951 else 952 fac = LOG_FAC(pri); 953 prilev = LOG_PRI(pri); 954 955 /* extract program name */ 956 for (i = 0; i < NAME_MAX; i++) { 957 if (!isprint((unsigned char)msg[i]) || 958 msg[i] == ':' || msg[i] == '[') 959 break; 960 prog[i] = msg[i]; 961 } 962 prog[i] = '\0'; 963 964 /* add kernel prefix for kernel messages */ 965 if (flags & ISKERNEL) { 966 snprintf(buf, sizeof(buf), "%s: %s", 967 _PATH_UNIX, msg); 968 msg = buf; 969 msglen = strlen(buf); 970 } 971 972 /* log the message to the particular outputs */ 973 if (!Initialized) { 974 f = &consfile; 975 f->f_file = open(ctty, O_WRONLY, 0); 976 977 if (f->f_file >= 0) { 978 (void)strncpy(f->f_lasttime, timestamp, 15); 979 fprintlog(f, flags, msg); 980 (void)close(f->f_file); 981 } 982 (void)sigsetmask(omask); 983 return; 984 } 985 for (f = Files; f; f = f->f_next) { 986 /* skip messages that are incorrect priority */ 987 if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev)) 988 ||((f->f_pcmp[fac] & PRI_LT) && (f->f_pmask[fac] < prilev)) 989 ||((f->f_pcmp[fac] & PRI_GT) && (f->f_pmask[fac] > prilev)) 990 ) 991 || f->f_pmask[fac] == INTERNAL_NOPRI) 992 continue; 993 994 /* skip messages with the incorrect host name */ 995 if (f->f_host != NULL) { 996 switch (f->f_host[0]) { 997 case '+': 998 if (! matches_spec(from, f->f_host + 1, 999 strcasestr)) 1000 continue; 1001 break; 1002 case '-': 1003 if (matches_spec(from, f->f_host + 1, 1004 strcasestr)) 1005 continue; 1006 break; 1007 } 1008 } 1009 1010 /* skip messages with the incorrect program name */ 1011 if (f->f_program != NULL) { 1012 switch (f->f_program[0]) { 1013 case '+': 1014 if (! matches_spec(prog, f->f_program + 1, 1015 strstr)) 1016 continue; 1017 break; 1018 case '-': 1019 if (matches_spec(prog, f->f_program + 1, 1020 strstr)) 1021 continue; 1022 break; 1023 default: 1024 if (! matches_spec(prog, f->f_program, 1025 strstr)) 1026 continue; 1027 break; 1028 } 1029 } 1030 1031 if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) 1032 continue; 1033 1034 /* don't output marks to recently written files */ 1035 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2) 1036 continue; 1037 1038 /* 1039 * suppress duplicate lines to this file unless NoRepeat 1040 */ 1041 if ((flags & MARK) == 0 && msglen == f->f_prevlen && 1042 !NoRepeat && 1043 !strcmp(msg, f->f_prevline) && 1044 !strcasecmp(from, f->f_prevhost)) { 1045 (void)strncpy(f->f_lasttime, timestamp, 15); 1046 f->f_prevcount++; 1047 dprintf("Msg repeated %d times, %ld sec of %d\n", 1048 f->f_prevcount, (long)(now - f->f_time), 1049 repeatinterval[f->f_repeatcount]); 1050 /* 1051 * If domark would have logged this by now, 1052 * flush it now (so we don't hold isolated messages), 1053 * but back off so we'll flush less often 1054 * in the future. 1055 */ 1056 if (now > REPEATTIME(f)) { 1057 fprintlog(f, flags, (char *)NULL); 1058 BACKOFF(f); 1059 } 1060 } else { 1061 /* new line, save it */ 1062 if (f->f_prevcount) 1063 fprintlog(f, 0, (char *)NULL); 1064 f->f_repeatcount = 0; 1065 f->f_prevpri = pri; 1066 (void)strncpy(f->f_lasttime, timestamp, 15); 1067 (void)strncpy(f->f_prevhost, from, 1068 sizeof(f->f_prevhost)); 1069 if (msglen < MAXSVLINE) { 1070 f->f_prevlen = msglen; 1071 (void)strlcpy(f->f_prevline, msg, 1072 sizeof(f->f_prevline)); 1073 fprintlog(f, flags, (char *)NULL); 1074 } else { 1075 f->f_prevline[0] = 0; 1076 f->f_prevlen = 0; 1077 fprintlog(f, flags, msg); 1078 } 1079 } 1080 } 1081 (void)sigsetmask(omask); 1082 } 1083 1084 void 1085 fprintlog(struct filed *f, int flags, char *msg) 1086 { 1087 struct iovec iov[10]; 1088 struct iovec *v; 1089 struct addrinfo *r; 1090 int j, l, lsent, fail, retry; 1091 char line[MAXLINE + 1], repbuf[80], greetings[200]; 1092 #define ADDEV() assert(++v - iov < A_CNT(iov)) 1093 1094 v = iov; 1095 if (f->f_type == F_WALL) { 1096 v->iov_base = greetings; 1097 v->iov_len = snprintf(greetings, sizeof greetings, 1098 "\r\n\7Message from syslogd@%s at %.24s ...\r\n", 1099 f->f_prevhost, ctime(&now)); 1100 ADDEV(); 1101 v->iov_base = ""; 1102 v->iov_len = 0; 1103 ADDEV(); 1104 } else { 1105 v->iov_base = f->f_lasttime; 1106 v->iov_len = 15; 1107 ADDEV(); 1108 v->iov_base = " "; 1109 v->iov_len = 1; 1110 ADDEV(); 1111 } 1112 1113 if (LogFacPri) { 1114 static char fp_buf[30]; 1115 const char *f_s = NULL, *p_s = NULL; 1116 int fac = f->f_prevpri & LOG_FACMASK; 1117 int pri = LOG_PRI(f->f_prevpri); 1118 char f_n[5], p_n[5]; 1119 1120 if (LogFacPri > 1) { 1121 CODE *c; 1122 1123 for (c = facilitynames; c->c_name != NULL; c++) { 1124 if (c->c_val == fac) { 1125 f_s = c->c_name; 1126 break; 1127 } 1128 } 1129 for (c = prioritynames; c->c_name != NULL; c++) { 1130 if (c->c_val == pri) { 1131 p_s = c->c_name; 1132 break; 1133 } 1134 } 1135 } 1136 if (f_s == NULL) { 1137 snprintf(f_n, sizeof(f_n), "%d", LOG_FAC(fac)); 1138 f_s = f_n; 1139 } 1140 if (p_s == NULL) { 1141 snprintf(p_n, sizeof(p_n), "%d", pri); 1142 p_s = p_n; 1143 } 1144 snprintf(fp_buf, sizeof(fp_buf), "<%s.%s>", f_s, p_s); 1145 v->iov_base = fp_buf; 1146 v->iov_len = strlen(fp_buf); 1147 } else { 1148 v->iov_base = ""; 1149 v->iov_len = 0; 1150 } 1151 ADDEV(); 1152 1153 v->iov_base = f->f_prevhost; 1154 v->iov_len = strlen(v->iov_base); 1155 ADDEV(); 1156 v->iov_base = " "; 1157 v->iov_len = 1; 1158 ADDEV(); 1159 1160 if (msg) { 1161 v->iov_base = msg; 1162 v->iov_len = strlen(msg); 1163 } else if (f->f_prevcount > 1) { 1164 v->iov_base = repbuf; 1165 v->iov_len = snprintf(repbuf, sizeof repbuf, 1166 "last message repeated %d times", f->f_prevcount); 1167 } else { 1168 v->iov_base = f->f_prevline; 1169 v->iov_len = f->f_prevlen; 1170 } 1171 ADDEV(); 1172 1173 dprintf("Logging to %s", TypeNames[f->f_type]); 1174 f->f_time = now; 1175 1176 switch (f->f_type) { 1177 case F_UNUSED: 1178 dprintf("\n"); 1179 break; 1180 1181 case F_FORW: 1182 dprintf(" %s\n", f->f_un.f_forw.f_hname); 1183 /* 1184 * check for local vs remote messages 1185 * (from FreeBSD PR#bin/7055) 1186 */ 1187 if (strcasecmp(f->f_prevhost, LocalHostName)) { 1188 l = snprintf(line, sizeof(line) - 1, 1189 "<%d>%.15s [%s]: %s", 1190 f->f_prevpri, (char *) iov[0].iov_base, 1191 f->f_prevhost, (char *) iov[5].iov_base); 1192 } else { 1193 l = snprintf(line, sizeof(line) - 1, "<%d>%.15s %s", 1194 f->f_prevpri, (char *) iov[0].iov_base, 1195 (char *) iov[5].iov_base); 1196 } 1197 if (l > MAXLINE) 1198 l = MAXLINE; 1199 if (finet) { 1200 lsent = -1; 1201 fail = 0; 1202 for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) { 1203 retry = 0; 1204 for (j = 0; j < *finet; j++) { 1205 #if 0 1206 /* 1207 * should we check AF first, or just 1208 * trial and error? FWD 1209 */ 1210 if (r->ai_family == 1211 address_family_of(finet[j+1])) 1212 #endif 1213 sendagain: 1214 lsent = sendto(finet[j+1], line, l, 0, 1215 r->ai_addr, r->ai_addrlen); 1216 if (lsent == -1) { 1217 switch (errno) { 1218 case ENOBUFS: 1219 /* wait/retry/drop */ 1220 if (++retry < 5) { 1221 usleep(1000); 1222 goto sendagain; 1223 } 1224 break; 1225 case EHOSTDOWN: 1226 case EHOSTUNREACH: 1227 case ENETDOWN: 1228 /* drop */ 1229 break; 1230 default: 1231 /* busted */ 1232 fail++; 1233 break; 1234 } 1235 } else if (lsent == l) 1236 break; 1237 } 1238 } 1239 if (lsent != l && fail) { 1240 f->f_type = F_UNUSED; 1241 logerror("sendto() failed"); 1242 } 1243 } 1244 break; 1245 1246 case F_PIPE: 1247 dprintf(" %s\n", f->f_un.f_pipe.f_pname); 1248 v->iov_base = "\n"; 1249 v->iov_len = 1; 1250 ADDEV(); 1251 if (f->f_un.f_pipe.f_pid == 0) { 1252 if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, 1253 &f->f_un.f_pipe.f_pid)) < 0) { 1254 f->f_type = F_UNUSED; 1255 logerror(f->f_un.f_pipe.f_pname); 1256 break; 1257 } 1258 } 1259 if (writev(f->f_file, iov, v - iov) < 0) { 1260 int e = errno; 1261 if (f->f_un.f_pipe.f_pid > 0) { 1262 (void) close(f->f_file); 1263 deadq_enter(f->f_un.f_pipe.f_pid, 1264 f->f_un.f_pipe.f_pname); 1265 } 1266 f->f_un.f_pipe.f_pid = 0; 1267 /* 1268 * If the error was EPIPE, then what is likely 1269 * has happened is we have a command that is 1270 * designed to take a single message line and 1271 * then exit, but we tried to feed it another 1272 * one before we reaped the child and thus 1273 * reset our state. 1274 * 1275 * Well, now we've reset our state, so try opening 1276 * the pipe and sending the message again if EPIPE 1277 * was the error. 1278 */ 1279 if (e == EPIPE) { 1280 if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, 1281 &f->f_un.f_pipe.f_pid)) < 0) { 1282 f->f_type = F_UNUSED; 1283 logerror(f->f_un.f_pipe.f_pname); 1284 break; 1285 } 1286 if (writev(f->f_file, iov, v - iov) < 0) { 1287 e = errno; 1288 if (f->f_un.f_pipe.f_pid > 0) { 1289 (void) close(f->f_file); 1290 deadq_enter(f->f_un.f_pipe.f_pid, 1291 f->f_un.f_pipe.f_pname); 1292 } 1293 f->f_un.f_pipe.f_pid = 0; 1294 } else 1295 e = 0; 1296 } 1297 if (e != 0) { 1298 errno = e; 1299 logerror(f->f_un.f_pipe.f_pname); 1300 } 1301 } 1302 break; 1303 1304 case F_CONSOLE: 1305 if (flags & IGN_CONS) { 1306 dprintf(" (ignored)\n"); 1307 break; 1308 } 1309 /* FALLTHROUGH */ 1310 1311 case F_TTY: 1312 case F_FILE: 1313 dprintf(" %s\n", f->f_un.f_fname); 1314 if (f->f_type != F_FILE) { 1315 v->iov_base = "\r\n"; 1316 v->iov_len = 2; 1317 } else { 1318 v->iov_base = "\n"; 1319 v->iov_len = 1; 1320 } 1321 ADDEV(); 1322 again: 1323 if (writev(f->f_file, iov, v - iov) < 0) { 1324 int e = errno; 1325 if (f->f_type == F_FILE && e == ENOSPC) { 1326 int lasterror = f->f_lasterror; 1327 f->f_lasterror = e; 1328 if (lasterror != e) 1329 logerror(f->f_un.f_fname); 1330 break; 1331 } 1332 (void)close(f->f_file); 1333 /* 1334 * Check for errors on TTY's due to loss of tty 1335 */ 1336 if ((e == EIO || e == EBADF) && f->f_type != F_FILE) { 1337 f->f_file = open(f->f_un.f_fname, 1338 O_WRONLY|O_APPEND, 0); 1339 if (f->f_file < 0) { 1340 f->f_type = F_UNUSED; 1341 logerror(f->f_un.f_fname); 1342 } else 1343 goto again; 1344 } else { 1345 f->f_type = F_UNUSED; 1346 errno = e; 1347 f->f_lasterror = e; 1348 logerror(f->f_un.f_fname); 1349 } 1350 } else { 1351 f->f_lasterror = 0; 1352 if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) 1353 (void)fsync(f->f_file); 1354 } 1355 break; 1356 1357 case F_USERS: 1358 case F_WALL: 1359 dprintf("\n"); 1360 v->iov_base = "\r\n"; 1361 v->iov_len = 2; 1362 ADDEV(); 1363 wallmsg(f, iov, v - iov); 1364 break; 1365 } 1366 f->f_prevcount = 0; 1367 } 1368 1369 /* 1370 * WALLMSG -- Write a message to the world at large 1371 * 1372 * Write the specified message to either the entire 1373 * world, or a list of approved users. 1374 */ 1375 void 1376 wallmsg(struct filed *f, struct iovec *iov, size_t iovcnt) 1377 { 1378 static int reenter; /* avoid calling ourselves */ 1379 int i; 1380 char *p; 1381 static struct utmpentry *ohead = NULL; 1382 struct utmpentry *ep; 1383 1384 if (reenter++) 1385 return; 1386 1387 (void)getutentries(NULL, &ep); 1388 if (ep != ohead) { 1389 freeutentries(ohead); 1390 ohead = ep; 1391 } 1392 /* NOSTRICT */ 1393 for (; ep; ep = ep->next) { 1394 if (f->f_type == F_WALL) { 1395 if ((p = ttymsg(iov, iovcnt, ep->line, TTYMSGTIME)) 1396 != NULL) { 1397 errno = 0; /* already in msg */ 1398 logerror(p); 1399 } 1400 continue; 1401 } 1402 /* should we send the message to this user? */ 1403 for (i = 0; i < MAXUNAMES; i++) { 1404 if (!f->f_un.f_uname[i][0]) 1405 break; 1406 if (strcmp(f->f_un.f_uname[i], ep->name) == 0) { 1407 if ((p = ttymsg(iov, iovcnt, ep->line, 1408 TTYMSGTIME)) != NULL) { 1409 errno = 0; /* already in msg */ 1410 logerror(p); 1411 } 1412 break; 1413 } 1414 } 1415 } 1416 reenter = 0; 1417 } 1418 1419 void 1420 reapchild(struct kevent *ev) 1421 { 1422 int status; 1423 pid_t pid; 1424 struct filed *f; 1425 1426 while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { 1427 if (!Initialized || ShuttingDown) { 1428 /* 1429 * Be silent while we are initializing or 1430 * shutting down. 1431 */ 1432 continue; 1433 } 1434 1435 if (deadq_remove(pid)) 1436 continue; 1437 1438 /* Now, look in the list of active processes. */ 1439 for (f = Files; f != NULL; f = f->f_next) { 1440 if (f->f_type == F_PIPE && 1441 f->f_un.f_pipe.f_pid == pid) { 1442 (void) close(f->f_file); 1443 f->f_un.f_pipe.f_pid = 0; 1444 log_deadchild(pid, status, 1445 f->f_un.f_pipe.f_pname); 1446 break; 1447 } 1448 } 1449 } 1450 } 1451 1452 /* 1453 * Return a printable representation of a host address. 1454 */ 1455 char * 1456 cvthname(struct sockaddr_storage *f) 1457 { 1458 int error; 1459 const int niflag = NI_DGRAM; 1460 static char host[NI_MAXHOST], ip[NI_MAXHOST]; 1461 1462 error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, 1463 ip, sizeof ip, NULL, 0, NI_NUMERICHOST|niflag); 1464 1465 dprintf("cvthname(%s)\n", ip); 1466 1467 if (error) { 1468 dprintf("Malformed from address %s\n", gai_strerror(error)); 1469 return ("???"); 1470 } 1471 1472 if (!UseNameService) 1473 return (ip); 1474 1475 error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, 1476 host, sizeof host, NULL, 0, niflag); 1477 if (error) { 1478 dprintf("Host name for your address (%s) unknown\n", ip); 1479 return (ip); 1480 } 1481 1482 trim_localdomain(host); 1483 1484 return (host); 1485 } 1486 1487 void 1488 trim_localdomain(char *host) 1489 { 1490 size_t hl; 1491 1492 hl = strlen(host); 1493 if (hl > 0 && host[hl - 1] == '.') 1494 host[--hl] = '\0'; 1495 1496 if (hl > LocalDomainLen && host[hl - LocalDomainLen - 1] == '.' && 1497 strcasecmp(&host[hl - LocalDomainLen], LocalDomain) == 0) 1498 host[hl - LocalDomainLen - 1] = '\0'; 1499 } 1500 1501 void 1502 domark(struct kevent *ev) 1503 { 1504 struct filed *f; 1505 dq_t q, nextq; 1506 1507 /* 1508 * XXX Should we bother to adjust for the # of times the timer 1509 * has expired (i.e. in case we miss one?). This information is 1510 * returned to us in ev->data. 1511 */ 1512 1513 now = time((time_t *)NULL); 1514 MarkSeq += TIMERINTVL; 1515 if (MarkSeq >= MarkInterval) { 1516 logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK); 1517 MarkSeq = 0; 1518 } 1519 1520 for (f = Files; f; f = f->f_next) { 1521 if (f->f_prevcount && now >= REPEATTIME(f)) { 1522 dprintf("Flush %s: repeated %d times, %d sec.\n", 1523 TypeNames[f->f_type], f->f_prevcount, 1524 repeatinterval[f->f_repeatcount]); 1525 fprintlog(f, 0, (char *)NULL); 1526 BACKOFF(f); 1527 } 1528 } 1529 1530 /* Walk the dead queue, and see if we should signal somebody. */ 1531 for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = nextq) { 1532 nextq = TAILQ_NEXT(q, dq_entries); 1533 switch (q->dq_timeout) { 1534 case 0: 1535 /* Already signalled once, try harder now. */ 1536 if (kill(q->dq_pid, SIGKILL) != 0) 1537 (void) deadq_remove(q->dq_pid); 1538 break; 1539 1540 case 1: 1541 /* 1542 * Timed out on the dead queue, send terminate 1543 * signal. Note that we leave the removal from 1544 * the dead queue to reapchild(), which will 1545 * also log the event (unless the process 1546 * didn't even really exist, in case we simply 1547 * drop it from the dead queue). 1548 */ 1549 if (kill(q->dq_pid, SIGTERM) != 0) { 1550 (void) deadq_remove(q->dq_pid); 1551 break; 1552 } 1553 /* FALLTHROUGH */ 1554 1555 default: 1556 q->dq_timeout--; 1557 } 1558 } 1559 } 1560 1561 /* 1562 * Print syslogd errors some place. 1563 */ 1564 void 1565 logerror(const char *fmt, ...) 1566 { 1567 static int logerror_running; 1568 va_list ap; 1569 char tmpbuf[BUFSIZ]; 1570 char buf[BUFSIZ]; 1571 1572 /* If there's an error while trying to log an error, give up. */ 1573 if (logerror_running) 1574 return; 1575 logerror_running = 1; 1576 1577 va_start(ap, fmt); 1578 1579 (void)vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, ap); 1580 1581 va_end(ap); 1582 1583 if (errno) 1584 (void)snprintf(buf, sizeof(buf), "syslogd: %s: %s", 1585 tmpbuf, strerror(errno)); 1586 else 1587 (void)snprintf(buf, sizeof(buf), "syslogd: %s", tmpbuf); 1588 1589 if (daemonized) 1590 logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); 1591 if (!daemonized && Debug) 1592 dprintf("%s\n", buf); 1593 if (!daemonized && !Debug) 1594 printf("%s\n", buf); 1595 1596 logerror_running = 0; 1597 } 1598 1599 void 1600 die(struct kevent *ev) 1601 { 1602 struct filed *f; 1603 char **p; 1604 1605 ShuttingDown = 1; /* Don't log SIGCHLDs. */ 1606 for (f = Files; f != NULL; f = f->f_next) { 1607 /* flush any pending output */ 1608 if (f->f_prevcount) 1609 fprintlog(f, 0, (char *)NULL); 1610 if (f->f_type == F_PIPE && f->f_un.f_pipe.f_pid > 0) { 1611 (void) close(f->f_file); 1612 f->f_un.f_pipe.f_pid = 0; 1613 } 1614 } 1615 errno = 0; 1616 if (ev != NULL) 1617 logerror("Exiting on signal %d", (int) ev->ident); 1618 else 1619 logerror("Fatal error, exiting"); 1620 for (p = LogPaths; p && *p; p++) 1621 unlink(*p); 1622 exit(0); 1623 } 1624 1625 /* 1626 * INIT -- Initialize syslogd from configuration table 1627 */ 1628 void 1629 init(struct kevent *ev) 1630 { 1631 size_t i; 1632 FILE *cf; 1633 struct filed *f, *next, **nextp; 1634 char *p; 1635 char cline[LINE_MAX]; 1636 char prog[NAME_MAX + 1]; 1637 char host[MAXHOSTNAMELEN]; 1638 char hostMsg[2*MAXHOSTNAMELEN + 40]; 1639 1640 dprintf("init\n"); 1641 1642 (void)strlcpy(oldLocalHostName, LocalHostName, 1643 sizeof(oldLocalHostName)); 1644 (void)gethostname(LocalHostName, sizeof(LocalHostName)); 1645 if ((p = strchr(LocalHostName, '.')) != NULL) { 1646 *p++ = '\0'; 1647 LocalDomain = p; 1648 } else 1649 LocalDomain = ""; 1650 LocalDomainLen = strlen(LocalDomain); 1651 1652 /* 1653 * Close all open log files. 1654 */ 1655 Initialized = 0; 1656 for (f = Files; f != NULL; f = next) { 1657 /* flush any pending output */ 1658 if (f->f_prevcount) 1659 fprintlog(f, 0, (char *)NULL); 1660 1661 switch (f->f_type) { 1662 case F_FILE: 1663 case F_TTY: 1664 case F_CONSOLE: 1665 (void)close(f->f_file); 1666 break; 1667 case F_PIPE: 1668 if (f->f_un.f_pipe.f_pid > 0) { 1669 (void)close(f->f_file); 1670 deadq_enter(f->f_un.f_pipe.f_pid, 1671 f->f_un.f_pipe.f_pname); 1672 } 1673 f->f_un.f_pipe.f_pid = 0; 1674 break; 1675 case F_FORW: 1676 if (f->f_un.f_forw.f_addr) 1677 freeaddrinfo(f->f_un.f_forw.f_addr); 1678 break; 1679 } 1680 next = f->f_next; 1681 if (f->f_program != NULL) 1682 free(f->f_program); 1683 if (f->f_host != NULL) 1684 free(f->f_host); 1685 free((char *)f); 1686 } 1687 Files = NULL; 1688 nextp = &Files; 1689 1690 /* 1691 * Close all open sockets 1692 */ 1693 1694 if (finet) { 1695 for (i = 0; i < *finet; i++) { 1696 if (close(finet[i+1]) < 0) { 1697 logerror("close() failed"); 1698 die(NULL); 1699 } 1700 } 1701 } 1702 1703 /* 1704 * Reset counter of forwarding actions 1705 */ 1706 1707 NumForwards=0; 1708 1709 /* open the configuration file */ 1710 if ((cf = fopen(ConfFile, "r")) == NULL) { 1711 dprintf("Cannot open `%s'\n", ConfFile); 1712 *nextp = (struct filed *)calloc(1, sizeof(*f)); 1713 cfline("*.ERR\t/dev/console", *nextp, "*", "*"); 1714 (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)); 1715 cfline("*.PANIC\t*", (*nextp)->f_next, "*", "*"); 1716 Initialized = 1; 1717 return; 1718 } 1719 1720 /* 1721 * Foreach line in the conf table, open that file. 1722 */ 1723 f = NULL; 1724 strcpy(prog, "*"); 1725 strcpy(host, "*"); 1726 while (fgets(cline, sizeof(cline), cf) != NULL) { 1727 /* 1728 * check for end-of-section, comments, strip off trailing 1729 * spaces and newline character. #!prog is treated specially: 1730 * following lines apply only to that program. 1731 */ 1732 for (p = cline; isspace((unsigned char)*p); ++p) 1733 continue; 1734 if (*p == '\0') 1735 continue; 1736 if (*p == '#') { 1737 p++; 1738 if (*p != '!' && *p != '+' && *p != '-') 1739 continue; 1740 } 1741 if (*p == '+' || *p == '-') { 1742 host[0] = *p++; 1743 while (isspace((unsigned char)*p)) 1744 p++; 1745 if (*p == '\0' || *p == '*') { 1746 strcpy(host, "*"); 1747 continue; 1748 } 1749 for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { 1750 if (*p == '@') { 1751 (void)strncpy(&host[i], LocalHostName, 1752 sizeof(host) - 1 - i); 1753 host[sizeof(host) - 1] = '\0'; 1754 i = strlen(host) - 1; 1755 p++; 1756 continue; 1757 } 1758 if (!isalnum((unsigned char)*p) && 1759 *p != '.' && *p != '-' && *p != ',') 1760 break; 1761 host[i] = *p++; 1762 } 1763 host[i] = '\0'; 1764 continue; 1765 } 1766 if (*p == '!') { 1767 p++; 1768 while (isspace((unsigned char)*p)) 1769 p++; 1770 if (*p == '\0' || *p == '*') { 1771 strcpy(prog, "*"); 1772 continue; 1773 } 1774 for (i = 0; i < NAME_MAX; i++) { 1775 if (!isprint((unsigned char)p[i])) 1776 break; 1777 prog[i] = p[i]; 1778 } 1779 prog[i] = '\0'; 1780 continue; 1781 } 1782 for (p = strchr(cline, '\0'); isspace((unsigned char)*--p);) 1783 continue; 1784 *++p = '\0'; 1785 f = (struct filed *)calloc(1, sizeof(*f)); 1786 *nextp = f; 1787 nextp = &f->f_next; 1788 cfline(cline, f, prog, host); 1789 } 1790 1791 /* close the configuration file */ 1792 (void)fclose(cf); 1793 1794 Initialized = 1; 1795 1796 if (Debug) { 1797 for (f = Files; f; f = f->f_next) { 1798 for (i = 0; i <= LOG_NFACILITIES; i++) 1799 if (f->f_pmask[i] == INTERNAL_NOPRI) 1800 printf("X "); 1801 else 1802 printf("%d ", f->f_pmask[i]); 1803 printf("%s: ", TypeNames[f->f_type]); 1804 switch (f->f_type) { 1805 case F_FILE: 1806 case F_TTY: 1807 case F_CONSOLE: 1808 printf("%s", f->f_un.f_fname); 1809 break; 1810 1811 case F_FORW: 1812 printf("%s", f->f_un.f_forw.f_hname); 1813 break; 1814 1815 case F_PIPE: 1816 printf("%s", f->f_un.f_pipe.f_pname); 1817 break; 1818 1819 case F_USERS: 1820 for (i = 0; 1821 i < MAXUNAMES && *f->f_un.f_uname[i]; i++) 1822 printf("%s, ", f->f_un.f_uname[i]); 1823 break; 1824 } 1825 if (f->f_program != NULL) 1826 printf(" (%s)", f->f_program); 1827 printf("\n"); 1828 } 1829 } 1830 1831 finet = socksetup(PF_UNSPEC, bindhostname); 1832 if (finet) { 1833 if (SecureMode) { 1834 for (i = 0; i < *finet; i++) { 1835 if (shutdown(finet[i+1], SHUT_RD) < 0) { 1836 logerror("shutdown() failed"); 1837 die(NULL); 1838 } 1839 } 1840 } else 1841 dprintf("Listening on inet and/or inet6 socket\n"); 1842 dprintf("Sending on inet and/or inet6 socket\n"); 1843 } 1844 1845 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); 1846 dprintf("syslogd: restarted\n"); 1847 /* 1848 * Log a change in hostname, but only on a restart (we detect this 1849 * by checking to see if we're passed a kevent). 1850 */ 1851 if (ev != NULL && strcmp(oldLocalHostName, LocalHostName) != 0) { 1852 (void)snprintf(hostMsg, sizeof(hostMsg), 1853 "syslogd: host name changed, \"%s\" to \"%s\"", 1854 oldLocalHostName, LocalHostName); 1855 logmsg(LOG_SYSLOG|LOG_INFO, hostMsg, LocalHostName, ADDDATE); 1856 dprintf("%s\n", hostMsg); 1857 } 1858 } 1859 1860 /* 1861 * Crack a configuration file line 1862 */ 1863 void 1864 cfline(char *line, struct filed *f, char *prog, char *host) 1865 { 1866 struct addrinfo hints, *res; 1867 int error, i, pri, syncfile; 1868 char *bp, *p, *q; 1869 char buf[MAXLINE]; 1870 1871 dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host); 1872 1873 errno = 0; /* keep strerror() stuff out of logerror messages */ 1874 1875 /* clear out file entry */ 1876 memset(f, 0, sizeof(*f)); 1877 for (i = 0; i <= LOG_NFACILITIES; i++) 1878 f->f_pmask[i] = INTERNAL_NOPRI; 1879 1880 /* 1881 * There should not be any space before the log facility. 1882 * Check this is okay, complain and fix if it is not. 1883 */ 1884 q = line; 1885 if (isblank((unsigned char)*line)) { 1886 errno = 0; 1887 logerror( 1888 "Warning: `%s' space or tab before the log facility", 1889 line); 1890 /* Fix: strip all spaces/tabs before the log facility */ 1891 while (*q++ && isblank((unsigned char)*q)) 1892 /* skip blanks */; 1893 line = q; 1894 } 1895 1896 /* 1897 * q is now at the first char of the log facility 1898 * There should be at least one tab after the log facility 1899 * Check this is okay, and complain and fix if it is not. 1900 */ 1901 q = line + strlen(line); 1902 while (!isblank((unsigned char)*q) && (q != line)) 1903 q--; 1904 if ((q == line) && strlen(line)) { 1905 /* No tabs or space in a non empty line: complain */ 1906 errno = 0; 1907 logerror( 1908 "Error: `%s' log facility or log target missing", 1909 line); 1910 return; 1911 } 1912 1913 /* save host name, if any */ 1914 if (*host == '*') 1915 f->f_host = NULL; 1916 else { 1917 f->f_host = strdup(host); 1918 trim_localdomain(f->f_host); 1919 } 1920 1921 /* save program name, if any */ 1922 if (*prog == '*') 1923 f->f_program = NULL; 1924 else 1925 f->f_program = strdup(prog); 1926 1927 /* scan through the list of selectors */ 1928 for (p = line; *p && !isblank((unsigned char)*p);) { 1929 int pri_done, pri_cmp, pri_invert; 1930 1931 /* find the end of this facility name list */ 1932 for (q = p; *q && !isblank((unsigned char)*q) && *q++ != '.'; ) 1933 continue; 1934 1935 /* get the priority comparison */ 1936 pri_cmp = 0; 1937 pri_done = 0; 1938 pri_invert = 0; 1939 if (*q == '!') { 1940 pri_invert = 1; 1941 q++; 1942 } 1943 while (! pri_done) { 1944 switch (*q) { 1945 case '<': 1946 pri_cmp = PRI_LT; 1947 q++; 1948 break; 1949 case '=': 1950 pri_cmp = PRI_EQ; 1951 q++; 1952 break; 1953 case '>': 1954 pri_cmp = PRI_GT; 1955 q++; 1956 break; 1957 default: 1958 pri_done = 1; 1959 break; 1960 } 1961 } 1962 1963 /* collect priority name */ 1964 for (bp = buf; *q && !strchr("\t ,;", *q); ) 1965 *bp++ = *q++; 1966 *bp = '\0'; 1967 1968 /* skip cruft */ 1969 while (strchr(",;", *q)) 1970 q++; 1971 1972 /* decode priority name */ 1973 if (*buf == '*') { 1974 pri = LOG_PRIMASK + 1; 1975 pri_cmp = PRI_LT | PRI_EQ | PRI_GT; 1976 } else { 1977 pri = decode(buf, prioritynames); 1978 if (pri < 0) { 1979 errno = 0; 1980 logerror("Unknown priority name `%s'", buf); 1981 return; 1982 } 1983 } 1984 if (pri_cmp == 0) 1985 pri_cmp = UniquePriority ? PRI_EQ 1986 : PRI_EQ | PRI_GT; 1987 if (pri_invert) 1988 pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT; 1989 1990 /* scan facilities */ 1991 while (*p && !strchr("\t .;", *p)) { 1992 for (bp = buf; *p && !strchr("\t ,;.", *p); ) 1993 *bp++ = *p++; 1994 *bp = '\0'; 1995 if (*buf == '*') 1996 for (i = 0; i < LOG_NFACILITIES; i++) { 1997 f->f_pmask[i] = pri; 1998 f->f_pcmp[i] = pri_cmp; 1999 } 2000 else { 2001 i = decode(buf, facilitynames); 2002 if (i < 0) { 2003 errno = 0; 2004 logerror("Unknown facility name `%s'", 2005 buf); 2006 return; 2007 } 2008 f->f_pmask[i >> 3] = pri; 2009 f->f_pcmp[i >> 3] = pri_cmp; 2010 } 2011 while (*p == ',' || *p == ' ') 2012 p++; 2013 } 2014 2015 p = q; 2016 } 2017 2018 /* skip to action part */ 2019 while (isblank((unsigned char)*p)) 2020 p++; 2021 2022 if (*p == '-') { 2023 syncfile = 0; 2024 p++; 2025 } else 2026 syncfile = 1; 2027 2028 switch (*p) { 2029 case '@': 2030 (void)strlcpy(f->f_un.f_forw.f_hname, ++p, 2031 sizeof(f->f_un.f_forw.f_hname)); 2032 memset(&hints, 0, sizeof(hints)); 2033 hints.ai_family = AF_UNSPEC; 2034 hints.ai_socktype = SOCK_DGRAM; 2035 hints.ai_protocol = 0; 2036 error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, 2037 &res); 2038 if (error) { 2039 logerror(gai_strerror(error)); 2040 break; 2041 } 2042 f->f_un.f_forw.f_addr = res; 2043 f->f_type = F_FORW; 2044 NumForwards++; 2045 break; 2046 2047 case '/': 2048 (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname)); 2049 if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) { 2050 f->f_type = F_UNUSED; 2051 logerror(p); 2052 break; 2053 } 2054 if (syncfile) 2055 f->f_flags |= FFLAG_SYNC; 2056 if (isatty(f->f_file)) 2057 f->f_type = F_TTY; 2058 else 2059 f->f_type = F_FILE; 2060 if (strcmp(p, ctty) == 0) 2061 f->f_type = F_CONSOLE; 2062 break; 2063 2064 case '|': 2065 f->f_un.f_pipe.f_pid = 0; 2066 (void) strlcpy(f->f_un.f_pipe.f_pname, p + 1, 2067 sizeof(f->f_un.f_pipe.f_pname)); 2068 f->f_type = F_PIPE; 2069 break; 2070 2071 case '*': 2072 f->f_type = F_WALL; 2073 break; 2074 2075 default: 2076 for (i = 0; i < MAXUNAMES && *p; i++) { 2077 for (q = p; *q && *q != ','; ) 2078 q++; 2079 (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); 2080 if ((q - p) > UT_NAMESIZE) 2081 f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; 2082 else 2083 f->f_un.f_uname[i][q - p] = '\0'; 2084 while (*q == ',' || *q == ' ') 2085 q++; 2086 p = q; 2087 } 2088 f->f_type = F_USERS; 2089 break; 2090 } 2091 } 2092 2093 2094 /* 2095 * Decode a symbolic name to a numeric value 2096 */ 2097 int 2098 decode(const char *name, CODE *codetab) 2099 { 2100 CODE *c; 2101 char *p, buf[40]; 2102 2103 if (isdigit((unsigned char)*name)) 2104 return (atoi(name)); 2105 2106 for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) { 2107 if (isupper((unsigned char)*name)) 2108 *p = tolower((unsigned char)*name); 2109 else 2110 *p = *name; 2111 } 2112 *p = '\0'; 2113 for (c = codetab; c->c_name; c++) 2114 if (!strcmp(buf, c->c_name)) 2115 return (c->c_val); 2116 2117 return (-1); 2118 } 2119 2120 /* 2121 * Retrieve the size of the kernel message buffer, via sysctl. 2122 */ 2123 int 2124 getmsgbufsize(void) 2125 { 2126 int msgbufsize, mib[2]; 2127 size_t size; 2128 2129 mib[0] = CTL_KERN; 2130 mib[1] = KERN_MSGBUFSIZE; 2131 size = sizeof msgbufsize; 2132 if (sysctl(mib, 2, &msgbufsize, &size, NULL, 0) == -1) { 2133 dprintf("Couldn't get kern.msgbufsize\n"); 2134 return (0); 2135 } 2136 return (msgbufsize); 2137 } 2138 2139 int * 2140 socksetup(int af, const char *hostname) 2141 { 2142 struct addrinfo hints, *res, *r; 2143 struct kevent *ev; 2144 int error, maxs, *s, *socks; 2145 const int on = 1; 2146 2147 if(SecureMode && !NumForwards) 2148 return(NULL); 2149 2150 memset(&hints, 0, sizeof(hints)); 2151 hints.ai_flags = AI_PASSIVE; 2152 hints.ai_family = af; 2153 hints.ai_socktype = SOCK_DGRAM; 2154 error = getaddrinfo(hostname, "syslog", &hints, &res); 2155 if (error) { 2156 logerror(gai_strerror(error)); 2157 errno = 0; 2158 die(NULL); 2159 } 2160 2161 /* Count max number of sockets we may open */ 2162 for (maxs = 0, r = res; r; r = r->ai_next, maxs++) 2163 continue; 2164 socks = malloc((maxs+1) * sizeof(int)); 2165 if (!socks) { 2166 logerror("Couldn't allocate memory for sockets"); 2167 die(NULL); 2168 } 2169 2170 *socks = 0; /* num of sockets counter at start of array */ 2171 s = socks + 1; 2172 for (r = res; r; r = r->ai_next) { 2173 *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 2174 if (*s < 0) { 2175 logerror("socket() failed"); 2176 continue; 2177 } 2178 if (r->ai_family == AF_INET6 && setsockopt(*s, IPPROTO_IPV6, 2179 IPV6_V6ONLY, &on, sizeof(on)) < 0) { 2180 logerror("setsockopt(IPV6_V6ONLY) failed"); 2181 close(*s); 2182 continue; 2183 } 2184 2185 if (!SecureMode) { 2186 if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { 2187 logerror("bind() failed"); 2188 close(*s); 2189 continue; 2190 } 2191 ev = allocevchange(); 2192 EV_SET(ev, *s, EVFILT_READ, EV_ADD | EV_ENABLE, 2193 0, 0, (intptr_t) dispatch_read_finet); 2194 } 2195 2196 *socks = *socks + 1; 2197 s++; 2198 } 2199 2200 if (*socks == 0) { 2201 free (socks); 2202 if(Debug) 2203 return(NULL); 2204 else 2205 die(NULL); 2206 } 2207 if (res) 2208 freeaddrinfo(res); 2209 2210 return(socks); 2211 } 2212 2213 /* 2214 * Fairly similar to popen(3), but returns an open descriptor, as opposed 2215 * to a FILE *. 2216 */ 2217 int 2218 p_open(char *prog, pid_t *rpid) 2219 { 2220 int pfd[2], nulldesc, i; 2221 pid_t pid; 2222 char *argv[4]; /* sh -c cmd NULL */ 2223 char errmsg[200]; 2224 2225 if (pipe(pfd) == -1) 2226 return (-1); 2227 if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1) { 2228 /* We are royally screwed anyway. */ 2229 return (-1); 2230 } 2231 2232 switch ((pid = fork())) { 2233 case -1: 2234 (void) close(nulldesc); 2235 return (-1); 2236 2237 case 0: 2238 argv[0] = "sh"; 2239 argv[1] = "-c"; 2240 argv[2] = prog; 2241 argv[3] = NULL; 2242 2243 (void) setsid(); /* avoid catching SIGHUPs. */ 2244 2245 /* 2246 * Reset ignored signals to their default behavior. 2247 */ 2248 (void)signal(SIGTERM, SIG_DFL); 2249 (void)signal(SIGINT, SIG_DFL); 2250 (void)signal(SIGQUIT, SIG_DFL); 2251 (void)signal(SIGPIPE, SIG_DFL); 2252 (void)signal(SIGHUP, SIG_DFL); 2253 2254 dup2(pfd[0], STDIN_FILENO); 2255 dup2(nulldesc, STDOUT_FILENO); 2256 dup2(nulldesc, STDERR_FILENO); 2257 for (i = getdtablesize(); i > 2; i--) 2258 (void) close(i); 2259 2260 (void) execvp(_PATH_BSHELL, argv); 2261 _exit(255); 2262 } 2263 2264 (void) close(nulldesc); 2265 (void) close(pfd[0]); 2266 2267 /* 2268 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are 2269 * supposed to get an EWOULDBLOCK on writev(2), which is 2270 * caught by the logic above anyway, which will in turn 2271 * close the pipe, and fork a new logging subprocess if 2272 * necessary. The stale subprocess will be killed some 2273 * time later unless it terminated itself due to closing 2274 * its input pipe. 2275 */ 2276 if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) { 2277 /* This is bad. */ 2278 (void) snprintf(errmsg, sizeof(errmsg), 2279 "Warning: cannot change pipe to pid %d to " 2280 "non-blocking.", (int) pid); 2281 logerror(errmsg); 2282 } 2283 *rpid = pid; 2284 return (pfd[1]); 2285 } 2286 2287 void 2288 deadq_enter(pid_t pid, const char *name) 2289 { 2290 dq_t p; 2291 int status; 2292 2293 /* 2294 * Be paranoid: if we can't signal the process, don't enter it 2295 * into the dead queue (perhaps it's already dead). If possible, 2296 * we try to fetch and log the child's status. 2297 */ 2298 if (kill(pid, 0) != 0) { 2299 if (waitpid(pid, &status, WNOHANG) > 0) 2300 log_deadchild(pid, status, name); 2301 return; 2302 } 2303 2304 p = malloc(sizeof(*p)); 2305 if (p == NULL) { 2306 errno = 0; 2307 logerror("panic: out of memory!"); 2308 exit(1); 2309 } 2310 2311 p->dq_pid = pid; 2312 p->dq_timeout = DQ_TIMO_INIT; 2313 TAILQ_INSERT_TAIL(&deadq_head, p, dq_entries); 2314 } 2315 2316 int 2317 deadq_remove(pid_t pid) 2318 { 2319 dq_t q; 2320 2321 for (q = TAILQ_FIRST(&deadq_head); q != NULL; 2322 q = TAILQ_NEXT(q, dq_entries)) { 2323 if (q->dq_pid == pid) { 2324 TAILQ_REMOVE(&deadq_head, q, dq_entries); 2325 free(q); 2326 return (1); 2327 } 2328 } 2329 return (0); 2330 } 2331 2332 void 2333 log_deadchild(pid_t pid, int status, const char *name) 2334 { 2335 int code; 2336 char buf[256]; 2337 const char *reason; 2338 2339 /* Keep strerror() struff out of logerror messages. */ 2340 errno = 0; 2341 if (WIFSIGNALED(status)) { 2342 reason = "due to signal"; 2343 code = WTERMSIG(status); 2344 } else { 2345 reason = "with status"; 2346 code = WEXITSTATUS(status); 2347 if (code == 0) 2348 return; 2349 } 2350 (void) snprintf(buf, sizeof(buf), 2351 "Logging subprocess %d (%s) exited %s %d.", 2352 pid, name, reason, code); 2353 logerror(buf); 2354 } 2355 2356 static struct kevent changebuf[8]; 2357 static int nchanges; 2358 2359 static struct kevent * 2360 allocevchange(void) 2361 { 2362 2363 if (nchanges == A_CNT(changebuf)) { 2364 /* XXX Error handling could be improved. */ 2365 (void) wait_for_events(NULL, 0); 2366 } 2367 2368 return (&changebuf[nchanges++]); 2369 } 2370 2371 static int 2372 wait_for_events(struct kevent *events, size_t nevents) 2373 { 2374 int rv; 2375 2376 rv = kevent(fkq, nchanges ? changebuf : NULL, nchanges, 2377 events, nevents, NULL); 2378 nchanges = 0; 2379 return (rv); 2380 } 2381