From: Johannes Maximilian Kuehn Date: Mon, 18 Aug 2008 12:37:27 +0000 (+0900) Subject: utilities.c, networking.c: X-Git-Tag: NTP_4_2_5P142~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd8101d06ba88fe2191fea9cea609ce115c81741;p=thirdparty%2Fntp.git utilities.c, networking.c: Fixes sntp-opts.def: added broadcast and timeout options log.c: Fixes, one bug with filelogging left main.c: Fixed KOD handling in on_Ãwire bk: 48a96d079oHeE72t-pYnaXhG2WD-4g --- diff --git a/gsoc_sntp/log.c b/gsoc_sntp/log.c index 71fd3e93c..e511b986f 100644 --- a/gsoc_sntp/log.c +++ b/gsoc_sntp/log.c @@ -1,4 +1,4 @@ -/* Check for isc/binds logging facility, probably interesting, probably worth adapting */ +/* Add timestamps to file logging!!! */ #include "log.h" #include "sntp-opts.h" @@ -10,11 +10,9 @@ FILE *log_file; void log_msg(char *message, char type) { if(init) { - printf("log!\n"); - printf(log_file, message); + fprintf(log_file, message); } else { - printf("ELSEZWEIG!!!!! HAAAAAARRRRRRRRRRRRRRRRRG!\n"); switch(type) { case 0: type = LOG_CONS; diff --git a/gsoc_sntp/main.c b/gsoc_sntp/main.c index 760167aaa..d0be5f873 100644 --- a/gsoc_sntp/main.c +++ b/gsoc_sntp/main.c @@ -15,7 +15,7 @@ #define DEBUG -int ai_fam_templ; +int ai_fam_pref; volatile int debug; char adr_buf[INET6_ADDRSTRLEN]; @@ -44,16 +44,25 @@ sntp_main ( ) { register int c; + struct kod_entry **reason = NULL; + /* IPv6 available? */ if (isc_net_probeipv6() != ISC_R_SUCCESS) { - ai_fam_templ = AF_INET; + ai_fam_pref = AF_INET; #ifdef DEBUG printf("No ipv6 support available, forcing ipv4\n"); #endif } + else { + /* Check for options -4 and -6 */ + if(ENABLED_OPT(IPV4)) + ai_fam_pref = AF_INET; + else if(ENABLED_OPT(IPV6)) + ai_fam_pref = AF_INET6; + else + ai_fam_pref = NULL; + } -#ifndef NO_DISK -#endif log_msg("Started sntp", 0); int optct = optionProcess(&sntpOptions, argc, argv); @@ -64,20 +73,25 @@ sntp_main ( /* Initialize logging system */ if(HAVE_OPT(FILELOG)) { - init_log((char *) OPT_ARG(FILELOG)); + init_log((char *)OPT_ARG(FILELOG)); } + /* If there's a specified KOD file init KOD system. + * If not and system may save to HD use default file. + */ if(HAVE_OPT(KOD)) { - kod_init_kod_db(OPT_ARG(KOD)); + kod_init_kod_db((char *)OPT_ARG(KOD)); + } + else { + kod_init_kod_db("sntp.kod"); } - /* Considering employing a variable that prevents functions of doing anything until * everything is initialized properly */ struct addrinfo **resh = (struct addrinfo **) malloc(sizeof(struct addrinfo **)); - int resc = resolve_hosts(argv, argc, resh); + int resc = resolve_hosts(argv, argc, resh, ai_fam_pref); if(resc < 1) { /* Error! Network down? */ @@ -91,31 +105,33 @@ sntp_main ( getnameinfo(resh[c]->ai_addr, resh[c]->ai_addrlen, adr_buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); - if(!kod_entry_exists(adr_buf) && + int kodc; + char *hostname = addrinfo_to_str(resh[c]); + + if((kodc = search_entry(hostname, reason)) == 0 && is_reachable(resh[c])) { int ow_ret = on_wire(resh[c]); if(ow_ret < 0) { - printf("on_wire failed!\n"); + printf("on_wire failed for server %s!\n", hostname); } else { sync_data_suc = 1; } } else { - struct kod_entry **reason; - int kodc = search_entry(resh[c], reason); - - printf("KoD package exists for %s, stopping any further communication.\n", - adr_buf); + printf("KoD %i packages exists for %s, stopping any further communication.\n", + kodc, adr_buf); } freeaddrinfo(resh[c]); + free(hostname); } return 0; } +/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */ int on_wire ( struct addrinfo *host @@ -132,9 +148,11 @@ on_wire ( double t21, t34, delta, offset; - int error, rsock, rpktl; + int error, rpktl, sw_case; + + char *hostname; - l_fp p_rec, p_xmt, p_ref, p_org, xmt, org, tmp, dst, theta; + l_fp p_rec, p_xmt, p_ref, p_org, xmt, tmp, dst; error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL); @@ -153,22 +171,55 @@ on_wire ( /* FIXME! Modus broadcast + adr. check -> bdr. pkt */ set_li_vn_mode(x_pkt, LEAP_NOTINSYNC, 4, 3); - - create_socket(&sock, (struct sockaddr_storage *)host->ai_addr); - rsock = sendpkt(sock, host->ai_addr, x_pkt, LEN_PKT_NOMAC); + sendpkt(sock, (struct sockaddr_storage *)host->ai_addr, x_pkt, LEN_PKT_NOMAC); rpktl = recvpkt(sock, r_pkt, x_pkt); close_socket(sock); -/* if(rpktl == -1) - return -1; */ - - /* -2 would indicate that we should try to get a packet - * from this server again - */ - if(rpktl != -2) { + if(rpktl > 0) + sw_case = 1; + else + sw_case = rpktl; + + switch(sw_case) { + case SERVER_UNUSEABLE: + return -1; + break; + + case PACKET_UNUSEABLE: + break; + + case SERVER_AUTH_FAIL: + break; + + case KOD_DEMOBILIZE: + /* Received a DENY or RESTR KOD packet */ + hostname = addrinfo_to_str(host); + add_entry(hostname, (char *) &r_pkt->refid); + + if(ENABLED_OPT(NORMALVERBOSE)) + printf("on_wire: Received KOD packet with code: %s from %s, demobilizing all connections\n", + (char *) r_pkt->refid, hostname); + + char *log_str = (char *) malloc(sizeof(char) * (INET6_ADDRSTRLEN + 72)); + snprintf(log_str, (INET6_ADDRSTRLEN + 72), + "Received a KOD packet with code %s from %s, demobilizing all connections", + (char *) &r_pkt->refid, hostname); + + log_msg(log_str, 2); + + free(log_msg); + break; + + case KOD_RATE: + /* Hmm... probably we should sleep a bit here */ + break; + + case 1: + + /* Convert timestamps from network to host byte order */ NTOHL_FP(&r_pkt->reftime, &p_ref); NTOHL_FP(&r_pkt->org, &p_org); NTOHL_FP(&r_pkt->rec, &p_rec); @@ -183,7 +234,7 @@ on_wire ( #ifdef DEBUG pkt_output(r_pkt, rpktl, stdout); - + printf("on_wire: rpkt->reftime:\n"); l_fp_output(&(r_pkt->reftime), stdout); printf("on_wire: rpkt->org:\n"); @@ -198,10 +249,11 @@ on_wire ( l_fp_output(&(r_pkt->xmt), stdout); #endif + /* Compute offset etc. */ GETTIMEOFDAY(&tv_dst, (struct timezone *)NULL); tv_dst.tv_sec += JAN_1970; - + tmp = p_rec; L_SUB(&tmp, &p_org); @@ -220,9 +272,9 @@ on_wire ( if(ENABLED_OPT(NORMALVERBOSE)) printf("on_wire: t21: %.6f\t t34: %.6f\ndelta: %.6f\t offset: %.6f\n", - t21, t34, delta, offset); + t21, t34, delta, offset); -/* set_time(offset); */ + set_time(offset); return 0; } @@ -242,6 +294,7 @@ on_wire ( return -1; } +/* Compute the 8 bits for li_vn_mode */ void set_li_vn_mode ( struct pkt *spkt, @@ -266,6 +319,9 @@ 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(). + */ int set_time ( double offset @@ -274,7 +330,6 @@ set_time ( struct timeval tp; if(ENABLED_OPT(SETTOD)) { - GETTIMEOFDAY(&tp, (struct timezone *)NULL); tp.tv_sec += (int) offset; @@ -309,7 +364,4 @@ set_time ( return 0; } } - - } - diff --git a/gsoc_sntp/networking.c b/gsoc_sntp/networking.c index e2f06f67e..f0841c60f 100644 --- a/gsoc_sntp/networking.c +++ b/gsoc_sntp/networking.c @@ -1,6 +1,3 @@ -#include -#include - #include "sntp-opts.h" #include "networking.h" #include "header.h" @@ -10,11 +7,18 @@ char adr_buf[INET6_ADDRSTRLEN]; +/* resolve_hosts consumes an arry 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 ( char **hosts, int hostc, - struct addrinfo **res + struct addrinfo **res, + int pref_family ) { register unsigned int a, b; @@ -36,10 +40,13 @@ resolve_hosts ( int error; memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; -/* hints.ai_protocol = IPPROTO_UDP; */ + if(pref_family == NULL) + hints.ai_family = PF_UNSPEC; + else + hints.ai_family = pref_family; + + hints.ai_socktype = SOCK_DGRAM; error = getaddrinfo(hosts[a], "123", &hints, tres[a]); @@ -109,6 +116,7 @@ resolve_hosts ( return entryc; } +/* Creates a socket and returns. */ void create_socket ( SOCKET *rsock, @@ -124,6 +132,7 @@ create_socket ( } +/* If there's nothing more to do here we might need this function */ void close_socket ( SOCKET rsock @@ -166,13 +175,13 @@ sendpkt ( #endif } +/* Receive raw data */ int recvdata ( SOCKET rsock, struct sockaddr_storage *sender, char *rdata, - size_t rdata_length, - char *done + size_t rdata_length ) { socklen_t slen = SOCKLEN(&rsock); @@ -200,19 +209,27 @@ recvdata ( printf("Failure, recvc: %i\n", recvc); } #endif - /* Remove this when found a reasonable max. size. For now - * notify when there's data left to fetch - */ - if(recvc >= 511) - *done = 0; - else - *done = 1; return recvc; } -/* Fetch data, check if it's data for us and whether it's useable or not. If not, return -1 - * so we can delete this server from our list and continue with another one. +/* Receive data from broadcast. Couldn't finish that. Need to do some digging + * here, especially for protocol independence and IPv6 multicast */ +int +recvbcst ( + SOCKET rsock, + struct pkt *rpkt, + struct sockaddr_storage *sas + ) +{ + + return 0; +} + + + +/* 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 ( @@ -222,12 +239,9 @@ recvpkt ( ) { register int a; - int has_mac; - int is_authentic; + int has_mac, is_authentic; - l_fp tmp; l_fp org; - l_fp rec; struct sockaddr_storage sender; @@ -236,7 +250,7 @@ recvpkt ( /* Much space, just to be sure */ rdata = (char *) malloc(sizeof(char) * 512); - int pkt_length = recvdata(rsock, &sender, rdata, 512, &done); + int pkt_length = recvdata(rsock, &sender, rdata, 512); if(!done) { /* Do something about it, first check for a maximum length of ntp packets, @@ -244,78 +258,91 @@ recvpkt ( */ } + pkt_length = min(pkt_length, sizeof(struct pkt)); + + for(a=0; a LEN_PKT_NOMAC) has_mac = pkt_length - LEN_PKT_NOMAC; else if(debug) { fprintf(stderr, "recvpkt: Funny packet length: %i. Discarding package.\n", pkt_length); - return -1; + return PACKET_UNUSEABLE; } - if(has_mac) { - if(has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { - return -1; - } - /* Do auth stuff */ - } - - /*struct pkt *tmp_rpkt = (struct pkt *)rdata; - rpkt->li_vn_mode = tmp_rpkt->li_vn_mode; - rpkt->stratum = tmp_rpkt->stratum; - rpkt->ppoll = tmp_rpkt->ppoll; - rpkt->precision = tmp_rpkt->precision; - rpkt->rootdelay = tmp_rpkt->rootdelay; - rpkt->rootdisp = tmp_rpkt->rootdisp; - rpkt->refid = tmp_rpkt->refid; - rpkt->reftime = tmp_rpkt->reftime; - rpkt->org = tmp_rpkt->org; - rpkt->rec = tmp_rpkt->rec; - rpkt->xmt = tmp_rpkt->xmt; */ - + /* Packet too big */ if(pkt_length > LEN_PKT_MAC) { if(ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: Received packet is too big (%i bytes), trying again to get a useable packet\n", pkt_length); - return -2; + return PACKET_UNUSEABLE; } - - for(a=0; ali_vn_mode), NTP_OLDVERSION); - if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || + /* MAC could be useable for us */ + if(has_mac) { + /* Two more things that the MAC must conform to */ + if(has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { + is_authentic = 0; /* Or should we discard this packet? */ + } + else { + /* Do auth stuff */ + } + } + + /* Check for server's ntp version */ + if(PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { - return -1; + return SERVER_UNUSEABLE; } - if (PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER + /* We want a server to sync with */ + if(PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { #ifdef DEBUG printf("sntp recvpkt: mode %d stratum %i\n", PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); #endif - return -1; + return SERVER_UNUSEABLE; } if(rpkt->stratum == STRATUM_PKT_UNSPEC) { if(ENABLED_OPT(NORMALVERBOSE)) - printf("sntp recvpkt: Unusable packet, discarding. (stratum: %i)\n", rpkt->stratum); + printf("sntp recvpkt: Stratum unspecified, going to check for KOD (stratum: %i)\n", rpkt->stratum); + + + char *ref_char = (char *) &rpkt->refid; - return -1; + /* If it's a KOD packet we'll just use the KOD information */ + if(ref_char[0] != 'X') { + if(strncmp(ref_char, "DENY", 4)) + return KOD_DEMOBILIZE; + + if(strncmp(ref_char, "RSTR", 4)) + return KOD_DEMOBILIZE; + + if(strncmp(ref_char, "RATE", 4)) + return KOD_RATE; + + /* 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 */ if(PKT_LEAP(rpkt->li_vn_mode) == LEAP_NOTINSYNC) { if(ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: Server not in sync, skipping this server\n"); - return -1; + return SERVER_UNUSEABLE; } @@ -327,32 +354,15 @@ recvpkt ( if (!L_ISEQU(&org, &spkt->xmt)) { if (debug) printf("receive: pkt.org and peer.xmt differ\n"); - return -1; + + return PACKET_UNUSEABLE; } - - /* Left for now, finishin other stuff. I think I might want that somewhere else, - * don't want this function to do on-wire tasks. Sanity checks are right here I think - * - server->leap = PKT_LEAP(rpkt->li_vn_mode); - server->stratum = PKT_TO_STRATUM(rpkt->stratum); - server->precision = rpkt->precision; - server->rootdelay = ntohl(rpkt->rootdelay); - server->rootdisp = ntohl(rpkt->rootdisp); - server->refid = rpkt->refid; - NTOHL_FP(&rpkt->reftime, &server->reftime); - NTOHL_FP(&rpkt->rec, &rec); - NTOHL_FP(&rpkt->xmt, &server->org); - - if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) - return -1; */ - return pkt_length; } /* * is_reachable - check to see if we have a route to given destination - * (non-blocking). */ int is_reachable ( diff --git a/gsoc_sntp/networking.h b/gsoc_sntp/networking.h index 03d391887..2b5e2d26e 100644 --- a/gsoc_sntp/networking.h +++ b/gsoc_sntp/networking.h @@ -1,34 +1,105 @@ -#ifndef NETWORK_H -#define NETWORK_H +#ifndef NETWORKING_H +#define NETWORKING_H #include #include +#include +#include + #include +#include +#include +#include -#include "data_formats.h" -/* FIXME, see portability issue 1 */ /* irrelevant for now */ -#ifndef SYS_WINNT -#define SOCKET int -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#define closesocket close -#endif +#define SERVER_UNUSEABLE -1 /* Skip server */ +#define PACKET_UNUSEABLE -2 /* Discard packet and try to get a useable packet again if not tried too often */ +#define SERVER_AUTH_FAIL -3 /* Authentication failed, act upon settings */ +#define KOD_DEMOBILIZE -4 /* KOD packet with code DENY or RSTR, stop all communication and save KOD information */ +#define KOD_RATE -5 /* KOD packet with code RATE, reduce poll intervall */ /* From ntpdate.c */ int is_reachable (struct addrinfo *dst); -int resolve_hosts (char **hosts, int hostc, struct addrinfo **res); +int resolve_hosts (char **hosts, int hostc, struct addrinfo **res, int pref_family); void create_socket (SOCKET *rsock, struct sockaddr_storage *dest); void close_socket (SOCKET rsock); -void send_pkt (SOCKET rsock, struct sockaddr_storage *dest, struct pkt *pkt, int len); +void sendpkt (SOCKET rsock, struct sockaddr_storage *dest, struct pkt *pkt, int len); -int recvdata (SOCKET rsock, struct sockaddr_storage *sender, char *rdata, size_t rdata_length, char *done); +int recvdata (SOCKET rsock, struct sockaddr_storage *sender, char *rdata, size_t rdata_length); int recvpkt (SOCKET rsock, struct pkt *rpkt, struct pkt *spkt); +int recvbcst (SOCKET rsock, struct pkt *rpkt, struct sockaddr_storage *sas); + +/* Shortened peer structure. Not absolutely necessary yet */ +struct speer { + struct speer *next; + struct sockaddr_storage srcadr; + u_char version; + u_char hmode; + u_char hpoll; + u_char minpoll; + u_char maxpoll; + u_int flags; + u_char num_events; + u_char ttl; + u_char leap; + u_char pmode; + u_char stratum; + u_char ppoll; + u_char precision; + u_int32 refid; + l_fp reftime; + keyid_t keyid; + +#ifdef OPENSSL +#define clear_to_zero opcode + u_int32 opcode; /* last request opcode */ + associd_t assoc; /* peer association ID */ + u_int32 crypto; /* peer status word */ + EVP_PKEY *pkey; /* public key */ + const EVP_MD *digest; /* message digest algorithm */ + char *subject; /* certificate subject name */ + char *issuer; /* certificate issuer name */ + struct cert_info *xinfo; /* issuer certificate */ + keyid_t pkeyid; /* previous key ID */ + keyid_t hcookie; /* host cookie */ + keyid_t pcookie; /* peer cookie */ + const struct pkey_info *ident_pkey; /* identity key */ + BIGNUM *iffval; /* identity challenge (IFF, GQ, MV) */ + const BIGNUM *grpkey; /* identity challenge key (GQ) */ + struct value cookval; /* receive cookie values */ + struct value recval; /* receive autokey values */ + struct exten *cmmd; /* extension pointer */ + u_long refresh; /* next refresh epoch */ + + /* + * Variables used by authenticated server + */ + keyid_t *keylist; /* session key ID list */ + int keynumber; /* current key number */ + struct value encrypt; /* send encrypt values */ + struct value sndval; /* send autokey values */ +#else /* OPENSSL */ +#define clear_to_zero status +#endif /* OPENSSL */ + + l_fp rec; /* receive time stamp */ + l_fp xmt; /* transmit time stamp */ + l_fp dst; /* destination timestamp */ + l_fp aorg; /* origin timestamp */ + l_fp borg; /* alternate origin timestamp */ + double offset; /* peer clock offset */ + double delay; /* peer roundtrip delay */ +}; + + + + + #endif diff --git a/gsoc_sntp/sntp-opts.def b/gsoc_sntp/sntp-opts.def index f7762d572..241a03436 100644 --- a/gsoc_sntp/sntp-opts.def +++ b/gsoc_sntp/sntp-opts.def @@ -142,6 +142,29 @@ flag = { _EndOfDoc_; }; +flag = { + name = broadcast; + value = b; + descrip = "Use broadcast packages for synchronisation"; + doc = <<- _EndOfDoc_ + If specified SNTP will wait 5 minutes for broadcast packets + for synchronisation. The amount of time SNTP waits can be + specified by option -t. + _EndOfDoc_; +}; + +flag = { + name = timeout; + value = t; + descrip = "Specify the number of seconds until SNTP times out when waiting for broadcast packets"; + arg-type = number; + doc = <<- _EndOfDoc_ + When waiting for a broadcast packet SNTP will wait the number + of seconds specified and times out. + _EndOfDoc_; +}; + + detail = <<- _END_DETAIL .I sntp can be used as a SNTP client to query a NTP or SNTP server and either display diff --git a/gsoc_sntp/utilities.c b/gsoc_sntp/utilities.c index f8a6d5c67..d6e712243 100644 --- a/gsoc_sntp/utilities.c +++ b/gsoc_sntp/utilities.c @@ -99,3 +99,15 @@ l_fp_output_dec ( } +char * +addrinfo_to_str ( + struct addrinfo *addr + ) +{ + char *buf = (char *) malloc(sizeof(char) * INET6_ADDRSTRLEN); + + getnameinfo(addr->ai_addr, addr->ai_addrlen, buf, + INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); + + return buf; +} diff --git a/gsoc_sntp/utilities.h b/gsoc_sntp/utilities.h index 25da6f9c8..c943f121e 100644 --- a/gsoc_sntp/utilities.h +++ b/gsoc_sntp/utilities.h @@ -17,5 +17,6 @@ void l_fp_output (l_fp *ts, FILE *output); void l_fp_output_bin (l_fp *ts, FILE *output); void l_fp_output_dec (l_fp *ts, FILE *output); +char *addrinfo_to_str (struct addrinfo *addr); #endif