...
 
Commits (14)
For Release:
Fix SecondsPerDay in nts_cookie.c
It is set to 3600 for testing
That makes too-old cookies if the polling interval is long enough
BUGS:
timeout on client connect too long (system default)
Is 3 seconds timeout OK? (both client and server)
......@@ -5,12 +10,11 @@ BUGS:
nts_log_ssl_error() No SSL param ??
ERR_error_string_n
Fix SecondsPerDay in nts_cookie.c
Set to 3600 for testing
multithread msyslog
libntp/lib_strbuf.c is used by socktoa and sockporttoa
strerror
I think this has been fixed.
Hourly logging?
ntpq get totals vs recent
documentation:
HOWTO on NTS
......
......@@ -73,7 +73,13 @@ You can read POSIX-1.2001, with 2004 Corrigendum, online for free here:
You can see POSIX.1-2001, SUSv3, online for free here:
http://www.unix-systems.org/version3/
POSIX threads *are* considered part of the standardized API and may be used.
POSIX threads *are* considered part of the standardized API, but their
use requires extreme care. The main part of ntpd assumes it is the only
thread. One interesting area is msyslog. The DNS thread doesn't call msyslog.
That was impractical for NTS, so msyslog is thread safe as of 2019-Apr.
Beware of calling strerror() from non-main threads. Use strerror_r()
into a buffer on the stack. Similarly, use socktoa_r() and sockporttoa_r()
and don't call lib_getbuf().
You *may* assume the clock_gettime(2) and clock_settime(2) calls, and
the related getitimer(2)/setitimer(2), from POSIX-1.2008.
......
......@@ -47,9 +47,11 @@ The options are as follows:
Read the private key to our certificate from _file_.
+ca+ _location_::
Use the file (or directory) specified by _location_ to
Use the file, or directory, specified by _location_ to
validate NTS-KE server certificates instead of the system
default root certificates.
default root certificates. If a directory is specified, it
must have files named with their hash, as created by
+openssl rehash+.
+cookie+ _location_::
Use the file (or directory) specified by _location_ to
......@@ -66,7 +68,7 @@ The options are as follows:
+mintls+ _string_::
Set the lowest allowable TLS version to negotiate. Will be useful in
the wake of a TLS compromise. Reasonable values are _TLS1.2_ and
_TLS1.3_ if your system supports it. 1.3 was first supported in
_TLS1.3_ if your system supports it. TLS 1.3 was first supported in
OpenSSL version 1.1.1.
+maxtls+ _string_::
......@@ -98,19 +100,18 @@ The following options of the +server+ command configure NTS.
+nts+::
Use Network Time Security (NTS) for authentication. Normally,
this is all you have to do to activate the client side of NTS.
+
The hostname following the +server+ command is used as the address
of the NTS key exchange server (NTS-KE) rather than the address
of a NTP server. The NTS-KE exchange defaults to using the same
IP Address for the NTP server.
Note that the server name must match the name on the certificate.
That is probably a FQDN rather than a short alias that you would
probably use to talk to an internal server.
IP address for the NTP server.
+
Note that the +server+ hostname must match the name on the NTS-KE
server's certificate.
+ask+ _address_:: (not implemented)
Use Network Time Security for authentication. Ask
for a specific NTS server, which may differ from the NTP server.
for a specific NTP server, which may differ from the NTS server.
Conforms to RFC 3896 section 3.2.2 prescription for the Host part of
a URI: that is, the _address_ may be a hostname, an FQDN, an IPv4
numeric address, or an IPv6 numeric address (in square brackets).
......@@ -118,7 +119,7 @@ The following options of the +server+ command configure NTS.
+require+ _address_:: (not implemented)
Use Network Time Security for authentication and encryption.
Require a specific NTS server, which may differ from the NTP server.
Require a specific NTP server, which may differ from the NTS server.
Address syntax is as for +ask+.
+noval+::
......@@ -132,22 +133,22 @@ The following options of the +server+ command configure NTS.
Present the certificate in _file_ as our client certificate,
overriding the site default.
+ca+ _location_:: (not implemented)
+ca+ _location_::
Use the file, or directory, specified by _location_ to validate the
NTS-KE server certificate, overriding the site default. Do not use
any other CA.
any other CA. If a directory is specified, it must have files named
with their hash, as created by +openssl rehash+.
+aead+ _string_::
Specify the prefered crypto algorithm to be used on the wire.
The only options supported are AES_SIV_CMAC_256, AES_SIV_CMAC_384, and
AES_SIV_CMAC_512. The server may ignore the request. See the _aead_
option above.
The same _aead_ algorithms are also used to encrypt cookies.
Specify the prefered crypto algorithm to be used on the wire.
The only options supported are AES_SIV_CMAC_256, AES_SIV_CMAC_384, and
AES_SIV_CMAC_512. The server may ignore the request. See the _aead_
option above.
+
The same _aead_ algorithms are also used to encrypt cookies.
The default is AES_SIV_CMAC_256. There is no config file option to
change it, but you can change it by editing the saved cookie key
file, probably /var/lib/ntp/nts-keys. Adjust the _L:_ slot to be
file, probably +/var/lib/ntp/nts-keys+. Adjust the _L:_ slot to be
48 or 64 and adjust the _I:_ slots to have the right number of bytes.
Then restart the server. (All old cookies held by clients will be
rejected so their next 8 NTP requests will be ignored. They should
......
......@@ -99,7 +99,9 @@ extern const char * k_st_flags (uint32_t);
extern char * statustoa (int, int);
extern sockaddr_u * netof6 (sockaddr_u *);
extern const char * socktoa (const sockaddr_u *);
extern const char * socktoa_r (const sockaddr_u *sock, char *buf, size_t buflen);
extern const char * sockporttoa(const sockaddr_u *);
extern const char * sockporttoa_r(const sockaddr_u *sock, char *buf, size_t buflen);
extern unsigned short sock_hash(const sockaddr_u *) __attribute__((pure));
extern const char *refid_str (uint32_t, int);
......@@ -119,6 +121,7 @@ extern char * ntp_optarg; /* global argument pointer */
extern int ntp_optind; /* global argv index */
/* lib_strbuf.c */
extern void getbuf_init (void);
extern bool ipv4_works;
extern bool ipv6_works;
......
Copyright (c) 2010 Serge A. Zaitsev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
JSMN
====
[![Build Status](https://travis-ci.org/zserge/jsmn.svg?branch=master)](https://travis-ci.org/zserge/jsmn)
jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be
easily integrated into resource-limited or embedded projects.
You can find more information about JSON format at [json.org][1]
Library sources are available at [bitbucket.org/zserge/jsmn][2]
Library sources are available at https://github.com/zserge/jsmn
The web page with some information about jsmn can be found at
[http://zserge.com/jsmn.html][3]
[http://zserge.com/jsmn.html][2]
Philosophy
----------
......@@ -24,7 +25,7 @@ JSON format itself is extremely simple, so why should we complicate it?
jsmn is designed to be **robust** (it should work fine even with erroneous
data), **fast** (it should parse data on the fly), **portable** (no superfluous
dependencies or non-standard C extensions). An of course, **simplicity** is a
dependencies or non-standard C extensions). And of course, **simplicity** is a
key feature - simple code style, simple algorithm, simple integration into
other projects.
......@@ -78,9 +79,9 @@ it possible to use zero-copy techniques.
Install
-------
To clone the repository you should have mercurial installed. Just run:
To clone the repository you should have Git installed. Just run:
$ hg clone http://bitbucket.org/zserge/jsmn jsmn
$ git clone https://github.com/zserge/jsmn
Repository layout is simple: jsmn.c and jsmn.h are library files, tests are in
the jsmn\_test.c, you will also find README, LICENSE and Makefile files inside.
......@@ -97,10 +98,11 @@ API
Token types are described by `jsmntype_t`:
typedef enum {
JSMN_PRIMITIVE = 0,
JSMN_UNDEFINED = 0,
JSMN_OBJECT = 1,
JSMN_ARRAY = 2,
JSMN_STRING = 3
JSMN_STRING = 3,
JSMN_PRIMITIVE = 4
} jsmntype_t;
**Note:** Unlike JSON data types, primitive tokens are not divided into
......@@ -134,12 +136,12 @@ All job is done by `jsmn_parser` object. You can initialize a new parser using:
// js - pointer to JSON string
// tokens - an array of tokens available
// 10 - number of tokens available
jsmn_parse(&parser, js, tokens, 10);
jsmn_parse(&parser, js, strlen(js), tokens, 10);
This will create a parser, and then it tries to parse up to 10 JSON tokens from
the `js` string.
A non-negative reutrn value of `jsmn_parse` is the number of tokens actually
A non-negative return value of `jsmn_parse` is the number of tokens actually
used by the parser.
Passing NULL instead of the tokens array would not store parsing results, but
instead the function will return the value of tokens needed to parse the given
......@@ -151,9 +153,9 @@ If something goes wrong, you will get an error. Error will be one of these:
* `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large
* `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data
If you get `JSON_ERROR_NOMEM`, you can re-allocate more tokens and call
If you get `JSMN_ERROR_NOMEM`, you can re-allocate more tokens and call
`jsmn_parse` once more. If you read json data from the stream, you can
periodically call `jsmn_parse` and check if return value is `JSON_ERROR_PART`.
periodically call `jsmn_parse` and check if return value is `JSMN_ERROR_PART`.
You will get this error until you reach the end of JSON data.
Other info
......@@ -163,5 +165,4 @@ This software is distributed under [MIT license](http://www.opensource.org/licen
so feel free to integrate it in your commercial products.
[1]: http://www.json.org/
[2]: https://bitbucket.org/zserge/jsmn/wiki/Home
[3]: http://zserge.com/jsmn.html
[2]: http://zserge.com/jsmn.html
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "../jsmn.h"
/* Function realloc_it() is a wrapper function for standard realloc()
* with one difference - it frees old memory pointer in case of realloc
* failure. Thus, DO NOT use old data pointer in anyway after call to
* realloc_it(). If your code has some kind of fallback algorithm if
* memory can't be re-allocated - use standard realloc() instead.
*/
static inline void *realloc_it(void *ptrmem, size_t size) {
void *p = realloc(ptrmem, size);
if (!p) {
free (ptrmem);
fprintf(stderr, "realloc(): errno=%d\n", errno);
}
return p;
}
/*
* An example of reading JSON from stdin and printing its content to stdout.
* The output looks like YAML, but I'm not sure if it's really compatible.
......@@ -82,12 +98,11 @@ int main() {
}
}
js = realloc(js, jslen + r + 1);
js = realloc_it(js, jslen + r + 1);
if (js == NULL) {
fprintf(stderr, "realloc(): errno=%d\n", errno);
return 3;
}
strlcpy(js + jslen, buf, r + 1);
strncpy(js + jslen, buf, r);
jslen = jslen + r;
again:
......@@ -95,9 +110,8 @@ again:
if (r < 0) {
if (r == JSMN_ERROR_NOMEM) {
tokcount = tokcount * 2;
tok = realloc(tok, sizeof(*tok) * tokcount);
tok = realloc_it(tok, sizeof(*tok) * tokcount);
if (tok == NULL) {
fprintf(stderr, "realloc(): errno=%d\n", errno);
return 3;
}
goto again;
......@@ -108,5 +122,5 @@ again:
}
}
return 0;
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../jsmn.h"
......@@ -7,7 +8,7 @@
* tokens is predictable.
*/
const char *JSON_STRING =
static const char *JSON_STRING =
"{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n "
"\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}";
......@@ -71,5 +72,5 @@ int main() {
JSON_STRING + t[i].start);
}
}
return 0;
return EXIT_SUCCESS;
}
/* SPDX-License-Identifier: MIT */
#include <stdlib.h>
#include "jsmn.h"
/**
* Allocates a fresh unused token from the token pull.
* Allocates a fresh unused token from the token pool.
*/
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
jsmntok_t *tokens, size_t num_tokens) {
......@@ -36,28 +32,25 @@ static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
/**
* Fills next available token with JSON primitive.
*/
static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
size_t len, jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
int start;
start = (int)parser->pos;
start = parser->pos;
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
switch (js[parser->pos]) {
#ifndef JSMN_STRICT
/* In strict mode primitive must be followed by "," or "}" or "]" */
case ':':
/* In strict mode primitive must be followed by "," or "}" or "]" */
case ':':
#endif
case '\t' : case '\r' : case '\n' : case ' ' :
case ',' : case ']' : case '}' :
goto found;
default:
/* huh? */
break;
case '\t' : case '\r' : case '\n' : case ' ' :
case ',' : case ']' : case '}' :
goto found;
}
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
parser->pos = (unsigned int)start;
parser->pos = start;
return JSMN_ERROR_INVAL;
}
}
......@@ -74,10 +67,10 @@ found:
}
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL) {
parser->pos = (unsigned int)start;
parser->pos = start;
return JSMN_ERROR_NOMEM;
}
jsmn_fill_token(token, JSMN_PRIMITIVE, start, (int)parser->pos);
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
#ifdef JSMN_PARENT_LINKS
token->parent = parser->toksuper;
#endif
......@@ -86,13 +79,13 @@ found:
}
/**
* Filsl next token with JSON string.
* Fills next token with JSON string.
*/
static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
size_t len, jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
int start = (int)parser->pos;
int start = parser->pos;
parser->pos++;
......@@ -107,11 +100,10 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
}
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL) {
parser->pos = (unsigned int)start;
parser->pos = start;
return JSMN_ERROR_NOMEM;
}
jsmn_fill_token(token, JSMN_STRING, start+1,
(int)parser->pos);
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
#ifdef JSMN_PARENT_LINKS
token->parent = parser->toksuper;
#endif
......@@ -131,37 +123,37 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
case 'u':
parser->pos++;
for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
/* If it isn't a hex character we have an error */
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
parser->pos = (unsigned int)start;
return JSMN_ERROR_INVAL;
}
parser->pos++;
/* If it isn't a hex character we have an error */
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
parser->pos = start;
return JSMN_ERROR_INVAL;
}
parser->pos++;
}
parser->pos--;
break;
/* Unexpected symbol */
default:
parser->pos = (unsigned int)start;
parser->pos = start;
return JSMN_ERROR_INVAL;
}
}
}
parser->pos = (unsigned int)start;
parser->pos = start;
return JSMN_ERROR_PART;
}
/**
* Parse JSON string and fill tokens.
*/
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
jsmntok_t *tokens, unsigned int num_tokens) {
jsmnerr_t r;
int r;
int i;
jsmntok_t *token;
int count = 0;
int count = parser->toknext;
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
char c;
......@@ -184,8 +176,8 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
#endif
}
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
token->start = (int)parser->pos;
parser->toksuper = (int)parser->toknext - 1;
token->start = parser->pos;
parser->toksuper = parser->toknext - 1;
break;
case '}': case ']':
if (tokens == NULL)
......@@ -198,14 +190,17 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
token = &tokens[parser->toknext - 1];
for (;;) {
if (token->start != -1 && token->end == -1) {
if (token->type != type) {
return JSMN_ERROR_INVAL;
}
token->end = (int)parser->pos + 1;
parser->toksuper = token->parent;
break;
if (token->type != type) {
return JSMN_ERROR_INVAL;
}
token->end = parser->pos + 1;
parser->toksuper = token->parent;
break;
}
if (token->parent == -1) {
if(token->type != type || parser->toksuper == -1) {
return JSMN_ERROR_INVAL;
}
break;
}
token = &tokens[token->parent];
......@@ -243,10 +238,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case '\t' : case '\r' : case '\n' : case ' ':
break;
case ':':
parser->toksuper = (int)parser->toknext - 1;
parser->toksuper = parser->toknext - 1;
break;
case ',':
if (tokens != NULL &&
if (tokens != NULL && parser->toksuper != -1 &&
tokens[parser->toksuper].type != JSMN_ARRAY &&
tokens[parser->toksuper].type != JSMN_OBJECT) {
#ifdef JSMN_PARENT_LINKS
......@@ -269,7 +264,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case '5': case '6': case '7' : case '8': case '9':
case 't': case 'f': case 'n' :
/* And they must not be keys of the object */
if (tokens != NULL) {
if (tokens != NULL && parser->toksuper != -1) {
jsmntok_t *t = &tokens[parser->toksuper];
if (t->type == JSMN_OBJECT ||
(t->type == JSMN_STRING && t->size != 0)) {
......@@ -294,8 +289,9 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
#endif
}
}
if (tokens != NULL) {
for (i = (int)parser->toknext - 1; i >= 0; i--) {
for (i = parser->toknext - 1; i >= 0; i--) {
/* Unmatched opened object or array */
if (tokens[i].start != -1 && tokens[i].end == -1) {
return JSMN_ERROR_PART;
......
/* SPDX-License-Identifier: MIT */
#ifndef GUARD_JSMN_H
#define GUARD_JSMN_H
#ifndef __JSMN_H_
#define __JSMN_H_
#include <stddef.h>
......@@ -17,26 +15,27 @@ extern "C" {
* o Other primitive: number, boolean (true/false) or null
*/
typedef enum {
JSMN_PRIMITIVE = 0,
JSMN_UNDEFINED = 0,
JSMN_OBJECT = 1,
JSMN_ARRAY = 2,
JSMN_STRING = 3
JSMN_STRING = 3,
JSMN_PRIMITIVE = 4
} jsmntype_t;
typedef enum {
enum jsmnerr {
/* Not enough tokens were provided */
JSMN_ERROR_NOMEM = -1,
/* Invalid character inside JSON string */
JSMN_ERROR_INVAL = -2,
/* The string is not a full JSON packet, more bytes expected */
JSMN_ERROR_PART = -3
} jsmnerr_t;
};
/**
* JSON token description.
* @param type type (object, array, string etc.)
* @param start start position in JSON data string
* @param end end position in JSON data string
* type type (object, array, string etc.)
* start start position in JSON data string
* end end position in JSON data string
*/
typedef struct {
jsmntype_t type;
......@@ -67,11 +66,11 @@ void jsmn_init(jsmn_parser *parser);
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
* a single JSON object.
*/
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
jsmntok_t *tokens, unsigned int num_tokens);
#ifdef __cplusplus
}
#endif
#endif /* GUARD_JSMN_H */
#endif /* __JSMN_H_ */
......@@ -7,6 +7,7 @@
#include "isc_netaddr.h"
#include "ntp_assert.h"
#include "ntp_fp.h"
#include "ntp_stdlib.h"
#include "lib_strbuf.h"
......@@ -14,10 +15,14 @@
/*
* Storage declarations
*/
int debug;
static pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t me;
void getbuf_init(void) {
me = pthread_self();
}
/*
* Function to get a pointer to the next buffer. Needs to be thread-safe because
* it's used in callers that need to be thread-safe, notably msyslog. For the
......@@ -28,13 +33,34 @@ static pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
* language, at which point something with this behavior will be
* better than all the contortions we'd have to go through to get rid
* of it in C.
*
* HGM: But I'm not willing to ship a lurking time bomb,
* so I fixed the non-main threads (NTS, DNS) not to call
* lib_getbuf and added a trap to make sure I really fixed them all.
*/
char *lib_getbuf(void)
{
static libbufstr lib_stringbuf[LIB_NUMBUF];
static int lib_nextbuf;
char *bufp;
// FIXME - need this until python tests can call getbuf_init
static bool init_done = false;
if (!init_done) {
getbuf_init();
init_done = true;
}
if (pthread_self() != me) {
msyslog(LOG_ERR, "ERR: lib_getbuf() called from non-main thread.");
#ifndef BACKTRACE_DISABLED
// backtrace_log();
#endif
// exit(1);
}
pthread_mutex_lock(&cookie_lock);
ZERO(lib_stringbuf[lib_nextbuf]);
(bufp) = &lib_stringbuf[lib_nextbuf++][0];
......
......@@ -32,6 +32,8 @@ static FILE * syslog_file;
static char * syslog_fname;
static char * syslog_abs_fname;
int debug;
/* libntp default ntp_syslogmask is all bits lit */
#define INIT_NTP_SYSLOGMASK ~(uint32_t)0
uint32_t ntp_syslogmask = INIT_NTP_SYSLOGMASK;
......
......@@ -24,48 +24,53 @@ const char *
socktoa(
const sockaddr_u *sock
)
{
char *buf = lib_getbuf();
socktoa_r(sock, buf, LIB_BUFLENGTH);
return buf;
}
const char *
socktoa_r(
const sockaddr_u *sock, char *buf, size_t buflen
)
{
int saved_errno;
char * res;
char * addr;
unsigned long scope;
saved_errno = errno;
res = lib_getbuf();
if (NULL == sock) {
strlcpy(res, "(null)", LIB_BUFLENGTH);
strlcpy(buf, "(null)", buflen);
} else {
switch(AF(sock)) {
case AF_INET:
case AF_UNSPEC:
inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
LIB_BUFLENGTH);
inet_ntop(AF_INET, PSOCK_ADDR4(sock), buf, buflen);
break;
case AF_INET6:
inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
LIB_BUFLENGTH);
inet_ntop(AF_INET6, PSOCK_ADDR6(sock), buf, buflen);
scope = SCOPE_VAR(sock);
if (0 != scope && !strchr(res, '%')) {
addr = res;
res = lib_getbuf();
snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
addr, scope);
res[LIB_BUFLENGTH - 1] = '\0';
if (0 != scope && !strchr(buf, '%')) {
char buf2[LIB_BUFLENGTH];
snprintf(buf2, sizeof(buf2), "%s%%%lu",
buf, scope);
buf2[LIB_BUFLENGTH - 1] = '\0';
strlcpy(buf, buf2, buflen);
}
break;
default:
snprintf(res, LIB_BUFLENGTH,
snprintf(buf, buflen,
"(socktoa unknown family %d)",
AF(sock));
}
}
errno = saved_errno;
return res;
return buf;
}
......@@ -74,18 +79,26 @@ sockporttoa(
const sockaddr_u *sock
)
{
int saved_errno;
const char * atext;
char * buf;
char *buf = lib_getbuf();
sockporttoa_r(sock, buf, LIB_BUFLENGTH);
return buf;
}
const char *
sockporttoa_r(
const sockaddr_u *sock, char *buf, size_t buflen
)
{
int saved_errno;
char buf2[LIB_BUFLENGTH];
saved_errno = errno;
atext = socktoa(sock);
buf = lib_getbuf();
snprintf(buf, LIB_BUFLENGTH,
socktoa_r(sock, buf2, sizeof(buf2));
snprintf(buf, buflen,
(IS_IPV6(sock))
? "[%s]:%hu"
: "%s:%hu",
atext, SRCPORT(sock));
buf2, SRCPORT(sock));
errno = saved_errno;
return buf;
......
......@@ -25,6 +25,7 @@ def build(ctx):
]
libntp_source_sharable = [
"assert.c",
"clockwork.c",
"emalloc.c",
"hextolfp.c",
......
......@@ -2848,6 +2848,7 @@ proto_clr_stats(void)
/* limit logging so bad guys can't DDoS us by sending crap
* log first 100 and 10/hour
* This gets too-old cookies
*/
void maybe_log_junk(struct recvbuf *rbufp) {
......
......@@ -512,6 +512,8 @@ ntpdmain(
saved_argc = argc;
saved_argv = argv;
progname = argv[0];
getbuf_init();
parse_cmdline_opts(argc, argv);
# ifdef DEBUG
setvbuf(stdout, NULL, _IOLBF, 0);
......
......@@ -18,6 +18,7 @@
#include <openssl/err.h>
#include "ntp_types.h"
#include "ntp_stdlib.h"
#include "ntpd.h"
#include "nts.h"
#include "nts2.h"
......@@ -207,9 +208,11 @@ bool nts_load_certificate(SSL_CTX *ctx) {
int nts_ssl_read(SSL *ssl, uint8_t *buff, int buff_length) {
int bytes_read;
char errbuf[100];
bytes_read = SSL_read(ssl, buff, buff_length);
if (0 >= bytes_read) {
msyslog(LOG_INFO, "NTS: SSL_read error: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_INFO, "NTS: SSL_read error: %s", errbuf);
nts_log_ssl_error();
return -1;
}
......@@ -218,9 +221,11 @@ int nts_ssl_read(SSL *ssl, uint8_t *buff, int buff_length) {
int nts_ssl_write(SSL *ssl, uint8_t *buff, int buff_length) {
int bytes_written;
char errbuf[100];
bytes_written = SSL_write(ssl, buff, buff_length);
if (0 >= bytes_written) {
msyslog(LOG_INFO, "NTS: SSL_write error: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_INFO, "NTS: SSL_write error: %s", errbuf);
nts_log_ssl_error();
return -1;
}
......
......@@ -27,8 +27,9 @@
#include "nts2.h"
#include "ntp_dns.h"
SSL_CTX* make_ssl_client_ctx(const char *filename);
int open_TCP_socket(struct peer *peer, const char *hostname);
bool nts_set_cert_search(SSL_CTX *ctx);
bool nts_set_cert_search(SSL_CTX *ctx, const char *filename);
void set_hostname(SSL *ssl, const char *hostname);
bool check_certificate(SSL *ssl, struct peer *peer);
bool nts_client_send_request(SSL *ssl, struct peer *peer);
......@@ -51,40 +52,8 @@ static bool addrOK;
// FreeBSD 11: 0x100020ffL 1.0.2o-freebsd
bool nts_client_init(void) {
bool ok = true;
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
client_ctx = SSL_CTX_new(TLS_client_method());
#else
OpenSSL_add_all_ciphers(); // FIXME needed on NetBSD
client_ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
if (NULL == client_ctx) {
/* Happens if no ciphers */
msyslog(LOG_INFO, "NTSs: NULL client_ctx");
nts_log_ssl_error();
return false;
}
#if (OPENSSL_VERSION_NUMBER > 0x1000200fL)
{
// 4., ALPN, RFC 7301
static unsigned char alpn [] = { 7, 'n', 't', 's', 'k', 'e', '/', '1' };
SSL_CTX_set_alpn_protos(client_ctx, alpn, sizeof(alpn));
}
#endif
SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_OFF);
SSL_CTX_set_timeout(client_ctx, NTS_KE_TIMEOUT);
ok &= nts_load_versions(client_ctx);
ok &= nts_load_ciphers(client_ctx);
ok &= nts_set_cert_search(client_ctx);
if (!ok) {
msyslog(LOG_ERR, "NTSc: Troubles setting up client SSL CTX");
exit(1);
};
client_ctx = make_ssl_client_ctx(ntsconfig.ca);
return true;
}
......@@ -93,6 +62,7 @@ bool nts_probe(struct peer * peer) {
struct timeval timeout = {.tv_sec = NTS_KE_TIMEOUT, .tv_usec = 0};
const char *hostname = peer->hostname;
char hostbuf[100];
char errbuf[100];
SSL *ssl;
int server;
l_fp start, finish;
......@@ -129,7 +99,8 @@ bool nts_probe(struct peer * peer) {
err = setsockopt(server, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
if (0 > err) {
msyslog(LOG_ERR, "NTSc: can't setsockopt: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSc: can't setsockopt: %s", errbuf);
close(server);
nts_ke_probes_bad++;
return false;
......@@ -139,7 +110,14 @@ bool nts_probe(struct peer * peer) {
// Not much error checking yet.
// Ugly since most SSL routines return 1 on success.
ssl = SSL_new(client_ctx);
if (NULL == peer->cfg.nts_cfg.ca)
ssl = SSL_new(client_ctx);
else {
SSL_CTX *ctx;
ctx = make_ssl_client_ctx(peer->cfg.nts_cfg.ca);
ssl = SSL_new(ctx);
SSL_CTX_free(ctx);
}
set_hostname(ssl, hostname);
SSL_set_fd(ssl, server);
......@@ -203,7 +181,11 @@ bail:
}
bool nts_check(struct peer *peer) {
// msyslog(LOG_INFO, "NTSc: nts_check %s, %d", sockporttoa(&sockaddr), addrOK);
if (0) {
char errbuf[100];
sockporttoa_r(&sockaddr, errbuf, sizeof(errbuf));
msyslog(LOG_INFO, "NTSc: nts_check %s, %d", errbuf, addrOK);
}
if (addrOK) {
dns_take_server(peer, &sockaddr);
dns_take_status(peer, DNS_good);
......@@ -212,8 +194,49 @@ bool nts_check(struct peer *peer) {
return addrOK;
}
SSL_CTX* make_ssl_client_ctx(const char * filename) {
bool ok = true;
SSL_CTX *ctx;
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
ctx = SSL_CTX_new(TLS_client_method());
#else
OpenSSL_add_all_ciphers(); // FIXME needed on NetBSD
ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
if (NULL == ctx) {
/* Happens if no ciphers */
msyslog(LOG_ERR, "NTSc: NULL ctx");
nts_log_ssl_error();
exit(1);
}
#if (OPENSSL_VERSION_NUMBER > 0x1000200fL)
{
// 4., ALPN, RFC 7301
static unsigned char alpn [] = { 7, 'n', 't', 's', 'k', 'e', '/', '1' };
SSL_CTX_set_alpn_protos(ctx, alpn, sizeof(alpn));
}
#endif
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
SSL_CTX_set_timeout(ctx, NTS_KE_TIMEOUT);
ok &= nts_load_versions(ctx);
ok &= nts_load_ciphers(ctx);
ok &= nts_set_cert_search(ctx, filename);
if (!ok) {
msyslog(LOG_ERR, "NTSc: Troubles setting up client SSL CTX");
exit(1);
};
return ctx;
}
int open_TCP_socket(struct peer *peer, const char *hostname) {
char host[256], port[32];
char errbuf[100];
char *tmp;
struct addrinfo hints;
struct addrinfo *answer;
......@@ -257,20 +280,24 @@ int open_TCP_socket(struct peer *peer, const char *hostname) {
msyslog(LOG_INFO, "NTSc: DNS lookup of %s took %.3Lf sec",
hostname, lfptod(finish));
/* Save first answer for NTP */
/* Save first answer for NTP, switch to NTP port in case of server-name:port */
memcpy(&sockaddr, answer->ai_addr, answer->ai_addrlen);
msyslog(LOG_INFO, "NTSc: nts_probe connecting to %s:%s => %s",
host, port, sockporttoa(&sockaddr));
/* switch to NTP port in case of server-name:port */
SET_PORT(&sockaddr, NTP_PORT);
sockporttoa_r(&sockaddr, errbuf, sizeof(errbuf));
msyslog(LOG_INFO, "NTSc: nts_probe connecting to %s:%s => %s",
host, port, errbuf);
sockfd = socket(answer->ai_family, SOCK_STREAM, 0);
if (-1 == sockfd) {
msyslog(LOG_INFO, "NTSc: nts_probe: no socket: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_INFO, "NTSc: nts_probe: no socket: %s", errbuf);
} else {
// Use first answer
err = connect(sockfd, answer->ai_addr, answer->ai_addrlen);
if (-1 == err) {
msyslog(LOG_INFO, "NTSc: nts_probe: connect failed: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_INFO, "NTSc: nts_probe: connect failed: %s", errbuf);
close(sockfd);
sockfd = -1;
}
......@@ -379,6 +406,7 @@ bool nts_make_keys(SSL *ssl, uint16_t aead, uint8_t *c2s, uint8_t *s2c, int keyl
bool nts_client_send_request(SSL *ssl, struct peer* peer) {
uint8_t buff[1000];
char errbuf[100];
int used, transferred;
struct BufCtl_t buf;
uint16_t aead = NO_AEAD;
......@@ -405,8 +433,9 @@ bool nts_client_send_request(SSL *ssl, struct peer* peer) {
used = sizeof(buff)-buf.left;
if (used >= (int)(sizeof(buff)-10)) {
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSc: write failed: %d, %ld, %s",
used, (long)sizeof(buff), strerror(errno));
used, (long)sizeof(buff), errbuf);
return false;
}
......@@ -439,6 +468,7 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
uint16_t type, data, port;
bool critical = false;
int length, keylength;
char errbuf[100];
#define MAX_SERVER 100
char server[MAX_SERVER];
......@@ -510,7 +540,8 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
if (!nts_server_lookup(server, &sockaddr))
return false;
SET_PORT(&sockaddr, port);
msyslog(LOG_ERR, "NTSc: Using server %s=>%s", server, socktoa(&sockaddr));
socktoa_r(&sockaddr, errbuf, sizeof(errbuf));
msyslog(LOG_ERR, "NTSc: Using server %s=>%s", server, errbuf);
break;
case nts_port_negotiation:
// FIXME check length
......@@ -554,29 +585,32 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
return true;
}
bool nts_set_cert_search(SSL_CTX *ctx) {
bool nts_set_cert_search(SSL_CTX *ctx, const char *filename) {
struct stat statbuf;
if (NULL == ntsconfig.ca) {
char errbuf[100];
if (NULL == filename) {
msyslog(LOG_INFO, "NTSc: Using system default root certificates.");
SSL_CTX_set_default_verify_paths(ctx); // Use system root certs
return true;
}
if (0 == stat(ntsconfig.ca, &statbuf)) {
if (0 == stat(filename, &statbuf)) {
if (S_ISDIR(statbuf.st_mode)) {
msyslog(LOG_INFO, "NTSc: Using dir %s for root certificates.", ntsconfig.ca);
SSL_CTX_load_verify_locations(ctx, NULL, ntsconfig.ca);
msyslog(LOG_INFO, "NTSc: Using dir %s for root certificates.", filename);
SSL_CTX_load_verify_locations(ctx, NULL, filename);
return true;
}
if (S_ISREG(statbuf.st_mode)) {
msyslog(LOG_INFO, "NTSc: Using file %s for root certificates.", ntsconfig.ca);
SSL_CTX_load_verify_locations(ctx, ntsconfig.ca, NULL);
msyslog(LOG_INFO, "NTSc: Using file %s for root certificates.", filename);
SSL_CTX_load_verify_locations(ctx, filename, NULL);
return true;
}
msyslog(LOG_ERR, "NTSc: cert dir/file isn't dir or file: %s. mode 0x%x",
ntsconfig.ca, statbuf.st_mode);
filename, statbuf.st_mode);
return false;
}
msyslog(LOG_ERR, "NTSc: can't stat cert dir/file: %s, %s", ntsconfig.ca, strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSc: can't stat cert dir/file: %s, %s",
ntsconfig.ca, errbuf);
return false;
}
......
......@@ -200,16 +200,19 @@ bool nts_write_cookie_keys(void) {
const char *cookie_filename = NTS_COOKIE_KEY_FILE;
int fd;
FILE *out;
char errbuf[100];
if (NULL != ntsconfig.KI)
cookie_filename = ntsconfig.KI;
fd = open(cookie_filename, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
if (-1 == fd) {
msyslog(LOG_ERR, "ERR: can't open %s: %s", cookie_filename, strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "ERR: can't open %s: %s", cookie_filename, errbuf);
return false;
}
out = fdopen(fd, "w");
if (NULL == out) {
msyslog(LOG_ERR, "ERR: can't fdopen %s: %s", cookie_filename, strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "ERR: can't fdopen %s: %s", cookie_filename, errbuf);
close(fd);
return false;
}
......
......@@ -21,6 +21,9 @@
#include "nts.h"
#include "nts2.h"
/* Beware: bind and accept take type sockaddr, but that's not big
* enough for an IPv6 address.
*/
static int create_listener(int port, int family);
static void* nts_ke_listener(void*);
......@@ -87,16 +90,19 @@ bool nts_server_init2(void) {
pthread_t worker;
sigset_t block_mask, saved_sig_mask;
int rc;
char errbuf[100];
sigfillset(&block_mask);
pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask);
rc = pthread_create(&worker, NULL, nts_ke_listener, &listner4_sock);
if (rc) {
msyslog(LOG_ERR, "NTSs: nts_start_server4: error from pthread_create: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: nts_start_server4: error from pthread_create: %s", errbuf);
}
rc = pthread_create(&worker, NULL, nts_ke_listener, &listner6_sock);
if (rc) {
msyslog(LOG_ERR, "NTSs: nts_start_server6: error from pthread_create: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: nts_start_server6: error from pthread_create: %s", errbuf);
}
pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
......@@ -106,6 +112,7 @@ bool nts_server_init2(void) {
void* nts_ke_listener(void* arg) {
struct timeval timeout = {.tv_sec = NTS_KE_TIMEOUT, .tv_usec = 0};
int sock = *(int*)arg;
char errbuf[100];
while(1) {
sockaddr_u addr;
......@@ -116,7 +123,8 @@ void* nts_ke_listener(void* arg) {
client = accept(sock, &addr.sa, &len);
if (client < 0) {
msyslog(LOG_ERR, "NTSs: TCP accept failed: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: TCP accept failed: %s", errbuf);
if (EBADF == errno)
return NULL;
sleep(1); /* avoid log clutter on bug */
......@@ -124,11 +132,13 @@ void* nts_ke_listener(void* arg) {
}
nts_ke_serves++;
get_systime(&start);
msyslog(LOG_INFO, "NTSs: TCP accept-ed from %s",
sockporttoa((sockaddr_u *)&addr));
sockporttoa_r(&addr, errbuf, sizeof(errbuf));
msyslog(LOG_INFO, "NTSs: TCP accept-ed from %s", errbuf);
err = setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't setsockopt: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't setsockopt: %s", errbuf);
close(client);
nts_ke_serves_bad++;
continue;
......@@ -141,8 +151,9 @@ void* nts_ke_listener(void* arg) {
if (SSL_accept(ssl) <= 0) {
get_systime(&finish);
finish -= start;
sockporttoa_r(&addr, errbuf, sizeof(errbuf));
msyslog(LOG_ERR, "NTSs: SSL accept from %s failed, %.3Lf sec",
sockporttoa((sockaddr_u *)&addr), lfptod(finish));
errbuf, lfptod(finish));
nts_log_ssl_error();
SSL_free(ssl);
close(client);
......@@ -219,70 +230,79 @@ bool nts_ke_request(SSL *ssl) {
int create_listener(int port, int family) {
int sock = -1;
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
sockaddr_u addr;
int on = 1;
int err;
char errbuf[100];
switch (family) {
case AF_INET:
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr= htonl(INADDR_ANY);
addr.sa4.sin_family = AF_INET;
addr.sa4.sin_port = htons(port);
addr.sa4.sin_addr.s_addr= htonl(INADDR_ANY);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
msyslog(LOG_ERR, "NTSs: Can't create socket4: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: Can't create socket4: %s", errbuf);
return -1;
}
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't setsockopt4: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't setsockopt4: %s", errbuf);
close(sock);
return -1;
}
err = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
err = bind(sock, &addr.sa, sizeof(addr.sa4));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't bind4: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't bind4: %s", errbuf);
close(sock);
return -1;
}
if (listen(sock, 6) < 0) {
msyslog(LOG_ERR, "NTSs: can't listen4: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't listen4: %s", errbuf);
close(sock);
return -1;
}
msyslog(LOG_INFO, "NTSs: listen4 worked");
break;
case AF_INET6:
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(port);
addr6.sin6_addr = in6addr_any;
addr.sa6.sin6_family = AF_INET6;
addr.sa6.sin6_port = htons(port);
addr.sa6.sin6_addr = in6addr_any;
sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock < 0) {
msyslog(LOG_ERR, "NTSs: Can't create socket6: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: Can't create socket6: %s", errbuf);
return -1;
}
/* Hack to keep IPV6 from listening on IPV4 too */
err = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't setsockopt6only: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't setsockopt6only: %s", errbuf);
close(sock);
return -1;
}
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't setsockopt6: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't setsockopt6: %s", errbuf);
close(sock);
return -1;
}
err = bind(sock, (struct sockaddr*)&addr6, sizeof(addr6));
err = bind(sock, &addr.sa, sizeof(addr.sa6));
if (0 > err) {
msyslog(LOG_ERR, "NTSs: can't bind6: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't bind6: %s", errbuf);
close(sock);
return -1;
}
if (listen(sock, 6) < 0) {
msyslog(LOG_ERR, "NTSs: can't listen6: %s", strerror(errno));
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't listen6: %s", errbuf);
close(sock);
return -1;
}
......
......@@ -519,12 +519,14 @@ gpsd_start(
}
if (-1 == ret ) {
/* more likely out of RAM */
msyslog(LOG_ERR, "REFCLOCK: %s: clock device name too long",
msyslog(LOG_ERR,
"REFCLOCK: %s: clock device name too long",
up->logname);
goto dev_fail;
}
if (-1 == stat(up->device, &sb) || !S_ISCHR(sb.st_mode)) {
msyslog(LOG_ERR, "REFCLOCK: %s: '%s' is not a character device",
msyslog(LOG_ERR,
"REFCLOCK: %s: '%s' is not a character device",
up->logname, up->device);
goto dev_fail;
}
......@@ -554,7 +556,8 @@ gpsd_start(
/* If the daemon name lookup failed, just give up now. */
if (NULL == up->addr) {
msyslog(LOG_ERR, "REFCLOCK: %s: no GPSD socket address, giving up",
msyslog(LOG_ERR,
"REFCLOCK: %s: no GPSD socket address, giving up",
up->logname);
goto dev_fail;
}
......@@ -661,8 +664,7 @@ gpsd_receive(
pdst = up->buffer + up->buflen;
edst = pdst + sizeof(up->buffer) - 1; /* for trailing NUL */
/* FIXME!! Check for overrun of "buffer" */
while (psrc != esrc) {
while (psrc < esrc) {
ch = *psrc++;
if (ch == '\n') {
/* trim trailing whitespace & terminate buffer */
......@@ -673,7 +675,7 @@ gpsd_receive(
up->buflen = (int)(pdst - up->buffer);
gpsd_parse(peer, &rbufp->recv_time);
pdst = up->buffer;
} else if (pdst != edst) {
} else if (pdst < edst) {
/* add next char, ignoring leading whitespace */
if (ch > ' ' || pdst != up->buffer)
*pdst++ = ch;
......@@ -1446,7 +1448,8 @@ process_version(
if (0 == errno) {
if ( ! up->fl_vers)
msyslog(LOG_INFO,
"REFCLOCK: %s: GPSD revision=%s release=%s protocol=%u.%u",
"REFCLOCK: %s: GPSD revision=%s release=%s "
"protocol=%u.%u",
up->logname, revision, release,
pvhi, pvlo);
up->proto_version = PROTO_VERSION(pvhi, pvlo);
......@@ -1495,7 +1498,8 @@ process_version(
* resulting data timeout will take care of the
* connection!
*/
msyslog(LOG_ERR, "REFCLOCK: %s: failed to write watch request (%s)",
msyslog(LOG_ERR,
"REFCLOCK: %s: failed to write watch request (%s)",
up->logname, strerror(errno));
}
}
......@@ -1853,7 +1857,8 @@ gpsd_init_socket(
if (-1 == rc) {
if (syslogok(pp, up))
msyslog(LOG_ERR,
"REFCLOCK: %s: cannot set GPSD socket to non-blocking: %s",
"REFCLOCK: %s: cannot set GPSD socket "
"to non-blocking: %s",
up->logname, strerror(errno));
goto no_socket;
}
......@@ -1904,7 +1909,8 @@ gpsd_init_socket(
if (0 == io_addclock(&pp->io)) {
if (syslogok(pp, up))
msyslog(LOG_ERR,
"REFCLOCK: %s: failed to register with I/O engine",
"REFCLOCK: %s: failed to register "
"with I/O engine",
up->logname);
goto no_socket;
}
......@@ -1986,8 +1992,8 @@ gpsd_test_socket(
if (0 == io_addclock(&pp->io)) {
if (syslogok(pp, up))
msyslog(LOG_ERR,
"REFCLOCK: %s: failed to register with I/O engine",
up->logname);
"REFCLOCK: %s: failed to register with I/O engine",
up->logname);
goto no_socket;
}
return;
......
......@@ -79,6 +79,7 @@ static void RunAllTests(void)
int main(int argc, const char * argv[]) {
getbuf_init();
ssl_init();
auth_init();
init_network();
......