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