mirror of
https://github.com/sheumann/hush.git
synced 2024-12-22 14:30:31 +00:00
ntp: simplifications; libbb: simpler resolution of numeric hostnames
function old new delta str2sockaddr 405 567 +162 ntp_init 310 317 +7 scale_interval 58 59 +1 error_interval 22 23 +1 ntpd_main 3257 3214 -43 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 171/-43) Total: 128 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
887d963037
commit
ca6c7e42f9
@ -161,6 +161,7 @@ static len_and_sockaddr* str2sockaddr(
|
||||
IF_FEATURE_IPV6(sa_family_t af,)
|
||||
int ai_flags)
|
||||
{
|
||||
IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
|
||||
int rc;
|
||||
len_and_sockaddr *r;
|
||||
struct addrinfo *result = NULL;
|
||||
@ -221,12 +222,40 @@ IF_FEATURE_IPV6(sa_family_t af,)
|
||||
skip: ;
|
||||
}
|
||||
|
||||
memset(&hint, 0 , sizeof(hint));
|
||||
#if !ENABLE_FEATURE_IPV6
|
||||
hint.ai_family = AF_INET; /* do not try to find IPv6 */
|
||||
#else
|
||||
hint.ai_family = af;
|
||||
/* Next two if blocks allow to skip getaddrinfo()
|
||||
* in case host is a numeric IP(v6) address,
|
||||
* getaddrinfo() initializes DNS resolution machinery,
|
||||
* scans network config and such - tens of syscalls.
|
||||
*/
|
||||
/* If we were not asked specifically for IPv6,
|
||||
* check whether this is a numeric IPv4 */
|
||||
IF_FEATURE_IPV6(if(af != AF_INET6)) {
|
||||
struct in_addr in4;
|
||||
if (inet_aton(host, &in4) != 0) {
|
||||
r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in));
|
||||
r->len = sizeof(struct sockaddr_in);
|
||||
r->u.sa.sa_family = AF_INET;
|
||||
r->u.sin.sin_addr = in4;
|
||||
goto set_port;
|
||||
}
|
||||
}
|
||||
#if ENABLE_FEATURE_IPV6
|
||||
/* If we were not asked specifically for IPv4,
|
||||
* check whether this is a numeric IPv6 */
|
||||
if (af != AF_INET) {
|
||||
struct in6_addr in6;
|
||||
if (inet_pton(AF_INET6, host, &in6) > 0) {
|
||||
r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in6));
|
||||
r->len = sizeof(struct sockaddr_in6);
|
||||
r->u.sa.sa_family = AF_INET6;
|
||||
r->u.sin6.sin6_addr = in6;
|
||||
goto set_port;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&hint, 0 , sizeof(hint));
|
||||
hint.ai_family = af;
|
||||
/* Needed. Or else we will get each address thrice (or more)
|
||||
* for each possible socket type (tcp,udp,raw...): */
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
@ -250,9 +279,11 @@ IF_FEATURE_IPV6(sa_family_t af,)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
r = xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen);
|
||||
r = xmalloc(LSA_LEN_SIZE + used_res->ai_addrlen);
|
||||
r->len = used_res->ai_addrlen;
|
||||
memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen);
|
||||
|
||||
IF_FEATURE_IPV6(set_port:)
|
||||
set_nport(r, htons(port));
|
||||
ret:
|
||||
freeaddrinfo(result);
|
||||
|
@ -5,7 +5,6 @@
|
||||
*
|
||||
* Licensed under GPLv2, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
|
||||
|
||||
@ -59,13 +58,15 @@ typedef struct {
|
||||
uint16_t fractions;
|
||||
} s_fixedpt_t;
|
||||
|
||||
#define NTP_DIGESTSIZE 16
|
||||
#define NTP_MSGSIZE_NOAUTH 48
|
||||
#define NTP_MSGSIZE (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE)
|
||||
enum {
|
||||
NTP_DIGESTSIZE = 16,
|
||||
NTP_MSGSIZE_NOAUTH = 48,
|
||||
NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE),
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t status; /* status of local clock and leap info */
|
||||
uint8_t stratum; /* Stratum level */
|
||||
uint8_t stratum; /* stratum level */
|
||||
uint8_t ppoll; /* poll value */
|
||||
int8_t precision;
|
||||
s_fixedpt_t rootdelay;
|
||||
@ -97,6 +98,7 @@ enum {
|
||||
/* Status Masks */
|
||||
MODE_MASK = (7 << 0),
|
||||
VERSION_MASK = (7 << 3),
|
||||
VERSION_SHIFT = 3,
|
||||
LI_MASK = (3 << 6),
|
||||
|
||||
/* Mode values */
|
||||
@ -107,7 +109,7 @@ enum {
|
||||
MODE_SERVER = 4, /* server */
|
||||
MODE_BROADCAST = 5, /* broadcast */
|
||||
MODE_RES1 = 6, /* reserved for NTP control message */
|
||||
MODE_RES2 = 7 /* reserved for private use */
|
||||
MODE_RES2 = 7, /* reserved for private use */
|
||||
};
|
||||
|
||||
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
|
||||
@ -115,7 +117,7 @@ enum {
|
||||
enum client_state {
|
||||
STATE_NONE,
|
||||
STATE_QUERY_SENT,
|
||||
STATE_REPLY_RECEIVED
|
||||
STATE_REPLY_RECEIVED,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -141,6 +143,9 @@ typedef struct {
|
||||
} ntp_offset_t;
|
||||
|
||||
typedef struct {
|
||||
//TODO:
|
||||
// (1) store dotted addr str, to avoid constant translations
|
||||
// (2) periodically re-resolve DNS names
|
||||
len_and_sockaddr *lsa;
|
||||
ntp_query_t query;
|
||||
ntp_offset_t reply[OFFSET_ARRAY_SIZE];
|
||||
@ -212,7 +217,6 @@ static double
|
||||
gettime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL); /* never fails */
|
||||
return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
|
||||
}
|
||||
@ -229,10 +233,19 @@ static double
|
||||
lfp_to_d(l_fixedpt_t lfp)
|
||||
{
|
||||
double ret;
|
||||
|
||||
lfp.int_partl = ntohl(lfp.int_partl);
|
||||
lfp.fractionl = ntohl(lfp.fractionl);
|
||||
ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
|
||||
ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static double
|
||||
sfp_to_d(s_fixedpt_t sfp)
|
||||
{
|
||||
double ret;
|
||||
sfp.int_parts = ntohs(sfp.int_parts);
|
||||
sfp.fractions = ntohs(sfp.fractions);
|
||||
ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -241,32 +254,21 @@ static l_fixedpt_t
|
||||
d_to_lfp(double d)
|
||||
{
|
||||
l_fixedpt_t lfp;
|
||||
|
||||
lfp.int_partl = htonl((uint32_t)d);
|
||||
lfp.fractionl = htonl((uint32_t)((d - (u_int32_t)d) * UINT_MAX));
|
||||
lfp.int_partl = (uint32_t)d;
|
||||
lfp.fractionl = (uint32_t)((d - lfp.int_partl) * UINT_MAX);
|
||||
lfp.int_partl = htonl(lfp.int_partl);
|
||||
lfp.fractionl = htonl(lfp.fractionl);
|
||||
return lfp;
|
||||
}
|
||||
#endif
|
||||
|
||||
static double
|
||||
sfp_to_d(s_fixedpt_t sfp)
|
||||
{
|
||||
double ret;
|
||||
|
||||
sfp.int_parts = ntohs(sfp.int_parts);
|
||||
sfp.fractions = ntohs(sfp.fractions);
|
||||
ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_NTPD_SERVER
|
||||
static s_fixedpt_t
|
||||
d_to_sfp(double d)
|
||||
{
|
||||
s_fixedpt_t sfp;
|
||||
|
||||
sfp.int_parts = htons((uint16_t)d);
|
||||
sfp.fractions = htons((uint16_t)((d - (u_int16_t)d) * USHRT_MAX));
|
||||
sfp.int_parts = (uint16_t)d;
|
||||
sfp.fractions = (uint16_t)((d - sfp.int_parts) * USHRT_MAX);
|
||||
sfp.int_parts = htons(sfp.int_parts);
|
||||
sfp.fractions = htons(sfp.fractions);
|
||||
return sfp;
|
||||
}
|
||||
#endif
|
||||
@ -282,9 +284,8 @@ static time_t
|
||||
error_interval(void)
|
||||
{
|
||||
time_t interval, r;
|
||||
|
||||
interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
|
||||
r = random() % (interval / 10);
|
||||
r = (unsigned)random() % (unsigned long)(interval / 10);
|
||||
return (interval + r);
|
||||
}
|
||||
|
||||
@ -352,12 +353,8 @@ client_query(ntp_peer_t *p)
|
||||
static int
|
||||
offset_compare(const void *aa, const void *bb)
|
||||
{
|
||||
const ntp_peer_t * const *a;
|
||||
const ntp_peer_t * const *b;
|
||||
|
||||
a = aa;
|
||||
b = bb;
|
||||
|
||||
const ntp_peer_t *const *a = aa;
|
||||
const ntp_peer_t *const *b = bb;
|
||||
if ((*a)->update.offset < (*b)->update.offset)
|
||||
return -1;
|
||||
return ((*a)->update.offset > (*b)->update.offset);
|
||||
@ -368,7 +365,6 @@ updated_scale(double offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
offset = -offset;
|
||||
|
||||
if (offset > QSCALE_OFF_MAX)
|
||||
return 1;
|
||||
if (offset < QSCALE_OFF_MIN)
|
||||
@ -559,9 +555,8 @@ static time_t
|
||||
scale_interval(time_t requested)
|
||||
{
|
||||
time_t interval, r;
|
||||
|
||||
interval = requested * G.scale;
|
||||
r = random() % MAX(5, interval / 10);
|
||||
r = (unsigned)random() % (unsigned long)(MAX(5, interval / 10));
|
||||
return (interval + r);
|
||||
}
|
||||
|
||||
@ -577,9 +572,10 @@ client_dispatch(ntp_peer_t *p)
|
||||
|
||||
addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
|
||||
|
||||
size = recvfrom(p->query.fd, &msg, sizeof(msg), 0, NULL, NULL);
|
||||
//TODO: use MSG_DONTWAIT flag?
|
||||
size = recv(p->query.fd, &msg, sizeof(msg), 0);
|
||||
if (size == -1) {
|
||||
bb_perror_msg("recvfrom(%s) error", addr);
|
||||
bb_perror_msg("recv(%s) error", addr);
|
||||
if (errno == EHOSTUNREACH || errno == EHOSTDOWN
|
||||
|| errno == ENETUNREACH || errno == ENETDOWN
|
||||
|| errno == ECONNREFUSED || errno == EADDRNOTAVAIL
|
||||
@ -698,43 +694,53 @@ server_dispatch(int fd)
|
||||
double rectime;
|
||||
len_and_sockaddr *to;
|
||||
struct sockaddr *from;
|
||||
ntp_msg_t query, reply;
|
||||
ntp_msg_t msg;
|
||||
uint8_t query_status;
|
||||
uint8_t query_ppoll;
|
||||
l_fixedpt_t query_xmttime;
|
||||
|
||||
to = get_sock_lsa(G.listen_fd);
|
||||
from = xzalloc(to->len);
|
||||
|
||||
size = recv_from_to(fd, &query, sizeof(query), 0, from, &to->u.sa, to->len);
|
||||
if (size == -1)
|
||||
bb_error_msg_and_die("recv_from_to");
|
||||
//TODO: use MGS_DONTWAIT flag?
|
||||
size = recv_from_to(fd, &msg, sizeof(msg), 0, from, &to->u.sa, to->len);
|
||||
if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
|
||||
char *addr = xmalloc_sockaddr2dotted_noport(from);
|
||||
char *addr;
|
||||
if (size < 0)
|
||||
bb_error_msg_and_die("recv_from_to");
|
||||
addr = xmalloc_sockaddr2dotted_noport(from);
|
||||
bb_error_msg("malformed packet received from %s", addr);
|
||||
free(addr);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
rectime = gettime();
|
||||
version = (query.status & VERSION_MASK) >> 3;
|
||||
query_status = msg.status;
|
||||
query_ppoll = msg.ppoll;
|
||||
query_xmttime = msg.xmttime;
|
||||
|
||||
memset(&reply, 0, sizeof(reply));
|
||||
reply.status = G.status.synced ? G.status.leap : LI_ALARM;
|
||||
reply.status |= (query.status & VERSION_MASK);
|
||||
reply.status |= ((query.status & MODE_MASK) == MODE_CLIENT) ?
|
||||
/* Build a reply packet */
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.status = G.status.synced ? G.status.leap : LI_ALARM;
|
||||
msg.status |= (query_status & VERSION_MASK);
|
||||
msg.status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
|
||||
MODE_SERVER : MODE_SYM_PAS;
|
||||
reply.stratum = G.status.stratum;
|
||||
reply.ppoll = query.ppoll;
|
||||
reply.precision = G.status.precision;
|
||||
reply.rectime = d_to_lfp(rectime);
|
||||
reply.reftime = d_to_lfp(G.status.reftime);
|
||||
reply.xmttime = d_to_lfp(gettime());
|
||||
reply.orgtime = query.xmttime;
|
||||
reply.rootdelay = d_to_sfp(G.status.rootdelay);
|
||||
reply.refid = (version > 3) ? G.status.refid4 : G.status.refid;
|
||||
msg.stratum = G.status.stratum;
|
||||
msg.ppoll = query_ppoll;
|
||||
msg.precision = G.status.precision;
|
||||
rectime = gettime();
|
||||
msg.xmttime = msg.rectime = d_to_lfp(rectime);
|
||||
msg.reftime = d_to_lfp(G.status.reftime);
|
||||
//msg.xmttime = d_to_lfp(gettime()); // = msg.rectime
|
||||
msg.orgtime = query_xmttime;
|
||||
msg.rootdelay = d_to_sfp(G.status.rootdelay);
|
||||
version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
|
||||
msg.refid = (version > (3 << VERSION_SHIFT)) ? G.status.refid4 : G.status.refid;
|
||||
|
||||
/* We reply from the address packet was sent to,
|
||||
* this makes to/from look swapped here: */
|
||||
sendmsg_wrap(fd, /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
|
||||
&reply, size);
|
||||
sendmsg_wrap(fd,
|
||||
/*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
|
||||
&msg, size);
|
||||
|
||||
bail:
|
||||
free(to);
|
||||
@ -835,7 +841,8 @@ static NOINLINE void ntp_init(char **argv)
|
||||
unsigned opts;
|
||||
llist_t *peers;
|
||||
|
||||
tzset();
|
||||
srandom(getpid());
|
||||
/* tzset(); - why? it's called automatically when needed, no? */
|
||||
|
||||
if (getuid())
|
||||
bb_error_msg_and_die("need root privileges");
|
||||
@ -911,7 +918,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
|
||||
|
||||
while (!bb_got_signal) {
|
||||
llist_t *item;
|
||||
unsigned i, j, idx_peers;
|
||||
unsigned i, j, first_peer_idx;
|
||||
unsigned sent_cnt, trial_cnt;
|
||||
int nfds, timeout;
|
||||
time_t nextaction;
|
||||
@ -926,7 +933,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
idx_peers = i;
|
||||
first_peer_idx = i;
|
||||
sent_cnt = trial_cnt = 0;
|
||||
for (item = g.ntp_peers; item != NULL; item = item->link) {
|
||||
ntp_peer_t *p = (ntp_peer_t *) item->data;
|
||||
@ -960,7 +967,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
|
||||
if (p->state == STATE_QUERY_SENT) {
|
||||
pfd[i].fd = p->query.fd;
|
||||
pfd[i].events = POLLIN;
|
||||
idx2peer[i - idx_peers] = p;
|
||||
idx2peer[i - first_peer_idx] = p;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@ -978,7 +985,8 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
|
||||
|
||||
j = 0;
|
||||
#if ENABLE_FEATURE_NTPD_SERVER
|
||||
for (; nfds > 0 && j < idx_peers; j++) {
|
||||
//TODO: simplify. There is only one server fd!
|
||||
for (; nfds > 0 && j < first_peer_idx; j++) {
|
||||
if (pfd[j].revents & (POLLIN|POLLERR)) {
|
||||
nfds--;
|
||||
server_dispatch(pfd[j].fd);
|
||||
@ -988,7 +996,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
|
||||
for (; nfds > 0 && j < i; j++) {
|
||||
if (pfd[j].revents & (POLLIN|POLLERR)) {
|
||||
nfds--;
|
||||
client_dispatch(idx2peer[j - idx_peers]);
|
||||
client_dispatch(idx2peer[j - first_peer_idx]);
|
||||
}
|
||||
}
|
||||
} /* while (!bb_got_signal) */
|
||||
|
Loading…
Reference in New Issue
Block a user