/** * Make sure each of the input files is findable. * Also, while we are at it, compute the output file mod time * based on the mod time of the most recent file. */ static void set_modtime(void) { int ct = STACKCT_OPT(INPUT); char const ** ppz = STACKLST_OPT(INPUT); struct stat stb; if ((ct == 1) && (strcmp(*ppz, "-") == 0)) { /* * Read the list of input files from stdin. */ loadStdin(); ct = STACKCT_OPT( INPUT); ppz = STACKLST_OPT(INPUT); } do { if (stat(*ppz++, &stb) != 0) break; if (! S_ISREG(stb.st_mode)) { errno = EINVAL; break; } if (++(stb.st_mtime) > modtime) modtime = stb.st_mtime; } while (--ct > 0); if (ct > 0) fserr_die("stat-ing %s for text file\n", ppz[-1]); }
/* * processEmbeddedOptions * * This routine processes the text contained within "/\*==--" * and "=\*\/" as a single option. If that option is the SUBBLOCK * option, it will need to be massaged for use. */ LOCAL void processEmbeddedOptions(char* pzText) { tSCC zStStr[] = "/*=--"; tSCC zEndSt[] = "=*/"; for (;;) { char* pzStart = strstr(pzText, zStStr); char* pzEnd; int sblct = 0; if (pzStart == NULL) return; if (HAVE_OPT(SUBBLOCK)) sblct = STACKCT_OPT(SUBBLOCK); pzEnd = strstr(pzStart, zEndSt); if (pzEnd == NULL) return; pzStart = compressOptionText(pzStart + sizeof(zStStr)-1, pzEnd); optionLoadLine(&getdefsOptions, pzStart); if (HAVE_OPT(SUBBLOCK) && (sblct != STACKCT_OPT(SUBBLOCK))) { tCC** ppz = STACKLST_OPT(SUBBLOCK); ppz[ sblct ] = fixupSubblockString(ppz[sblct]); } pzText = pzEnd + sizeof(zEndSt); } }
static void exec_autogen(char ** pzBase) { char const ** paparg; char const ** pparg; int argCt = 5; /* * IF we don't have template search directories, * THEN allocate the default arg counter of pointers and * set the program name into it. * ELSE insert each one into the arg list. */ if (! HAVE_OPT(AGARG)) { paparg = pparg = (char const **)malloc(argCt * sizeof(char*)); *pparg++ = pzAutogen; } else { int ct = STACKCT_OPT(AGARG); char const ** ppz = STACKLST_OPT(AGARG); argCt += ct; paparg = pparg = (char const **)malloc(argCt * sizeof(char*)); *pparg++ = pzAutogen; do { *pparg++ = *ppz++; } while (--ct > 0); } *pparg++ = *pzBase; *pparg++ = "--"; *pparg++ = "-"; *pparg++ = NULL; #ifdef DEBUG fputc('\n', stderr); pparg = paparg; for (;;) { fputs(*pparg++, stderr); if (*pparg == NULL) break; fputc(' ', stderr); } fputc('\n', stderr); fputc('\n', stderr); #endif execvp(pzAutogen, (char**)(void*)paparg); fserr_die("exec of %s %s %s %s\n", paparg[0], paparg[1], paparg[2], paparg[3]); }
static FILE* open_ag_file(char ** pzBase) { switch (WHICH_IDX_AUTOGEN) { case INDEX_OPT_OUTPUT: { static char const zFileFmt[] = " * %s\n"; FILE* fp; if (*pzBase != NULL) free(*pzBase); if (strcmp(OPT_ARG(OUTPUT), "-") == 0) return stdout; unlink(OPT_ARG(OUTPUT)); fp = fopen(OPT_ARG(OUTPUT), "w" FOPEN_BINARY_FLAG); fprintf(fp, zDne, OPT_ARG(OUTPUT)); if (HAVE_OPT(INPUT)) { int ct = STACKCT_OPT(INPUT); char const ** ppz = STACKLST_OPT(INPUT); do { fprintf(fp, zFileFmt, *ppz++); } while (--ct > 0); } fputs(" */\n", fp); return fp; } case INDEX_OPT_AUTOGEN: if (! ENABLED_OPT(AUTOGEN)) { if (*pzBase != NULL) free(*pzBase); return stdout; } if ( ( OPT_ARG(AUTOGEN) != NULL) && (*OPT_ARG(AUTOGEN) != NUL )) pzAutogen = OPT_ARG(AUTOGEN); break; } return NULL; }
void write_results(void) { int ct = STACKCT_OPT(OUTPUT); char **output = (char **) &STACKLST_OPT(OUTPUT); int i; xmlDocPtr doc; doc = UpwatchXmlDoc("result", NULL); g_hash_table_foreach(cache, write_probe, doc); xmlSetDocCompressMode(doc, OPT_VALUE_COMPRESS); for (i=0; i < ct; i++) { spool_result(OPT_ARG(SPOOLDIR), output[i], doc, NULL); } xmlFreeDoc(doc); }
/* * This is where you should define all your AutoGen AutoOpts option parsing. * Any user specified option should have it's bit turned on in the 'provides' * bit mask. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_user_parse_opts(tcpeditdlt_t *ctx) { tcpeditdlt_plugin_t *plugin; user_config_t *config; assert(ctx); plugin = tcpedit_dlt_getplugin(ctx, dlt_value); config = plugin->config; /* * --user-dlt will override the output DLT type, otherwise we'll use * the DLT of the decoder */ if (HAVE_OPT(USER_DLT)) { config->dlt = OPT_VALUE_USER_DLT; } else { config->dlt = ctx->decoder->dlt; } /* --user-dlink */ if (HAVE_OPT(USER_DLINK)) { int ct = STACKCT_OPT(USER_DLINK); char **list = STACKLST_OPT(USER_DLINK); int first = 1; do { char *p = *list++; if (first) { config->length = read_hexstring(p, config->l2server, USER_L2MAXLEN); memcpy(config->l2client, config->l2server, config->length); } else { if (config->length != read_hexstring(p, config->l2client, USER_L2MAXLEN)) { tcpedit_seterr(ctx->tcpedit, "%s", "both --dlink's must contain the same number of bytes"); return TCPEDIT_ERROR; } } first = 0; } while (--ct > 0); } return TCPEDIT_OK; /* success */ }
/* * loadStdin * * The input file list is from stdin. * * We make some simplifying assumptions: * *ALL* input lines are less than 4096 bytes. If this is not true, * we may strip some white space in the middle of a line and presume * a comment begins in the middle of a line or we only comment out * the first 4096 bytes of a comment line. So, rather than all these * problems, we just choke on it. */ static void loadStdin(void) { char z[ 4096 ]; int ct = 0; tCC** ppz = STACKLST_OPT(INPUT); if (isatty(STDIN_FILENO)) { fputs("getdefs error: no inputs were specified and stdin is a tty\n", stderr); USAGE(EXIT_FAILURE); } while (fgets(z, (int)sizeof(z), stdin) != NULL) { char* pz = z + strlen(z); if (pz[-1] != '\n') { tSCC zErr[] = "getdefs error: input line not newline terminated\n"; fputs(zErr, stderr); exit(EXIT_FAILURE); } while ((pz > z) && isspace(pz[-1])) pz--; *pz = '\0'; pz = z; while (isspace(*pz)) pz++; if ((*pz == '\0') || (*pz == '#')) continue; if (access(pz, R_OK) != 0) continue; if (ct++ == 0) *ppz = strdup(z); /* replace the "-" */ else SET_OPT_INPUT(strdup(z)); /* if 'strdup' fails, we die later */ } }
/* * Main program. Initialize us, disconnect us from the tty if necessary, * and loop waiting for I/O and/or timer expiries. */ int ntpdmain( int argc, char *argv[] ) { l_fp now; struct recvbuf *rbuf; #ifdef _AIX /* HMS: ifdef SIGDANGER? */ struct sigaction sa; #endif progname = argv[0]; initializing = 1; /* mark that we are initializing */ process_commandline_opts(&argc, &argv); init_logging(progname, 1); /* Open the log file */ char *error = NULL; if (sandbox_init("ntpd", SANDBOX_NAMED, &error) == -1) { msyslog(LOG_ERR, "sandbox_init(ntpd, SANDBOX_NAMED) failed: %s", error); sandbox_free_error(error); } #ifdef HAVE_UMASK { mode_t uv; uv = umask(0); if(uv) (void) umask(uv); else (void) umask(022); } #endif #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ { uid_t uid; uid = getuid(); if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); printf("must be run as root, not uid %ld\n", (long)uid); exit(1); } } #endif /* getstartup(argc, argv); / * startup configuration, may set debug */ #ifdef DEBUG debug = DESC(DEBUG_LEVEL).optOccCt; DPRINTF(1, ("%s\n", Version)); #endif /* honor -l/--logfile option to log to a file */ setup_logfile(); /* * Enable the Multi-Media Timer for Windows? */ #ifdef SYS_WINNT if (HAVE_OPT( MODIFYMMTIMER )) set_mm_timer(MM_TIMER_HIRES); #endif if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ) #ifdef DEBUG || debug #endif || HAVE_OPT( SAVECONFIGQUIT )) nofork = 1; if (HAVE_OPT( NOVIRTUALIPS )) listen_to_virtual_ips = 0; /* * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); isc_netaddr_t netaddr; while (ifacect-- > 0) { add_nic_rule( is_ip_address(*ifaces, &netaddr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN); ifaces++; } } if (HAVE_OPT( NICE )) priority_done = 0; #if defined(HAVE_SCHED_SETSCHEDULER) if (HAVE_OPT( PRIORITY )) { config_priority = OPT_VALUE_PRIORITY; config_priority_override = 1; priority_done = 0; } #endif #ifdef SYS_WINNT /* * Start interpolation thread, must occur before first * get_systime() */ init_winnt_time(); #endif /* * Initialize random generator and public key pair */ get_systime(&now); ntp_srandom((int)(now.l_i * now.l_uf)); #if !defined(VMS) # ifndef NODETACH /* * Detach us from the terminal. May need an #ifndef GIZMO. */ if (!nofork) { /* * Install trap handlers to log errors and assertion * failures. Default handlers print to stderr which * doesn't work if detached. */ isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); # ifndef SYS_WINNT # ifdef HAVE_DAEMON daemon(0, 0); # else /* not HAVE_DAEMON */ if (fork()) /* HMS: What about a -1? */ exit(0); { #if !defined(F_CLOSEM) u_long s; int max_fd; #endif /* !FCLOSEM */ if (syslog_file != NULL) { fclose(syslog_file); syslog_file = NULL; } #if defined(F_CLOSEM) /* * From 'Writing Reliable AIX Daemons,' SG24-4946-00, * by Eric Agar (saves us from doing 32767 system * calls) */ if (fcntl(0, F_CLOSEM, 0) == -1) msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); #else /* not F_CLOSEM */ # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) max_fd = sysconf(_SC_OPEN_MAX); # else /* HAVE_SYSCONF && _SC_OPEN_MAX */ max_fd = getdtablesize(); # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ for (s = 0; s < max_fd; s++) (void) close((int)s); #endif /* not F_CLOSEM */ (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); init_logging(progname, 0); /* we lost our logfile (if any) daemonizing */ setup_logfile(); #ifdef SYS_DOMAINOS { uid_$t puid; status_$t st; proc2_$who_am_i(&puid); proc2_$make_server(&puid, &st); } #endif /* SYS_DOMAINOS */ #if defined(HAVE_SETPGID) || defined(HAVE_SETSID) # ifdef HAVE_SETSID if (setsid() == (pid_t)-1) msyslog(LOG_ERR, "ntpd: setsid(): %m"); # else if (setpgid(0, 0) == -1) msyslog(LOG_ERR, "ntpd: setpgid(): %m"); # endif #else /* HAVE_SETPGID || HAVE_SETSID */ { # if defined(TIOCNOTTY) int fid; fid = open("/dev/tty", 2); if (fid >= 0) { (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); (void) close(fid); } # endif /* defined(TIOCNOTTY) */ # ifdef HAVE_SETPGRP_0 (void) setpgrp(); # else /* HAVE_SETPGRP_0 */ (void) setpgrp(0, getpid()); # endif /* HAVE_SETPGRP_0 */ } #endif /* HAVE_SETPGID || HAVE_SETSID */ #ifdef _AIX /* Don't get killed by low-on-memory signal. */ sa.sa_handler = catch_danger; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; (void) sigaction(SIGDANGER, &sa, NULL); #endif /* _AIX */ } # endif /* not HAVE_DAEMON */ # endif /* SYS_WINNT */ } # endif /* NODETACH */ #endif /* VMS */ #ifdef SCO5_CLOCK /* * SCO OpenServer's system clock offers much more precise timekeeping * on the base CPU than the other CPUs (for multiprocessor systems), * so we must lock to the base CPU. */ { int fd = open("/dev/at1", O_RDONLY); if (fd >= 0) { int zero = 0; if (ioctl(fd, ACPU_LOCK, &zero) < 0) msyslog(LOG_ERR, "cannot lock to base CPU: %m"); close( fd ); } /* else ... * If we can't open the device, this probably just isn't * a multiprocessor system, so we're A-OK. */ } #endif #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) # ifdef HAVE_SETRLIMIT /* * Set the stack limit to something smaller, so that we don't lock a lot * of unused stack memory. */ { struct rlimit rl; /* HMS: must make the rlim_cur amount configurable */ if (getrlimit(RLIMIT_STACK, &rl) != -1 && (rl.rlim_cur = 50 * 4096) < rl.rlim_max) { if (setrlimit(RLIMIT_STACK, &rl) == -1) { msyslog(LOG_ERR, "Cannot adjust stack limit for mlockall: %m"); } } # ifdef RLIMIT_MEMLOCK /* * The default RLIMIT_MEMLOCK is very low on Linux systems. * Unless we increase this limit malloc calls are likely to * fail if we drop root privlege. To be useful the value * has to be larger than the largest ntpd resident set size. */ rl.rlim_cur = rl.rlim_max = 32*1024*1024; if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) { msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); } # endif /* RLIMIT_MEMLOCK */ } # endif /* HAVE_SETRLIMIT */ /* * lock the process into memory */ if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) msyslog(LOG_ERR, "mlockall(): %m"); #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ # ifdef HAVE_PLOCK # ifdef PROCLOCK # ifdef _AIX /* * set the stack limit for AIX for plock(). * see get_aix_stack() for more info. */ if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) { msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); } # endif /* _AIX */ /* * lock the process into memory */ if (plock(PROCLOCK) < 0) msyslog(LOG_ERR, "plock(PROCLOCK): %m"); # else /* not PROCLOCK */ # ifdef TXTLOCK /* * Lock text into ram */ if (plock(TXTLOCK) < 0) msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); # else /* not TXTLOCK */ msyslog(LOG_ERR, "plock() - don't know what to lock!"); # endif /* not TXTLOCK */ # endif /* not PROCLOCK */ # endif /* HAVE_PLOCK */ #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ /* * Set up signals we pay attention to locally. */ #ifdef SIGDIE1 (void) signal_no_reset(SIGDIE1, finish); #endif /* SIGDIE1 */ #ifdef SIGDIE2 (void) signal_no_reset(SIGDIE2, finish); #endif /* SIGDIE2 */ #ifdef SIGDIE3 (void) signal_no_reset(SIGDIE3, finish); #endif /* SIGDIE3 */ #ifdef SIGDIE4 (void) signal_no_reset(SIGDIE4, finish); #endif /* SIGDIE4 */ #ifdef SIGBUS (void) signal_no_reset(SIGBUS, finish); #endif /* SIGBUS */ #if !defined(SYS_WINNT) && !defined(VMS) # ifdef DEBUG (void) signal_no_reset(MOREDEBUGSIG, moredebug); (void) signal_no_reset(LESSDEBUGSIG, lessdebug); # else (void) signal_no_reset(MOREDEBUGSIG, no_debug); (void) signal_no_reset(LESSDEBUGSIG, no_debug); # endif /* DEBUG */ #endif /* !SYS_WINNT && !VMS */ /* * Set up signals we should never pay attention to. */ #if defined SIGPIPE (void) signal_no_reset(SIGPIPE, SIG_IGN); #endif /* SIGPIPE */ /* * Call the init_ routines to initialize the data structures. * * Exactly what command-line options are we expecting here? */ init_auth(); init_util(); init_restrict(); init_mon(); init_timer(); init_lib(); init_request(); init_control(); init_peer(); #ifdef REFCLOCK init_refclock(); #endif set_process_priority(); init_proto(); /* Call at high priority */ init_io(); init_loopfilter(); mon_start(MON_ON); /* monitor on by default now */ /* turn off in config if unwanted */ /* * Get the configuration. This is done in a separate module * since this will definitely be different for the gizmo board. */ getconfig(argc, argv); NLOG(NLOG_SYSINFO) /* 'if' clause for syslog */ msyslog(LOG_NOTICE, "%s", Version); report_event(EVNT_SYSRESTART, NULL, NULL); loop_config(LOOP_DRIFTCOMP, old_drift); initializing = 0; #ifdef HAVE_DROPROOT if( droproot ) { /* Drop super-user privileges and chroot now if the OS supports this */ #ifdef HAVE_LINUX_CAPABILITIES /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); exit(-1); } #else /* we need a user to switch to */ if (user == NULL) { msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); exit(-1); } #endif /* HAVE_LINUX_CAPABILITIES */ if (user != NULL) { if (isdigit((unsigned char)*user)) { sw_uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; if ((pw = getpwuid(sw_uid)) != NULL) { user = strdup(pw->pw_name); if (NULL == user) { msyslog(LOG_ERR, "strdup() failed: %m"); exit (-1); } sw_gid = pw->pw_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find user ID %s", user); exit (-1); } } else { getuser: errno = 0; if ((pw = getpwnam(user)) != NULL) { sw_uid = pw->pw_uid; sw_gid = pw->pw_gid; } else { if (errno) msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); else msyslog(LOG_ERR, "Cannot find user `%s'", user); exit (-1); } } } if (group != NULL) { if (isdigit((unsigned char)*group)) { sw_gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gr = getgrnam(group)) != NULL) { sw_gid = gr->gr_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find group `%s'", group); exit (-1); } } } if (chrootdir ) { /* make sure cwd is inside the jail: */ if (chdir(chrootdir)) { msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); exit (-1); } if (chroot(chrootdir)) { msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); exit (-1); } if (chdir("/")) { msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); exit (-1); } } if (user && initgroups(user, sw_gid)) { msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); exit (-1); } if (group && setgid(sw_gid)) { msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); exit (-1); } if (group && setegid(sw_gid)) { msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); exit (-1); } if (user && setuid(sw_uid)) { msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); exit (-1); } if (user && seteuid(sw_uid)) { msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); exit (-1); } #ifndef HAVE_LINUX_CAPABILITIES /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on * ports that allow binding to NTP_PORT with uid != 0 */ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ #endif if (disable_dynamic_updates && interface_interval) { interface_interval = 0; msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking"); } #ifdef HAVE_LINUX_CAPABILITIES do { /* * We may be running under non-root uid now, but we still hold full root privileges! * We drop all of them, except for the crucial one or two: cap_sys_time and * cap_net_bind_service if doing dynamic interface tracking. */ cap_t caps; char *captext = (interface_interval) ? "cap_sys_time,cap_net_bind_service=ipe" : "cap_sys_time=ipe"; if( ! ( caps = cap_from_text( captext ) ) ) { msyslog( LOG_ERR, "cap_from_text() failed: %m" ); exit(-1); } if( cap_set_proc( caps ) == -1 ) { msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" ); exit(-1); } cap_free( caps ); } while(0); #endif /* HAVE_LINUX_CAPABILITIES */ } /* if( droproot ) */ #endif /* HAVE_DROPROOT */ /* * Use select() on all on all input fd's for unlimited * time. select() will terminate on SIGALARM or on the * reception of input. Using select() means we can't do * robust signal handling and we get a potential race * between checking for alarms and doing the select(). * Mostly harmless, I think. */ /* On VMS, I suspect that select() can't be interrupted * by a "signal" either, so I take the easy way out and * have select() time out after one second. * System clock updates really aren't time-critical, * and - lacking a hardware reference clock - I have * yet to learn about anything else that is. */ #if defined(HAVE_IO_COMPLETION_PORT) for (;;) { GetReceivedBuffers(); #else /* normal I/O */ BLOCK_IO_AND_ALARM(); was_alarmed = 0; for (;;) { # if !defined(HAVE_SIGNALED_IO) extern fd_set activefds; extern int maxactivefd; fd_set rdfdes; int nfound; # endif if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE) { /* * Nothing to do. Wait for something. */ # ifndef HAVE_SIGNALED_IO rdfdes = activefds; # if defined(VMS) || defined(SYS_VXWORKS) /* make select() wake up after one second */ { struct timeval t1; t1.tv_sec = 1; t1.tv_usec = 0; nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, &t1); } # else nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, (struct timeval *)0); # endif /* VMS */ if (nfound > 0) { l_fp ts; get_systime(&ts); (void)input_handler(&ts); } else if (nfound == -1 && errno != EINTR) msyslog(LOG_ERR, "select() error: %m"); # ifdef DEBUG else if (debug > 5) msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); # endif /* DEBUG */ # else /* HAVE_SIGNALED_IO */ wait_for_signal(); # endif /* HAVE_SIGNALED_IO */ if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } } if (was_alarmed) { UNBLOCK_IO_AND_ALARM(); /* * Out here, signals are unblocked. Call timer routine * to process expiry. */ timer(); was_alarmed = 0; BLOCK_IO_AND_ALARM(); } #endif /* ! HAVE_IO_COMPLETION_PORT */ #ifdef DEBUG_TIMING { l_fp pts; l_fp tsa, tsb; int bufcount = 0; get_systime(&pts); tsa = pts; #endif rbuf = get_full_recv_buffer(); while (rbuf != NULL) { if (alarm_flag) { was_alarmed = 1; alarm_flag = 0; } UNBLOCK_IO_AND_ALARM(); if (was_alarmed) { /* avoid timer starvation during lengthy I/O handling */ timer(); was_alarmed = 0; } /* * Call the data procedure to handle each received * packet. */ if (rbuf->receiver != NULL) /* This should always be true */ { #ifdef DEBUG_TIMING l_fp dts = pts; L_SUB(&dts, &rbuf->recv_time); DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); collect_timing(rbuf, "buffer processing delay", 1, &dts); bufcount++; #endif (rbuf->receiver)(rbuf); } else { msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING"); abort(); } BLOCK_IO_AND_ALARM(); freerecvbuf(rbuf); rbuf = get_full_recv_buffer(); } #ifdef DEBUG_TIMING get_systime(&tsb); L_SUB(&tsb, &tsa); if (bufcount) { collect_timing(NULL, "processing", bufcount, &tsb); DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); } } #endif /* * Go around again */ #ifdef HAVE_DNSREGISTRATION if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { mdnsreg = current_time; msyslog(LOG_INFO, "Attemping to register mDNS"); if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { if (!--mdnstries) { msyslog(LOG_ERR, "Unable to register mDNS, giving up."); } else { msyslog(LOG_INFO, "Unable to register mDNS, will try later."); } } else { msyslog(LOG_INFO, "mDNS service registered."); mdnsreg = 0; } } #endif /* HAVE_DNSREGISTRATION */ } UNBLOCK_IO_AND_ALARM(); return 1; } #ifdef SIGDIE2 /* * finish - exit gracefully */ static RETSIGTYPE finish( int sig ) { msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); #ifdef HAVE_DNSREGISTRATION if (mdns != NULL) DNSServiceRefDeallocate(mdns); #endif switch (sig) { # ifdef SIGBUS case SIGBUS: printf("\nfinish(SIGBUS)\n"); exit(0); # endif case 0: /* Should never happen... */ return; default: exit(0); } }
/** * returns 0 for sucess w/o errors * returns 1 for sucess w/ warnings * returns -1 for error */ int tcpedit_post_args(tcpedit_t **tcpedit_ex) { tcpedit_t *tcpedit; int rcode = 0; long ttl; assert(tcpedit_ex); tcpedit = *tcpedit_ex; assert(tcpedit); /* --pnat */ if (HAVE_OPT(PNAT)) { int ct = STACKCT_OPT(PNAT); char **list = STACKLST_OPT(PNAT); int first = 1; tcpedit->rewrite_ip ++; do { char *p = *list++; if (first) { if (! parse_cidr_map(&tcpedit->cidrmap1, p)) { tcpedit_seterr(tcpedit, "Unable to parse first --pnat=%s", p); return -1; } } else { if (! parse_cidr_map(&tcpedit->cidrmap2, p)) { tcpedit_seterr(tcpedit, "Unable to parse second --pnat=%s", p); return -1; } } first = 0; } while (--ct > 0); } /* --srcipmap */ if (HAVE_OPT(SRCIPMAP)) { tcpedit->rewrite_ip ++; if (! parse_cidr_map(&tcpedit->srcipmap, OPT_ARG(SRCIPMAP))) { tcpedit_seterr(tcpedit, "Unable to parse --srcipmap=%s", OPT_ARG(SRCIPMAP)); return -1; } } /* --dstipmap */ if (HAVE_OPT(DSTIPMAP)) { tcpedit->rewrite_ip ++; if (! parse_cidr_map(&tcpedit->dstipmap, OPT_ARG(DSTIPMAP))) { tcpedit_seterr(tcpedit, "Unable to parse --dstipmap=%s", OPT_ARG(DSTIPMAP)); return -1; } } /* * If we have one and only one -N, then use the same map data * for both interfaces/files */ if ((tcpedit->cidrmap1 != NULL) && (tcpedit->cidrmap2 == NULL)) tcpedit->cidrmap2 = tcpedit->cidrmap1; /* --fixcsum */ if (HAVE_OPT(FIXCSUM)) { tcpedit->fixcsum = TCPEDIT_FIXCSUM_ON; } else if (HAVE_OPT(NOFIXCSUM)) { tcpedit->fixcsum = TCPEDIT_FIXCSUM_DISABLE; } /* --efcs */ if (HAVE_OPT(EFCS)) tcpedit->efcs = 1; /* --ttl */ if (HAVE_OPT(TTL)) { if (strchr(OPT_ARG(TTL), '+')) { tcpedit->ttl_mode = TCPEDIT_TTL_ADD; } else if (strchr(OPT_ARG(TTL), '-')) { tcpedit->ttl_mode = TCPEDIT_TTL_SUB; } else { tcpedit->ttl_mode = TCPEDIT_TTL_SET; } ttl = strtol(OPT_ARG(TTL), (char **)NULL, 10); if (ttl < 0) ttl *= -1; /* convert to positive value */ if (ttl > 255) errx(-1, "Invalid --ttl value (must be 0-255): %ld", ttl); tcpedit->ttl_value = (u_int8_t)ttl; } /* --tos */ if (HAVE_OPT(TOS)) tcpedit->tos = OPT_VALUE_TOS; /* --flowlabel */ if (HAVE_OPT(FLOWLABEL)) tcpedit->flowlabel = OPT_VALUE_FLOWLABEL; /* --mtu */ if (HAVE_OPT(MTU)) tcpedit->mtu = OPT_VALUE_MTU; /* --mtu-trunc */ if (HAVE_OPT(MTU_TRUNC)) tcpedit->mtu_truncate = 1; /* --skipbroadcast */ if (HAVE_OPT(SKIPBROADCAST)) tcpedit->skip_broadcast = 1; /* --fixlen */ if (HAVE_OPT(FIXLEN)) { if (strcmp(OPT_ARG(FIXLEN), "pad") == 0) { tcpedit->fixlen = TCPEDIT_FIXLEN_PAD; } else if (strcmp(OPT_ARG(FIXLEN), "trunc") == 0) { tcpedit->fixlen = TCPEDIT_FIXLEN_TRUNC; } else if (strcmp(OPT_ARG(FIXLEN), "del") == 0) { tcpedit->fixlen = TCPEDIT_FIXLEN_DEL; } else { tcpedit_seterr(tcpedit, "Invalid --fixlen=%s", OPT_ARG(FIXLEN)); return -1; } } /* TCP/UDP port rewriting */ if (HAVE_OPT(PORTMAP)) { int ct = STACKCT_OPT(PORTMAP); char **list = STACKLST_OPT(PORTMAP); int first = 1; tcpedit_portmap_t *portmap_head, *portmap; do { char *p = *list++; if (first) { if (! parse_portmap(&tcpedit->portmap, p)) { tcpedit_seterr(tcpedit, "Unable to parse --portmap=%s", p); return -1; } } else { if (! parse_portmap(&portmap, p)) { tcpedit_seterr(tcpedit, "Unable to parse --portmap=%s", p); return -1; } /* append to end of tcpedit->portmap linked list */ portmap_head = tcpedit->portmap; while (portmap_head->next != NULL) portmap_head = portmap_head->next; portmap_head->next = portmap; } first = 0; } while (--ct > 0); } /* * IP address rewriting processing. Call srandom() then add up * 5 calls to random() as our mixer for randomizing. This should * work better since most people aren't going to write out values * close to 32bit integers. */ if (HAVE_OPT(SEED)) { tcpedit->rewrite_ip = TCPEDIT_REWRITE_IP_ON; srandom(OPT_VALUE_SEED); tcpedit->seed = random() + random() + random() + random() + random(); } if (HAVE_OPT(ENDPOINTS)) { tcpedit->rewrite_ip = TCPEDIT_REWRITE_IP_ON; if (! parse_endpoints(&tcpedit->cidrmap1, &tcpedit->cidrmap2, OPT_ARG(ENDPOINTS))) { tcpedit_seterr(tcpedit, "Unable to parse --endpoints=%s", OPT_ARG(ENDPOINTS)); return -1; } } /* * figure out the max packet len if (tcpedit->l2.enabled) { // custom l2 header dbg(1, "Using custom L2 header to calculate max frame size\n"); tcpedit->maxpacket = tcpedit->mtu + tcpedit->l2.len; } else if (tcpedit->l2.dlt == DLT_EN10MB || tcpedit->l2.dlt == DLT_VLAN) { // ethernet dbg(1, "Using Ethernet to calculate max frame size\n"); tcpedit->maxpacket = tcpedit->mtu + TCPR_ETH_H; } else { // uh, wtf is this now? we'll just assume ethernet and hope things work tcpedit->maxpacket = tcpedit->mtu + TCPR_ETH_H; tcpedit_seterr(tcpedit, "Unsupported DLT type: %s. We'll just treat it as ethernet.\n" "You may need to increase the MTU (-t <size>) if you get errors\n", pcap_datalink_val_to_name(tcpedit->l2.dlt)); rcode = 1; } */ return rcode; }
/** * Starting with the current directory, search the directory * list trying to find the base template file name. */ LOCAL tSuccess findFile(char const * pzFName, char * pzFullName, char const * const * papSuffixList, char const * pzReferrer) { char * pzRoot; char * pzSfx; void * deallocAddr = NULL; tSuccess res = SUCCESS; /* * Expand leading environment variables. * We will not mess with embedded ones. */ if (*pzFName == '$') { if (! optionMakePath(pzFullName, (int)AG_PATH_MAX, pzFName, autogenOptions.pzProgPath)) return FAILURE; AGDUPSTR(pzFName, pzFullName, "find file name"); deallocAddr = (void*)pzFName; /* * pzFName now points to the name the file system can use. * It must _not_ point to pzFullName because we will likely * rewrite that value using this pointer! */ } /* * Not a complete file name. If there is not already * a suffix for the file name, then append ".tpl". * Check for immediate access once again. */ pzRoot = strrchr(pzFName, '/'); pzSfx = (pzRoot != NULL) ? strchr(++pzRoot, '.') : strchr(pzFName, '.'); /* * The referrer is useful only if it includes a directory name. */ if (pzReferrer != NULL) { char * pz = strrchr(pzReferrer, '/'); if (pz == NULL) pzReferrer = NULL; else { AGDUPSTR(pzReferrer, pzReferrer, "pzReferrer"); pz = strrchr(pzReferrer, '/'); *pz = NUL; } } /* * IF the file name does not contain a directory separator, * then we will use the TEMPL_DIR search list to keep hunting. */ { static char const curdir[] = "."; static char const zDirFmt[] = "%s/%s"; /* * Search each directory in our directory search list * for the file. We always force one copy of this option. */ int ct = STACKCT_OPT(TEMPL_DIRS); char const ** ppzDir = STACKLST_OPT(TEMPL_DIRS) + ct - 1; char const * pzDir = curdir; if (*pzFName == '/') ct = 0; do { char * pzEnd; void * coerce; /* * IF one of our template paths starts with '$', then expand it. */ if (*pzDir == '$') { if (! optionMakePath(pzFullName, (int)AG_PATH_MAX, pzDir, autogenOptions.pzProgPath)) { coerce = (void *)pzDir; strcpy(coerce, curdir); } else { AGDUPSTR(pzDir, pzFullName, "find directory name"); coerce = (void *)ppzDir[1]; free(coerce); ppzDir[1] = pzDir; /* save the computed name for later */ } } if ((*pzFName == '/') || (pzDir == curdir)) { size_t nln = strlen(pzFName); if (nln >= AG_PATH_MAX - MAX_SUFFIX_LEN) break; memcpy(pzFullName, pzFName, nln); pzEnd = pzFullName + nln; *pzEnd = NUL; } else { pzEnd = pzFullName + snprintf(pzFullName, AG_PATH_MAX - MAX_SUFFIX_LEN, zDirFmt, pzDir, pzFName); } if (read_okay(pzFullName)) goto findFileReturn; /* * IF the file does not already have a suffix, * THEN try the ones that are okay for this file. */ if ((pzSfx == NULL) && (papSuffixList != NULL)) { char const * const * papSL = papSuffixList; *(pzEnd++) = '.'; do { strcpy(pzEnd, *(papSL++)); /* must fit */ if (read_okay(pzFullName)) goto findFileReturn; } while (*papSL != NULL); } if (*pzFName == '/') break; /* * IF there is a referrer, use it before the rest of the * TEMPL_DIRS We detect first time through by *both* pzDir value * and ct value. "ct" will have this same value next time * through and occasionally "pzDir" will be set to "curdir", but * never again when ct is STACKCT_OPT(TEMPL_DIRS) */ if ( (pzReferrer != NULL) && (pzDir == curdir) && (ct == STACKCT_OPT(TEMPL_DIRS))) { pzDir = pzReferrer; ct++; } else { pzDir = *(ppzDir--); } } while (--ct >= 0); } res = FAILURE; findFileReturn: AGFREE(deallocAddr); AGFREE(pzReferrer); return res; }
int ntpdmain( int argc, char *argv[] ) { l_fp now; struct recvbuf *rbuf; const char * logfilename; # ifdef HAVE_UMASK mode_t uv; # endif # if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ uid_t uid; # endif # if defined(HAVE_WORKING_FORK) long wait_sync = 0; int pipe_fds[2]; int rc; int exit_code; # ifdef _AIX struct sigaction sa; # endif # if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY) int fid; # endif # endif /* HAVE_WORKING_FORK*/ # ifdef SCO5_CLOCK int fd; int zero; # endif # ifdef NEED_PTHREAD_WARMUP my_pthread_warmup(); # endif # ifdef HAVE_UMASK uv = umask(0); if (uv) umask(uv); else umask(022); # endif saved_argc = argc; saved_argv = argv; progname = argv[0]; initializing = TRUE; /* mark that we are initializing */ parse_cmdline_opts(&argc, &argv); # ifdef DEBUG debug = OPT_VALUE_SET_DEBUG_LEVEL; # ifdef HAVE_SETLINEBUF setlinebuf(stdout); # endif # endif if (HAVE_OPT(NOFORK) || HAVE_OPT(QUIT) # ifdef DEBUG || debug # endif || HAVE_OPT(SAVECONFIGQUIT)) nofork = TRUE; init_logging(progname, NLOG_SYNCMASK, TRUE); /* honor -l/--logfile option to log to a file */ if (HAVE_OPT(LOGFILE)) { logfilename = OPT_ARG(LOGFILE); syslogit = FALSE; change_logfile(logfilename, FALSE); } else { logfilename = NULL; if (nofork) msyslog_term = TRUE; if (HAVE_OPT(SAVECONFIGQUIT)) syslogit = FALSE; } msyslog(LOG_NOTICE, "%s: Starting", Version); { int i; char buf[1024]; /* Secret knowledge of msyslog buf length */ char *cp = buf; /* Note that every arg has an initial space character */ snprintf(cp, sizeof(buf), "Command line:"); cp += strlen(cp); for (i = 0; i < saved_argc ; ++i) { snprintf(cp, sizeof(buf) - (cp - buf), " %s", saved_argv[i]); cp += strlen(cp); } msyslog(LOG_INFO, "%s", buf); } /* * Install trap handlers to log errors and assertion failures. * Default handlers print to stderr which doesn't work if detached. */ isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); /* MPE lacks the concept of root */ # if defined(HAVE_GETUID) && !defined(MPE) uid = getuid(); if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { msyslog_term = TRUE; msyslog(LOG_ERR, "must be run as root, not uid %ld", (long)uid); exit(1); } # endif /* * Enable the Multi-Media Timer for Windows? */ # ifdef SYS_WINNT if (HAVE_OPT( MODIFYMMTIMER )) set_mm_timer(MM_TIMER_HIRES); # endif #ifdef HAVE_DNSREGISTRATION /* * Enable mDNS registrations? */ if (HAVE_OPT( MDNS )) { mdnsreg = TRUE; } #endif /* HAVE_DNSREGISTRATION */ if (HAVE_OPT( NOVIRTUALIPS )) listen_to_virtual_ips = 0; /* * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); sockaddr_u addr; while (ifacect-- > 0) { add_nic_rule( is_ip_address(*ifaces, AF_UNSPEC, &addr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN); ifaces++; } } if (HAVE_OPT( NICE )) priority_done = 0; # ifdef HAVE_SCHED_SETSCHEDULER if (HAVE_OPT( PRIORITY )) { config_priority = OPT_VALUE_PRIORITY; config_priority_override = 1; priority_done = 0; } # endif # ifdef HAVE_WORKING_FORK /* make sure the FDs are initialised */ pipe_fds[0] = -1; pipe_fds[1] = -1; do { /* 'loop' once */ if (!HAVE_OPT( WAIT_SYNC )) break; wait_sync = OPT_VALUE_WAIT_SYNC; if (wait_sync <= 0) { wait_sync = 0; break; } /* -w requires a fork() even with debug > 0 */ nofork = FALSE; if (pipe(pipe_fds)) { exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "Pipe creation failed for --wait-sync: %m"); exit(exit_code); } waitsync_fd_to_close = pipe_fds[1]; } while (0); /* 'loop' once */ # endif /* HAVE_WORKING_FORK */ init_lib(); # ifdef SYS_WINNT /* * Start interpolation thread, must occur before first * get_systime() */ init_winnt_time(); # endif /* * Initialize random generator and public key pair */ get_systime(&now); ntp_srandom((int)(now.l_i * now.l_uf)); /* * Detach us from the terminal. May need an #ifndef GIZMO. */ if (!nofork) { # ifdef HAVE_WORKING_FORK rc = fork(); if (-1 == rc) { exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "fork: %m"); exit(exit_code); } if (rc > 0) { /* parent */ exit_code = wait_child_sync_if(pipe_fds[0], wait_sync); exit(exit_code); } /* * child/daemon * close all open files excepting waitsync_fd_to_close. * msyslog() unreliable until after init_logging(). */ closelog(); if (syslog_file != NULL) { fclose(syslog_file); syslog_file = NULL; syslogit = TRUE; } close_all_except(waitsync_fd_to_close); INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \ && 2 == dup2(0, 2)); init_logging(progname, 0, TRUE); /* we lost our logfile (if any) daemonizing */ setup_logfile(logfilename); # ifdef SYS_DOMAINOS { uid_$t puid; status_$t st; proc2_$who_am_i(&puid); proc2_$make_server(&puid, &st); } # endif /* SYS_DOMAINOS */ # ifdef HAVE_SETSID if (setsid() == (pid_t)-1) msyslog(LOG_ERR, "setsid(): %m"); # elif defined(HAVE_SETPGID) if (setpgid(0, 0) == -1) msyslog(LOG_ERR, "setpgid(): %m"); # else /* !HAVE_SETSID && !HAVE_SETPGID follows */ # ifdef TIOCNOTTY fid = open("/dev/tty", 2); if (fid >= 0) { ioctl(fid, (u_long)TIOCNOTTY, NULL); close(fid); } # endif /* TIOCNOTTY */ ntp_setpgrp(0, getpid()); # endif /* !HAVE_SETSID && !HAVE_SETPGID */ # ifdef _AIX /* Don't get killed by low-on-memory signal. */ sa.sa_handler = catch_danger; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGDANGER, &sa, NULL); # endif /* _AIX */ # endif /* HAVE_WORKING_FORK */ } # ifdef SCO5_CLOCK /* * SCO OpenServer's system clock offers much more precise timekeeping * on the base CPU than the other CPUs (for multiprocessor systems), * so we must lock to the base CPU. */ fd = open("/dev/at1", O_RDONLY); if (fd >= 0) { zero = 0; if (ioctl(fd, ACPU_LOCK, &zero) < 0) msyslog(LOG_ERR, "cannot lock to base CPU: %m"); close(fd); } # endif /* Setup stack size in preparation for locking pages in memory. */ # if defined(HAVE_MLOCKALL) # ifdef HAVE_SETRLIMIT ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k"); # ifdef RLIMIT_MEMLOCK /* * The default RLIMIT_MEMLOCK is very low on Linux systems. * Unless we increase this limit malloc calls are likely to * fail if we drop root privilege. To be useful the value * has to be larger than the largest ntpd resident set size. */ ntp_rlimit(RLIMIT_MEMLOCK, DFLT_RLIMIT_MEMLOCK * 1024 * 1024, 1024 * 1024, "MB"); # endif /* RLIMIT_MEMLOCK */ # endif /* HAVE_SETRLIMIT */ # else /* !HAVE_MLOCKALL follows */ # ifdef HAVE_PLOCK # ifdef PROCLOCK # ifdef _AIX /* * set the stack limit for AIX for plock(). * see get_aix_stack() for more info. */ if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0) msyslog(LOG_ERR, "Cannot adjust stack limit for plock: %m"); # endif /* _AIX */ # endif /* PROCLOCK */ # endif /* HAVE_PLOCK */ # endif /* !HAVE_MLOCKALL */ /* * Set up signals we pay attention to locally. */ # ifdef SIGDIE1 signal_no_reset(SIGDIE1, finish); signal_no_reset(SIGDIE2, finish); signal_no_reset(SIGDIE3, finish); signal_no_reset(SIGDIE4, finish); # endif # ifdef SIGBUS signal_no_reset(SIGBUS, finish); # endif # if !defined(SYS_WINNT) && !defined(VMS) # ifdef DEBUG (void) signal_no_reset(MOREDEBUGSIG, moredebug); (void) signal_no_reset(LESSDEBUGSIG, lessdebug); # else (void) signal_no_reset(MOREDEBUGSIG, no_debug); (void) signal_no_reset(LESSDEBUGSIG, no_debug); # endif /* DEBUG */ # endif /* !SYS_WINNT && !VMS */ /* * Set up signals we should never pay attention to. */ # ifdef SIGPIPE signal_no_reset(SIGPIPE, SIG_IGN); # endif /* * Call the init_ routines to initialize the data structures. * * Exactly what command-line options are we expecting here? */ INIT_SSL(); init_auth(); init_util(); init_restrict(); init_mon(); init_timer(); init_request(); init_control(); init_peer(); # ifdef REFCLOCK init_refclock(); # endif set_process_priority(); init_proto(); /* Call at high priority */ init_io(); init_loopfilter(); mon_start(MON_ON); /* monitor on by default now */ /* turn off in config if unwanted */ /* * Get the configuration. This is done in a separate module * since this will definitely be different for the gizmo board. */ getconfig(argc, argv); if (-1 == cur_memlock) { # if defined(HAVE_MLOCKALL) /* * lock the process into memory */ if ( !HAVE_OPT(SAVECONFIGQUIT) # ifdef RLIMIT_MEMLOCK && -1 != DFLT_RLIMIT_MEMLOCK # endif && 0 != mlockall(MCL_CURRENT|MCL_FUTURE)) msyslog(LOG_ERR, "mlockall(): %m"); # else /* !HAVE_MLOCKALL follows */ # ifdef HAVE_PLOCK # ifdef PROCLOCK /* * lock the process into memory */ if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(PROCLOCK)) msyslog(LOG_ERR, "plock(PROCLOCK): %m"); # else /* !PROCLOCK follows */ # ifdef TXTLOCK /* * Lock text into ram */ if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(TXTLOCK)) msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); # else /* !TXTLOCK follows */ msyslog(LOG_ERR, "plock() - don't know what to lock!"); # endif /* !TXTLOCK */ # endif /* !PROCLOCK */ # endif /* HAVE_PLOCK */ # endif /* !HAVE_MLOCKALL */ } loop_config(LOOP_DRIFTINIT, 0); report_event(EVNT_SYSRESTART, NULL, NULL); initializing = FALSE; # ifdef HAVE_DROPROOT if (droproot) { /* Drop super-user privileges and chroot now if the OS supports this */ # ifdef HAVE_LINUX_CAPABILITIES /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); exit(-1); } # elif HAVE_SOLARIS_PRIVS /* Nothing to do here */ # else /* we need a user to switch to */ if (user == NULL) { msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); exit(-1); } # endif /* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */ if (user != NULL) { if (isdigit((unsigned char)*user)) { sw_uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; if ((pw = getpwuid(sw_uid)) != NULL) { free(user); user = estrdup(pw->pw_name); sw_gid = pw->pw_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find user ID %s", user); exit (-1); } } else { getuser: errno = 0; if ((pw = getpwnam(user)) != NULL) { sw_uid = pw->pw_uid; sw_gid = pw->pw_gid; } else { if (errno) msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); else msyslog(LOG_ERR, "Cannot find user `%s'", user); exit (-1); } } } if (group != NULL) { if (isdigit((unsigned char)*group)) { sw_gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gr = getgrnam(group)) != NULL) { sw_gid = gr->gr_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find group `%s'", group); exit (-1); } } } if (chrootdir ) { /* make sure cwd is inside the jail: */ if (chdir(chrootdir)) { msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); exit (-1); } if (chroot(chrootdir)) { msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); exit (-1); } if (chdir("/")) { msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); exit (-1); } } # ifdef HAVE_SOLARIS_PRIVS if ((lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { msyslog(LOG_ERR, "priv_str_to_set() failed:%m"); exit(-1); } if ((highprivs = priv_allocset()) == NULL) { msyslog(LOG_ERR, "priv_allocset() failed:%m"); exit(-1); } (void) getppriv(PRIV_PERMITTED, highprivs); (void) priv_intersect(highprivs, lowprivs); if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { msyslog(LOG_ERR, "setppriv() failed:%m"); exit(-1); } # endif /* HAVE_SOLARIS_PRIVS */ if (user && initgroups(user, sw_gid)) { msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); exit (-1); } if (group && setgid(sw_gid)) { msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); exit (-1); } if (group && setegid(sw_gid)) { msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); exit (-1); } if (group) { if (0 != setgroups(1, &sw_gid)) { msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid); exit (-1); } } else if (pw) if (0 != initgroups(pw->pw_name, pw->pw_gid)) { msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid); exit (-1); } if (user && setuid(sw_uid)) { msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); exit (-1); } if (user && seteuid(sw_uid)) { msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); exit (-1); } # if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS) /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on * ports that allow binding to NTP_PORT with uid != 0 */ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ # endif /* !HAVE_LINUX_CAPABILITIES && !HAVE_SOLARIS_PRIVS */ if (disable_dynamic_updates && interface_interval) { interface_interval = 0; msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking"); } # ifdef HAVE_LINUX_CAPABILITIES { /* * We may be running under non-root uid now, but we still hold full root privileges! * We drop all of them, except for the crucial one or two: cap_sys_time and * cap_net_bind_service if doing dynamic interface tracking. */ cap_t caps; char *captext; captext = (0 != interface_interval) ? "cap_sys_time,cap_net_bind_service=pe" : "cap_sys_time=pe"; caps = cap_from_text(captext); if (!caps) { msyslog(LOG_ERR, "cap_from_text(%s) failed: %m", captext); exit(-1); } if (-1 == cap_set_proc(caps)) { msyslog(LOG_ERR, "cap_set_proc() failed to drop root privs: %m"); exit(-1); } cap_free(caps); } # endif /* HAVE_LINUX_CAPABILITIES */ # ifdef HAVE_SOLARIS_PRIVS if (priv_delset(lowprivs, "proc_setid") == -1) { msyslog(LOG_ERR, "priv_delset() failed:%m"); exit(-1); } if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { msyslog(LOG_ERR, "setppriv() failed:%m"); exit(-1); } priv_freeset(lowprivs); priv_freeset(highprivs); # endif /* HAVE_SOLARIS_PRIVS */ root_dropped = TRUE; fork_deferred_worker(); } /* if (droproot) */ # endif /* HAVE_DROPROOT */ /* libssecomp sandboxing */ #if defined (LIBSECCOMP) && (KERN_SECCOMP) scmp_filter_ctx ctx; if ((ctx = seccomp_init(SCMP_ACT_KILL)) < 0) msyslog(LOG_ERR, "%s: seccomp_init(SCMP_ACT_KILL) failed: %m", __func__); else { msyslog(LOG_DEBUG, "%s: seccomp_init(SCMP_ACT_KILL) succeeded", __func__); } #ifdef __x86_64__ int scmp_sc[] = { SCMP_SYS(adjtimex), SCMP_SYS(bind), SCMP_SYS(brk), SCMP_SYS(chdir), SCMP_SYS(clock_gettime), SCMP_SYS(clock_settime), SCMP_SYS(close), SCMP_SYS(connect), SCMP_SYS(exit_group), SCMP_SYS(fstat), SCMP_SYS(fsync), SCMP_SYS(futex), SCMP_SYS(getitimer), SCMP_SYS(getsockname), SCMP_SYS(ioctl), SCMP_SYS(lseek), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(munmap), SCMP_SYS(open), SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(recvmsg), SCMP_SYS(rename), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigreturn), SCMP_SYS(select), SCMP_SYS(sendto), SCMP_SYS(setitimer), SCMP_SYS(setsid), SCMP_SYS(socket), SCMP_SYS(stat), SCMP_SYS(time), SCMP_SYS(write), }; #endif #ifdef __i386__ int scmp_sc[] = { SCMP_SYS(_newselect), SCMP_SYS(adjtimex), SCMP_SYS(brk), SCMP_SYS(chdir), SCMP_SYS(clock_gettime), SCMP_SYS(clock_settime), SCMP_SYS(close), SCMP_SYS(exit_group), SCMP_SYS(fsync), SCMP_SYS(futex), SCMP_SYS(getitimer), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2), SCMP_SYS(munmap), SCMP_SYS(open), SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(rename), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(select), SCMP_SYS(setitimer), SCMP_SYS(setsid), SCMP_SYS(sigprocmask), SCMP_SYS(sigreturn), SCMP_SYS(socketcall), SCMP_SYS(stat64), SCMP_SYS(time), SCMP_SYS(write), }; #endif { int i; for (i = 0; i < COUNTOF(scmp_sc); i++) { if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, scmp_sc[i], 0) < 0) { msyslog(LOG_ERR, "%s: seccomp_rule_add() failed: %m", __func__); } } } if (seccomp_load(ctx) < 0) msyslog(LOG_ERR, "%s: seccomp_load() failed: %m", __func__); else { msyslog(LOG_DEBUG, "%s: seccomp_load() succeeded", __func__); } #endif /* LIBSECCOMP and KERN_SECCOMP */ # ifdef HAVE_IO_COMPLETION_PORT for (;;) { GetReceivedBuffers(); # else /* normal I/O */ BLOCK_IO_AND_ALARM(); was_alarmed = FALSE; for (;;) { if (alarm_flag) { /* alarmed? */ was_alarmed = TRUE; alarm_flag = FALSE; } if (!was_alarmed && !has_full_recv_buffer()) { /* * Nothing to do. Wait for something. */ io_handler(); } if (alarm_flag) { /* alarmed? */ was_alarmed = TRUE; alarm_flag = FALSE; } if (was_alarmed) { UNBLOCK_IO_AND_ALARM(); /* * Out here, signals are unblocked. Call timer routine * to process expiry. */ timer(); was_alarmed = FALSE; BLOCK_IO_AND_ALARM(); } # endif /* !HAVE_IO_COMPLETION_PORT */ # ifdef DEBUG_TIMING { l_fp pts; l_fp tsa, tsb; int bufcount = 0; get_systime(&pts); tsa = pts; # endif rbuf = get_full_recv_buffer(); while (rbuf != NULL) { if (alarm_flag) { was_alarmed = TRUE; alarm_flag = FALSE; } UNBLOCK_IO_AND_ALARM(); if (was_alarmed) { /* avoid timer starvation during lengthy I/O handling */ timer(); was_alarmed = FALSE; } /* * Call the data procedure to handle each received * packet. */ if (rbuf->receiver != NULL) { # ifdef DEBUG_TIMING l_fp dts = pts; L_SUB(&dts, &rbuf->recv_time); DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); collect_timing(rbuf, "buffer processing delay", 1, &dts); bufcount++; # endif (*rbuf->receiver)(rbuf); } else { msyslog(LOG_ERR, "fatal: receive buffer callback NULL"); abort(); } BLOCK_IO_AND_ALARM(); freerecvbuf(rbuf); rbuf = get_full_recv_buffer(); } # ifdef DEBUG_TIMING get_systime(&tsb); L_SUB(&tsb, &tsa); if (bufcount) { collect_timing(NULL, "processing", bufcount, &tsb); DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); } } # endif /* * Go around again */ # ifdef HAVE_DNSREGISTRATION if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { mdnsreg = current_time; msyslog(LOG_INFO, "Attempting to register mDNS"); if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { if (!--mdnstries) { msyslog(LOG_ERR, "Unable to register mDNS, giving up."); } else { msyslog(LOG_INFO, "Unable to register mDNS, will try later."); } } else { msyslog(LOG_INFO, "mDNS service registered."); mdnsreg = FALSE; } } # endif /* HAVE_DNSREGISTRATION */ } UNBLOCK_IO_AND_ALARM(); return 1; } #endif /* !SIM */ #if !defined(SIM) && defined(SIGDIE1) /* * finish - exit gracefully */ static RETSIGTYPE finish( int sig ) { const char *sig_desc; sig_desc = NULL; #ifdef HAVE_STRSIGNAL sig_desc = strsignal(sig); #endif if (sig_desc == NULL) sig_desc = ""; msyslog(LOG_NOTICE, "%s exiting on signal %d (%s)", progname, sig, sig_desc); /* See Bug 2513 and Bug 2522 re the unlink of PIDFILE */ # ifdef HAVE_DNSREGISTRATION if (mdns != NULL) DNSServiceRefDeallocate(mdns); # endif peer_cleanup(); exit(0); } #endif /* !SIM && SIGDIE1 */ #ifndef SIM /* * wait_child_sync_if - implements parent side of -w/--wait-sync */ # ifdef HAVE_WORKING_FORK static int wait_child_sync_if( int pipe_read_fd, long wait_sync ) { int rc; int exit_code; time_t wait_end_time; time_t cur_time; time_t wait_rem; fd_set readset; struct timeval wtimeout; if (0 == wait_sync) return 0; /* waitsync_fd_to_close used solely by child */ close(waitsync_fd_to_close); wait_end_time = time(NULL) + wait_sync; do { cur_time = time(NULL); wait_rem = (wait_end_time > cur_time) ? (wait_end_time - cur_time) : 0; wtimeout.tv_sec = wait_rem; wtimeout.tv_usec = 0; FD_ZERO(&readset); FD_SET(pipe_read_fd, &readset); rc = select(pipe_read_fd + 1, &readset, NULL, NULL, &wtimeout); if (-1 == rc) { if (EINTR == errno) continue; exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "--wait-sync select failed: %m"); return exit_code; } if (0 == rc) { /* * select() indicated a timeout, but in case * its timeouts are affected by a step of the * system clock, select() again with a zero * timeout to confirm. */ FD_ZERO(&readset); FD_SET(pipe_read_fd, &readset); wtimeout.tv_sec = 0; wtimeout.tv_usec = 0; rc = select(pipe_read_fd + 1, &readset, NULL, NULL, &wtimeout); if (0 == rc) /* select() timeout */ break; else /* readable */ return 0; } else /* readable */ return 0; } while (wait_rem > 0); fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n", progname, wait_sync); return ETIMEDOUT; }
void post_args(_U_ int argc, _U_ char *argv[]) { char ebuf[SENDPACKET_ERRBUF_SIZE]; struct tcpr_ether_addr *eth_buff; char *intname; sendpacket_t *sp; #ifdef ENABLE_PCAP_FINDALLDEVS interface_list_t *intlist = get_interface_list(); #else interface_list_t *intlist = NULL; #endif #ifdef DEBUG if (HAVE_OPT(DBUG)) debug = OPT_VALUE_DBUG; #else if (HAVE_OPT(DBUG)) warn("not configured with --enable-debug. Debugging disabled."); #endif #ifdef ENABLE_VERBOSE if (HAVE_OPT(VERBOSE)) options.verbose = 1; if (HAVE_OPT(DECODE)) options.tcpdump->args = safe_strdup(OPT_ARG(DECODE)); #endif if (HAVE_OPT(UNIDIR)) options.unidir = 1; if (HAVE_OPT(LIMIT)) options.limit_send = OPT_VALUE_LIMIT; /* default is -1 */ if ((intname = get_interface(intlist, OPT_ARG(INTF1))) == NULL) errx(-1, "Invalid interface name/alias: %s", OPT_ARG(INTF1)); options.intf1 = safe_strdup(intname); if (HAVE_OPT(INTF2)) { if ((intname = get_interface(intlist, OPT_ARG(INTF2))) == NULL) errx(-1, "Invalid interface name/alias: %s", OPT_ARG(INTF2)); options.intf2 = safe_strdup(intname); } if (HAVE_OPT(MAC)) { int ct = STACKCT_OPT(MAC); char **list = STACKLST_OPT(MAC); int first = 1; do { char *p = *list++; if (first) mac2hex(p, (u_char *)options.intf1_mac, ETHER_ADDR_LEN); else mac2hex(p, (u_char *)options.intf2_mac, ETHER_ADDR_LEN); first = 0; } while (--ct > 0); } /* * Figure out MAC addresses of sending interface(s) * if user doesn't specify MAC address on CLI, query for it */ if (memcmp(options.intf1_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0) { if ((sp = sendpacket_open(NULL, options.intf1, ebuf, TCPR_DIR_C2S)) == NULL) errx(-1, "Unable to open interface %s: %s", options.intf1, ebuf); if ((eth_buff = sendpacket_get_hwaddr(sp)) == NULL) { warnx("Unable to get MAC address: %s", sendpacket_geterr(sp)); err(-1, "Please consult the man page for using the -M option."); } sendpacket_close(sp); memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN); } if (memcmp(options.intf2_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0) { if ((sp = sendpacket_open(NULL, options.intf2, ebuf, TCPR_DIR_S2C)) == NULL) errx(-1, "Unable to open interface %s: %s", options.intf2, ebuf); if ((eth_buff = sendpacket_get_hwaddr(sp)) == NULL) { warnx("Unable to get MAC address: %s", sendpacket_geterr(sp)); err(-1, "Please consult the man page for using the -M option."); } sendpacket_close(sp); memcpy(options.intf2_mac, eth_buff, ETHER_ADDR_LEN); } /* * Open interfaces for sending & receiving */ if ((options.pcap1 = pcap_open_live(options.intf1, options.snaplen, options.promisc, options.to_ms, ebuf)) == NULL) errx(-1, "Unable to open interface %s: %s", options.intf1, ebuf); if (strcmp(options.intf1, options.intf2) == 0) errx(-1, "Whoa tiger! You don't want to use %s twice!", options.intf1); /* we always have to open the other pcap handle to send, but we may not listen */ if ((options.pcap2 = pcap_open_live(options.intf2, options.snaplen, options.promisc, options.to_ms, ebuf)) == NULL) errx(-1, "Unable to open interface %s: %s", options.intf2, ebuf); /* poll should be -1 to wait indefinitely */ options.poll_timeout = -1; }
/** * Figure out what to use as the base name of the output file. * If an argument is not provided, we use the base name of * the definitions file. */ static void open_output(tOutSpec * spec) { static char const write_mode[] = "w" FOPEN_BINARY_FLAG "+"; char const * out_file = NULL; if (strcmp(spec->zSuffix, OPEN_OUTPUT_NULL) == 0) { static int const flags = FPF_NOUNLINK | FPF_NOCHMOD | FPF_TEMPFILE; null_open: open_output_file(DEV_NULL, DEV_NULL_LEN, write_mode, flags); return; } /* * IF we are to skip the current suffix, * we will redirect the output to /dev/null and * perform all the work. There may be side effects. */ if (HAVE_OPT(SKIP_SUFFIX)) { int ct = STACKCT_OPT(SKIP_SUFFIX); const char ** ppz = STACKLST_OPT(SKIP_SUFFIX); while (--ct >= 0) { if (strcmp(spec->zSuffix, *ppz++) == 0) goto null_open; } } /* * Remove any suffixes in the last file name */ { char const * def_file = OPT_ARG(BASE_NAME); char z[AG_PATH_MAX]; const char * pst = strrchr(def_file, '/'); char * end; pst = (pst == NULL) ? def_file : (pst + 1); /* * We allow users to specify a suffix with '-' and '_', but when * stripping a suffix from the "base name", we do not recognize 'em. */ end = strchr(pst, '.'); if (end != NULL) { size_t len = (unsigned)(end - pst); if (len >= sizeof(z)) AG_ABEND("--base-name name is too long"); memcpy(z, pst, len); z[ end - pst ] = NUL; pst = z; } /* * Now formulate the output file name in the buffer * provided as the input argument. */ out_file = aprf(spec->pzFileFmt, pst, spec->zSuffix); if (out_file == NULL) AG_ABEND(aprf(OPEN_OUTPUT_BAD_FMT, spec->pzFileFmt, pst, spec->zSuffix)); } open_output_file(out_file, strlen(out_file), write_mode, 0); free((void *)out_file); }
int init(void) { int ct = 0; char **input; char **host, **port, **user, **pwd, **thr; int i = 0; #ifndef USE_ST struct sigaction new_action; new_action.sa_handler = sigalarm_handler; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGALRM, &new_action, NULL); #endif hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, queue_free); if (!HAVE_OPT(THREADS)) { fprintf(stderr, "missing threads option\n"); return 0; } if (!HAVE_OPT(INPUT)) { fprintf(stderr, "missing input option\n"); return 0; } ct = STACKCT_OPT( INPUT ); input = (char **) &STACKLST_OPT(INPUT); host = (char **) &STACKLST_OPT(HOST); port = (char **) &STACKLST_OPT(PORT); user = (char **) &STACKLST_OPT(UWUSER); pwd = (char **) &STACKLST_OPT(UWPASSWD); thr = (char **) &STACKLST_OPT(THREADS); // read in options for queuing for (i=0; input[i] && i < ct && i < 4; i++) { struct q_info *q = g_hash_table_lookup(hash, input[i]); char buf[256]; if (q == NULL) { q = g_malloc0(sizeof(struct q_info)); q->name = strdup(input[i]); g_hash_table_insert(hash, strdup(input[i]), q); } if (!host || !host[i]) { fprintf(stderr, "missing host option for input %s\n", input[i]); return 0; } else if (strcmp(host[i], "none") == 0) { g_hash_table_remove(hash, host[i]); continue; } if (!port || !port[i]) { fprintf(stderr, "missing port option for input queue %s\n", input[i]); return 0; } if (!user || !user[i]) { fprintf(stderr, "missing uwuser option for input queue %s\n", input[i]); return 0; } if (!pwd || !pwd[i]) { fprintf(stderr, "missing uwpasswd option for input %s\n", input[i]); return 0; } if (q->host) g_free(q->host); if (q->user) g_free(q->user); if (q->pwd) g_free(q->pwd); q->host = strdup(host[i]); q->port = atoi(port[i]); strcpy(buf, user[i]); // preset if (!strchr(user[i], '@') && HAVE_OPT(REALM)) { sprintf(buf, "%s@%s", user[i], OPT_ARG(REALM)); } q->user = strdup(buf); q->pwd = strdup(pwd[i]); q->maxthreads = thr[i] ? atoi(thr[i]) : 1; } if (HAVE_OPT(ONCE)) { every = ONE_SHOT; daemonize = FALSE; } else { daemonize = TRUE; every = EVERY_5SECS; } xmlSetGenericErrorFunc(NULL, UpwatchXmlGenericErrorFunc); return(1); }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * MAIN */ int main(int argc, char ** argv) { FILE* outFp; optionProcess(&getdefsOptions, argc, argv); validateOptions(); outFp = startAutogen(); doPreamble(outFp); /* * Process each input file */ { int ct = STACKCT_OPT(INPUT); char const ** ppz = STACKLST_OPT(INPUT); do { processFile(*ppz++); } while (--ct > 0); } /* * IF we don't have an ordering file, but we do have a "first index", * THEN alphabetize by definition name. */ if ((pzIndexText == NULL) && HAVE_OPT(FIRST_INDEX)) { qsort((void*)papzBlocks, blkUseCt, sizeof(char*), compar_defname); set_first_idx(); } else if (ENABLED_OPT(ORDERING) && (blkUseCt > 1)) qsort((void*)papzBlocks, blkUseCt, sizeof(char*), &compar_text); printEntries(outFp); fclose(outFp); /* * IF output is to a file * THEN set the permissions and modification times */ if ( (WHICH_IDX_AUTOGEN == INDEX_OPT_OUTPUT) && (outFp != stdout) ) { struct utimbuf tbuf; tbuf.actime = time((time_t*)NULL); tbuf.modtime = modtime + 1; utime(OPT_ARG(OUTPUT), &tbuf); chmod(OPT_ARG(OUTPUT), S_IRUSR|S_IRGRP|S_IROTH); } /* * IF we are keeping a database of indexes * AND we have augmented the contents, * THEN append the new entries to the file. */ if ((pzIndexText != NULL) && (pzEndIndex != pzIndexEOF)) updateDatabase(); if (agPid != -1) return awaitAutogen(); return EXIT_SUCCESS; }
/* * doPreamble */ static void doPreamble(FILE* outFp) { /* * Emit the "autogen definitions xxx;" line */ fprintf(outFp, zAgDef, OPT_ARG(TEMPLATE)); if (HAVE_OPT(FILELIST)) { static char const zFmt[] = "%-12s = '%s';\n"; char const * pzName = OPT_ARG(FILELIST); if ((pzName == NULL) || (*pzName == NUL)) pzName = "infile"; if (HAVE_OPT(INPUT)) { int ct = STACKCT_OPT(INPUT); char const ** ppz = STACKLST_OPT(INPUT); do { fprintf(outFp, zFmt, pzName, *ppz++); } while (--ct > 0); } if (HAVE_OPT(COPY)) { int ct = STACKCT_OPT(COPY); char const ** ppz = STACKLST_OPT(COPY); do { fprintf(outFp, zFmt, pzName, *ppz++); } while (--ct > 0); } fputc('\n', outFp); } /* * IF there are COPY files to be included, * THEN emit the '#include' directives */ if (HAVE_OPT(COPY)) { int ct = STACKCT_OPT(COPY); char const ** ppz = STACKLST_OPT(COPY); do { fprintf(outFp, "#include %s\n", *ppz++); } while (--ct > 0); fputc('\n', outFp); } /* * IF there are global assignments, then emit them * (these do not get sorted, so we write directly now.) */ if (HAVE_OPT(ASSIGN)) { int ct = STACKCT_OPT(ASSIGN); char const ** ppz = STACKLST_OPT(ASSIGN); do { fprintf(outFp, "%s;\n", *ppz++); } while (--ct > 0); fputc('\n', outFp); } }
/* * buildDefinition */ static void buildDefinition(char * pzDef, char const * pzFile, int line, char * pzOut) { static char const zSrcFile[] = " %s = '%s';\n"; static char const zLineNum[] = " %s = '%d';\n"; ag_bool these_are_global_defs; tSuccess preamble; int re_res; char* pzNextDef = NULL; regmatch_t match[2]; if (*pzDef == '*') { these_are_global_defs = AG_TRUE; strcpy(pzOut, zGlobal); pzOut += sizeof(zGlobal)-1; pzOut += sprintf(pzOut, zLineId, line, pzFile); pzDef = strchr(pzDef, '\n'); preamble = PROBLEM; } else { these_are_global_defs = AG_FALSE; preamble = buildPreamble(&pzDef, &pzOut, pzFile, line); if (FAILED(preamble)) { *pzOut = NUL; return; } } /* * FOR each attribute for this entry, ... */ for (;;) { /* * Find the next attribute regular expression */ re_res = regexec(&attrib_re, pzDef, COUNT(match), match, 0); switch (re_res) { case 0: /* * NUL-terminate the current attribute. * Set the "next" pointer to the start of the next attribute name. */ pzDef[ match[0].rm_so ] = NUL; if (pzNextDef != NULL) pzOut = emitDefinition(pzNextDef, pzOut); pzNextDef = pzDef = pzDef + match[1].rm_so; break; case REG_NOMATCH: /* * No more attributes. */ if (pzNextDef == NULL) { *pzOut++ = '\n'; *pzOut++ = '#'; sprintf(pzOut, zNoData, pzFile, line); fputs(pzOut, stderr); pzOut += strlen(pzOut); return; } pzOut = emitDefinition(pzNextDef, pzOut); goto eachAttrDone; break; default: { char zRER[ MAXNAMELEN ]; static char const zErr[] = "error %d (%s) finding `%s' in\n%s\n\n"; regerror(re_res, &attrib_re, zRER, sizeof(zRER)); *pzOut++ = '\n'; *pzOut++ = '#'; sprintf(pzOut, zErr, re_res, zRER, zAttribRe, pzDef); fprintf(stderr, "getdefs: %s", zErr); return; } } } eachAttrDone:; if (these_are_global_defs) { *pzOut = NUL; return; } if (HAVE_OPT(COMMON_ASSIGN)) { int ct = STACKCT_OPT(COMMON_ASSIGN); char const ** ppz = STACKLST_OPT(COMMON_ASSIGN); do { pzOut += sprintf(pzOut, " %s;\n", *ppz++); } while (--ct > 0); } if (HAVE_OPT(SRCFILE)) pzOut += sprintf(pzOut, zSrcFile, OPT_ARG(SRCFILE), pzFile); if (HAVE_OPT(LINENUM)) pzOut += sprintf(pzOut, zLineNum, OPT_ARG(LINENUM), line); /* * IF the preamble had a problem, it is because it could not * emit the final "#endif\n" directive. Do that now. */ if (HADGLITCH(preamble)) strcpy(pzOut, "};\n#endif\n"); else strcpy(pzOut, "};\n"); }
/** * validateOptions * * - Sanity check the options * - massage the SUBBLOCK options into something * more easily used during the source text processing. * - compile the regular expressions * - make sure we can find all the input files and their mod times * - Set up our entry ordering database (if specified) * - Make sure we have valid strings for SRCFILE and LINENUM * (if we are to use these things). * - Initialize the user name characters array. */ LOCAL void validateOptions(void) { set_define_re(); /* * Prepare each sub-block entry so we can parse easily later. */ if (HAVE_OPT(SUBBLOCK)) { int ct = STACKCT_OPT( SUBBLOCK); tCC** ppz = STACKLST_OPT(SUBBLOCK); /* * FOR each SUBBLOCK argument, * DO condense each name list to be a list of names * separated by a single space and NUL terminated. */ do { *ppz = fixupSubblockString(*ppz); ppz++; } while (--ct > 0); } if (! HAVE_OPT(INPUT)) SET_OPT_INPUT("-"); set_modtime(); /* * IF the output is to have order AND it is to be based on a file, * THEN load the contents of that file. * IF we cannot load the file, * THEN it must be new or empty. Allocate several K to start. */ if ( HAVE_OPT(ORDERING) && (OPT_ARG(ORDERING) != NULL)) { tSCC zIndexPreamble[] = "# -*- buffer-read-only: t -*- vi: set ro:\n" "#\n# DO NOT EDIT THIS FILE - it is auto-edited by getdefs\n"; pzIndexText = loadFile(OPT_ARG(ORDERING)); if (pzIndexText == NULL) { pzIndexText = pzEndIndex = pzIndexEOF = malloc((size_t)0x4000); indexAlloc = 0x4000; pzEndIndex += sprintf(pzEndIndex, "%s", zIndexPreamble); } else { pzEndIndex = pzIndexEOF = pzIndexText + strlen(pzIndexText); indexAlloc = (pzEndIndex - pzIndexText) + 1; } /* * We map the name entries to a connonical form. * By default, everything is mapped to lower case already. * This call will map these three characters to '_'. */ strequate("_-^"); } { char const * pz = OPT_ARG(SRCFILE); if ((pz == NULL) || (*pz == NUL)) OPT_ARG(SRCFILE) = "srcfile"; pz = OPT_ARG(LINENUM); if ((pz == NULL) || (*pz == NUL)) OPT_ARG(LINENUM) = "linenum"; } { tSCC zAgNameChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "_-^"; tSCC zUserNameChs[] = ":.$%*!~<>&@"; tCC* p = zAgNameChars; while (*p) zUserNameCh[(unsigned)(*p++)] = 3; p = zUserNameChs; while (*p) zUserNameCh[(unsigned)(*p++)] = 1; } }
int init(void) { struct sockaddr_in from, to; const char *msg; int i, idx; FILE *in; if (!HAVE_OPT(OUTPUT)) { LOG(LOG_ERR, "missing output option"); return 0; } if (OPT_VALUE_SERVERID == 0) { fprintf(stderr, "Please set serverid first\n"); return 0; } if (HAVE_OPT(ERRLOG)) { int ct = STACKCT_OPT(ERRLOG); char **errlog = (char **) &STACKLST_OPT(ERRLOG); for (idx=0, i=0; i < ct && idx < 255; i++) { char *start, *end; start = end = errlog[i]; while (*end && !isspace(*end)) { end++; } if (!*end) { LOG(LOG_WARNING, "Illegal format: %s", errlog[i]); continue; } *end++ = 0; errlogspec[idx].style = start; while (*end && isspace(*end)) { end++; } if (!*end) { LOG(LOG_WARNING, "Illegal format: %s", errlog[i]); continue; } start = end; while (*end && !isspace(*end)) { end++; } *end = 0; errlogspec[idx++].path = start; } #if HAVE_LIBPCRE in = fopen(STATFILE, "r"); if (in) { while (!feof(in)) { char path[PATH_MAX]; long long offset; int i; if (fscanf(in, "%s %Ld", path, &offset) != 2) continue; for (i=0; errlogspec[i].path; i++) { if (strcmp(errlogspec[i].path, path)) continue; errlogspec[i].offset = offset; break; } } fclose(in); } #endif } #if USE_XMBMON if (OPT_VALUE_HWSTATS) { if (OPT_VALUE_TYAN_TIGER_MP) { TyanTigerMP_flag = 1; } if ((i = InitMBInfo(' ')) != 0) { LOG(LOG_ERR, "InitMBInfo: %m"); if (i < 0) { LOG(LOG_ERR,"This program needs setuid root"); } } } else { LOG(LOG_INFO,"Hardware stats will not be generated"); } #endif // determine ip address for default gateway interface setsin(&to, inet_addr("1.1.1.1")); msg = findsaddr(&to, &from); if (msg) { LOG(LOG_INFO, (char *)msg); strcpy(ipaddress, OPT_ARG(IPADDRESS)); } else { strcpy(ipaddress, inet_ntoa(from.sin_addr)); } LOG(LOG_INFO, "using ipaddress %s", ipaddress); daemonize = TRUE; every = EVERY_SECOND; xmlSetGenericErrorFunc(NULL, UpwatchXmlGenericErrorFunc); sleep(2); // ensure we wait until the next minute setpriority(PRIO_PROCESS, 0, 5); // we are not very important - be nice to other processes return 1; }
/* * The actual main function. */ int sntp_main ( int argc, char **argv, const char *sntpVersion ) { int i; int exitcode; int optct; struct event_config * evcfg; /* Initialize logging system - sets up progname */ sntp_init_logging(argv[0]); if (!libevent_version_ok()) exit(EX_SOFTWARE); init_lib(); init_auth(); optct = ntpOptionProcess(&sntpOptions, argc, argv); argc -= optct; argv += optct; debug = OPT_VALUE_SET_DEBUG_LEVEL; TRACE(2, ("init_lib() done, %s%s\n", (ipv4_works) ? "ipv4_works " : "", (ipv6_works) ? "ipv6_works " : "")); ntpver = OPT_VALUE_NTPVERSION; steplimit = OPT_VALUE_STEPLIMIT / 1e3; gap.tv_usec = max(0, OPT_VALUE_GAP * 1000); gap.tv_usec = min(gap.tv_usec, 999999); if (HAVE_OPT(LOGFILE)) open_logfile(OPT_ARG(LOGFILE)); msyslog(LOG_INFO, "%s", sntpVersion); if (0 == argc && !HAVE_OPT(BROADCAST) && !HAVE_OPT(CONCURRENT)) { printf("%s: Must supply at least one of -b hostname, -c hostname, or hostname.\n", progname); exit(EX_USAGE); } /* ** Eventually, we probably want: ** - separate bcst and ucst timeouts (why?) ** - multiple --timeout values in the commandline */ response_timeout = OPT_VALUE_TIMEOUT; response_tv.tv_sec = response_timeout; response_tv.tv_usec = 0; /* IPv6 available? */ if (isc_net_probeipv6() != ISC_R_SUCCESS) { ai_fam_pref = AF_INET; TRACE(1, ("No ipv6 support available, forcing ipv4\n")); } else { /* Check for options -4 and -6 */ if (HAVE_OPT(IPV4)) ai_fam_pref = AF_INET; else if (HAVE_OPT(IPV6)) ai_fam_pref = AF_INET6; } /* TODO: Parse config file if declared */ /* ** Init the KOD system. ** For embedded systems with no writable filesystem, ** -K /dev/null can be used to disable KoD storage. */ kod_init_kod_db(OPT_ARG(KOD), FALSE); // HMS: Should we use arg-defalt for this too? if (HAVE_OPT(KEYFILE)) auth_init(OPT_ARG(KEYFILE), &keys); /* ** Considering employing a variable that prevents functions of doing ** anything until everything is initialized properly ** ** HMS: What exactly does the above mean? */ event_set_log_callback(&sntp_libevent_log_cb); if (debug > 0) event_enable_debug_mode(); #ifdef WORK_THREAD evthread_use_pthreads(); /* we use libevent from main thread only, locks should be academic */ if (debug > 0) evthread_enable_lock_debuging(); #endif evcfg = event_config_new(); if (NULL == evcfg) { printf("%s: event_config_new() failed!\n", progname); return -1; } #ifndef HAVE_SOCKETPAIR event_config_require_features(evcfg, EV_FEATURE_FDS); #endif /* all libevent calls are from main thread */ /* event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); */ base = event_base_new_with_config(evcfg); event_config_free(evcfg); if (NULL == base) { printf("%s: event_base_new() failed!\n", progname); return -1; } /* wire into intres resolver */ worker_per_query = TRUE; addremove_io_fd = &sntp_addremove_fd; open_sockets(); if (HAVE_OPT(BROADCAST)) { int cn = STACKCT_OPT( BROADCAST ); const char ** cp = STACKLST_OPT( BROADCAST ); while (cn-- > 0) { handle_lookup(*cp, CTX_BCST); cp++; } } if (HAVE_OPT(CONCURRENT)) { int cn = STACKCT_OPT( CONCURRENT ); const char ** cp = STACKLST_OPT( CONCURRENT ); while (cn-- > 0) { handle_lookup(*cp, CTX_UCST | CTX_CONC); cp++; } } for (i = 0; i < argc; ++i) handle_lookup(argv[i], CTX_UCST); gettimeofday_cached(base, &start_tv); event_base_dispatch(base); event_base_free(base); if (!time_adjusted && (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW))) exitcode = 1; else exitcode = 0; return exitcode; }
void add_diskfree_info(xmlNodePtr node) { float fullest = 0.0; char info[32768]; int i, ignore; if (st.disk) { sg_fs_stats *disk_stat_ptr = st.disk; int counter; for (counter=0, ignore=0; counter < st.disk_entries; counter++){ float use; if (HAVE_OPT( IGNOREDISKFREE )) { int ct = STACKCT_OPT( IGNOREDISKFREE ); char** pp = (char **) &STACKLST_OPT( IGNOREDISKFREE ); do { char* p = *pp++; if (strcmp(disk_stat_ptr->device_name, p) ==0 ) ignore=1; } while (--ct > 0); } if (ignore == 0 ) { use = 100.00 * ((float) disk_stat_ptr->used / (float) (disk_stat_ptr->used + disk_stat_ptr->avail)); if (use > fullest) fullest = use; } ignore=0; /* Reset the ignore flag */ disk_stat_ptr++; /* next partition please */ } } if (fullest > OPT_VALUE_DISKFREE_YELLOW) { // if some disk is more then the yellow treshold full give `df` listing char cmd[1024]; char buffer[24]; FILE *in; if (fullest > OPT_VALUE_DISKFREE_YELLOW) sprintf(buffer, "%d", STAT_YELLOW); if (fullest > OPT_VALUE_DISKFREE_RED) sprintf(buffer, "%d", STAT_RED); xmlSetProp(node, "color", buffer); sprintf(cmd, "%s > /tmp/.uw_sysstat.tmp", OPT_ARG(DF_COMMAND)); LOG(LOG_INFO, cmd); uw_setproctitle("running %s", OPT_ARG(DF_COMMAND)); system(cmd); in = fopen("/tmp/.uw_sysstat.tmp", "r"); if (in) { signed char *s = info; size_t len; for (len=0; len < sizeof(info)-1; len++) { int c; if ((c = fgetc(in)) != EOF) { if (c < 0) c = ' '; *s++ = c; } } *s = 0; fclose(in); } else { strcpy(info, strerror(errno)); } unlink("/tmp/.uw_sysstat.tmp"); xmlNewTextChild(node, NULL, "info", info); } }
/* * main - parse arguments and handle options */ int ntpdcmain( int argc, char *argv[] ) { extern int ntp_optind; delay_time.l_ui = 0; delay_time.l_uf = DEFDELAY; #ifdef SYS_VXWORKS clear_globals(); taskPrioritySet(taskIdSelf(), 100 ); #endif init_lib(); /* sets up ipv4_works, ipv6_works */ ssl_applink(); /* Check to see if we have IPv6. Otherwise default to IPv4 */ if (!ipv6_works) ai_fam_default = AF_INET; progname = argv[0]; { int optct = ntpOptionProcess(&ntpdcOptions, argc, argv); argc -= optct; argv += optct; } if (HAVE_OPT(IPV4)) ai_fam_templ = AF_INET; else if (HAVE_OPT(IPV6)) ai_fam_templ = AF_INET6; else ai_fam_templ = ai_fam_default; if (HAVE_OPT(COMMAND)) { int cmdct = STACKCT_OPT( COMMAND ); const char** cmds = STACKLST_OPT( COMMAND ); while (cmdct-- > 0) { ADDCMD(*cmds++); } } debug = DESC(DEBUG_LEVEL).optOccCt; if (HAVE_OPT(INTERACTIVE)) { interactive = 1; } if (HAVE_OPT(NUMERIC)) { showhostnames = 0; } if (HAVE_OPT(LISTPEERS)) { ADDCMD("listpeers"); } if (HAVE_OPT(PEERS)) { ADDCMD("peers"); } if (HAVE_OPT(SHOWPEERS)) { ADDCMD("dmpeers"); } if (ntp_optind == argc) { ADDHOST(DEFHOST); } else { for (; ntp_optind < argc; ntp_optind++) ADDHOST(argv[ntp_optind]); } if (numcmds == 0 && interactive == 0 && isatty(fileno(stdin)) && isatty(fileno(stderr))) { interactive = 1; } #if 0 ai_fam_templ = ai_fam_default; while ((c = ntp_getopt(argc, argv, "46c:dilnps")) != EOF) switch (c) { case '4': ai_fam_templ = AF_INET; break; case '6': ai_fam_templ = AF_INET6; break; case 'c': ADDCMD(ntp_optarg); break; case 'd': ++debug; break; case 'i': interactive = 1; break; case 'l': ADDCMD("listpeers"); break; case 'n': showhostnames = 0; break; case 'p': ADDCMD("peers"); break; case 's': ADDCMD("dmpeers"); break; default: errflg++; break; } if (errflg) { (void) fprintf(stderr, "usage: %s [-46dilnps] [-c cmd] host ...\n", progname); exit(2); } if (ntp_optind == argc) { ADDHOST(DEFHOST); } else { for (; ntp_optind < argc; ntp_optind++) ADDHOST(argv[ntp_optind]); } if (numcmds == 0 && interactive == 0 && isatty(fileno(stdin)) && isatty(fileno(stderr))) { interactive = 1; } #endif #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */ if (interactive) (void) signal_no_reset(SIGINT, abortcmd); #endif /* SYS_WINNT */ /* * Initialize the packet data buffer */ pktdatasize = INITDATASIZE; pktdata = emalloc(INITDATASIZE); if (numcmds == 0) { (void) openhost(chosts[0]); getcmds(); } else { int ihost; int icmd; for (ihost = 0; ihost < numhosts; ihost++) { if (openhost(chosts[ihost])) for (icmd = 0; icmd < numcmds; icmd++) { if (numhosts > 1) printf ("--- %s ---\n",chosts[ihost]); docmd(ccmds[icmd]); } } } #ifdef SYS_WINNT WSACleanup(); #endif return(0); } /* main end */
int run(void) { xmlDocPtr doc; xmlNodePtr node; int ct = STACKCT_OPT(OUTPUT); char **output = (char **) &STACKLST_OPT(OUTPUT); GString *log; int i; int color; int highest_color = STAT_GREEN; char buf[24]; extern int forever; uw_setproctitle("sleeping"); for (i=0; i < OPT_VALUE_INTERVAL; i++) { // wait some minutes sleep(1); if (!forever) { return(0); } } uw_setproctitle("getting system statistics"); get_stats(); doc = UpwatchXmlDoc("result", NULL); xmlSetDocCompressMode(doc, OPT_VALUE_COMPRESS); // do the sysstat node = (xmlNodePtr) newnode(doc, "sysstat"); add_loadavg(node); add_cpu(node); add_paging(node); add_blockio(node); add_swap(node); add_memory(node); add_systemp(node); add_sysstat_info(node); color = xmlGetPropInt(node, "color"); if (color > highest_color) highest_color = color; #if USE_XMBMON|| defined (__OpenBSD__) if (OPT_VALUE_HWSTATS ) { // do the hwstat get_hwstats(); node = (xmlNodePtr) newnode(doc, "hwstat"); add_hwstat(node); color = xmlGetPropInt(node, "color"); if (color > highest_color) highest_color = color; } #endif if (OPT_VALUE_LOCALCHECKS ) { // do the local checks color = do_local((xmlNodePtr) doc); if (color > highest_color) highest_color = color; } #if HAVE_LIBPCRE // do the errlog node = (xmlNodePtr) newnode(doc, "errlog"); log = check_logs(&color); if (color > highest_color) highest_color = color; sprintf(buf, "%u", color); xmlSetProp(node, "color", buf); if (log) { if (log->str && strlen(log->str) > 0) { xmlNewTextChild(node, NULL, "info", log->str); } g_string_free(log, TRUE); } #endif // do the diskfree uw_setproctitle("checking diskspace"); node = (xmlNodePtr) newnode(doc, "diskfree"); add_diskfree_info(node); color = xmlGetPropInt(node, "color"); if (color > highest_color) highest_color = color; if (HAVE_OPT(HPQUEUE) && (highest_color != prv_highest_color)) { // if status changed, it needs to be sent immediately. So drop into // the high priority queue. Else just drop in the normal queue where // uw_send in batched mode will pick it up later spool_result(OPT_ARG(SPOOLDIR), OPT_ARG(HPQUEUE), doc, NULL); } else { for (i=0; i < ct; i++) { spool_result(OPT_ARG(SPOOLDIR), output[i], doc, NULL); } } prv_highest_color = highest_color; // remember for next time xmlFreeDoc(doc); return 0; }
/* * getCmdOpts - get command line options */ void getCmdOpts( int argc, char *argv[] ) { extern const char *config_file; int errflg; tOptions *myOptions = &OPTSTRUCT; /* * Initialize, initialize */ errflg = 0; switch (WHICH_IDX_IPV4) { case INDEX_OPT_IPV4: default_ai_family = AF_INET; break; case INDEX_OPT_IPV6: default_ai_family = AF_INET6; break; default: /* ai_fam_templ = ai_fam_default; */ break; } if (HAVE_OPT( AUTHREQ )) proto_config(PROTO_AUTHENTICATE, 1, 0., NULL); if (HAVE_OPT( AUTHNOREQ )) proto_config(PROTO_AUTHENTICATE, 0, 0., NULL); if (HAVE_OPT( BCASTSYNC )) proto_config(PROTO_BROADCLIENT, 1, 0., NULL); if (HAVE_OPT( CONFIGFILE )) { config_file = OPT_ARG( CONFIGFILE ); #ifdef HAVE_NETINFO check_netinfo = 0; #endif } if (HAVE_OPT( DRIFTFILE )) stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE )); if (HAVE_OPT( PANICGATE )) allow_panic = TRUE; if (HAVE_OPT( JAILDIR )) { #ifdef HAVE_DROPROOT droproot = 1; chrootdir = OPT_ARG( JAILDIR ); #else fprintf(stderr, "command line -i option (jaildir) is not supported by this binary" # ifndef SYS_WINNT ",\n" "can not drop root privileges. See configure options\n" "--enable-clockctl and --enable-linuxcaps.\n"); # else ".\n"); # endif msyslog(LOG_ERR, "command line -i option (jaildir) is not supported by this binary."); errflg++; #endif } if (HAVE_OPT( KEYFILE )) getauthkeys(OPT_ARG( KEYFILE )); if (HAVE_OPT( PIDFILE )) stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE )); if (HAVE_OPT( QUIT )) mode_ntpdate = TRUE; if (HAVE_OPT( PROPAGATIONDELAY )) do { double tmp; const char *my_ntp_optarg = OPT_ARG( PROPAGATIONDELAY ); if (sscanf(my_ntp_optarg, "%lf", &tmp) != 1) { msyslog(LOG_ERR, "command line broadcast delay value %s undecodable", my_ntp_optarg); } else { proto_config(PROTO_BROADDELAY, 0, tmp, NULL); } } while (0); if (HAVE_OPT( STATSDIR )) stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR )); if (HAVE_OPT( TRUSTEDKEY )) { int ct = STACKCT_OPT( TRUSTEDKEY ); const char** pp = STACKLST_OPT( TRUSTEDKEY ); do { u_long tkey; const char* p = *pp++; tkey = (int)atol(p); if (tkey == 0 || tkey > NTP_MAXKEY) { msyslog(LOG_ERR, "command line trusted key %s is invalid", p); } else { authtrust(tkey, 1); } } while (--ct > 0); } if (HAVE_OPT( USER )) { #ifdef HAVE_DROPROOT char *ntp_optarg = OPT_ARG( USER ); droproot = 1; user = emalloc(strlen(ntp_optarg) + 1); (void)strncpy(user, ntp_optarg, strlen(ntp_optarg) + 1); group = rindex(user, ':'); if (group) *group++ = '\0'; /* get rid of the ':' */ #else fprintf(stderr, "command line -u/--user option is not supported by this binary" # ifndef SYS_WINNT ",\n" "can not drop root privileges. See configure options\n" "--enable-clockctl and --enable-linuxcaps.\n"); # else ".\n"); # endif msyslog(LOG_ERR, "command line -u/--user option is not supported by this binary."); errflg++; #endif } if (HAVE_OPT( VAR )) { int ct = STACKCT_OPT( VAR ); const char** pp = STACKLST_OPT( VAR ); do { const char* my_ntp_optarg = *pp++; set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1, (u_short) (RW)); } while (--ct > 0); } if (HAVE_OPT( DVAR )) { int ct = STACKCT_OPT( DVAR ); const char** pp = STACKLST_OPT( DVAR ); do { const char* my_ntp_optarg = *pp++; set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1, (u_short) (RW | DEF)); } while (--ct > 0); } if (HAVE_OPT( SLEW )) clock_max = 600; if (HAVE_OPT( UPDATEINTERVAL )) { long val = OPT_VALUE_UPDATEINTERVAL; if (val >= 0) interface_interval = val; else { fprintf(stderr, "command line interface update interval %ld must not be negative\n", val); msyslog(LOG_ERR, "command line interface update interval %ld must not be negative", val); errflg++; } } #ifdef SIM if (HAVE_OPT( SIMBROADCASTDELAY )) sscanf(OPT_ARG( SIMBROADCASTDELAY ), "%lf", &ntp_node.bdly); if (HAVE_OPT( PHASENOISE )) sscanf(OPT_ARG( PHASENOISE ), "%lf", &ntp_node.snse); if (HAVE_OPT( SIMSLEW )) sscanf(OPT_ARG( SIMSLEW ), "%lf", &ntp_node.slew); if (HAVE_OPT( SERVERTIME )) sscanf(OPT_ARG( SERVERTIME ), "%lf", &ntp_node.clk_time); if (HAVE_OPT( ENDSIMTIME )) sscanf(OPT_ARG( ENDSIMTIME ), "%lf", &ntp_node.sim_time); if (HAVE_OPT( FREQERR )) sscanf(OPT_ARG( FREQERR ), "%lf", &ntp_node.ferr); if (HAVE_OPT( WALKNOISE )) sscanf(OPT_ARG( WALKNOISE ), "%lf", &ntp_node.fnse); if (HAVE_OPT( NDELAY )) sscanf(OPT_ARG( NDELAY ), "%lf", &ntp_node.ndly); if (HAVE_OPT( PDELAY )) sscanf(OPT_ARG( PDELAY ), "%lf", &ntp_node.pdly); #endif /* SIM */ if (errflg || argc) { if (argc) fprintf(stderr, "argc after processing is <%d>\n", argc); optionUsage(myOptions, 2); } return; }
/* * emitDefinition */ LOCAL char* emitDefinition(char* pzDef, char* pzOut) { char sep_char; char zEntryName[ MAXNAMELEN ]; /* * Indent attribute definitions four spaces */ { char* p = zEntryName; *pzOut++ = ' '; *pzOut++ = ' '; *pzOut++ = ' '; *pzOut++ = ' '; while (AG_NAME_CHAR(*pzDef)) *p++ = *pzOut++ = *pzDef++; if (p >= zEntryName + sizeof(zEntryName)) die("names are constrained to %d bytes\n", MAXNAMELEN); *p = NUL; } /* * Strip the prefixes from all the definition lines * (viz., the "^.*\*" text, except that it is a shortest match * instead of longest match). Skip the ':' before starting. */ compress_def(++pzDef); if (HAVE_OPT( SUBBLOCK )) { int ct = STACKCT_OPT( SUBBLOCK ); char const ** ppz = STACKLST_OPT( SUBBLOCK ); do { char const * pz = *ppz++; if (strcmp(pz, zEntryName) == 0) return emit_subblock(pz, pzDef, pzOut); } while (--ct > 0); } if (HAVE_OPT( LISTATTR )) { int ct = STACKCT_OPT( LISTATTR ); char const ** ppz = STACKLST_OPT( LISTATTR ); do { if (strcmp(*ppz++, zEntryName) == 0) return list_attrib(pzDef, pzOut); } while (--ct > 0); } if (isspace(*pzDef)) sep_char = *pzDef++; else sep_char = ' '; switch (*pzDef) { case NUL: *pzOut++ = ';'; *pzOut++ = '\n'; break; case '"': case '\'': case '{': /* * Quoted entries or subblocks do their own stringification * sprintf is safe because we are copying strings around * and *always* making the result smaller than the original */ pzOut += sprintf(pzOut, " =%c%s;\n", sep_char, pzDef); break; default: *pzOut++ = ' '; *pzOut++ = '='; *pzOut++ = sep_char; *pzOut++ = '\''; for (;;) { switch (*pzOut++ = *pzDef++) { case '\\': *pzOut++ = '\\'; break; case '\'': pzOut[-1] = '\\'; *pzOut++ = '\''; break; case NUL: goto unquotedDone; } } unquotedDone:; pzOut[-1] = '\''; *pzOut++ = ';'; *pzOut++ = '\n'; break; } return pzOut; }
/* * getCmdOpts - get command line options */ void getCmdOpts( int argc, char *argv[] ) { extern const char *config_file; int errflg; tOptions *myOptions = &ntpdOptions; /* * Initialize, initialize */ errflg = 0; if (HAVE_OPT( IPV4 )) default_ai_family = AF_INET; else if (HAVE_OPT( IPV6 )) default_ai_family = AF_INET6; if (HAVE_OPT( AUTHREQ )) proto_config(PROTO_AUTHENTICATE, 1, 0., NULL); else if (HAVE_OPT( AUTHNOREQ )) proto_config(PROTO_AUTHENTICATE, 0, 0., NULL); if (HAVE_OPT( BCASTSYNC )) proto_config(PROTO_BROADCLIENT, 1, 0., NULL); if (HAVE_OPT( CONFIGFILE )) { config_file = OPT_ARG( CONFIGFILE ); #ifdef HAVE_NETINFO check_netinfo = 0; #endif } if (HAVE_OPT( DRIFTFILE )) stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE )); if (HAVE_OPT( PANICGATE )) allow_panic = TRUE; #ifdef HAVE_DROPROOT if (HAVE_OPT( JAILDIR )) { droproot = 1; chrootdir = OPT_ARG( JAILDIR ); } #endif if (HAVE_OPT( KEYFILE )) getauthkeys(OPT_ARG( KEYFILE )); if (HAVE_OPT( PIDFILE )) stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE )); if (HAVE_OPT( QUIT )) mode_ntpdate = TRUE; if (HAVE_OPT( PROPAGATIONDELAY )) do { double tmp; const char *my_ntp_optarg = OPT_ARG( PROPAGATIONDELAY ); if (sscanf(my_ntp_optarg, "%lf", &tmp) != 1) { msyslog(LOG_ERR, "command line broadcast delay value %s undecodable", my_ntp_optarg); } else { proto_config(PROTO_BROADDELAY, 0, tmp, NULL); } } while (0); if (HAVE_OPT( STATSDIR )) stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR )); if (HAVE_OPT( TRUSTEDKEY )) { int ct = STACKCT_OPT( TRUSTEDKEY ); const char** pp = STACKLST_OPT( TRUSTEDKEY ); do { u_long tkey; const char* p = *pp++; tkey = (int)atol(p); if (tkey == 0 || tkey > NTP_MAXKEY) { msyslog(LOG_ERR, "command line trusted key %s is invalid", p); } else { authtrust(tkey, 1); } } while (--ct > 0); } #ifdef HAVE_DROPROOT if (HAVE_OPT( USER )) { droproot = 1; user = estrdup(OPT_ARG( USER )); group = rindex(user, ':'); if (group) *group++ = '\0'; /* get rid of the ':' */ } #endif if (HAVE_OPT( VAR )) { int ct = STACKCT_OPT( VAR ); const char** pp = STACKLST_OPT( VAR ); do { const char* my_ntp_optarg = *pp++; set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1, (u_short) (RW)); } while (--ct > 0); } if (HAVE_OPT( DVAR )) { int ct = STACKCT_OPT( DVAR ); const char** pp = STACKLST_OPT( DVAR ); do { const char* my_ntp_optarg = *pp++; set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1, (u_short) (RW | DEF)); } while (--ct > 0); } if (HAVE_OPT( SLEW )) { clock_max = 600; kern_enable = 0; } if (HAVE_OPT( UPDATEINTERVAL )) { long val = OPT_VALUE_UPDATEINTERVAL; if (val >= 0) interface_interval = val; else { fprintf(stderr, "command line interface update interval %ld must not be negative\n", val); msyslog(LOG_ERR, "command line interface update interval %ld must not be negative", val); errflg++; } } #ifdef SIM /* SK: * The simulator no longer takes any command line arguments. Hence, * all the code that was here has been removed. */ #endif /* SIM */ if (errflg || argc) { if (argc) fprintf(stderr, "argc after processing is <%d>\n", argc); optionUsage(myOptions, 2); } return; }
/* * getCmdOpts - apply most command line options * * A few options are examined earlier in ntpd.c ntpdmain() and * ports/winnt/ntpd/ntservice.c main(). */ void getCmdOpts( int argc, char ** argv ) { extern const char *config_file; int errflg; /* * Initialize, initialize */ errflg = 0; if (ipv4_works && ipv6_works) { if (HAVE_OPT( IPV4 )) ipv6_works = 0; else if (HAVE_OPT( IPV6 )) ipv4_works = 0; } else if (!ipv4_works && !ipv6_works) { msyslog(LOG_ERR, "Neither IPv4 nor IPv6 networking detected, fatal."); exit(1); } else if (HAVE_OPT( IPV4 ) && !ipv4_works) msyslog(LOG_WARNING, "-4/--ipv4 ignored, IPv4 networking not found."); else if (HAVE_OPT( IPV6 ) && !ipv6_works) msyslog(LOG_WARNING, "-6/--ipv6 ignored, IPv6 networking not found."); if (HAVE_OPT( AUTHREQ )) proto_config(PROTO_AUTHENTICATE, 1, 0., NULL); else if (HAVE_OPT( AUTHNOREQ )) proto_config(PROTO_AUTHENTICATE, 0, 0., NULL); if (HAVE_OPT( BCASTSYNC )) proto_config(PROTO_BROADCLIENT, 1, 0., NULL); if (HAVE_OPT( CONFIGFILE )) { config_file = OPT_ARG( CONFIGFILE ); #ifdef HAVE_NETINFO check_netinfo = 0; #endif } if (HAVE_OPT( DRIFTFILE )) stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE )); if (HAVE_OPT( PANICGATE )) allow_panic = TRUE; if (HAVE_OPT( FORCE_STEP_ONCE )) force_step_once = TRUE; #ifdef HAVE_DROPROOT if (HAVE_OPT( JAILDIR )) { droproot = 1; chrootdir = OPT_ARG( JAILDIR ); } #endif if (HAVE_OPT( KEYFILE )) getauthkeys(OPT_ARG( KEYFILE )); if (HAVE_OPT( PIDFILE )) stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE )); if (HAVE_OPT( QUIT )) mode_ntpdate = TRUE; if (HAVE_OPT( PROPAGATIONDELAY )) do { double tmp; const char *my_ntp_optarg = OPT_ARG( PROPAGATIONDELAY ); if (sscanf(my_ntp_optarg, "%lf", &tmp) != 1) { msyslog(LOG_ERR, "command line broadcast delay value %s undecodable", my_ntp_optarg); } else { proto_config(PROTO_BROADDELAY, 0, tmp, NULL); } } while (0); if (HAVE_OPT( STATSDIR )) stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR )); if (HAVE_OPT( TRUSTEDKEY )) { int ct = STACKCT_OPT( TRUSTEDKEY ); const char** pp = STACKLST_OPT( TRUSTEDKEY ); do { u_long tkey; const char* p = *pp++; tkey = (int)atol(p); if (tkey == 0 || tkey > NTP_MAXKEY) { msyslog(LOG_ERR, "command line trusted key %s is invalid", p); } else { authtrust(tkey, 1); } } while (--ct > 0); } #ifdef HAVE_DROPROOT if (HAVE_OPT( USER )) { droproot = 1; user = estrdup(OPT_ARG( USER )); group = strrchr(user, ':'); if (group != NULL) { size_t len; *group++ = '\0'; /* get rid of the ':' */ len = group - user; group = estrdup(group); user = erealloc(user, len); } } #endif if (HAVE_OPT( VAR )) { int ct; const char ** pp; const char * v_assign; ct = STACKCT_OPT( VAR ); pp = STACKLST_OPT( VAR ); do { v_assign = *pp++; set_sys_var(v_assign, strlen(v_assign) + 1, RW); } while (--ct > 0); } if (HAVE_OPT( DVAR )) { int ct = STACKCT_OPT( DVAR ); const char** pp = STACKLST_OPT( DVAR ); do { const char* my_ntp_optarg = *pp++; set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1, (u_short) (RW | DEF)); } while (--ct > 0); } if (HAVE_OPT( SLEW )) loop_config(LOOP_MAX, 600); if (HAVE_OPT( UPDATEINTERVAL )) { long val = OPT_VALUE_UPDATEINTERVAL; if (val >= 0) interface_interval = val; else { fprintf(stderr, "command line interface update interval %ld must not be negative\n", val); msyslog(LOG_ERR, "command line interface update interval %ld must not be negative", val); errflg++; } } /* save list of servers from cmd line for config_peers() use */ if (argc > 0) { cmdline_server_count = argc; cmdline_servers = argv; } /* display usage & exit with any option processing errors */ if (errflg) optionUsage(&ntpdOptions, 2); /* does not return */ }