📄 ntp_control.c
字号:
(u_int32)clock_stat->fudgeval2, NULL); else ctl_putid(clock_var[CC_FUDGEVAL2].text, (char *)&clock_stat->fudgeval2); } break; case CC_FLAGS: if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 | CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4))) ctl_putuint(clock_var[CC_FLAGS].text, clock_stat->flags); break; case CC_DEVICE: if (clock_stat->clockdesc == NULL || *(clock_stat->clockdesc) == '\0') { if (mustput) ctl_putstr(clock_var[CC_DEVICE].text, "", 0); } else { ctl_putstr(clock_var[CC_DEVICE].text, clock_stat->clockdesc, strlen(clock_stat->clockdesc)); } break; case CC_VARLIST: { char buf[CTL_MAX_DATA_LEN]; register char *s, *t, *be; register const char *ss; register int i; register struct ctl_var *k; s = buf; be = buf + sizeof(buf); if (s + strlen(clock_var[CC_VARLIST].text) + 4 > be) break; /* really long var name */ strcpy(s, clock_var[CC_VARLIST].text); strcat(s, "=\""); s += strlen(s); t = s; for (k = clock_var; !(k->flags &EOV); k++) { if (k->flags & PADDING) continue; i = strlen(k->text); if (s + i + 1 >= be) break; if (s != t) *s++ = ','; strcpy(s, k->text); s += i; } for (k = clock_stat->kv_list; k && !(k->flags & EOV); k++) { if (k->flags & PADDING) continue; ss = k->text; if (!ss) continue; while (*ss && *ss != '=') ss++; i = ss - k->text; if (s+i+1 >= be) break; if (s != t) *s++ = ','; strncpy(s, k->text, (unsigned)i); s += i; *s = '\0'; } if (s+2 >= be) break; *s++ = '"'; *s = '\0'; ctl_putdata(buf, (unsigned)( s - buf ), 0); } break; }}#endif/* * ctl_getitem - get the next data item from the incoming packet */static struct ctl_var *ctl_getitem( struct ctl_var *var_list, char **data ){ register struct ctl_var *v; register char *cp; register char *tp; static struct ctl_var eol = { 0, EOV, }; static char buf[128]; /* * Delete leading commas and white space */ while (reqpt < reqend && (*reqpt == ',' || isspace((unsigned char)*reqpt))) reqpt++; if (reqpt >= reqend) return (0); if (var_list == (struct ctl_var *)0) return (&eol); /* * Look for a first character match on the tag. If we find * one, see if it is a full match. */ v = var_list; cp = reqpt; while (!(v->flags & EOV)) { if (!(v->flags & PADDING) && *cp == *(v->text)) { tp = v->text; while (*tp != '\0' && *tp != '=' && cp < reqend && *cp == *tp) { cp++; tp++; } if ((*tp == '\0') || (*tp == '=')) { while (cp < reqend && isspace((unsigned char)*cp)) cp++; if (cp == reqend || *cp == ',') { buf[0] = '\0'; *data = buf; if (cp < reqend) cp++; reqpt = cp; return v; } if (*cp == '=') { cp++; tp = buf; while (cp < reqend && isspace((unsigned char)*cp)) cp++; while (cp < reqend && *cp != ',') { *tp++ = *cp++; if (tp >= buf + sizeof(buf)) { ctl_error(CERR_BADFMT); numctlbadpkts++;#if 0 /* Avoid possible DOS attack *//* If we get a smarter msyslog we can re-enable this */ msyslog(LOG_WARNING, "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n", stoa(rmt_addr), SRCPORT(rmt_addr) );#endif return (0); } } if (cp < reqend) cp++; *tp-- = '\0'; while (tp >= buf) { if (!isspace((unsigned int)(*tp))) break; *tp-- = '\0'; } reqpt = cp; *data = buf; return (v); } } cp = reqpt; } v++; } return v;}/* * control_unspec - response to an unspecified op-code *//*ARGSUSED*/static voidcontrol_unspec( struct recvbuf *rbufp, int restrict_mask ){ struct peer *peer; /* * What is an appropriate response to an unspecified op-code? * I return no errors and no data, unless a specified assocation * doesn't exist. */ if (res_associd != 0) { if ((peer = findpeerbyassoc(res_associd)) == 0) { ctl_error(CERR_BADASSOC); return; } rpkt.status = htons(ctlpeerstatus(peer)); } else { rpkt.status = htons(ctlsysstatus()); } ctl_flushpkt(0);}/* * read_status - return either a list of associd's, or a particular * peer's status. *//*ARGSUSED*/static voidread_status( struct recvbuf *rbufp, int restrict_mask ){ register int i; register struct peer *peer; u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];#ifdef DEBUG if (debug > 2) printf("read_status: ID %d\n", res_associd);#endif /* * Two choices here. If the specified association ID is * zero we return all known assocation ID's. Otherwise * we return a bunch of stuff about the particular peer. */ if (res_associd == 0) { register int n; n = 0; rpkt.status = htons(ctlsysstatus()); for (i = 0; i < NTP_HASH_SIZE; i++) { for (peer = assoc_hash[i]; peer != 0; peer = peer->ass_next) { ass_stat[n++] = htons(peer->associd); ass_stat[n++] = htons(ctlpeerstatus(peer)); if (n == CTL_MAX_DATA_LEN/sizeof(u_short)) { ctl_putdata((char *)ass_stat, n * sizeof(u_short), 1); n = 0; } } } if (n != 0) ctl_putdata((char *)ass_stat, n * sizeof(u_short), 1); ctl_flushpkt(0); } else { peer = findpeerbyassoc(res_associd); if (peer == 0) { ctl_error(CERR_BADASSOC); } else { register u_char *cp; rpkt.status = htons(ctlpeerstatus(peer)); if (res_authokay) peer->num_events = 0; /* * For now, output everything we know about the * peer. May be more selective later. */ for (cp = def_peer_var; *cp != 0; cp++) ctl_putpeer((int)*cp, peer); ctl_flushpkt(0); } }}/* * read_variables - return the variables the caller asks for *//*ARGSUSED*/static voidread_variables( struct recvbuf *rbufp, int restrict_mask ){ register struct ctl_var *v; register int i; char *valuep; u_char *wants; unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE + 1) : (CP_MAXCODE + 1); if (res_associd == 0) { /* * Wants system variables. Figure out which he wants * and give them to him. */ rpkt.status = htons(ctlsysstatus()); if (res_authokay) ctl_sys_num_events = 0; gotvar += count_var(ext_sys_var); wants = (u_char *)emalloc(gotvar); memset((char *)wants, 0, gotvar); gotvar = 0; while ((v = ctl_getitem(sys_var, &valuep)) != 0) { if (v->flags & EOV) { if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { if (v->flags & EOV) { ctl_error(CERR_UNKNOWNVAR); free((char *)wants); return; } wants[CS_MAXCODE + 1 + v->code] = 1; gotvar = 1; continue; } else { break; /* shouldn't happen ! */ } } wants[v->code] = 1; gotvar = 1; } if (gotvar) { for (i = 1; i <= CS_MAXCODE; i++) if (wants[i]) ctl_putsys(i); for (i = 0; ext_sys_var && !(ext_sys_var[i].flags & EOV); i++) if (wants[i + CS_MAXCODE + 1]) ctl_putdata(ext_sys_var[i].text, strlen(ext_sys_var[i].text), 0); } else { register u_char *cs; register struct ctl_var *kv; for (cs = def_sys_var; *cs != 0; cs++) ctl_putsys((int)*cs); for (kv = ext_sys_var; kv && !(kv->flags & EOV); kv++) if (kv->flags & DEF) ctl_putdata(kv->text, strlen(kv->text), 0); } free((char *)wants); } else { register struct peer *peer; /* * Wants info for a particular peer. See if we know * the guy. */ peer = findpeerbyassoc(res_associd); if (peer == 0) { ctl_error(CERR_BADASSOC); return; } rpkt.status = htons(ctlpeerstatus(peer)); if (res_authokay) peer->num_events = 0; wants = (u_char *)emalloc(gotvar); memset((char*)wants, 0, gotvar); gotvar = 0; while ((v = ctl_getitem(peer_var, &valuep)) != 0) { if (v->flags & EOV) { ctl_error(CERR_UNKNOWNVAR); free((char *)wants); return; } wants[v->code] = 1; gotvar = 1; } if (gotvar) { for (i = 1; i <= CP_MAXCODE; i++) if (wants[i]) ctl_putpeer(i, peer); } else { register u_char *cp; for (cp = def_peer_var; *cp != 0; cp++) ctl_putpeer((int)*cp, peer); } free((char *)wants); } ctl_flushpkt(0);}/* * write_variables - write into variables. We only allow leap bit * writing this way. *//*ARGSUSED*/static voidwrite_variables( struct recvbuf *rbufp, int restrict_mask ){ register struct ctl_var *v; register int ext_var; char *valuep; long val = 0; /* * If he's trying to write into a peer tell him no way */ if (res_associd != 0) { ctl_error(CERR_PERMISSION); return; } /* * Set status */ rpkt.status = htons(ctlsysstatus()); /* * Look through the variables. Dump out at the first sign of * trouble. */ while ((v = ctl_getitem(sys_var, &valuep)) != 0) { ext_var = 0; if (v->flags & EOV) { if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { if (v->flags & EOV) { ctl_error(CERR_UNKNOWNVAR); return; } ext_var = 1; } else { break; } } if (!(v->flags & CAN_WRITE)) { ctl_error(CERR_PERMISSION); return; } if (!ext_var && (*valuep == '\0' || !atoint(valuep, &val))) { ctl_error(CERR_BADFMT); return; } if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) { ctl_error(CERR_BADVALUE); return; } if (ext_var) { char *s = (char *)emalloc(strlen(v->text) + strlen(valuep) + 2); const char *t; char *tt = s; t = v->text; while (*t && *t != '=') *tt++ = *t++; *tt++ = '='; strcat(tt, valuep); set_sys_var(s, strlen(s)+1, v->flags); free(s); } else { /* * This one seems sane. Save it. */ switch(v->code) { case CS_LEAP: default: ctl_error(CERR_UNSPEC); /* really */ return; } } } /* * If we got anything, do it. xxx nothing to do *** */ /* if (leapind != ~0 || leapwarn != ~0) { if (!leap_setleap((int)leapind, (int)leapwarn)) { ctl_error(CERR_PERMISSION); return; } } */ ctl_flushpkt(0);}/* * read_clock_status - return clock radio status *//*ARGSUSED*/static voidread_clock_status( struct recvbuf *rbufp, int restrict_mask ){#ifndef REFCLOCK /* * If no refclock support, no data to return */ ctl_error(CERR_BADASSOC);#else register struct ctl_var *v; register int i; register struct peer *peer; char *valuep; u_char *wants; unsigned int gotvar; struct refclockstat clock_stat; if (res_associd == 0) { /* * Find a clock for this jerk. If the system peer * is a clock use it, else search the hash tables * for one. */ if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK)) { peer = sys_peer; } else { peer = 0; for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) { for (peer = assoc_hash[i]; peer != 0; peer = peer->ass_next) { if (peer->flags & FLAG_REFCLOCK) break; } } if (peer == 0) { ctl_error(CERR_BADASSOC); return; } } } else { peer = findpeerbyassoc(res_associd); if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) { ctl_error(CERR_BADASSOC); return; } } /* * If we got here we have a peer which is a clock. Get his * status. */ clock_stat.kv_list = (struct ctl_var *)0; refclock_control(&peer->srcadr, (struct refclockstat *)0, &clock_stat); /* * Look for variables in the packet. */ rpkt.status = htons(ctlclkstatus(&clock_stat)); gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list); wants = (u_char *)emalloc(gotvar); memset((char*)wants, 0, gotvar); gotvar = 0; while ((v = ctl_getitem(clock_var, &valuep)) != 0) { if (v->flags & EOV) { if ((v = ctl_getitem(clock_stat.kv_list, &valuep)) != 0) { if (v->flags & EOV) { ctl_error(CERR_UNKNOWNVAR); free((char*)wants); free_varlist(clock_stat.kv_list); return; } wants[CC_MAXCODE + 1 + v->code] = 1; gotvar = 1; continue; } else { break; /* shouldn't happen ! */ } } wants[v->code] = 1; gotvar = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -