📄 ntp_config.c
字号:
info_auth_keyid = req_keyid;#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */ if (res_fp != NULL) { if (call_resolver) { /* * Need name resolution */ do_resolve_internal(); } }}#ifdef HAVE_NETINFO/* * get_netinfo_config - find the nearest NetInfo domain with an ntp * configuration and initialize the configuration state. */static struct netinfo_config_state *get_netinfo_config(){ ni_status status; void *domain; ni_id config_dir; struct netinfo_config_state *config; if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { void *next_domain; if (ni_open(domain, "..", &next_domain) != NI_OK) { ni_free(next_domain); break; } ni_free(domain); domain = next_domain; } if (status != NI_OK) { ni_free(domain); return NULL; } config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state)); config->domain = domain; config->config_dir = config_dir; config->prop_index = 0; config->val_index = 0; config->val_list = NULL; return config;}/* * free_netinfo_config - release NetInfo configuration state */static voidfree_netinfo_config(struct netinfo_config_state *config){ ni_free(config->domain); free(config);}/* * gettokens_netinfo - return tokens from NetInfo */static intgettokens_netinfo ( struct netinfo_config_state *config, char **tokenlist, int *ntokens ){ int prop_index = config->prop_index; int val_index = config->val_index; char **val_list = config->val_list; /* * Iterate through each keyword and look for a property that matches it. */ again: if (!val_list) { for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++) { ni_namelist namelist; struct keyword current_prop = keywords[prop_index]; /* * For each value associated in the property, we're going to return * a separate line. We squirrel away the values in the config state * so the next time through, we don't need to do this lookup. */ NI_INIT(&namelist); if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) { ni_index index; /* Found the property, but it has no values */ if (namelist.ni_namelist_len == 0) continue; if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1)))) { msyslog(LOG_ERR, "out of memory while configuring"); break; } for (index = 0; index < namelist.ni_namelist_len; index++) { char *value = namelist.ni_namelist_val[index]; if (! (val_list[index] = (char*)malloc(strlen(value)+1))) { msyslog(LOG_ERR, "out of memory while configuring"); break; } strcpy(val_list[index], value); } val_list[index] = NULL; break; } ni_namelist_free(&namelist); } config->prop_index = prop_index; } /* No list; we're done here. */ if (!val_list) return CONFIG_UNKNOWN; /* * We have a list of values for the current property. * Iterate through them and return each in order. */ if (val_list[val_index]) { int ntok = 1; int quoted = 0; char *tokens = val_list[val_index]; msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); (const char*)tokenlist[0] = keywords[prop_index].text; for (ntok = 1; ntok < MAXTOKENS; ntok++) { tokenlist[ntok] = tokens; while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) quoted ^= (*tokens++ == '"'); if (ISEOL(*tokens)) { *tokens = '\0'; break; } else { /* must be space */ *tokens++ = '\0'; while (ISSPACE(*tokens)) tokens++; if (ISEOL(*tokens)) break; } } if (ntok == MAXTOKENS) { /* HMS: chomp it to lose the EOL? */ msyslog(LOG_ERR, "gettokens_netinfo: too many tokens. Ignoring: %s", tokens); } else { *ntokens = ntok + 1; } config->val_index++; /* HMS: Should this be in the 'else'? */ return keywords[prop_index].keytype; } /* We're done with the current property. */ prop_index = ++config->prop_index; /* Free val_list and reset counters. */ for (val_index = 0; val_list[val_index]; val_index++) free(val_list[val_index]); free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0; goto again;}#endif /* HAVE_NETINFO *//* * gettokens - read a line and return tokens */static intgettokens ( FILE *fp, char *line, char **tokenlist, int *ntokens ){ register char *cp; register int ntok; register int quoted = 0; /* * Find start of first token */ again: while ((cp = fgets(line, MAXLINE, fp)) != NULL) { cp = line; while (ISSPACE(*cp)) cp++; if (!ISEOL(*cp)) break; } if (cp == NULL) { *ntokens = 0; return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */ } /* * Now separate out the tokens */ for (ntok = 0; ntok < MAXTOKENS; ntok++) { tokenlist[ntok] = cp; while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted)) quoted ^= (*cp++ == '"'); if (ISEOL(*cp)) { *cp = '\0'; break; } else { /* must be space */ *cp++ = '\0'; while (ISSPACE(*cp)) cp++; if (ISEOL(*cp)) break; } } /* Heiko: Remove leading and trailing quotes around tokens */ { int i,j = 0; for (i = 0; i < ntok; i++) { /* Now check if the first char is a quote and remove that */ if ( tokenlist[ntok][0] == '"' ) tokenlist[ntok]++; /* Now check the last char ... */ j = strlen(tokenlist[ntok])-1; if ( tokenlist[ntok][j] == '"' ) tokenlist[ntok][j] = '\0'; } } if (ntok == MAXTOKENS) { --ntok; /* HMS: chomp it to lose the EOL? */ msyslog(LOG_ERR, "gettokens: too many tokens on the line. Ignoring %s", cp); } else { /* * Return the match */ *ntokens = ntok + 1; ntok = matchkey(tokenlist[0], keywords, 1); if (ntok == CONFIG_UNKNOWN) goto again; } return ntok;}/* * matchkey - match a keyword to a list */static intmatchkey( register char *word, register struct keyword *keys, int complain ){ for (;;) { if (keys->keytype == CONFIG_UNKNOWN) { if (complain) msyslog(LOG_ERR, "configure: keyword \"%s\" unknown, line ignored", word); return CONFIG_UNKNOWN; } if (STRSAME(word, keys->text)) return keys->keytype; keys++; }}/* * getnetnum - return a net number (this is crude, but careful) */static intgetnetnum( const char *num, struct sockaddr_storage *addr, int complain, enum gnn_type a_type ){ struct addrinfo hints; struct addrinfo *ptr; int retval; /* Get host address. Looking for UDP datagram connection */ memset(&hints, 0, sizeof (hints)); if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6) hints.ai_family = addr->ss_family; else hints.ai_family = AF_UNSPEC; /* * If we don't have an IPv6 stack, just look up IPv4 addresses */ if (isc_net_probeipv6() != ISC_R_SUCCESS) hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM;#ifdef DEBUG if (debug > 3) printf("getaddrinfo %s\n", num);#endif retval = getaddrinfo(num, "ntp", &hints, &ptr); if (retval != 0 || (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) { if (complain) msyslog(LOG_ERR, "getaddrinfo: \"%s\" invalid host address, ignored", num);#ifdef DEBUG if (debug > 0) printf( "getaddrinfo: \"%s\" invalid host address%s.\n", num, (complain) ? ", ignored" : "");#endif if (retval == 0 && ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS) { return -1; } else { return 0; } } memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);#ifdef DEBUG if (debug > 1) printf("getnetnum given %s, got %s \n", num, stoa(addr));#endif freeaddrinfo(ptr); return 1;}#if !defined(VMS) && !defined(SYS_WINNT)/* * catchchild - receive the resolver's exit status */static RETSIGTYPEcatchchild( int sig ){ /* * We only start up one child, and if we're here * it should have already exited. Hence the following * shouldn't hang. If it does, please tell me. */#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS) (void) wait(0);#endif /* SYS_WINNT && VXWORKS*/}#endif /* VMS *//* * save_resolve - save configuration info into a file for later name resolution */static voidsave_resolve( char *name, int mode, int version, int minpoll, int maxpoll, u_int flags, int ttl, keyid_t keyid, u_char *keystr ){#ifndef SYS_VXWORKS if (res_fp == NULL) {#ifndef SYS_WINNT (void) strcpy(res_file, RES_TEMPFILE);#else /* no /tmp directory under NT */ { if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) { msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m"); return; } (void) strcat(res_file, "ntpdXXXXXX"); }#endif /* SYS_WINNT */#ifdef HAVE_MKSTEMP { int fd; res_fp = NULL; if ((fd = mkstemp(res_file)) != -1) res_fp = fdopen(fd, "r+"); }#else (void) mktemp(res_file); res_fp = fopen(res_file, "w");#endif if (res_fp == NULL) { msyslog(LOG_ERR, "open failed for %s: %m", res_file); return; } }#ifdef DEBUG if (debug) { printf("resolving %s\n", name); }#endif (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name, mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);#ifdef DEBUG if (debug > 1) printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);#endif#else /* SYS_VXWORKS */ /* save resolve info to a struct */#endif /* SYS_VXWORKS */}/* * abort_resolve - terminate the resolver stuff and delete the file */static voidabort_resolve(void){ /* * In an ideal world we would might reread the file and * log the hosts which aren't getting configured. Since * this is too much work, however, just close and delete * the temp file. */ if (res_fp != NULL) (void) fclose(res_fp); res_fp = NULL;#ifndef SYS_VXWORKS /* we don't open the file to begin with */#if !defined(VMS) (void) unlink(res_file);#else (void) delete(res_file);#endif /* VMS */#endif /* SYS_VXWORKS */}/* * do_resolve_internal - start up the resolver function (not program) *//* * On VMS, this routine will simply refuse to resolve anything. * * Possible implementation: keep `res_file' in memory, do async * name resolution via QIO, update from within completion AST. * I'm unlikely to find the time for doing this, though. -wjm */static voiddo_resolve_internal(void){ int i; if (res_fp == NULL) { /* belch */ msyslog(LOG_ERR, "do_resolve_internal: Fatal: res_fp == NULL"); exit(1); } /* we are done with this now */ (void) fclose(res_fp); res_fp = NULL;#if !defined(VMS) && !defined (SYS_VXWORKS) req_file = res_file; /* set up pointer to res file */#ifndef SYS_WINNT (void) signal_no_reset(SIGCHLD, catchchild);#ifndef SYS_VXWORKS i = fork(); if (i == 0) { /* * this used to close everything * I don't think this is necessary */ /* * To the unknown commenter above: * Well, I think it's better to clean up * after oneself. I have had problems with * refclock-io when intres was running - things * where fine again when ntpintres was gone. * So some systems react erratic at least. * * Frank Kardel * * 94-11-16: * Further debugging has proven that the above is * absolutely harmful. The internal resolver * is still in the SIGIO process group and the lingering * async io information causes it to process requests from * all file decriptor causing a race between the NTP daemon * and the resolver. which then eats data when it wins 8-(. * It is absolutly necessary to kill any IO associations * shared with the NTP daemon. * * We also block SIGIO (currently no ports means to * disable the signal handle for IO). * * Thanks to wgstuken@informatik.uni-erlangen.de to notice * that it is the ntp-resolver child running into trouble. * * THUS: */ closelog(); kill_asyncio(0); (void) signal_no_reset(SIGCHLD, SIG_DFL);#ifdef DEBUG if (0) debug = 2;#endif# ifndef LOG_DAEMON openlog("ntpd_initres", LOG_PID);# else /* LOG_DAEMON */# ifndef LOG_NTP# define LOG_NTP LOG_DAEMON# endif openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);#ifndef SYS_CYGWIN32# ifdef DEBUG if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); else# endif /* DEBUG */ setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */# endif /* LOG_DAEMON */#endif ntp_intres(); /* * If we got here, the intres code screwed up. * Print something so we don't die without complaint */ msyslog(LOG_ERR, "call to ntp_intres lost"); abort_resolve(); exit(1); }#else /* vxWorks spawns a thread... -casey */ i = sp (ntp_intres); /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/#endif if (i == -1) { msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m"); (void) signal_no_reset(SIGCHLD, SIG_DFL); abort_resolve(); }#else /* SYS_WINNT */ { /* NT's equivalent of fork() is _spawn(), but the start point * of the new process is an executable filename rather than * a function name as desired here. */ DWORD dwThreadId; fflush(stdout); ResolverThreadHandle = CreateThread( NULL, /* no security attributes */ 0, /* use default stack size */ (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */ NULL, /* argument to thread function */ 0, /* use default creation flags */ &dwThreadId); /* returns the thread identifier */ if (ResolverThreadHandle == NULL) { msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres"); abort_resolve(); } }#endif /* SYS_WINNT */#else /* VMS VX_WORKS */ msyslog(LOG_ERR, "Name resolution not implemented for VMS - use numeric addresses"); abort_resolve();#endif /* VMS VX_WORKS */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -