From: Harlan Stenn Date: Thu, 6 Jan 2011 07:58:30 +0000 (+0000) Subject: libevent changes X-Git-Tag: NTP_4_2_7P131~47^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25b34852ec688921d7fc0a881f259867ed4cb680;p=thirdparty%2Fntp.git libevent changes bk: 4d257626nNLx94XrE05gNQaR3rIsEg --- diff --git a/m4/ntp_libevent.m4 b/m4/ntp_libevent.m4 new file mode 100644 index 000000000..e8c270f59 --- /dev/null +++ b/m4/ntp_libevent.m4 @@ -0,0 +1,80 @@ +dnl NTP_LIBEVENT_CHECK([MINVERSION, [DIR [, NOBUILD]]]) -*- Autoconf -*- +dnl +dnl Look for libevent, which must be at least MINVERSION. +dnl DIR is the location of our "bundled" copy of libevent. +dnl If NOBUILD is provided as the 3rd argument, do all of the above, +dnl but DO NOT invoke DIR/configure if we are going to use our bundled +dnl version. This may be the case for nested packages. +dnl +dnl provide --enable-local-libevent . +dnl +dnl Examples: +dnl +dnl NTP_LIBEVENT_CHECK([2.0.9], [sntp/libevent], NOBUILD) +dnl NTP_LIBEVENT_CHECK +dnl + +dnl +dnl NOTE WELL: right now, if we build the local libevent, the 'install' +dnl target *will fire* +dnl + +AC_DEFUN([NTP_LIBEVENT_CHECK], [ +_ntp_pkg_min_version=m4_default([$1], [0.9.0]) +_ntp_libevent_min_version=m4_default([$1], [2.0.9]) +_ntp_libevent_path=m4_default([$2], [libevent]) +_ntp_libevent_nobuild=m4_default([$3],[]) +_ntp_libevent_found=no + +NEED_LIBEVENT_DIR= + +AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +# Make sure pkg-config is recent enough +case "$PKG_CONFIG" in + /*) + AC_MSG_CHECKING([pkg-config is at least version $_ntp_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_ntp_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + ;; +esac + +AC_ARG_ENABLE([local-libevent], + AC_HELP_STRING([-enable-local-libevent], + [Force using the supplied libevent tearoff code]),[ + use_local_libevent=$enableval]) + +case "$use_local_libevent" in + yes) + ;; + *) # If we have (a good enough) pkg-config, see if it can find libevent + case "$PKG_CONFIG" in + /*) + if $PKG_CONFIG --atleast-version=$_ntp_libevent_min_version libevent + then + AC_MSG_NOTICE([Using the installed libevent]) + LIBEVENT_CPPFLAGS=`$PKG_CONFIG --cflags libevent` + LIBEVENT_LDADD=`$PKG_CONFIG --libs libevent` + _ntp_libevent_found=yes + fi + ;; + esac + ;; +esac + +case "$_ntp_libevent_found" in + no) + AC_MSG_NOTICE([Using supplied libevent tearoff]) + LIBEVENT_CPPFLAGS='-I$(top_builddir)'/_il/include + LIBEVENT_LDADD='$(top_builddir)'/_il/lib/libevent.la + NEED_LIBEVENT_DIR=true + ;; +esac + +AM_CONDITIONAL([NEED_LIBEVENT], [test -n "${NEED_LIBEVENT_DIR}"]) +AC_SUBST(LIBEVENT_CPPFLAGS) +AC_SUBST(LIBEVENT_LDADD) +]) diff --git a/sntp/Makefile.am b/sntp/Makefile.am index 82a6d93fd..66258f28a 100644 --- a/sntp/Makefile.am +++ b/sntp/Makefile.am @@ -6,12 +6,16 @@ NULL = AUTOMAKE_OPTIONS = foreign 1.10 ACLOCAL_AMFLAGS = -I ../m4 -I libopts/m4 -AM_CPPFLAGS = $(LIBOPTS_CFLAGS) -I$(top_srcdir)/../include \ - -I$(top_srcdir)/../lib/isc/include \ - -I$(top_srcdir)/../lib/isc/nothreads/include \ - -I$(top_srcdir)/../lib/isc/unix/include +AM_CPPFLAGS = \ + $(LIBEVENT_CPPFLAGS) \ + $(LIBOPTS_CFLAGS) \ + -I$(top_srcdir)/../include \ + -I$(top_srcdir)/../lib/isc/include \ + -I$(top_srcdir)/../lib/isc/nothreads/include \ + -I$(top_srcdir)/../lib/isc/unix/include \ + $(NULL) -LDADD = $(LIBOPTS_LDADD) $(LIBM) ../libntp/libntp.a @LCRYPTO@ +LDADD = $(LIBOPTS_LDADD) $(LIBEVENT_LDADD) $(LIBM) ../libntp/libntp.a @LCRYPTO@ run_ag = cd $(srcdir) && env PATH="$(abs_builddir):$(PATH)" \ autogen -L ../include --writable @@ -28,6 +32,9 @@ SUBDIRS = if NEED_LIBOPTS SUBDIRS += libopts endif +if NEED_LIBEVENT +SUBDIRS += build-libevent +endif if GTEST_AVAILABLE SUBDIRS += tests @@ -171,7 +178,7 @@ $(srcdir)/COPYRIGHT: check-COPYRIGHT $(srcdir)/sntp-opts.h: $(srcdir)/sntp-opts.c @: do-nothing action to avoid default SCCS get, .h built with .c - + $(srcdir)/sntp-opts.c: $(srcdir)/sntp-opts.def $(srcdir)/version.def $(srcdir)/../include/copyright.def $(run_ag) sntp-opts.def @@ -180,7 +187,7 @@ $(srcdir)/sntp.1: $(srcdir)/sntp-opts.def $(srcdir)/version.def $(srcdir)/../inc $(srcdir)/sntp-opts.menu: $(srcdir)/sntp-opts.texi @: do-nothing action to avoid default SCCS get, .menu built with .texi - + $(srcdir)/sntp-opts.texi: $(srcdir)/sntp-opts.def $(srcdir)/version.def $(srcdir)/../include/copyright.def $(run_ag) -Taginfo.tpl -DLEVEL=section sntp-opts.def $(top_srcdir)/../scripts/check--help $@ diff --git a/sntp/build-libevent/Makefile.am b/sntp/build-libevent/Makefile.am new file mode 100644 index 000000000..d65fdaccc --- /dev/null +++ b/sntp/build-libevent/Makefile.am @@ -0,0 +1,61 @@ +# +# libevent sources are in libevent/ +# we need to install the built stuff in builddir/sntp/_il/ (or something) +# make sure 'distcheck' still works... + +NULL = + +EXTRA_DIST = \ + $(NULL) + +DISTCLEANFILES= \ + ../_il \ + _b \ + libevent-check \ + libevent-configure \ + libevent-make \ + local-install-libevent \ + $(NULL) + +BUILT_SOURCES= \ + local-install-libevent \ + $(NULL) + +local-install-libevent: libevent-check + ( cd _b \ + && $(MAKE) install \ + ) && touch $@ + +libevent-check: libevent-make + ( cd _b \ + && $(MAKE) check \ + ) && touch $@ + +libevent-make: libevent-configure + ( cd _b \ + && $(MAKE) \ + ) && touch $@ + +libevent-configure: Makefile.am _b + ( cd _b \ + && ../$(srcdir)/../libevent/configure \ + --prefix=$(abs_top_builddir)/_il \ + --disable-shared \ + $(NULL) \ + ) && touch $@ + +_b: + test -d _b || mkdir _b + +clean-local: + -( cd _b && make clean ) + +FRC: + @: do-nothing action to prevent default SCCS get + @: FRC "force" depends on nothing and is not a file, so is + @: always out-of-date causing targets which depend on it to + @: similarly always be outdated causing their rules to fire + @: each time they or a dependent is built. + +# include $(top_srcdir)/bincheck.mf +# include $(top_srcdir)/depsver.mf diff --git a/sntp/configure.ac b/sntp/configure.ac index 3d91fe55d..7e6e51a86 100644 --- a/sntp/configure.ac +++ b/sntp/configure.ac @@ -147,6 +147,7 @@ case "${enable_libopts_install+set}" in *) enable_libopts_install=no ;; esac LIBOPTS_CHECK +NTP_LIBEVENT_CHECK NTP_DIR_SEP @@ -1000,5 +1001,12 @@ esac AM_CONDITIONAL([GTEST_AVAILABLE], [$gta]) +case "$NEED_LIBEVENT_DIR" in + true) + AC_CONFIG_SUBDIRS([libevent]) + ;; +esac + +AC_CONFIG_FILES(build-libevent/Makefile) AC_CONFIG_FILES(tests/Makefile) AC_OUTPUT diff --git a/sntp/main.c b/sntp/main.c index b96a0cab8..99cb6acc6 100644 --- a/sntp/main.c +++ b/sntp/main.c @@ -6,10 +6,40 @@ #include "utilities.h" #include "log.h" +#include +#include +#include + +#if 0 +// Might need: +#include +#include +#include +#endif + +int n_pending_dns = 0; +int n_pending_ntp = 0; int ai_fam_pref = AF_UNSPEC; +char *progname; +struct event_base *base = NULL; + +struct dns_cb_ctx { + char *name; + int flags; +#define CTX_BCST 0x0001 +#define CTX_UCST 0x0002 +#define CTX_unused 0xfffd +}; + +struct ntp_cb_ctx { + char *name; + int flags; +}; struct key *keys = NULL; +void dns_cb (int errcode, struct evutil_addrinfo *addr, void *ptr); +void ntp_cb (int errcode, struct evutil_addrinfo *addr, void *ptr); void set_li_vn_mode (struct pkt *spkt, char leap, char version, char mode); int sntp_main (int argc, char **argv); int on_wire (struct addrinfo *host, struct addrinfo *bcastaddr); @@ -37,19 +67,13 @@ sntp_main ( char **argv ) { - register int c; - struct kod_entry *reason = NULL; + int i; int optct; /* boolean, u_int quiets gcc4 signed overflow warning */ - u_int sync_data_suc; - struct addrinfo **bcastaddr = NULL; - struct addrinfo **resh = NULL; - struct addrinfo *ai; - int resc; - int kodc; - int ow_ret; - int bcast = 0; - char *hostname; + // struct addrinfo *ai; + struct evdns_base *dnsbase; + + progname = argv[0]; optct = optionProcess(&sntpOptions, argc, argv); argc -= optct; @@ -78,11 +102,11 @@ sntp_main ( /* Parse config file if declared TODO */ - /* - * If there's a specified KOD file init KOD system. If not use - * default file. For embedded systems with no writable - * filesystem, -K /dev/null can be used to disable KoD storage. - */ + /* + ** If there's a specified KOD file init KOD system. If not use + ** default file. For embedded systems with no writable filesystem, + ** -K /dev/null can be used to disable KoD storage. + */ if (HAVE_OPT(KOD)) kod_init_kod_db(OPT_ARG(KOD)); else @@ -106,26 +130,96 @@ sntp_main ( free(reason); #endif - /* Considering employing a variable that prevents functions of doing anything until - * everything is initialized properly - */ - resc = resolve_hosts((const char **)argv, argc, &resh, ai_fam_pref); - if (resc < 1) { - printf("Unable to resolve hostname(s)\n"); + /* + ** Considering employing a variable that prevents functions of doing + ** anything until everything is initialized properly + ** + ** HMS: What exactly does the above mean? + */ + + base = event_base_new(); + if (!base) { + printf("%s: event_base_new() failed!\n", progname); return -1; } - bcast = ENABLED_OPT(BROADCAST); - if (bcast) { - const char * myargv[2]; - myargv[0] = OPT_ARG(BROADCAST); - myargv[1] = NULL; - bcast = resolve_hosts(myargv, 1, &bcastaddr, ai_fam_pref); + dnsbase = evdns_base_new(base, 1); + if (!dnsbase) { + printf("%s: evdns_base_new() failed!\n", progname); + return -1; } - /* Select a certain ntp server according to simple criteria? For now - * let's just pay attention to previous KoDs. - */ + if (ENABLED_OPT(BROADCAST)) { + struct evutil_addrinfo hints; + struct dns_cb_ctx *dns_ctx; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = ai_fam_pref; + hints.ai_flags = EVUTIL_AI_CANONNAME; + /* + ** Unless we specify a socktype, we'll get at least two + ** entries for each address: one for TCP and one for + ** UDP. That's not what we want. + */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + dns_ctx = emalloc(sizeof *dns_ctx); + dns_ctx->name = OPT_ARG(BROADCAST); + dns_ctx->flags = CTX_BCST; + + printf("broadcast-before: <%s> n_pending_dns = %d\n", OPT_ARG(BROADCAST), n_pending_dns); + ++n_pending_dns; + evdns_getaddrinfo(dnsbase, OPT_ARG(BROADCAST), NULL, &hints, + dns_cb, (void *)dns_ctx); + printf("broadcast-after: <%s> n_pending_dns = %d\n", OPT_ARG(BROADCAST), n_pending_dns); + } + + for (i = 0; i < argc; ++i) { + struct evutil_addrinfo hints; /* is 1 copy really OK? */ + struct dns_cb_ctx *dns_ctx; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = ai_fam_pref; + hints.ai_flags = EVUTIL_AI_CANONNAME; + /* + ** Unless we specify a socktype, we'll get at least two + ** entries for each address: one for TCP and one for + ** UDP. That's not what we want. + */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + dns_ctx = emalloc(sizeof *dns_ctx); + dns_ctx->name = argv[i]; + dns_ctx->flags = CTX_UCST; + + printf("unicast-before: <%s> n_pending_dns = %d\n", argv[i], n_pending_dns); + ++n_pending_dns; + evdns_getaddrinfo(dnsbase, argv[i], NULL, &hints, + dns_cb, (void *)dns_ctx); + printf("unicast-after: <%s> n_pending_dns = %d\n", argv[i], n_pending_dns); + } + + printf("unicast: n_pending_dns = %d\n", n_pending_dns); + + event_base_dispatch(base); + + evdns_base_free(dnsbase, 0); + event_base_free(base); + + return 0; /* Might not want 0... */ +} + + +#if 0 +void +handle_later() { + /* + ** Select a certain ntp server according to simple criteria? + ** + ** For now let's just pay attention to previous KoDs. + */ sync_data_suc = FALSE; for (c = 0; c < resc && !sync_data_suc; c++) { ai = resh[c]; @@ -133,7 +227,10 @@ sntp_main ( hostname = addrinfo_to_str(ai); if ((kodc = search_entry(hostname, &reason)) == 0) { if (is_reachable(ai)) { - ow_ret = on_wire(ai, bcast ? bcastaddr[0] : NULL); + ow_ret = on_wire(ai, + (bcast) + ? bcastaddr[0] + : NULL); if (0 == ow_ret) sync_data_suc = TRUE; } @@ -153,6 +250,90 @@ sntp_main ( return 1; return 0; } +#endif + + +/* +** DNS Callback: +** - For each IP: +** - - open a socket +** - - increment n_pending_ntp +** - - send a request if this is a Unicast callback +** - - queue wait for response +** - decrement n_pending_dns +*/ +void +dns_cb( + int errcode, + struct evutil_addrinfo *addr, + void *ptr + ) +{ + struct dns_cb_ctx *ctx = ptr; + + if (errcode) { + printf("%s -> %s\n", ctx->name, evutil_gai_strerror(errcode)); + } else { + struct evutil_addrinfo *ai; + + printf("%s [%s]\n", ctx->name, + (addr->ai_canonname) + ? addr->ai_canonname + : ""); + for (ai = addr; ai; ai = ai->ai_next) { + char buf[128]; + const char *s = NULL; + + /* + ** If we get something good, bump n_pending_ntp and + ** send a packet. + */ + if (ai->ai_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; + s = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, 128); + } else if (ai->ai_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; + s = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128); + } + if (s) + printf(" -> %s\n", s); + } + evutil_freeaddrinfo(addr); + free(ptr); + } + printf("n_pending_dns = %d, n_pending_ntp = %d\n", + n_pending_dns, n_pending_ntp); + /* n_pending_dns really should be >0 here... */ + if (--n_pending_dns == 0 && n_pending_ntp == 0) + event_base_loopexit(base, NULL); +} + + +/* +** NTP Callback: +** Unicast: +** - close socket +** - decrement n_pending_ntp +** - If packet is good, set the time and "exit" +** Broadcast: +** - If packet is good, set the time and "exit" +*/ +void +ntp_cb( + int errcode, + struct evutil_addrinfo *addr, + void *ptr + ) +{ + struct dns_cb_ctx *ctx = ptr; + + if (errcode) { + printf("%s -> %s\n", ctx->name, evutil_gai_strerror(errcode)); + } else { + } +} + + static union { struct pkt pkt; @@ -161,6 +342,7 @@ static union { #define r_pkt rbuf.pkt + int generate_pkt ( struct pkt *x_pkt, @@ -171,6 +353,7 @@ generate_pkt ( { l_fp xmt; int pkt_len = LEN_PKT_NOMAC; + memset(x_pkt, 0, sizeof(struct pkt)); TVTOTS(tv_xmt, &xmt); HTONL_FP(&xmt, &(x_pkt->xmt)); @@ -181,13 +364,15 @@ generate_pkt ( if (pkt_key != NULL) { int mac_size = 20; /* max room for MAC */ x_pkt->exten[0] = htonl(key_id); - mac_size = make_mac((char *)x_pkt, pkt_len, mac_size, pkt_key, (char *)&x_pkt->exten[1]); + mac_size = make_mac((char *)x_pkt, pkt_len, mac_size, + pkt_key, (char *)&x_pkt->exten[1]); if (mac_size) pkt_len += mac_size + 4; } return pkt_len; } + int handle_pkt ( int rpktl, @@ -203,23 +388,23 @@ handle_pkt ( char *p_SNTP_PRETEND_TIME; time_t pretend_time; - if(rpktl > 0) + if (rpktl > 0) sw_case = 1; else sw_case = rpktl; switch(sw_case) { - case SERVER_UNUSEABLE: + case SERVER_UNUSEABLE: return -1; break; - case PACKET_UNUSEABLE: + case PACKET_UNUSEABLE: break; - case SERVER_AUTH_FAIL: + case SERVER_AUTH_FAIL: break; - case KOD_DEMOBILIZE: + case KOD_DEMOBILIZE: /* Received a DENY or RESTR KOD packet */ hostname = addrinfo_to_str(host); ref = (char *)&rpkt->refid; @@ -234,15 +419,16 @@ handle_pkt ( ref[0], ref[1], ref[2], ref[3], hostname); break; - case KOD_RATE: + case KOD_RATE: /* Hmm... probably we should sleep a bit here */ break; - case 1: + case 1: if (ENABLED_OPT(NORMALVERBOSE)) { getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); - printf("sntp handle_pkt: Received %i bytes from %s\n", rpktl, addr_buf); + printf("sntp handle_pkt: Received %i bytes from %s\n", + rpktl, addr_buf); } GETTIMEOFDAY(&tv_dst, (struct timezone *)NULL); @@ -289,6 +475,7 @@ handle_pkt ( return 1; } + void offset_calculation ( struct pkt *rpkt, @@ -355,7 +542,12 @@ offset_calculation ( t21, t34, delta, *offset); } -/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */ + +/* +** The heart of (S)NTP: +** +** Exchange NTP packets and compute values to correct the local clock. +*/ int on_wire ( struct addrinfo *host, @@ -371,7 +563,6 @@ on_wire ( struct pkt x_pkt; int error, rpktl, handle_pkt_res; - if (ENABLED_OPT(AUTHENTICATION)) { key_id = (int) OPT_ARG(AUTHENTICATION); get_key(key_id, &pkt_key); @@ -383,19 +574,23 @@ on_wire ( tv_xmt.tv_sec += JAN_1970; #ifdef DEBUG - printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec, - (unsigned int) tv_xmt.tv_usec); + printf("sntp on_wire: Current time sec: %i msec: %i\n", + (unsigned int) tv_xmt.tv_sec, + (unsigned int) tv_xmt.tv_usec); #endif if (bcast) { create_socket(&sock, (sockaddr_u *)bcast->ai_addr); - rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr); + rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, + (sockaddr_u *)bcast->ai_addr); closesocket(sock); } else { - int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key); + int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, + pkt_key); create_socket(&sock, (sockaddr_u *)host->ai_addr); - sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len); + sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, + pkt_len); rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt); closesocket(sock); } @@ -405,12 +600,14 @@ on_wire ( return handle_pkt_res; } - getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); + getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, + sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf); return -1; } + /* Compute the 8 bits for li_vn_mode */ void set_li_vn_mode ( @@ -435,9 +632,11 @@ set_li_vn_mode ( spkt->li_vn_mode |= mode; } -/* set_time corrects the local clock by offset with either settimeofday() or by default - * with adjtime()/adjusttimeofday(). - */ + +/* +** set_time corrects the local clock by offset with either settimeofday() or +** by default with adjtime()/adjusttimeofday(). +*/ int set_time( double offset diff --git a/sntp/networking.c b/sntp/networking.c index 33a5bad01..ba29593bd 100644 --- a/sntp/networking.c +++ b/sntp/networking.c @@ -4,19 +4,27 @@ char adr_buf[INET6_ADDRSTRLEN]; -/* resolve_hosts consumes an array of hostnames/addresses and its length, stores a pointer - * to the array with the resolved hosts in res and returns the size of the array res. - * pref_family enforces IPv4 or IPv6 depending on commandline options and system - * capability. If pref_family is NULL or PF_UNSPEC any compatible family will be accepted. - * Check here: Probably getaddrinfo() can do without ISC's IPv6 availability check? - */ +/* +** resolve_hosts consumes an array of hostnames/addresses and its length, +** stores a pointer to the array with the resolved hosts in res and returns +** the size of the array res. +** +** pref_family enforces IPv4 or IPv6 depending on commandline options and +** system capability. +** +** If pref_family is NULL or PF_UNSPEC any compatible family will be +** accepted. +** +** Check here: Probably getaddrinfo() can do without ISC's IPv6 availability +** check? +*/ int resolve_hosts ( - const char **hosts, - int hostc, - struct addrinfo ***res, - int pref_family - ) + const char **hosts, + int hostc, + struct addrinfo ***res, + int pref_family + ) { register unsigned int a; unsigned int resc; @@ -74,12 +82,13 @@ resolve_hosts ( return resc; } + /* Creates a socket and returns. */ void create_socket ( - SOCKET *rsock, - sockaddr_u *dest - ) + SOCKET *rsock, + sockaddr_u *dest + ) { *rsock = socket(AF(dest), SOCK_DGRAM, 0); @@ -87,6 +96,7 @@ create_socket ( printf("Failed to create UDP socket with family %d\n", AF(dest)); } + /* Send a packet */ void sendpkt ( @@ -104,7 +114,8 @@ sendpkt ( #endif if (ENABLED_OPT(NORMALVERBOSE)) { - getnameinfo(&dest->sa, SOCKLEN(dest), adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST); + getnameinfo(&dest->sa, SOCKLEN(dest), adr_buf, + sizeof(adr_buf), NULL, 0, NI_NUMERICHOST); printf("sntp sendpkt: Sending packet to %s... ", adr_buf); } @@ -121,6 +132,7 @@ sendpkt ( } } + /* Receive raw data */ int recvdata( @@ -152,8 +164,15 @@ recvdata( return recvc; } -/* Receive data from broadcast. Couldn't finish that. Need to do some digging - * here, especially for protocol independence and IPv6 multicast */ + +/* +** Receive data from broadcast. +** +** Couldn't finish that. +** +** Need to do some digging here, especially for protocol independence and +** IPv6 multicast. +*/ int recv_bcst_data ( SOCKET rsock, @@ -250,18 +269,18 @@ recv_bcst_data ( timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv); switch (rdy_socks) { - case -1: + case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: select()"); return BROADCAST_FAILED; break; - case 0: + case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return BROADCAST_FAILED; break; - default: + default: ss_len = sizeof(*ras); recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len); break; @@ -273,15 +292,18 @@ recv_bcst_data ( } #ifdef MCAST if (IS_IPV4(sas)) - setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue)); + setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, + sizeof(btrue)); #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (IS_IPV6(sas)) - setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue)); + setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, + sizeof(btrue)); #endif return recv_bytes; } + int process_pkt ( struct pkt *rpkt, @@ -297,6 +319,7 @@ process_pkt ( int is_authentic = 0; unsigned int exten_words, exten_words_used = 0; int mac_size; + /* * Parse the extension field if present. We figure out whether * an extension field is present by measuring the MAC size. If @@ -319,6 +342,7 @@ unusable: exten_words = ((unsigned)pkt_len - LEN_PKT_NOMAC) >> 2; while (exten_words > 6) { unsigned int exten_len; + exten_len = ntohl(rpkt->exten[exten_words_used]) & 0xffff; exten_len = (exten_len + 7) >> 2; /* convert to words, add 1 */ if (exten_len > exten_words || exten_len < 5) @@ -328,23 +352,31 @@ unusable: } switch (exten_words) { - case 1: + case 0: + break; + case 1: key_id = ntohl(rpkt->exten[exten_words_used]); printf("Crypto NAK = 0x%08x\n", key_id); break; - case 5: - case 6: - /* Look for the key used by the server in the specified keyfile - * and if existent, fetch it or else leave the pointer untouched */ + case 5: + case 6: + /* + ** Look for the key used by the server in the specified + ** keyfile and if existent, fetch it or else leave the + ** pointer untouched + */ key_id = ntohl(rpkt->exten[exten_words_used]); get_key(key_id, &pkt_key); if (!pkt_key) { printf("unrecognized key ID = 0x%08x\n", key_id); break; } - /* Seems like we've got a key with matching keyid */ - /* Generate a md5sum of the packet with the key from our keyfile - * and compare those md5sums */ + /* + ** Seems like we've got a key with matching keyid. + ** + ** Generate a md5sum of the packet with the key from our + ** keyfile and compare those md5sums. + */ mac_size = exten_words << 2; if (!auth_md5((char *)rpkt, pkt_len - mac_size, mac_size - 4, pkt_key)) { break; @@ -358,9 +390,7 @@ unusable: } is_authentic = 1; break; - case 0: - break; - default: + default: goto unusable; break; } @@ -375,10 +405,13 @@ unusable: } return SERVER_AUTH_FAIL; } - /* We don't know if the user wanted authentication so let's - * use it anyways */ + /* + ** We don't know if the user wanted authentication so let's + ** use it anyways + */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); + printf("sntp %s: packet received from %s is not authentic. Authentication not enforced.\n", func_name, hostname); free(hostname); @@ -403,6 +436,7 @@ unusable: /* Stratum is unspecified (0) check what's going on */ if (STRATUM_PKT_UNSPEC == rpkt->stratum) { char *ref_char; + if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Stratum unspecified, going to check for KOD (stratum: %i)\n", func_name, rpkt->stratum); @@ -418,7 +452,10 @@ unusable: return KOD_DEMOBILIZE; if (strncmp(ref_char, "RATE", 4) == 0) return KOD_RATE; - /* There are other interesting kiss codes which might be interesting for authentication */ + /* + ** There are other interesting kiss codes which + ** might be interesting for authentication. + */ } } /* If the server is not synced it's not really useable for us */ @@ -447,6 +484,7 @@ unusable: return pkt_len; } + int recv_bcst_pkt ( SOCKET rsock, @@ -457,6 +495,7 @@ recv_bcst_pkt ( { sockaddr_u sender; int pkt_len = recv_bcst_data(rsock, (char *)rpkt, rsize, sas, &sender); + if (pkt_len < 0) { return BROADCAST_FAILED; } @@ -464,9 +503,13 @@ recv_bcst_pkt ( return pkt_len; } -/* Fetch data, check if it's data for us and whether it's useable or not. If not, return - * a failure code so we can delete this server from our list and continue with another one. - */ + +/* +** Fetch data, check if it's data for us and whether it's useable or not. +** +** If not, return a failure code so we can delete this server from our list +** and continue with another one. +*/ int recvpkt ( SOCKET rsock, @@ -490,18 +533,18 @@ recvpkt ( timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &recv_fd, 0, 0, &timeout_tv); switch (rdy_socks) { - case -1: + case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recvpkt: select()"); return PACKET_UNUSEABLE; break; - case 0: + case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return PACKET_UNUSEABLE; break; - default: + default: break; } pkt_len = recvdata(rsock, &sender, (char *)rpkt, rsize); @@ -511,6 +554,7 @@ recvpkt ( return pkt_len; } + /* * is_reachable - check to see if we have a route to given destination */