1 /* 2 * Copyright (c) 1983, 1988, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef lint 31 static const char copyright[] = 32 "@(#) Copyright (c) 1983, 1988, 1993, 1994\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94"; 39 #endif 40 #endif /* not lint */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 /* 46 * syslogd -- log system messages 47 * 48 * This program implements a system log. It takes a series of lines. 49 * Each line may have a priority, signified as "<n>" as 50 * the first characters of the line. If this is 51 * not present, a default priority is used. 52 * 53 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will 54 * cause it to reread its configuration file. 55 * 56 * Defined Constants: 57 * 58 * MAXLINE -- the maximum line length that can be handled. 59 * DEFUPRI -- the default priority for user messages 60 * DEFSPRI -- the default priority for kernel messages 61 * 62 * Author: Eric Allman 63 * extensive changes by Ralph Campbell 64 * more extensive changes by Eric Allman (again) 65 * Extension to log by program name as well as facility and priority 66 * by Peter da Silva. 67 * -u and -v by Harlan Stenn. 68 * Priority comparison code by Harlan Stenn. 69 */ 70 71 #define MAXLINE 1024 /* maximum line length */ 72 #define MAXSVLINE 120 /* maximum saved line length */ 73 #define DEFUPRI (LOG_USER|LOG_NOTICE) 74 #define DEFSPRI (LOG_KERN|LOG_CRIT) 75 #define TIMERINTVL 30 /* interval for checking flush, mark */ 76 #define TTYMSGTIME 1 /* timeout passed to ttymsg */ 77 #define RCVBUF_MINSIZE (80 * 1024) /* minimum size of dgram rcv buffer */ 78 79 #include <sys/param.h> 80 #include <sys/ioctl.h> 81 #include <sys/mman.h> 82 #include <sys/stat.h> 83 #include <sys/wait.h> 84 #include <sys/socket.h> 85 #include <sys/queue.h> 86 #include <sys/uio.h> 87 #include <sys/un.h> 88 #include <sys/time.h> 89 #include <sys/resource.h> 90 #include <sys/syslimits.h> 91 #include <sys/types.h> 92 93 #include <netinet/in.h> 94 #include <netdb.h> 95 #include <arpa/inet.h> 96 97 #include <ctype.h> 98 #include <err.h> 99 #include <errno.h> 100 #include <fcntl.h> 101 #include <libutil.h> 102 #include <limits.h> 103 #include <paths.h> 104 #include <signal.h> 105 #include <stdio.h> 106 #include <stdlib.h> 107 #include <string.h> 108 #include <sysexits.h> 109 #include <unistd.h> 110 #include <utmpx.h> 111 112 #include "pathnames.h" 113 #include "ttymsg.h" 114 115 #define SYSLOG_NAMES 116 #include <sys/syslog.h> 117 118 const char *ConfFile = _PATH_LOGCONF; 119 const char *PidFile = _PATH_LOGPID; 120 const char ctty[] = _PATH_CONSOLE; 121 122 #define dprintf if (Debug) printf 123 124 #define MAXUNAMES 20 /* maximum number of user names */ 125 126 /* 127 * Unix sockets. 128 * We have two default sockets, one with 666 permissions, 129 * and one for privileged programs. 130 */ 131 struct funix { 132 int s; 133 const char *name; 134 mode_t mode; 135 STAILQ_ENTRY(funix) next; 136 }; 137 struct funix funix_secure = { -1, _PATH_LOG_PRIV, S_IRUSR | S_IWUSR, 138 { NULL } }; 139 struct funix funix_default = { -1, _PATH_LOG, DEFFILEMODE, 140 { &funix_secure } }; 141 142 STAILQ_HEAD(, funix) funixes = { &funix_default, 143 &(funix_secure.next.stqe_next) }; 144 145 /* 146 * Flags to logmsg(). 147 */ 148 149 #define IGN_CONS 0x001 /* don't print on console */ 150 #define SYNC_FILE 0x002 /* do fsync on file after printing */ 151 #define ADDDATE 0x004 /* add a date to the message */ 152 #define MARK 0x008 /* this message is a mark */ 153 #define ISKERNEL 0x010 /* kernel generated message */ 154 155 /* 156 * This structure represents the files that will have log 157 * copies printed. 158 * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY 159 * or if f_type if F_PIPE and f_pid > 0. 160 */ 161 162 struct filed { 163 struct filed *f_next; /* next in linked list */ 164 short f_type; /* entry type, see below */ 165 short f_file; /* file descriptor */ 166 time_t f_time; /* time this was last written */ 167 char *f_host; /* host from which to recd. */ 168 u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ 169 u_char f_pcmp[LOG_NFACILITIES+1]; /* compare priority */ 170 #define PRI_LT 0x1 171 #define PRI_EQ 0x2 172 #define PRI_GT 0x4 173 char *f_program; /* program this applies to */ 174 union { 175 char f_uname[MAXUNAMES][MAXLOGNAME]; 176 struct { 177 char f_hname[MAXHOSTNAMELEN]; 178 struct addrinfo *f_addr; 179 180 } f_forw; /* forwarding address */ 181 char f_fname[MAXPATHLEN]; 182 struct { 183 char f_pname[MAXPATHLEN]; 184 pid_t f_pid; 185 } f_pipe; 186 } f_un; 187 char f_prevline[MAXSVLINE]; /* last message logged */ 188 char f_lasttime[16]; /* time of last occurrence */ 189 char f_prevhost[MAXHOSTNAMELEN]; /* host from which recd. */ 190 int f_prevpri; /* pri of f_prevline */ 191 int f_prevlen; /* length of f_prevline */ 192 int f_prevcount; /* repetition cnt of prevline */ 193 u_int f_repeatcount; /* number of "repeated" msgs */ 194 int f_flags; /* file-specific flags */ 195 #define FFLAG_SYNC 0x01 196 #define FFLAG_NEEDSYNC 0x02 197 }; 198 199 /* 200 * Queue of about-to-be dead processes we should watch out for. 201 */ 202 203 TAILQ_HEAD(stailhead, deadq_entry) deadq_head; 204 struct stailhead *deadq_headp; 205 206 struct deadq_entry { 207 pid_t dq_pid; 208 int dq_timeout; 209 TAILQ_ENTRY(deadq_entry) dq_entries; 210 }; 211 212 /* 213 * The timeout to apply to processes waiting on the dead queue. Unit 214 * of measure is `mark intervals', i.e. 20 minutes by default. 215 * Processes on the dead queue will be terminated after that time. 216 */ 217 218 #define DQ_TIMO_INIT 2 219 220 typedef struct deadq_entry *dq_t; 221 222 223 /* 224 * Struct to hold records of network addresses that are allowed to log 225 * to us. 226 */ 227 struct allowedpeer { 228 int isnumeric; 229 u_short port; 230 union { 231 struct { 232 struct sockaddr_storage addr; 233 struct sockaddr_storage mask; 234 } numeric; 235 char *name; 236 } u; 237 #define a_addr u.numeric.addr 238 #define a_mask u.numeric.mask 239 #define a_name u.name 240 }; 241 242 243 /* 244 * Intervals at which we flush out "message repeated" messages, 245 * in seconds after previous message is logged. After each flush, 246 * we move to the next interval until we reach the largest. 247 */ 248 int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ 249 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) 250 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) 251 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \ 252 (f)->f_repeatcount = MAXREPEAT; \ 253 } 254 255 /* values for f_type */ 256 #define F_UNUSED 0 /* unused entry */ 257 #define F_FILE 1 /* regular file */ 258 #define F_TTY 2 /* terminal */ 259 #define F_CONSOLE 3 /* console terminal */ 260 #define F_FORW 4 /* remote machine */ 261 #define F_USERS 5 /* list of users */ 262 #define F_WALL 6 /* everyone logged on */ 263 #define F_PIPE 7 /* pipe to program */ 264 265 const char *TypeNames[8] = { 266 "UNUSED", "FILE", "TTY", "CONSOLE", 267 "FORW", "USERS", "WALL", "PIPE" 268 }; 269 270 static struct filed *Files; /* Log files that we write to */ 271 static struct filed consfile; /* Console */ 272 273 static int Debug; /* debug flag */ 274 static int Foreground = 0; /* Run in foreground, instead of daemonizing */ 275 static int resolve = 1; /* resolve hostname */ 276 static char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ 277 static const char *LocalDomain; /* our local domain name */ 278 static int *finet; /* Internet datagram socket */ 279 static int fklog = -1; /* /dev/klog */ 280 static int Initialized; /* set when we have initialized ourselves */ 281 static int MarkInterval = 20 * 60; /* interval between marks in seconds */ 282 static int MarkSeq; /* mark sequence number */ 283 static int NoBind; /* don't bind() as suggested by RFC 3164 */ 284 static int SecureMode; /* when true, receive only unix domain socks */ 285 #ifdef INET6 286 static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */ 287 #else 288 static int family = PF_INET; /* protocol family (IPv4 only) */ 289 #endif 290 static int mask_C1 = 1; /* mask characters from 0x80 - 0x9F */ 291 static int send_to_all; /* send message to all IPv4/IPv6 addresses */ 292 static int use_bootfile; /* log entire bootfile for every kern msg */ 293 static int no_compress; /* don't compress messages (1=pipes, 2=all) */ 294 static int logflags = O_WRONLY|O_APPEND; /* flags used to open log files */ 295 296 static char bootfile[MAXLINE+1]; /* booted kernel file */ 297 298 struct allowedpeer *AllowedPeers; /* List of allowed peers */ 299 static int NumAllowed; /* Number of entries in AllowedPeers */ 300 static int RemoteAddDate; /* Always set the date on remote messages */ 301 302 static int UniquePriority; /* Only log specified priority? */ 303 static int LogFacPri; /* Put facility and priority in log message: */ 304 /* 0=no, 1=numeric, 2=names */ 305 static int KeepKernFac; /* Keep remotely logged kernel facility */ 306 static int needdofsync = 0; /* Are any file(s) waiting to be fsynced? */ 307 static struct pidfh *pfh; 308 309 volatile sig_atomic_t MarkSet, WantDie; 310 311 static int allowaddr(char *); 312 static void cfline(const char *, struct filed *, 313 const char *, const char *); 314 static const char *cvthname(struct sockaddr *); 315 static void deadq_enter(pid_t, const char *); 316 static int deadq_remove(pid_t); 317 static int decode(const char *, const CODE *); 318 static void die(int); 319 static void dodie(int); 320 static void dofsync(void); 321 static void domark(int); 322 static void fprintlog(struct filed *, int, const char *); 323 static int *socksetup(int, char *); 324 static void init(int); 325 static void logerror(const char *); 326 static void logmsg(int, const char *, const char *, int); 327 static void log_deadchild(pid_t, int, const char *); 328 static void markit(void); 329 static int skip_message(const char *, const char *, int); 330 static void printline(const char *, char *, int); 331 static void printsys(char *); 332 static int p_open(const char *, pid_t *); 333 static void readklog(void); 334 static void reapchild(int); 335 static void usage(void); 336 static int validate(struct sockaddr *, const char *); 337 static void unmapped(struct sockaddr *); 338 static void wallmsg(struct filed *, struct iovec *, const int iovlen); 339 static int waitdaemon(int, int, int); 340 static void timedout(int); 341 static void increase_rcvbuf(int); 342 343 int 344 main(int argc, char *argv[]) 345 { 346 int ch, i, fdsrmax = 0, l; 347 struct sockaddr_un sunx, fromunix; 348 struct sockaddr_storage frominet; 349 fd_set *fdsr = NULL; 350 char line[MAXLINE + 1]; 351 char *bindhostname; 352 const char *hname; 353 struct timeval tv, *tvp; 354 struct sigaction sact; 355 struct funix *fx, *fx1; 356 sigset_t mask; 357 pid_t ppid = 1, spid; 358 socklen_t len; 359 360 if (madvise(NULL, 0, MADV_PROTECT) != 0) 361 dprintf("madvise() failed: %s\n", strerror(errno)); 362 363 bindhostname = NULL; 364 while ((ch = getopt(argc, argv, "468Aa:b:cCdf:Fkl:m:nNop:P:sS:Tuv")) 365 != -1) 366 switch (ch) { 367 case '4': 368 family = PF_INET; 369 break; 370 #ifdef INET6 371 case '6': 372 family = PF_INET6; 373 break; 374 #endif 375 case '8': 376 mask_C1 = 0; 377 break; 378 case 'A': 379 send_to_all++; 380 break; 381 case 'a': /* allow specific network addresses only */ 382 if (allowaddr(optarg) == -1) 383 usage(); 384 break; 385 case 'b': 386 bindhostname = optarg; 387 break; 388 case 'c': 389 no_compress++; 390 break; 391 case 'C': 392 logflags |= O_CREAT; 393 break; 394 case 'd': /* debug */ 395 Debug++; 396 break; 397 case 'f': /* configuration file */ 398 ConfFile = optarg; 399 break; 400 case 'F': /* run in foreground instead of daemon */ 401 Foreground++; 402 break; 403 case 'k': /* keep remote kern fac */ 404 KeepKernFac = 1; 405 break; 406 case 'l': 407 { 408 long perml; 409 mode_t mode; 410 char *name, *ep; 411 412 if (optarg[0] == '/') { 413 mode = DEFFILEMODE; 414 name = optarg; 415 } else if ((name = strchr(optarg, ':')) != NULL) { 416 *name++ = '\0'; 417 if (name[0] != '/') 418 errx(1, "socket name must be absolute " 419 "path"); 420 if (isdigit(*optarg)) { 421 perml = strtol(optarg, &ep, 8); 422 if (*ep || perml < 0 || 423 perml & ~(S_IRWXU|S_IRWXG|S_IRWXO)) 424 errx(1, "invalid mode %s, exiting", 425 optarg); 426 mode = (mode_t )perml; 427 } else 428 errx(1, "invalid mode %s, exiting", 429 optarg); 430 } else /* doesn't begin with '/', and no ':' */ 431 errx(1, "can't parse path %s", optarg); 432 433 if (strlen(name) >= sizeof(sunx.sun_path)) 434 errx(1, "%s path too long, exiting", name); 435 if ((fx = malloc(sizeof(struct funix))) == NULL) 436 errx(1, "malloc failed"); 437 fx->s = -1; 438 fx->name = name; 439 fx->mode = mode; 440 STAILQ_INSERT_TAIL(&funixes, fx, next); 441 break; 442 } 443 case 'm': /* mark interval */ 444 MarkInterval = atoi(optarg) * 60; 445 break; 446 case 'N': 447 NoBind = 1; 448 SecureMode = 1; 449 break; 450 case 'n': 451 resolve = 0; 452 break; 453 case 'o': 454 use_bootfile = 1; 455 break; 456 case 'p': /* path */ 457 if (strlen(optarg) >= sizeof(sunx.sun_path)) 458 errx(1, "%s path too long, exiting", optarg); 459 funix_default.name = optarg; 460 break; 461 case 'P': /* path for alt. PID */ 462 PidFile = optarg; 463 break; 464 case 's': /* no network mode */ 465 SecureMode++; 466 break; 467 case 'S': /* path for privileged originator */ 468 if (strlen(optarg) >= sizeof(sunx.sun_path)) 469 errx(1, "%s path too long, exiting", optarg); 470 funix_secure.name = optarg; 471 break; 472 case 'T': 473 RemoteAddDate = 1; 474 break; 475 case 'u': /* only log specified priority */ 476 UniquePriority++; 477 break; 478 case 'v': /* log facility and priority */ 479 LogFacPri++; 480 break; 481 default: 482 usage(); 483 } 484 if ((argc -= optind) != 0) 485 usage(); 486 487 pfh = pidfile_open(PidFile, 0600, &spid); 488 if (pfh == NULL) { 489 if (errno == EEXIST) 490 errx(1, "syslogd already running, pid: %d", spid); 491 warn("cannot open pid file"); 492 } 493 494 if ((!Foreground) && (!Debug)) { 495 ppid = waitdaemon(0, 0, 30); 496 if (ppid < 0) { 497 warn("could not become daemon"); 498 pidfile_remove(pfh); 499 exit(1); 500 } 501 } else if (Debug) { 502 setlinebuf(stdout); 503 } 504 505 if (NumAllowed) 506 endservent(); 507 508 consfile.f_type = F_CONSOLE; 509 (void)strlcpy(consfile.f_un.f_fname, ctty + sizeof _PATH_DEV - 1, 510 sizeof(consfile.f_un.f_fname)); 511 (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile)); 512 (void)signal(SIGTERM, dodie); 513 (void)signal(SIGINT, Debug ? dodie : SIG_IGN); 514 (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN); 515 /* 516 * We don't want the SIGCHLD and SIGHUP handlers to interfere 517 * with each other; they are likely candidates for being called 518 * simultaneously (SIGHUP closes pipe descriptor, process dies, 519 * SIGCHLD happens). 520 */ 521 sigemptyset(&mask); 522 sigaddset(&mask, SIGHUP); 523 sact.sa_handler = reapchild; 524 sact.sa_mask = mask; 525 sact.sa_flags = SA_RESTART; 526 (void)sigaction(SIGCHLD, &sact, NULL); 527 (void)signal(SIGALRM, domark); 528 (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */ 529 (void)alarm(TIMERINTVL); 530 531 TAILQ_INIT(&deadq_head); 532 533 #ifndef SUN_LEN 534 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) 535 #endif 536 STAILQ_FOREACH_SAFE(fx, &funixes, next, fx1) { 537 (void)unlink(fx->name); 538 memset(&sunx, 0, sizeof(sunx)); 539 sunx.sun_family = AF_LOCAL; 540 (void)strlcpy(sunx.sun_path, fx->name, sizeof(sunx.sun_path)); 541 fx->s = socket(PF_LOCAL, SOCK_DGRAM, 0); 542 if (fx->s < 0 || 543 bind(fx->s, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 || 544 chmod(fx->name, fx->mode) < 0) { 545 (void)snprintf(line, sizeof line, 546 "cannot create %s", fx->name); 547 logerror(line); 548 dprintf("cannot create %s (%d)\n", fx->name, errno); 549 if (fx == &funix_default || fx == &funix_secure) 550 die(0); 551 else { 552 STAILQ_REMOVE(&funixes, fx, funix, next); 553 continue; 554 } 555 } 556 increase_rcvbuf(fx->s); 557 } 558 if (SecureMode <= 1) 559 finet = socksetup(family, bindhostname); 560 561 if (finet) { 562 if (SecureMode) { 563 for (i = 0; i < *finet; i++) { 564 if (shutdown(finet[i+1], SHUT_RD) < 0 && 565 errno != ENOTCONN) { 566 logerror("shutdown"); 567 if (!Debug) 568 die(0); 569 } 570 } 571 } else { 572 dprintf("listening on inet and/or inet6 socket\n"); 573 } 574 dprintf("sending on inet and/or inet6 socket\n"); 575 } 576 577 if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0) 578 if (fcntl(fklog, F_SETFL, O_NONBLOCK) < 0) 579 fklog = -1; 580 if (fklog < 0) 581 dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); 582 583 /* tuck my process id away */ 584 pidfile_write(pfh); 585 586 dprintf("off & running....\n"); 587 588 init(0); 589 /* prevent SIGHUP and SIGCHLD handlers from running in parallel */ 590 sigemptyset(&mask); 591 sigaddset(&mask, SIGCHLD); 592 sact.sa_handler = init; 593 sact.sa_mask = mask; 594 sact.sa_flags = SA_RESTART; 595 (void)sigaction(SIGHUP, &sact, NULL); 596 597 tvp = &tv; 598 tv.tv_sec = tv.tv_usec = 0; 599 600 if (fklog != -1 && fklog > fdsrmax) 601 fdsrmax = fklog; 602 if (finet && !SecureMode) { 603 for (i = 0; i < *finet; i++) { 604 if (finet[i+1] != -1 && finet[i+1] > fdsrmax) 605 fdsrmax = finet[i+1]; 606 } 607 } 608 STAILQ_FOREACH(fx, &funixes, next) 609 if (fx->s > fdsrmax) 610 fdsrmax = fx->s; 611 612 fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS), 613 sizeof(fd_mask)); 614 if (fdsr == NULL) 615 errx(1, "calloc fd_set"); 616 617 for (;;) { 618 if (MarkSet) 619 markit(); 620 if (WantDie) 621 die(WantDie); 622 623 bzero(fdsr, howmany(fdsrmax+1, NFDBITS) * 624 sizeof(fd_mask)); 625 626 if (fklog != -1) 627 FD_SET(fklog, fdsr); 628 if (finet && !SecureMode) { 629 for (i = 0; i < *finet; i++) { 630 if (finet[i+1] != -1) 631 FD_SET(finet[i+1], fdsr); 632 } 633 } 634 STAILQ_FOREACH(fx, &funixes, next) 635 FD_SET(fx->s, fdsr); 636 637 i = select(fdsrmax+1, fdsr, NULL, NULL, 638 needdofsync ? &tv : tvp); 639 switch (i) { 640 case 0: 641 dofsync(); 642 needdofsync = 0; 643 if (tvp) { 644 tvp = NULL; 645 if (ppid != 1) 646 kill(ppid, SIGALRM); 647 } 648 continue; 649 case -1: 650 if (errno != EINTR) 651 logerror("select"); 652 continue; 653 } 654 if (fklog != -1 && FD_ISSET(fklog, fdsr)) 655 readklog(); 656 if (finet && !SecureMode) { 657 for (i = 0; i < *finet; i++) { 658 if (FD_ISSET(finet[i+1], fdsr)) { 659 len = sizeof(frominet); 660 l = recvfrom(finet[i+1], line, MAXLINE, 661 0, (struct sockaddr *)&frominet, 662 &len); 663 if (l > 0) { 664 line[l] = '\0'; 665 hname = cvthname((struct sockaddr *)&frominet); 666 unmapped((struct sockaddr *)&frominet); 667 if (validate((struct sockaddr *)&frominet, hname)) 668 printline(hname, line, RemoteAddDate ? ADDDATE : 0); 669 } else if (l < 0 && errno != EINTR) 670 logerror("recvfrom inet"); 671 } 672 } 673 } 674 STAILQ_FOREACH(fx, &funixes, next) { 675 if (FD_ISSET(fx->s, fdsr)) { 676 len = sizeof(fromunix); 677 l = recvfrom(fx->s, line, MAXLINE, 0, 678 (struct sockaddr *)&fromunix, &len); 679 if (l > 0) { 680 line[l] = '\0'; 681 printline(LocalHostName, line, 0); 682 } else if (l < 0 && errno != EINTR) 683 logerror("recvfrom unix"); 684 } 685 } 686 } 687 if (fdsr) 688 free(fdsr); 689 } 690 691 static void 692 unmapped(struct sockaddr *sa) 693 { 694 struct sockaddr_in6 *sin6; 695 struct sockaddr_in sin4; 696 697 if (sa->sa_family != AF_INET6) 698 return; 699 if (sa->sa_len != sizeof(struct sockaddr_in6) || 700 sizeof(sin4) > sa->sa_len) 701 return; 702 sin6 = (struct sockaddr_in6 *)sa; 703 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 704 return; 705 706 memset(&sin4, 0, sizeof(sin4)); 707 sin4.sin_family = AF_INET; 708 sin4.sin_len = sizeof(struct sockaddr_in); 709 memcpy(&sin4.sin_addr, &sin6->sin6_addr.s6_addr[12], 710 sizeof(sin4.sin_addr)); 711 sin4.sin_port = sin6->sin6_port; 712 713 memcpy(sa, &sin4, sin4.sin_len); 714 } 715 716 static void 717 usage(void) 718 { 719 720 fprintf(stderr, "%s\n%s\n%s\n%s\n", 721 "usage: syslogd [-468ACcdFknosTuv] [-a allowed_peer]", 722 " [-b bind_address] [-f config_file]", 723 " [-l [mode:]path] [-m mark_interval]", 724 " [-P pid_file] [-p log_socket]"); 725 exit(1); 726 } 727 728 /* 729 * Take a raw input line, decode the message, and print the message 730 * on the appropriate log files. 731 */ 732 static void 733 printline(const char *hname, char *msg, int flags) 734 { 735 char *p, *q; 736 long n; 737 int c, pri; 738 char line[MAXLINE + 1]; 739 740 /* test for special codes */ 741 p = msg; 742 pri = DEFUPRI; 743 if (*p == '<') { 744 errno = 0; 745 n = strtol(p + 1, &q, 10); 746 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 747 p = q + 1; 748 pri = n; 749 } 750 } 751 if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) 752 pri = DEFUPRI; 753 754 /* 755 * Don't allow users to log kernel messages. 756 * NOTE: since LOG_KERN == 0 this will also match 757 * messages with no facility specified. 758 */ 759 if ((pri & LOG_FACMASK) == LOG_KERN && !KeepKernFac) 760 pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); 761 762 q = line; 763 764 while ((c = (unsigned char)*p++) != '\0' && 765 q < &line[sizeof(line) - 4]) { 766 if (mask_C1 && (c & 0x80) && c < 0xA0) { 767 c &= 0x7F; 768 *q++ = 'M'; 769 *q++ = '-'; 770 } 771 if (isascii(c) && iscntrl(c)) { 772 if (c == '\n') { 773 *q++ = ' '; 774 } else if (c == '\t') { 775 *q++ = '\t'; 776 } else { 777 *q++ = '^'; 778 *q++ = c ^ 0100; 779 } 780 } else { 781 *q++ = c; 782 } 783 } 784 *q = '\0'; 785 786 logmsg(pri, line, hname, flags); 787 } 788 789 /* 790 * Read /dev/klog while data are available, split into lines. 791 */ 792 static void 793 readklog(void) 794 { 795 char *p, *q, line[MAXLINE + 1]; 796 int len, i; 797 798 len = 0; 799 for (;;) { 800 i = read(fklog, line + len, MAXLINE - 1 - len); 801 if (i > 0) { 802 line[i + len] = '\0'; 803 } else { 804 if (i < 0 && errno != EINTR && errno != EAGAIN) { 805 logerror("klog"); 806 fklog = -1; 807 } 808 break; 809 } 810 811 for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { 812 *q = '\0'; 813 printsys(p); 814 } 815 len = strlen(p); 816 if (len >= MAXLINE - 1) { 817 printsys(p); 818 len = 0; 819 } 820 if (len > 0) 821 memmove(line, p, len + 1); 822 } 823 if (len > 0) 824 printsys(line); 825 } 826 827 /* 828 * Take a raw input line from /dev/klog, format similar to syslog(). 829 */ 830 static void 831 printsys(char *msg) 832 { 833 char *p, *q; 834 long n; 835 int flags, isprintf, pri; 836 837 flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */ 838 p = msg; 839 pri = DEFSPRI; 840 isprintf = 1; 841 if (*p == '<') { 842 errno = 0; 843 n = strtol(p + 1, &q, 10); 844 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 845 p = q + 1; 846 pri = n; 847 isprintf = 0; 848 } 849 } 850 /* 851 * Kernel printf's and LOG_CONSOLE messages have been displayed 852 * on the console already. 853 */ 854 if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE) 855 flags |= IGN_CONS; 856 if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) 857 pri = DEFSPRI; 858 logmsg(pri, p, LocalHostName, flags); 859 } 860 861 static time_t now; 862 863 /* 864 * Match a program or host name against a specification. 865 * Return a non-0 value if the message must be ignored 866 * based on the specification. 867 */ 868 static int 869 skip_message(const char *name, const char *spec, int checkcase) 870 { 871 const char *s; 872 char prev, next; 873 int exclude = 0; 874 /* Behaviour on explicit match */ 875 876 if (spec == NULL) 877 return 0; 878 switch (*spec) { 879 case '-': 880 exclude = 1; 881 /*FALLTHROUGH*/ 882 case '+': 883 spec++; 884 break; 885 default: 886 break; 887 } 888 if (checkcase) 889 s = strstr (spec, name); 890 else 891 s = strcasestr (spec, name); 892 893 if (s != NULL) { 894 prev = (s == spec ? ',' : *(s - 1)); 895 next = *(s + strlen (name)); 896 897 if (prev == ',' && (next == '\0' || next == ',')) 898 /* Explicit match: skip iff the spec is an 899 exclusive one. */ 900 return exclude; 901 } 902 903 /* No explicit match for this name: skip the message iff 904 the spec is an inclusive one. */ 905 return !exclude; 906 } 907 908 /* 909 * Log a message to the appropriate log files, users, etc. based on 910 * the priority. 911 */ 912 static void 913 logmsg(int pri, const char *msg, const char *from, int flags) 914 { 915 struct filed *f; 916 int i, fac, msglen, omask, prilev; 917 const char *timestamp; 918 char prog[NAME_MAX+1]; 919 char buf[MAXLINE+1]; 920 921 dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", 922 pri, flags, from, msg); 923 924 omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); 925 926 /* 927 * Check to see if msg looks non-standard. 928 */ 929 msglen = strlen(msg); 930 if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || 931 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') 932 flags |= ADDDATE; 933 934 (void)time(&now); 935 if (flags & ADDDATE) { 936 timestamp = ctime(&now) + 4; 937 } else { 938 timestamp = msg; 939 msg += 16; 940 msglen -= 16; 941 } 942 943 /* skip leading blanks */ 944 while (isspace(*msg)) { 945 msg++; 946 msglen--; 947 } 948 949 /* extract facility and priority level */ 950 if (flags & MARK) 951 fac = LOG_NFACILITIES; 952 else 953 fac = LOG_FAC(pri); 954 955 /* Check maximum facility number. */ 956 if (fac > LOG_NFACILITIES) { 957 (void)sigsetmask(omask); 958 return; 959 } 960 961 prilev = LOG_PRI(pri); 962 963 /* extract program name */ 964 for (i = 0; i < NAME_MAX; i++) { 965 if (!isprint(msg[i]) || msg[i] == ':' || msg[i] == '[' || 966 msg[i] == '/' || isspace(msg[i])) 967 break; 968 prog[i] = msg[i]; 969 } 970 prog[i] = 0; 971 972 /* add kernel prefix for kernel messages */ 973 if (flags & ISKERNEL) { 974 snprintf(buf, sizeof(buf), "%s: %s", 975 use_bootfile ? bootfile : "kernel", msg); 976 msg = buf; 977 msglen = strlen(buf); 978 } 979 980 /* log the message to the particular outputs */ 981 if (!Initialized) { 982 f = &consfile; 983 /* 984 * Open in non-blocking mode to avoid hangs during open 985 * and close(waiting for the port to drain). 986 */ 987 f->f_file = open(ctty, O_WRONLY | O_NONBLOCK, 0); 988 989 if (f->f_file >= 0) { 990 (void)strlcpy(f->f_lasttime, timestamp, 991 sizeof(f->f_lasttime)); 992 fprintlog(f, flags, msg); 993 (void)close(f->f_file); 994 } 995 (void)sigsetmask(omask); 996 return; 997 } 998 for (f = Files; f; f = f->f_next) { 999 /* skip messages that are incorrect priority */ 1000 if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev)) 1001 ||((f->f_pcmp[fac] & PRI_LT) && (f->f_pmask[fac] < prilev)) 1002 ||((f->f_pcmp[fac] & PRI_GT) && (f->f_pmask[fac] > prilev)) 1003 ) 1004 || f->f_pmask[fac] == INTERNAL_NOPRI) 1005 continue; 1006 1007 /* skip messages with the incorrect hostname */ 1008 if (skip_message(from, f->f_host, 0)) 1009 continue; 1010 1011 /* skip messages with the incorrect program name */ 1012 if (skip_message(prog, f->f_program, 1)) 1013 continue; 1014 1015 /* skip message to console if it has already been printed */ 1016 if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) 1017 continue; 1018 1019 /* don't output marks to recently written files */ 1020 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2) 1021 continue; 1022 1023 /* 1024 * suppress duplicate lines to this file 1025 */ 1026 if (no_compress - (f->f_type != F_PIPE) < 1 && 1027 (flags & MARK) == 0 && msglen == f->f_prevlen && 1028 !strcmp(msg, f->f_prevline) && 1029 !strcasecmp(from, f->f_prevhost)) { 1030 (void)strlcpy(f->f_lasttime, timestamp, 1031 sizeof(f->f_lasttime)); 1032 f->f_prevcount++; 1033 dprintf("msg repeated %d times, %ld sec of %d\n", 1034 f->f_prevcount, (long)(now - f->f_time), 1035 repeatinterval[f->f_repeatcount]); 1036 /* 1037 * If domark would have logged this by now, 1038 * flush it now (so we don't hold isolated messages), 1039 * but back off so we'll flush less often 1040 * in the future. 1041 */ 1042 if (now > REPEATTIME(f)) { 1043 fprintlog(f, flags, (char *)NULL); 1044 BACKOFF(f); 1045 } 1046 } else { 1047 /* new line, save it */ 1048 if (f->f_prevcount) 1049 fprintlog(f, 0, (char *)NULL); 1050 f->f_repeatcount = 0; 1051 f->f_prevpri = pri; 1052 (void)strlcpy(f->f_lasttime, timestamp, 1053 sizeof(f->f_lasttime)); 1054 (void)strlcpy(f->f_prevhost, from, 1055 sizeof(f->f_prevhost)); 1056 if (msglen < MAXSVLINE) { 1057 f->f_prevlen = msglen; 1058 (void)strlcpy(f->f_prevline, msg, sizeof(f->f_prevline)); 1059 fprintlog(f, flags, (char *)NULL); 1060 } else { 1061 f->f_prevline[0] = 0; 1062 f->f_prevlen = 0; 1063 fprintlog(f, flags, msg); 1064 } 1065 } 1066 } 1067 (void)sigsetmask(omask); 1068 } 1069 1070 static void 1071 dofsync(void) 1072 { 1073 struct filed *f; 1074 1075 for (f = Files; f; f = f->f_next) { 1076 if ((f->f_type == F_FILE) && 1077 (f->f_flags & FFLAG_NEEDSYNC)) { 1078 f->f_flags &= ~FFLAG_NEEDSYNC; 1079 (void)fsync(f->f_file); 1080 } 1081 } 1082 } 1083 1084 #define IOV_SIZE 7 1085 static void 1086 fprintlog(struct filed *f, int flags, const char *msg) 1087 { 1088 struct iovec iov[IOV_SIZE]; 1089 struct iovec *v; 1090 struct addrinfo *r; 1091 int i, l, lsent = 0; 1092 char line[MAXLINE + 1], repbuf[80], greetings[200], *wmsg = NULL; 1093 char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n"; 1094 const char *msgret; 1095 1096 v = iov; 1097 if (f->f_type == F_WALL) { 1098 v->iov_base = greetings; 1099 /* The time displayed is not synchornized with the other log 1100 * destinations (like messages). Following fragment was using 1101 * ctime(&now), which was updating the time every 30 sec. 1102 * With f_lasttime, time is synchronized correctly. 1103 */ 1104 v->iov_len = snprintf(greetings, sizeof greetings, 1105 "\r\n\7Message from syslogd@%s at %.24s ...\r\n", 1106 f->f_prevhost, f->f_lasttime); 1107 if (v->iov_len >= sizeof greetings) 1108 v->iov_len = sizeof greetings - 1; 1109 v++; 1110 v->iov_base = nul; 1111 v->iov_len = 0; 1112 v++; 1113 } else { 1114 v->iov_base = f->f_lasttime; 1115 v->iov_len = strlen(f->f_lasttime); 1116 v++; 1117 v->iov_base = space; 1118 v->iov_len = 1; 1119 v++; 1120 } 1121 1122 if (LogFacPri) { 1123 static char fp_buf[30]; /* Hollow laugh */ 1124 int fac = f->f_prevpri & LOG_FACMASK; 1125 int pri = LOG_PRI(f->f_prevpri); 1126 const char *f_s = NULL; 1127 char f_n[5]; /* Hollow laugh */ 1128 const char *p_s = NULL; 1129 char p_n[5]; /* Hollow laugh */ 1130 1131 if (LogFacPri > 1) { 1132 const CODE *c; 1133 1134 for (c = facilitynames; c->c_name; c++) { 1135 if (c->c_val == fac) { 1136 f_s = c->c_name; 1137 break; 1138 } 1139 } 1140 for (c = prioritynames; c->c_name; c++) { 1141 if (c->c_val == pri) { 1142 p_s = c->c_name; 1143 break; 1144 } 1145 } 1146 } 1147 if (!f_s) { 1148 snprintf(f_n, sizeof f_n, "%d", LOG_FAC(fac)); 1149 f_s = f_n; 1150 } 1151 if (!p_s) { 1152 snprintf(p_n, sizeof p_n, "%d", pri); 1153 p_s = p_n; 1154 } 1155 snprintf(fp_buf, sizeof fp_buf, "<%s.%s> ", f_s, p_s); 1156 v->iov_base = fp_buf; 1157 v->iov_len = strlen(fp_buf); 1158 } else { 1159 v->iov_base = nul; 1160 v->iov_len = 0; 1161 } 1162 v++; 1163 1164 v->iov_base = f->f_prevhost; 1165 v->iov_len = strlen(v->iov_base); 1166 v++; 1167 v->iov_base = space; 1168 v->iov_len = 1; 1169 v++; 1170 1171 if (msg) { 1172 wmsg = strdup(msg); /* XXX iov_base needs a `const' sibling. */ 1173 if (wmsg == NULL) { 1174 logerror("strdup"); 1175 exit(1); 1176 } 1177 v->iov_base = wmsg; 1178 v->iov_len = strlen(msg); 1179 } else if (f->f_prevcount > 1) { 1180 v->iov_base = repbuf; 1181 v->iov_len = snprintf(repbuf, sizeof repbuf, 1182 "last message repeated %d times", f->f_prevcount); 1183 } else { 1184 v->iov_base = f->f_prevline; 1185 v->iov_len = f->f_prevlen; 1186 } 1187 v++; 1188 1189 dprintf("Logging to %s", TypeNames[f->f_type]); 1190 f->f_time = now; 1191 1192 switch (f->f_type) { 1193 int port; 1194 case F_UNUSED: 1195 dprintf("\n"); 1196 break; 1197 1198 case F_FORW: 1199 port = (int)ntohs(((struct sockaddr_in *) 1200 (f->f_un.f_forw.f_addr->ai_addr))->sin_port); 1201 if (port != 514) { 1202 dprintf(" %s:%d\n", f->f_un.f_forw.f_hname, port); 1203 } else { 1204 dprintf(" %s\n", f->f_un.f_forw.f_hname); 1205 } 1206 /* check for local vs remote messages */ 1207 if (strcasecmp(f->f_prevhost, LocalHostName)) 1208 l = snprintf(line, sizeof line - 1, 1209 "<%d>%.15s Forwarded from %s: %s", 1210 f->f_prevpri, (char *)iov[0].iov_base, 1211 f->f_prevhost, (char *)iov[5].iov_base); 1212 else 1213 l = snprintf(line, sizeof line - 1, "<%d>%.15s %s", 1214 f->f_prevpri, (char *)iov[0].iov_base, 1215 (char *)iov[5].iov_base); 1216 if (l < 0) 1217 l = 0; 1218 else if (l > MAXLINE) 1219 l = MAXLINE; 1220 1221 if (finet) { 1222 for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) { 1223 for (i = 0; i < *finet; i++) { 1224 #if 0 1225 /* 1226 * should we check AF first, or just 1227 * trial and error? FWD 1228 */ 1229 if (r->ai_family == 1230 address_family_of(finet[i+1])) 1231 #endif 1232 lsent = sendto(finet[i+1], line, l, 0, 1233 r->ai_addr, r->ai_addrlen); 1234 if (lsent == l) 1235 break; 1236 } 1237 if (lsent == l && !send_to_all) 1238 break; 1239 } 1240 dprintf("lsent/l: %d/%d\n", lsent, l); 1241 if (lsent != l) { 1242 int e = errno; 1243 logerror("sendto"); 1244 errno = e; 1245 switch (errno) { 1246 case ENOBUFS: 1247 case ENETDOWN: 1248 case ENETUNREACH: 1249 case EHOSTUNREACH: 1250 case EHOSTDOWN: 1251 case EADDRNOTAVAIL: 1252 break; 1253 /* case EBADF: */ 1254 /* case EACCES: */ 1255 /* case ENOTSOCK: */ 1256 /* case EFAULT: */ 1257 /* case EMSGSIZE: */ 1258 /* case EAGAIN: */ 1259 /* case ENOBUFS: */ 1260 /* case ECONNREFUSED: */ 1261 default: 1262 dprintf("removing entry: errno=%d\n", e); 1263 f->f_type = F_UNUSED; 1264 break; 1265 } 1266 } 1267 } 1268 break; 1269 1270 case F_FILE: 1271 dprintf(" %s\n", f->f_un.f_fname); 1272 v->iov_base = lf; 1273 v->iov_len = 1; 1274 if (writev(f->f_file, iov, IOV_SIZE) < 0) { 1275 /* 1276 * If writev(2) fails for potentially transient errors 1277 * like the filesystem being full, ignore it. 1278 * Otherwise remove this logfile from the list. 1279 */ 1280 if (errno != ENOSPC) { 1281 int e = errno; 1282 (void)close(f->f_file); 1283 f->f_type = F_UNUSED; 1284 errno = e; 1285 logerror(f->f_un.f_fname); 1286 } 1287 } else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) { 1288 f->f_flags |= FFLAG_NEEDSYNC; 1289 needdofsync = 1; 1290 } 1291 break; 1292 1293 case F_PIPE: 1294 dprintf(" %s\n", f->f_un.f_pipe.f_pname); 1295 v->iov_base = lf; 1296 v->iov_len = 1; 1297 if (f->f_un.f_pipe.f_pid == 0) { 1298 if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, 1299 &f->f_un.f_pipe.f_pid)) < 0) { 1300 f->f_type = F_UNUSED; 1301 logerror(f->f_un.f_pipe.f_pname); 1302 break; 1303 } 1304 } 1305 if (writev(f->f_file, iov, IOV_SIZE) < 0) { 1306 int e = errno; 1307 (void)close(f->f_file); 1308 if (f->f_un.f_pipe.f_pid > 0) 1309 deadq_enter(f->f_un.f_pipe.f_pid, 1310 f->f_un.f_pipe.f_pname); 1311 f->f_un.f_pipe.f_pid = 0; 1312 errno = e; 1313 logerror(f->f_un.f_pipe.f_pname); 1314 } 1315 break; 1316 1317 case F_CONSOLE: 1318 if (flags & IGN_CONS) { 1319 dprintf(" (ignored)\n"); 1320 break; 1321 } 1322 /* FALLTHROUGH */ 1323 1324 case F_TTY: 1325 dprintf(" %s%s\n", _PATH_DEV, f->f_un.f_fname); 1326 v->iov_base = crlf; 1327 v->iov_len = 2; 1328 1329 errno = 0; /* ttymsg() only sometimes returns an errno */ 1330 if ((msgret = ttymsg(iov, IOV_SIZE, f->f_un.f_fname, 10))) { 1331 f->f_type = F_UNUSED; 1332 logerror(msgret); 1333 } 1334 break; 1335 1336 case F_USERS: 1337 case F_WALL: 1338 dprintf("\n"); 1339 v->iov_base = crlf; 1340 v->iov_len = 2; 1341 wallmsg(f, iov, IOV_SIZE); 1342 break; 1343 } 1344 f->f_prevcount = 0; 1345 free(wmsg); 1346 } 1347 1348 /* 1349 * WALLMSG -- Write a message to the world at large 1350 * 1351 * Write the specified message to either the entire 1352 * world, or a list of approved users. 1353 */ 1354 static void 1355 wallmsg(struct filed *f, struct iovec *iov, const int iovlen) 1356 { 1357 static int reenter; /* avoid calling ourselves */ 1358 struct utmpx *ut; 1359 int i; 1360 const char *p; 1361 1362 if (reenter++) 1363 return; 1364 setutxent(); 1365 /* NOSTRICT */ 1366 while ((ut = getutxent()) != NULL) { 1367 if (ut->ut_type != USER_PROCESS) 1368 continue; 1369 if (f->f_type == F_WALL) { 1370 if ((p = ttymsg(iov, iovlen, ut->ut_line, 1371 TTYMSGTIME)) != NULL) { 1372 errno = 0; /* already in msg */ 1373 logerror(p); 1374 } 1375 continue; 1376 } 1377 /* should we send the message to this user? */ 1378 for (i = 0; i < MAXUNAMES; i++) { 1379 if (!f->f_un.f_uname[i][0]) 1380 break; 1381 if (!strcmp(f->f_un.f_uname[i], ut->ut_user)) { 1382 if ((p = ttymsg(iov, iovlen, ut->ut_line, 1383 TTYMSGTIME)) != NULL) { 1384 errno = 0; /* already in msg */ 1385 logerror(p); 1386 } 1387 break; 1388 } 1389 } 1390 } 1391 endutxent(); 1392 reenter = 0; 1393 } 1394 1395 static void 1396 reapchild(int signo __unused) 1397 { 1398 int status; 1399 pid_t pid; 1400 struct filed *f; 1401 1402 while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) { 1403 if (!Initialized) 1404 /* Don't tell while we are initting. */ 1405 continue; 1406 1407 /* First, look if it's a process from the dead queue. */ 1408 if (deadq_remove(pid)) 1409 goto oncemore; 1410 1411 /* Now, look in list of active processes. */ 1412 for (f = Files; f; f = f->f_next) 1413 if (f->f_type == F_PIPE && 1414 f->f_un.f_pipe.f_pid == pid) { 1415 (void)close(f->f_file); 1416 f->f_un.f_pipe.f_pid = 0; 1417 log_deadchild(pid, status, 1418 f->f_un.f_pipe.f_pname); 1419 break; 1420 } 1421 oncemore: 1422 continue; 1423 } 1424 } 1425 1426 /* 1427 * Return a printable representation of a host address. 1428 */ 1429 static const char * 1430 cvthname(struct sockaddr *f) 1431 { 1432 int error, hl; 1433 sigset_t omask, nmask; 1434 static char hname[NI_MAXHOST], ip[NI_MAXHOST]; 1435 1436 error = getnameinfo((struct sockaddr *)f, 1437 ((struct sockaddr *)f)->sa_len, 1438 ip, sizeof ip, NULL, 0, NI_NUMERICHOST); 1439 dprintf("cvthname(%s)\n", ip); 1440 1441 if (error) { 1442 dprintf("Malformed from address %s\n", gai_strerror(error)); 1443 return ("???"); 1444 } 1445 if (!resolve) 1446 return (ip); 1447 1448 sigemptyset(&nmask); 1449 sigaddset(&nmask, SIGHUP); 1450 sigprocmask(SIG_BLOCK, &nmask, &omask); 1451 error = getnameinfo((struct sockaddr *)f, 1452 ((struct sockaddr *)f)->sa_len, 1453 hname, sizeof hname, NULL, 0, NI_NAMEREQD); 1454 sigprocmask(SIG_SETMASK, &omask, NULL); 1455 if (error) { 1456 dprintf("Host name for your address (%s) unknown\n", ip); 1457 return (ip); 1458 } 1459 hl = strlen(hname); 1460 if (hl > 0 && hname[hl-1] == '.') 1461 hname[--hl] = '\0'; 1462 trimdomain(hname, hl); 1463 return (hname); 1464 } 1465 1466 static void 1467 dodie(int signo) 1468 { 1469 1470 WantDie = signo; 1471 } 1472 1473 static void 1474 domark(int signo __unused) 1475 { 1476 1477 MarkSet = 1; 1478 } 1479 1480 /* 1481 * Print syslogd errors some place. 1482 */ 1483 static void 1484 logerror(const char *type) 1485 { 1486 char buf[512]; 1487 static int recursed = 0; 1488 1489 /* If there's an error while trying to log an error, give up. */ 1490 if (recursed) 1491 return; 1492 recursed++; 1493 if (errno) 1494 (void)snprintf(buf, 1495 sizeof buf, "syslogd: %s: %s", type, strerror(errno)); 1496 else 1497 (void)snprintf(buf, sizeof buf, "syslogd: %s", type); 1498 errno = 0; 1499 dprintf("%s\n", buf); 1500 logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); 1501 recursed--; 1502 } 1503 1504 static void 1505 die(int signo) 1506 { 1507 struct filed *f; 1508 struct funix *fx; 1509 int was_initialized; 1510 char buf[100]; 1511 1512 was_initialized = Initialized; 1513 Initialized = 0; /* Don't log SIGCHLDs. */ 1514 for (f = Files; f != NULL; f = f->f_next) { 1515 /* flush any pending output */ 1516 if (f->f_prevcount) 1517 fprintlog(f, 0, (char *)NULL); 1518 if (f->f_type == F_PIPE && f->f_un.f_pipe.f_pid > 0) { 1519 (void)close(f->f_file); 1520 f->f_un.f_pipe.f_pid = 0; 1521 } 1522 } 1523 Initialized = was_initialized; 1524 if (signo) { 1525 dprintf("syslogd: exiting on signal %d\n", signo); 1526 (void)snprintf(buf, sizeof(buf), "exiting on signal %d", signo); 1527 errno = 0; 1528 logerror(buf); 1529 } 1530 STAILQ_FOREACH(fx, &funixes, next) 1531 (void)unlink(fx->name); 1532 pidfile_remove(pfh); 1533 1534 exit(1); 1535 } 1536 1537 /* 1538 * INIT -- Initialize syslogd from configuration table 1539 */ 1540 static void 1541 init(int signo) 1542 { 1543 int i; 1544 FILE *cf; 1545 struct filed *f, *next, **nextp; 1546 char *p; 1547 char cline[LINE_MAX]; 1548 char prog[LINE_MAX]; 1549 char host[MAXHOSTNAMELEN]; 1550 char oldLocalHostName[MAXHOSTNAMELEN]; 1551 char hostMsg[2*MAXHOSTNAMELEN+40]; 1552 char bootfileMsg[LINE_MAX]; 1553 1554 dprintf("init\n"); 1555 1556 /* 1557 * Load hostname (may have changed). 1558 */ 1559 if (signo != 0) 1560 (void)strlcpy(oldLocalHostName, LocalHostName, 1561 sizeof(oldLocalHostName)); 1562 if (gethostname(LocalHostName, sizeof(LocalHostName))) 1563 err(EX_OSERR, "gethostname() failed"); 1564 if ((p = strchr(LocalHostName, '.')) != NULL) { 1565 *p++ = '\0'; 1566 LocalDomain = p; 1567 } else { 1568 LocalDomain = ""; 1569 } 1570 1571 /* 1572 * Close all open log files. 1573 */ 1574 Initialized = 0; 1575 for (f = Files; f != NULL; f = next) { 1576 /* flush any pending output */ 1577 if (f->f_prevcount) 1578 fprintlog(f, 0, (char *)NULL); 1579 1580 switch (f->f_type) { 1581 case F_FILE: 1582 case F_FORW: 1583 case F_CONSOLE: 1584 case F_TTY: 1585 (void)close(f->f_file); 1586 break; 1587 case F_PIPE: 1588 if (f->f_un.f_pipe.f_pid > 0) { 1589 (void)close(f->f_file); 1590 deadq_enter(f->f_un.f_pipe.f_pid, 1591 f->f_un.f_pipe.f_pname); 1592 } 1593 f->f_un.f_pipe.f_pid = 0; 1594 break; 1595 } 1596 next = f->f_next; 1597 if (f->f_program) free(f->f_program); 1598 if (f->f_host) free(f->f_host); 1599 free((char *)f); 1600 } 1601 Files = NULL; 1602 nextp = &Files; 1603 1604 /* open the configuration file */ 1605 if ((cf = fopen(ConfFile, "r")) == NULL) { 1606 dprintf("cannot open %s\n", ConfFile); 1607 *nextp = (struct filed *)calloc(1, sizeof(*f)); 1608 if (*nextp == NULL) { 1609 logerror("calloc"); 1610 exit(1); 1611 } 1612 cfline("*.ERR\t/dev/console", *nextp, "*", "*"); 1613 (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)); 1614 if ((*nextp)->f_next == NULL) { 1615 logerror("calloc"); 1616 exit(1); 1617 } 1618 cfline("*.PANIC\t*", (*nextp)->f_next, "*", "*"); 1619 Initialized = 1; 1620 return; 1621 } 1622 1623 /* 1624 * Foreach line in the conf table, open that file. 1625 */ 1626 f = NULL; 1627 (void)strlcpy(host, "*", sizeof(host)); 1628 (void)strlcpy(prog, "*", sizeof(prog)); 1629 while (fgets(cline, sizeof(cline), cf) != NULL) { 1630 /* 1631 * check for end-of-section, comments, strip off trailing 1632 * spaces and newline character. #!prog is treated specially: 1633 * following lines apply only to that program. 1634 */ 1635 for (p = cline; isspace(*p); ++p) 1636 continue; 1637 if (*p == 0) 1638 continue; 1639 if (*p == '#') { 1640 p++; 1641 if (*p != '!' && *p != '+' && *p != '-') 1642 continue; 1643 } 1644 if (*p == '+' || *p == '-') { 1645 host[0] = *p++; 1646 while (isspace(*p)) 1647 p++; 1648 if ((!*p) || (*p == '*')) { 1649 (void)strlcpy(host, "*", sizeof(host)); 1650 continue; 1651 } 1652 if (*p == '@') 1653 p = LocalHostName; 1654 for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { 1655 if (!isalnum(*p) && *p != '.' && *p != '-' 1656 && *p != ',' && *p != ':' && *p != '%') 1657 break; 1658 host[i] = *p++; 1659 } 1660 host[i] = '\0'; 1661 continue; 1662 } 1663 if (*p == '!') { 1664 p++; 1665 while (isspace(*p)) p++; 1666 if ((!*p) || (*p == '*')) { 1667 (void)strlcpy(prog, "*", sizeof(prog)); 1668 continue; 1669 } 1670 for (i = 0; i < LINE_MAX - 1; i++) { 1671 if (!isprint(p[i]) || isspace(p[i])) 1672 break; 1673 prog[i] = p[i]; 1674 } 1675 prog[i] = 0; 1676 continue; 1677 } 1678 for (p = cline + 1; *p != '\0'; p++) { 1679 if (*p != '#') 1680 continue; 1681 if (*(p - 1) == '\\') { 1682 strcpy(p - 1, p); 1683 p--; 1684 continue; 1685 } 1686 *p = '\0'; 1687 break; 1688 } 1689 for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) 1690 cline[i] = '\0'; 1691 f = (struct filed *)calloc(1, sizeof(*f)); 1692 if (f == NULL) { 1693 logerror("calloc"); 1694 exit(1); 1695 } 1696 *nextp = f; 1697 nextp = &f->f_next; 1698 cfline(cline, f, prog, host); 1699 } 1700 1701 /* close the configuration file */ 1702 (void)fclose(cf); 1703 1704 Initialized = 1; 1705 1706 if (Debug) { 1707 int port; 1708 for (f = Files; f; f = f->f_next) { 1709 for (i = 0; i <= LOG_NFACILITIES; i++) 1710 if (f->f_pmask[i] == INTERNAL_NOPRI) 1711 printf("X "); 1712 else 1713 printf("%d ", f->f_pmask[i]); 1714 printf("%s: ", TypeNames[f->f_type]); 1715 switch (f->f_type) { 1716 case F_FILE: 1717 printf("%s", f->f_un.f_fname); 1718 break; 1719 1720 case F_CONSOLE: 1721 case F_TTY: 1722 printf("%s%s", _PATH_DEV, f->f_un.f_fname); 1723 break; 1724 1725 case F_FORW: 1726 port = (int)ntohs(((struct sockaddr_in *) 1727 (f->f_un.f_forw.f_addr->ai_addr))->sin_port); 1728 if (port != 514) { 1729 printf("%s:%d", 1730 f->f_un.f_forw.f_hname, port); 1731 } else { 1732 printf("%s", f->f_un.f_forw.f_hname); 1733 } 1734 break; 1735 1736 case F_PIPE: 1737 printf("%s", f->f_un.f_pipe.f_pname); 1738 break; 1739 1740 case F_USERS: 1741 for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++) 1742 printf("%s, ", f->f_un.f_uname[i]); 1743 break; 1744 } 1745 if (f->f_program) 1746 printf(" (%s)", f->f_program); 1747 printf("\n"); 1748 } 1749 } 1750 1751 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); 1752 dprintf("syslogd: restarted\n"); 1753 /* 1754 * Log a change in hostname, but only on a restart. 1755 */ 1756 if (signo != 0 && strcmp(oldLocalHostName, LocalHostName) != 0) { 1757 (void)snprintf(hostMsg, sizeof(hostMsg), 1758 "syslogd: hostname changed, \"%s\" to \"%s\"", 1759 oldLocalHostName, LocalHostName); 1760 logmsg(LOG_SYSLOG|LOG_INFO, hostMsg, LocalHostName, ADDDATE); 1761 dprintf("%s\n", hostMsg); 1762 } 1763 /* 1764 * Log the kernel boot file if we aren't going to use it as 1765 * the prefix, and if this is *not* a restart. 1766 */ 1767 if (signo == 0 && !use_bootfile) { 1768 (void)snprintf(bootfileMsg, sizeof(bootfileMsg), 1769 "syslogd: kernel boot file is %s", bootfile); 1770 logmsg(LOG_KERN|LOG_INFO, bootfileMsg, LocalHostName, ADDDATE); 1771 dprintf("%s\n", bootfileMsg); 1772 } 1773 } 1774 1775 /* 1776 * Crack a configuration file line 1777 */ 1778 static void 1779 cfline(const char *line, struct filed *f, const char *prog, const char *host) 1780 { 1781 struct addrinfo hints, *res; 1782 int error, i, pri, syncfile; 1783 const char *p, *q; 1784 char *bp; 1785 char buf[MAXLINE], ebuf[100]; 1786 1787 dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host); 1788 1789 errno = 0; /* keep strerror() stuff out of logerror messages */ 1790 1791 /* clear out file entry */ 1792 memset(f, 0, sizeof(*f)); 1793 for (i = 0; i <= LOG_NFACILITIES; i++) 1794 f->f_pmask[i] = INTERNAL_NOPRI; 1795 1796 /* save hostname if any */ 1797 if (host && *host == '*') 1798 host = NULL; 1799 if (host) { 1800 int hl; 1801 1802 f->f_host = strdup(host); 1803 if (f->f_host == NULL) { 1804 logerror("strdup"); 1805 exit(1); 1806 } 1807 hl = strlen(f->f_host); 1808 if (hl > 0 && f->f_host[hl-1] == '.') 1809 f->f_host[--hl] = '\0'; 1810 trimdomain(f->f_host, hl); 1811 } 1812 1813 /* save program name if any */ 1814 if (prog && *prog == '*') 1815 prog = NULL; 1816 if (prog) { 1817 f->f_program = strdup(prog); 1818 if (f->f_program == NULL) { 1819 logerror("strdup"); 1820 exit(1); 1821 } 1822 } 1823 1824 /* scan through the list of selectors */ 1825 for (p = line; *p && *p != '\t' && *p != ' ';) { 1826 int pri_done; 1827 int pri_cmp; 1828 int pri_invert; 1829 1830 /* find the end of this facility name list */ 1831 for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; ) 1832 continue; 1833 1834 /* get the priority comparison */ 1835 pri_cmp = 0; 1836 pri_done = 0; 1837 pri_invert = 0; 1838 if (*q == '!') { 1839 pri_invert = 1; 1840 q++; 1841 } 1842 while (!pri_done) { 1843 switch (*q) { 1844 case '<': 1845 pri_cmp |= PRI_LT; 1846 q++; 1847 break; 1848 case '=': 1849 pri_cmp |= PRI_EQ; 1850 q++; 1851 break; 1852 case '>': 1853 pri_cmp |= PRI_GT; 1854 q++; 1855 break; 1856 default: 1857 pri_done++; 1858 break; 1859 } 1860 } 1861 1862 /* collect priority name */ 1863 for (bp = buf; *q && !strchr("\t,; ", *q); ) 1864 *bp++ = *q++; 1865 *bp = '\0'; 1866 1867 /* skip cruft */ 1868 while (strchr(",;", *q)) 1869 q++; 1870 1871 /* decode priority name */ 1872 if (*buf == '*') { 1873 pri = LOG_PRIMASK; 1874 pri_cmp = PRI_LT | PRI_EQ | PRI_GT; 1875 } else { 1876 /* Ignore trailing spaces. */ 1877 for (i = strlen(buf) - 1; i >= 0 && buf[i] == ' '; i--) 1878 buf[i] = '\0'; 1879 1880 pri = decode(buf, prioritynames); 1881 if (pri < 0) { 1882 errno = 0; 1883 (void)snprintf(ebuf, sizeof ebuf, 1884 "unknown priority name \"%s\"", buf); 1885 logerror(ebuf); 1886 return; 1887 } 1888 } 1889 if (!pri_cmp) 1890 pri_cmp = (UniquePriority) 1891 ? (PRI_EQ) 1892 : (PRI_EQ | PRI_GT) 1893 ; 1894 if (pri_invert) 1895 pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT; 1896 1897 /* scan facilities */ 1898 while (*p && !strchr("\t.; ", *p)) { 1899 for (bp = buf; *p && !strchr("\t,;. ", *p); ) 1900 *bp++ = *p++; 1901 *bp = '\0'; 1902 1903 if (*buf == '*') { 1904 for (i = 0; i < LOG_NFACILITIES; i++) { 1905 f->f_pmask[i] = pri; 1906 f->f_pcmp[i] = pri_cmp; 1907 } 1908 } else { 1909 i = decode(buf, facilitynames); 1910 if (i < 0) { 1911 errno = 0; 1912 (void)snprintf(ebuf, sizeof ebuf, 1913 "unknown facility name \"%s\"", 1914 buf); 1915 logerror(ebuf); 1916 return; 1917 } 1918 f->f_pmask[i >> 3] = pri; 1919 f->f_pcmp[i >> 3] = pri_cmp; 1920 } 1921 while (*p == ',' || *p == ' ') 1922 p++; 1923 } 1924 1925 p = q; 1926 } 1927 1928 /* skip to action part */ 1929 while (*p == '\t' || *p == ' ') 1930 p++; 1931 1932 if (*p == '-') { 1933 syncfile = 0; 1934 p++; 1935 } else 1936 syncfile = 1; 1937 1938 switch (*p) { 1939 case '@': 1940 { 1941 char *tp; 1942 char endkey = ':'; 1943 /* 1944 * scan forward to see if there is a port defined. 1945 * so we can't use strlcpy.. 1946 */ 1947 i = sizeof(f->f_un.f_forw.f_hname); 1948 tp = f->f_un.f_forw.f_hname; 1949 p++; 1950 1951 /* 1952 * an ipv6 address should start with a '[' in that case 1953 * we should scan for a ']' 1954 */ 1955 if (*p == '[') { 1956 p++; 1957 endkey = ']'; 1958 } 1959 while (*p && (*p != endkey) && (i-- > 0)) { 1960 *tp++ = *p++; 1961 } 1962 if (endkey == ']' && *p == endkey) 1963 p++; 1964 *tp = '\0'; 1965 } 1966 /* See if we copied a domain and have a port */ 1967 if (*p == ':') 1968 p++; 1969 else 1970 p = NULL; 1971 1972 memset(&hints, 0, sizeof(hints)); 1973 hints.ai_family = family; 1974 hints.ai_socktype = SOCK_DGRAM; 1975 error = getaddrinfo(f->f_un.f_forw.f_hname, 1976 p ? p : "syslog", &hints, &res); 1977 if (error) { 1978 logerror(gai_strerror(error)); 1979 break; 1980 } 1981 f->f_un.f_forw.f_addr = res; 1982 f->f_type = F_FORW; 1983 break; 1984 1985 case '/': 1986 if ((f->f_file = open(p, logflags, 0600)) < 0) { 1987 f->f_type = F_UNUSED; 1988 logerror(p); 1989 break; 1990 } 1991 if (syncfile) 1992 f->f_flags |= FFLAG_SYNC; 1993 if (isatty(f->f_file)) { 1994 if (strcmp(p, ctty) == 0) 1995 f->f_type = F_CONSOLE; 1996 else 1997 f->f_type = F_TTY; 1998 (void)strlcpy(f->f_un.f_fname, p + sizeof(_PATH_DEV) - 1, 1999 sizeof(f->f_un.f_fname)); 2000 } else { 2001 (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname)); 2002 f->f_type = F_FILE; 2003 } 2004 break; 2005 2006 case '|': 2007 f->f_un.f_pipe.f_pid = 0; 2008 (void)strlcpy(f->f_un.f_pipe.f_pname, p + 1, 2009 sizeof(f->f_un.f_pipe.f_pname)); 2010 f->f_type = F_PIPE; 2011 break; 2012 2013 case '*': 2014 f->f_type = F_WALL; 2015 break; 2016 2017 default: 2018 for (i = 0; i < MAXUNAMES && *p; i++) { 2019 for (q = p; *q && *q != ','; ) 2020 q++; 2021 (void)strncpy(f->f_un.f_uname[i], p, MAXLOGNAME - 1); 2022 if ((q - p) >= MAXLOGNAME) 2023 f->f_un.f_uname[i][MAXLOGNAME - 1] = '\0'; 2024 else 2025 f->f_un.f_uname[i][q - p] = '\0'; 2026 while (*q == ',' || *q == ' ') 2027 q++; 2028 p = q; 2029 } 2030 f->f_type = F_USERS; 2031 break; 2032 } 2033 } 2034 2035 2036 /* 2037 * Decode a symbolic name to a numeric value 2038 */ 2039 static int 2040 decode(const char *name, const CODE *codetab) 2041 { 2042 const CODE *c; 2043 char *p, buf[40]; 2044 2045 if (isdigit(*name)) 2046 return (atoi(name)); 2047 2048 for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) { 2049 if (isupper(*name)) 2050 *p = tolower(*name); 2051 else 2052 *p = *name; 2053 } 2054 *p = '\0'; 2055 for (c = codetab; c->c_name; c++) 2056 if (!strcmp(buf, c->c_name)) 2057 return (c->c_val); 2058 2059 return (-1); 2060 } 2061 2062 static void 2063 markit(void) 2064 { 2065 struct filed *f; 2066 dq_t q, next; 2067 2068 now = time((time_t *)NULL); 2069 MarkSeq += TIMERINTVL; 2070 if (MarkSeq >= MarkInterval) { 2071 logmsg(LOG_INFO, "-- MARK --", 2072 LocalHostName, ADDDATE|MARK); 2073 MarkSeq = 0; 2074 } 2075 2076 for (f = Files; f; f = f->f_next) { 2077 if (f->f_prevcount && now >= REPEATTIME(f)) { 2078 dprintf("flush %s: repeated %d times, %d sec.\n", 2079 TypeNames[f->f_type], f->f_prevcount, 2080 repeatinterval[f->f_repeatcount]); 2081 fprintlog(f, 0, (char *)NULL); 2082 BACKOFF(f); 2083 } 2084 } 2085 2086 /* Walk the dead queue, and see if we should signal somebody. */ 2087 for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = next) { 2088 next = TAILQ_NEXT(q, dq_entries); 2089 2090 switch (q->dq_timeout) { 2091 case 0: 2092 /* Already signalled once, try harder now. */ 2093 if (kill(q->dq_pid, SIGKILL) != 0) 2094 (void)deadq_remove(q->dq_pid); 2095 break; 2096 2097 case 1: 2098 /* 2099 * Timed out on dead queue, send terminate 2100 * signal. Note that we leave the removal 2101 * from the dead queue to reapchild(), which 2102 * will also log the event (unless the process 2103 * didn't even really exist, in case we simply 2104 * drop it from the dead queue). 2105 */ 2106 if (kill(q->dq_pid, SIGTERM) != 0) 2107 (void)deadq_remove(q->dq_pid); 2108 /* FALLTHROUGH */ 2109 2110 default: 2111 q->dq_timeout--; 2112 } 2113 } 2114 MarkSet = 0; 2115 (void)alarm(TIMERINTVL); 2116 } 2117 2118 /* 2119 * fork off and become a daemon, but wait for the child to come online 2120 * before returing to the parent, or we get disk thrashing at boot etc. 2121 * Set a timer so we don't hang forever if it wedges. 2122 */ 2123 static int 2124 waitdaemon(int nochdir, int noclose, int maxwait) 2125 { 2126 int fd; 2127 int status; 2128 pid_t pid, childpid; 2129 2130 switch (childpid = fork()) { 2131 case -1: 2132 return (-1); 2133 case 0: 2134 break; 2135 default: 2136 signal(SIGALRM, timedout); 2137 alarm(maxwait); 2138 while ((pid = wait3(&status, 0, NULL)) != -1) { 2139 if (WIFEXITED(status)) 2140 errx(1, "child pid %d exited with return code %d", 2141 pid, WEXITSTATUS(status)); 2142 if (WIFSIGNALED(status)) 2143 errx(1, "child pid %d exited on signal %d%s", 2144 pid, WTERMSIG(status), 2145 WCOREDUMP(status) ? " (core dumped)" : 2146 ""); 2147 if (pid == childpid) /* it's gone... */ 2148 break; 2149 } 2150 exit(0); 2151 } 2152 2153 if (setsid() == -1) 2154 return (-1); 2155 2156 if (!nochdir) 2157 (void)chdir("/"); 2158 2159 if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 2160 (void)dup2(fd, STDIN_FILENO); 2161 (void)dup2(fd, STDOUT_FILENO); 2162 (void)dup2(fd, STDERR_FILENO); 2163 if (fd > 2) 2164 (void)close (fd); 2165 } 2166 return (getppid()); 2167 } 2168 2169 /* 2170 * We get a SIGALRM from the child when it's running and finished doing it's 2171 * fsync()'s or O_SYNC writes for all the boot messages. 2172 * 2173 * We also get a signal from the kernel if the timer expires, so check to 2174 * see what happened. 2175 */ 2176 static void 2177 timedout(int sig __unused) 2178 { 2179 int left; 2180 left = alarm(0); 2181 signal(SIGALRM, SIG_DFL); 2182 if (left == 0) 2183 errx(1, "timed out waiting for child"); 2184 else 2185 _exit(0); 2186 } 2187 2188 /* 2189 * Add `s' to the list of allowable peer addresses to accept messages 2190 * from. 2191 * 2192 * `s' is a string in the form: 2193 * 2194 * [*]domainname[:{servicename|portnumber|*}] 2195 * 2196 * or 2197 * 2198 * netaddr/maskbits[:{servicename|portnumber|*}] 2199 * 2200 * Returns -1 on error, 0 if the argument was valid. 2201 */ 2202 static int 2203 allowaddr(char *s) 2204 { 2205 char *cp1, *cp2; 2206 struct allowedpeer ap; 2207 struct servent *se; 2208 int masklen = -1; 2209 struct addrinfo hints, *res; 2210 struct in_addr *addrp, *maskp; 2211 #ifdef INET6 2212 int i; 2213 u_int32_t *addr6p, *mask6p; 2214 #endif 2215 char ip[NI_MAXHOST]; 2216 2217 #ifdef INET6 2218 if (*s != '[' || (cp1 = strchr(s + 1, ']')) == NULL) 2219 #endif 2220 cp1 = s; 2221 if ((cp1 = strrchr(cp1, ':'))) { 2222 /* service/port provided */ 2223 *cp1++ = '\0'; 2224 if (strlen(cp1) == 1 && *cp1 == '*') 2225 /* any port allowed */ 2226 ap.port = 0; 2227 else if ((se = getservbyname(cp1, "udp"))) { 2228 ap.port = ntohs(se->s_port); 2229 } else { 2230 ap.port = strtol(cp1, &cp2, 0); 2231 if (*cp2 != '\0') 2232 return (-1); /* port not numeric */ 2233 } 2234 } else { 2235 if ((se = getservbyname("syslog", "udp"))) 2236 ap.port = ntohs(se->s_port); 2237 else 2238 /* sanity, should not happen */ 2239 ap.port = 514; 2240 } 2241 2242 if ((cp1 = strchr(s, '/')) != NULL && 2243 strspn(cp1 + 1, "0123456789") == strlen(cp1 + 1)) { 2244 *cp1 = '\0'; 2245 if ((masklen = atoi(cp1 + 1)) < 0) 2246 return (-1); 2247 } 2248 #ifdef INET6 2249 if (*s == '[') { 2250 cp2 = s + strlen(s) - 1; 2251 if (*cp2 == ']') { 2252 ++s; 2253 *cp2 = '\0'; 2254 } else { 2255 cp2 = NULL; 2256 } 2257 } else { 2258 cp2 = NULL; 2259 } 2260 #endif 2261 memset(&hints, 0, sizeof(hints)); 2262 hints.ai_family = PF_UNSPEC; 2263 hints.ai_socktype = SOCK_DGRAM; 2264 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 2265 if (getaddrinfo(s, NULL, &hints, &res) == 0) { 2266 ap.isnumeric = 1; 2267 memcpy(&ap.a_addr, res->ai_addr, res->ai_addrlen); 2268 memset(&ap.a_mask, 0, sizeof(ap.a_mask)); 2269 ap.a_mask.ss_family = res->ai_family; 2270 if (res->ai_family == AF_INET) { 2271 ap.a_mask.ss_len = sizeof(struct sockaddr_in); 2272 maskp = &((struct sockaddr_in *)&ap.a_mask)->sin_addr; 2273 addrp = &((struct sockaddr_in *)&ap.a_addr)->sin_addr; 2274 if (masklen < 0) { 2275 /* use default netmask */ 2276 if (IN_CLASSA(ntohl(addrp->s_addr))) 2277 maskp->s_addr = htonl(IN_CLASSA_NET); 2278 else if (IN_CLASSB(ntohl(addrp->s_addr))) 2279 maskp->s_addr = htonl(IN_CLASSB_NET); 2280 else 2281 maskp->s_addr = htonl(IN_CLASSC_NET); 2282 } else if (masklen <= 32) { 2283 /* convert masklen to netmask */ 2284 if (masklen == 0) 2285 maskp->s_addr = 0; 2286 else 2287 maskp->s_addr = htonl(~((1 << (32 - masklen)) - 1)); 2288 } else { 2289 freeaddrinfo(res); 2290 return (-1); 2291 } 2292 /* Lose any host bits in the network number. */ 2293 addrp->s_addr &= maskp->s_addr; 2294 } 2295 #ifdef INET6 2296 else if (res->ai_family == AF_INET6 && masklen <= 128) { 2297 ap.a_mask.ss_len = sizeof(struct sockaddr_in6); 2298 if (masklen < 0) 2299 masklen = 128; 2300 mask6p = (u_int32_t *)&((struct sockaddr_in6 *)&ap.a_mask)->sin6_addr; 2301 /* convert masklen to netmask */ 2302 while (masklen > 0) { 2303 if (masklen < 32) { 2304 *mask6p = htonl(~(0xffffffff >> masklen)); 2305 break; 2306 } 2307 *mask6p++ = 0xffffffff; 2308 masklen -= 32; 2309 } 2310 /* Lose any host bits in the network number. */ 2311 mask6p = (u_int32_t *)&((struct sockaddr_in6 *)&ap.a_mask)->sin6_addr; 2312 addr6p = (u_int32_t *)&((struct sockaddr_in6 *)&ap.a_addr)->sin6_addr; 2313 for (i = 0; i < 4; i++) 2314 addr6p[i] &= mask6p[i]; 2315 } 2316 #endif 2317 else { 2318 freeaddrinfo(res); 2319 return (-1); 2320 } 2321 freeaddrinfo(res); 2322 } else { 2323 /* arg `s' is domain name */ 2324 ap.isnumeric = 0; 2325 ap.a_name = s; 2326 if (cp1) 2327 *cp1 = '/'; 2328 #ifdef INET6 2329 if (cp2) { 2330 *cp2 = ']'; 2331 --s; 2332 } 2333 #endif 2334 } 2335 2336 if (Debug) { 2337 printf("allowaddr: rule %d: ", NumAllowed); 2338 if (ap.isnumeric) { 2339 printf("numeric, "); 2340 getnameinfo((struct sockaddr *)&ap.a_addr, 2341 ((struct sockaddr *)&ap.a_addr)->sa_len, 2342 ip, sizeof ip, NULL, 0, NI_NUMERICHOST); 2343 printf("addr = %s, ", ip); 2344 getnameinfo((struct sockaddr *)&ap.a_mask, 2345 ((struct sockaddr *)&ap.a_mask)->sa_len, 2346 ip, sizeof ip, NULL, 0, NI_NUMERICHOST); 2347 printf("mask = %s; ", ip); 2348 } else { 2349 printf("domainname = %s; ", ap.a_name); 2350 } 2351 printf("port = %d\n", ap.port); 2352 } 2353 2354 if ((AllowedPeers = realloc(AllowedPeers, 2355 ++NumAllowed * sizeof(struct allowedpeer))) 2356 == NULL) { 2357 logerror("realloc"); 2358 exit(1); 2359 } 2360 memcpy(&AllowedPeers[NumAllowed - 1], &ap, sizeof(struct allowedpeer)); 2361 return (0); 2362 } 2363 2364 /* 2365 * Validate that the remote peer has permission to log to us. 2366 */ 2367 static int 2368 validate(struct sockaddr *sa, const char *hname) 2369 { 2370 int i; 2371 size_t l1, l2; 2372 char *cp, name[NI_MAXHOST], ip[NI_MAXHOST], port[NI_MAXSERV]; 2373 struct allowedpeer *ap; 2374 struct sockaddr_in *sin4, *a4p = NULL, *m4p = NULL; 2375 #ifdef INET6 2376 int j, reject; 2377 struct sockaddr_in6 *sin6, *a6p = NULL, *m6p = NULL; 2378 #endif 2379 struct addrinfo hints, *res; 2380 u_short sport; 2381 2382 if (NumAllowed == 0) 2383 /* traditional behaviour, allow everything */ 2384 return (1); 2385 2386 (void)strlcpy(name, hname, sizeof(name)); 2387 memset(&hints, 0, sizeof(hints)); 2388 hints.ai_family = PF_UNSPEC; 2389 hints.ai_socktype = SOCK_DGRAM; 2390 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 2391 if (getaddrinfo(name, NULL, &hints, &res) == 0) 2392 freeaddrinfo(res); 2393 else if (strchr(name, '.') == NULL) { 2394 strlcat(name, ".", sizeof name); 2395 strlcat(name, LocalDomain, sizeof name); 2396 } 2397 if (getnameinfo(sa, sa->sa_len, ip, sizeof ip, port, sizeof port, 2398 NI_NUMERICHOST | NI_NUMERICSERV) != 0) 2399 return (0); /* for safety, should not occur */ 2400 dprintf("validate: dgram from IP %s, port %s, name %s;\n", 2401 ip, port, name); 2402 sport = atoi(port); 2403 2404 /* now, walk down the list */ 2405 for (i = 0, ap = AllowedPeers; i < NumAllowed; i++, ap++) { 2406 if (ap->port != 0 && ap->port != sport) { 2407 dprintf("rejected in rule %d due to port mismatch.\n", i); 2408 continue; 2409 } 2410 2411 if (ap->isnumeric) { 2412 if (ap->a_addr.ss_family != sa->sa_family) { 2413 dprintf("rejected in rule %d due to address family mismatch.\n", i); 2414 continue; 2415 } 2416 if (ap->a_addr.ss_family == AF_INET) { 2417 sin4 = (struct sockaddr_in *)sa; 2418 a4p = (struct sockaddr_in *)&ap->a_addr; 2419 m4p = (struct sockaddr_in *)&ap->a_mask; 2420 if ((sin4->sin_addr.s_addr & m4p->sin_addr.s_addr) 2421 != a4p->sin_addr.s_addr) { 2422 dprintf("rejected in rule %d due to IP mismatch.\n", i); 2423 continue; 2424 } 2425 } 2426 #ifdef INET6 2427 else if (ap->a_addr.ss_family == AF_INET6) { 2428 sin6 = (struct sockaddr_in6 *)sa; 2429 a6p = (struct sockaddr_in6 *)&ap->a_addr; 2430 m6p = (struct sockaddr_in6 *)&ap->a_mask; 2431 if (a6p->sin6_scope_id != 0 && 2432 sin6->sin6_scope_id != a6p->sin6_scope_id) { 2433 dprintf("rejected in rule %d due to scope mismatch.\n", i); 2434 continue; 2435 } 2436 reject = 0; 2437 for (j = 0; j < 16; j += 4) { 2438 if ((*(u_int32_t *)&sin6->sin6_addr.s6_addr[j] & *(u_int32_t *)&m6p->sin6_addr.s6_addr[j]) 2439 != *(u_int32_t *)&a6p->sin6_addr.s6_addr[j]) { 2440 ++reject; 2441 break; 2442 } 2443 } 2444 if (reject) { 2445 dprintf("rejected in rule %d due to IP mismatch.\n", i); 2446 continue; 2447 } 2448 } 2449 #endif 2450 else 2451 continue; 2452 } else { 2453 cp = ap->a_name; 2454 l1 = strlen(name); 2455 if (*cp == '*') { 2456 /* allow wildmatch */ 2457 cp++; 2458 l2 = strlen(cp); 2459 if (l2 > l1 || memcmp(cp, &name[l1 - l2], l2) != 0) { 2460 dprintf("rejected in rule %d due to name mismatch.\n", i); 2461 continue; 2462 } 2463 } else { 2464 /* exact match */ 2465 l2 = strlen(cp); 2466 if (l2 != l1 || memcmp(cp, name, l1) != 0) { 2467 dprintf("rejected in rule %d due to name mismatch.\n", i); 2468 continue; 2469 } 2470 } 2471 } 2472 dprintf("accepted in rule %d.\n", i); 2473 return (1); /* hooray! */ 2474 } 2475 return (0); 2476 } 2477 2478 /* 2479 * Fairly similar to popen(3), but returns an open descriptor, as 2480 * opposed to a FILE *. 2481 */ 2482 static int 2483 p_open(const char *prog, pid_t *rpid) 2484 { 2485 int pfd[2], nulldesc; 2486 pid_t pid; 2487 sigset_t omask, mask; 2488 char *argv[4]; /* sh -c cmd NULL */ 2489 char errmsg[200]; 2490 2491 if (pipe(pfd) == -1) 2492 return (-1); 2493 if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1) 2494 /* we are royally screwed anyway */ 2495 return (-1); 2496 2497 sigemptyset(&mask); 2498 sigaddset(&mask, SIGALRM); 2499 sigaddset(&mask, SIGHUP); 2500 sigprocmask(SIG_BLOCK, &mask, &omask); 2501 switch ((pid = fork())) { 2502 case -1: 2503 sigprocmask(SIG_SETMASK, &omask, 0); 2504 close(nulldesc); 2505 return (-1); 2506 2507 case 0: 2508 argv[0] = strdup("sh"); 2509 argv[1] = strdup("-c"); 2510 argv[2] = strdup(prog); 2511 argv[3] = NULL; 2512 if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) { 2513 logerror("strdup"); 2514 exit(1); 2515 } 2516 2517 alarm(0); 2518 (void)setsid(); /* Avoid catching SIGHUPs. */ 2519 2520 /* 2521 * Throw away pending signals, and reset signal 2522 * behaviour to standard values. 2523 */ 2524 signal(SIGALRM, SIG_IGN); 2525 signal(SIGHUP, SIG_IGN); 2526 sigprocmask(SIG_SETMASK, &omask, 0); 2527 signal(SIGPIPE, SIG_DFL); 2528 signal(SIGQUIT, SIG_DFL); 2529 signal(SIGALRM, SIG_DFL); 2530 signal(SIGHUP, SIG_DFL); 2531 2532 dup2(pfd[0], STDIN_FILENO); 2533 dup2(nulldesc, STDOUT_FILENO); 2534 dup2(nulldesc, STDERR_FILENO); 2535 closefrom(3); 2536 2537 (void)execvp(_PATH_BSHELL, argv); 2538 _exit(255); 2539 } 2540 2541 sigprocmask(SIG_SETMASK, &omask, 0); 2542 close(nulldesc); 2543 close(pfd[0]); 2544 /* 2545 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are 2546 * supposed to get an EWOULDBLOCK on writev(2), which is 2547 * caught by the logic above anyway, which will in turn close 2548 * the pipe, and fork a new logging subprocess if necessary. 2549 * The stale subprocess will be killed some time later unless 2550 * it terminated itself due to closing its input pipe (so we 2551 * get rid of really dead puppies). 2552 */ 2553 if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) { 2554 /* This is bad. */ 2555 (void)snprintf(errmsg, sizeof errmsg, 2556 "Warning: cannot change pipe to PID %d to " 2557 "non-blocking behaviour.", 2558 (int)pid); 2559 logerror(errmsg); 2560 } 2561 *rpid = pid; 2562 return (pfd[1]); 2563 } 2564 2565 static void 2566 deadq_enter(pid_t pid, const char *name) 2567 { 2568 dq_t p; 2569 int status; 2570 2571 /* 2572 * Be paranoid, if we can't signal the process, don't enter it 2573 * into the dead queue (perhaps it's already dead). If possible, 2574 * we try to fetch and log the child's status. 2575 */ 2576 if (kill(pid, 0) != 0) { 2577 if (waitpid(pid, &status, WNOHANG) > 0) 2578 log_deadchild(pid, status, name); 2579 return; 2580 } 2581 2582 p = malloc(sizeof(struct deadq_entry)); 2583 if (p == NULL) { 2584 logerror("malloc"); 2585 exit(1); 2586 } 2587 2588 p->dq_pid = pid; 2589 p->dq_timeout = DQ_TIMO_INIT; 2590 TAILQ_INSERT_TAIL(&deadq_head, p, dq_entries); 2591 } 2592 2593 static int 2594 deadq_remove(pid_t pid) 2595 { 2596 dq_t q; 2597 2598 TAILQ_FOREACH(q, &deadq_head, dq_entries) { 2599 if (q->dq_pid == pid) { 2600 TAILQ_REMOVE(&deadq_head, q, dq_entries); 2601 free(q); 2602 return (1); 2603 } 2604 } 2605 2606 return (0); 2607 } 2608 2609 static void 2610 log_deadchild(pid_t pid, int status, const char *name) 2611 { 2612 int code; 2613 char buf[256]; 2614 const char *reason; 2615 2616 errno = 0; /* Keep strerror() stuff out of logerror messages. */ 2617 if (WIFSIGNALED(status)) { 2618 reason = "due to signal"; 2619 code = WTERMSIG(status); 2620 } else { 2621 reason = "with status"; 2622 code = WEXITSTATUS(status); 2623 if (code == 0) 2624 return; 2625 } 2626 (void)snprintf(buf, sizeof buf, 2627 "Logging subprocess %d (%s) exited %s %d.", 2628 pid, name, reason, code); 2629 logerror(buf); 2630 } 2631 2632 static int * 2633 socksetup(int af, char *bindhostname) 2634 { 2635 struct addrinfo hints, *res, *r; 2636 const char *bindservice; 2637 char *cp; 2638 int error, maxs, *s, *socks; 2639 2640 /* 2641 * We have to handle this case for backwards compatibility: 2642 * If there are two (or more) colons but no '[' and ']', 2643 * assume this is an inet6 address without a service. 2644 */ 2645 bindservice = "syslog"; 2646 if (bindhostname != NULL) { 2647 #ifdef INET6 2648 if (*bindhostname == '[' && 2649 (cp = strchr(bindhostname + 1, ']')) != NULL) { 2650 ++bindhostname; 2651 *cp = '\0'; 2652 if (cp[1] == ':' && cp[2] != '\0') 2653 bindservice = cp + 2; 2654 } else { 2655 #endif 2656 cp = strchr(bindhostname, ':'); 2657 if (cp != NULL && strchr(cp + 1, ':') == NULL) { 2658 *cp = '\0'; 2659 if (cp[1] != '\0') 2660 bindservice = cp + 1; 2661 if (cp == bindhostname) 2662 bindhostname = NULL; 2663 } 2664 #ifdef INET6 2665 } 2666 #endif 2667 } 2668 2669 memset(&hints, 0, sizeof(hints)); 2670 hints.ai_flags = AI_PASSIVE; 2671 hints.ai_family = af; 2672 hints.ai_socktype = SOCK_DGRAM; 2673 error = getaddrinfo(bindhostname, bindservice, &hints, &res); 2674 if (error) { 2675 logerror(gai_strerror(error)); 2676 errno = 0; 2677 die(0); 2678 } 2679 2680 /* Count max number of sockets we may open */ 2681 for (maxs = 0, r = res; r; r = r->ai_next, maxs++); 2682 socks = malloc((maxs+1) * sizeof(int)); 2683 if (socks == NULL) { 2684 logerror("couldn't allocate memory for sockets"); 2685 die(0); 2686 } 2687 2688 *socks = 0; /* num of sockets counter at start of array */ 2689 s = socks + 1; 2690 for (r = res; r; r = r->ai_next) { 2691 int on = 1; 2692 *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 2693 if (*s < 0) { 2694 logerror("socket"); 2695 continue; 2696 } 2697 #ifdef INET6 2698 if (r->ai_family == AF_INET6) { 2699 if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, 2700 (char *)&on, sizeof (on)) < 0) { 2701 logerror("setsockopt"); 2702 close(*s); 2703 continue; 2704 } 2705 } 2706 #endif 2707 if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, 2708 (char *)&on, sizeof (on)) < 0) { 2709 logerror("setsockopt"); 2710 close(*s); 2711 continue; 2712 } 2713 /* 2714 * RFC 3164 recommends that client side message 2715 * should come from the privileged syslogd port. 2716 * 2717 * If the system administrator choose not to obey 2718 * this, we can skip the bind() step so that the 2719 * system will choose a port for us. 2720 */ 2721 if (!NoBind) { 2722 if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { 2723 logerror("bind"); 2724 close(*s); 2725 continue; 2726 } 2727 2728 if (!SecureMode) 2729 increase_rcvbuf(*s); 2730 } 2731 2732 (*socks)++; 2733 s++; 2734 } 2735 2736 if (*socks == 0) { 2737 free(socks); 2738 if (Debug) 2739 return (NULL); 2740 else 2741 die(0); 2742 } 2743 if (res) 2744 freeaddrinfo(res); 2745 2746 return (socks); 2747 } 2748 2749 static void 2750 increase_rcvbuf(int fd) 2751 { 2752 socklen_t len, slen; 2753 2754 slen = sizeof(len); 2755 2756 if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, &slen) == 0) { 2757 if (len < RCVBUF_MINSIZE) { 2758 len = RCVBUF_MINSIZE; 2759 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)); 2760 } 2761 } 2762 } 2763