#define RETRANSMISSION_TIMEOUT (1.0)
-typedef struct { unsigned long ip_addr;
+typedef struct {
+ IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source
looks sane or not */
int n_dead_probes; /* Number of probes sent to the server
static int init_slew_threshold = -1;
-static int sock_fd = -1;
+union sockaddr_in46 {
+ struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr u;
+};
+
+static int sock_fd4 = -1;
+#ifdef HAVE_IPV6
+static int sock_fd6 = -1;
+#endif
/* ================================================== */
/* ================================================== */
-static void
-initialise_io(void)
+static int
+prepare_socket(int family)
{
unsigned short port_number = CNF_GetAcquisitionPort();
+ int sock_fd;
- sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) {
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
/* Don't bother binding this socket - we're not fussed what port
number it gets */
} else {
- struct sockaddr_in my_addr;
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(port_number);
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+ union sockaddr_in46 my_addr;
+
+ memset(&my_addr, 0, sizeof (my_addr));
+
+ switch (family) {
+ case AF_INET:
+ my_addr.in4.sin_family = family;
+ my_addr.in4.sin_port = htons(port_number);
+ my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ my_addr.in6.sin6_family = family;
+ my_addr.in6.sin6_port = htons(port_number);
+ my_addr.in6.sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ assert(0);
+ }
+
+ if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
/* but keep running */
}
}
- SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
+ SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
+ return sock_fd;
+}
+/* ================================================== */
+
+static void
+initialise_io(int family)
+{
+ if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
+ sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+ if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
+ sock_fd6 = prepare_socket(AF_INET6);
+#endif
}
/* ================================================== */
static void
finalise_io(void)
{
- if (sock_fd >= 0) {
- SCH_RemoveInputFileHandler(sock_fd);
- close(sock_fd);
+ if (sock_fd4 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd4);
+ close(sock_fd4);
+ }
+ sock_fd4 = -1;
+#ifdef HAVE_IPV6
+ if (sock_fd6 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd6);
+ close(sock_fd6);
}
+ sock_fd6 = -1;
+#endif
return;
}
NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked;
double local_time_err;
- struct sockaddr_in his_addr;
+ union sockaddr_in46 his_addr;
+ int sock_fd;
#if 0
- printf("Sending probe to %08lx sent=%d samples=%d\n", src->ip_addr, src->n_probes_sent, src->n_samples);
+ printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
#endif
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
pkt.receive_ts.lo = 0; /* Set to 0 */
/* And do transmission */
- his_addr.sin_addr.s_addr = htonl(src->ip_addr);
- his_addr.sin_port = htons(123); /* Fixed for now */
- his_addr.sin_family = AF_INET;
+
+ memset(&his_addr, 0, sizeof (his_addr));
+ switch (src->ip_addr.family) {
+ case IPADDR_INET4:
+ his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
+ his_addr.in4.sin_port = htons(123); /* Fixed for now */
+ his_addr.in4.sin_family = AF_INET;
+ sock_fd = sock_fd4;
+ break;
+#ifdef HAVE_IPV6
+ case IPADDR_INET6:
+ memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
+ sizeof (his_addr.in6.sin6_addr.s6_addr));
+ his_addr.in6.sin6_port = htons(123); /* Fixed for now */
+ his_addr.in6.sin6_family = AF_INET6;
+ sock_fd = sock_fd6;
+ break;
+#endif
+ default:
+ assert(0);
+ }
+
LCL_ReadCookedTime(&cooked, &local_time_err);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
0,
- (struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) {
+ &his_addr.u, sizeof(his_addr)) < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
- UTI_IPToDottedQuad(src->ip_addr),
+ UTI_IPToString(&src->ip_addr),
strerror(errno));
}
src->timer_running = 0;
#if 0
- printf("Timeout expired for server %08lx\n", src->ip_addr);
+ printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
#endif
if (src->n_dead_probes < MAX_DEAD_PROBES) {
{
int status;
ReceiveBuffer msg;
- struct sockaddr_in his_addr;
+ union sockaddr_in46 his_addr;
+ int sock_fd;
socklen_t his_addr_len;
int flags;
int message_length;
- unsigned long remote_ip;
+ IPAddr remote_ip;
int i, ok;
struct timeval now;
double local_time_err;
/* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err);
+ sock_fd = (long)anything;
status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
- (struct sockaddr *) &his_addr, &his_addr_len);
+ &his_addr.u, &his_addr_len);
if (status < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
return;
}
- remote_ip = ntohl(his_addr.sin_addr.s_addr);
+ switch (his_addr.u.sa_family) {
+ case AF_INET:
+ remote_ip.family = IPADDR_INET4;
+ remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ remote_ip.family = IPADDR_INET6;
+ memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
+ sizeof (remote_ip.addr.in6));
+ break;
+#endif
+ default:
+ assert(0);
+ }
#if 0
- printf("Got message from %08lx\n", remote_ip);
+ printf("Got message from %s\n", UTI_IPToString(&remote_ip));
#endif
/* Find matching host */
ok = 0;
for (i=0; i<n_sources; i++) {
- if (remote_ip == sources[i].ip_addr) {
+ if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
ok = 1;
break;
}
(src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources;
#if 0
- printf("Source %08lx completed\n", src->ip_addr);
+ printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
#endif
if (n_completed_sources == n_sources) {
wind_up_acquisition();
{
probe_source(sources + n_started_sources);
#if 0
- printf("Trying to start source %08lx\n", sources[n_started_sources].ip_addr);
+ printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
#endif
n_started_sources++;
for (i=0; i<2*n_sane_sources; i++) {
#if 0
- fprintf(stderr, "Endpoint type %s source index %d [ip=%08lx] offset=%.6f\n",
+ fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
(eps[i].type == LO) ? "LO" : "HIGH",
eps[i].index,
- sources[eps[i].index].ip_addr,
+ UTI_IPToString(&sources[eps[i].index].ip_addr),
eps[i].offset);
#endif
/* ================================================== */
void
-ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
+ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
{
- int i;
+ int i, ip4, ip6;
saved_after_hook = after_hook;
saved_after_hook_anything = anything;
n_sources = n;
sources = MallocArray(SourceRecord, n);
- for (i=0; i<n; i++) {
+ for (i = ip4 = ip6 = 0; i < n; i++) {
sources[i].ip_addr = ip_addrs[i];
sources[i].n_samples = 0;
sources[i].n_total_samples = 0;
sources[i].n_dead_probes = 0;
+ if (ip_addrs[i].family == IPADDR_INET4)
+ ip4++;
+ else if (ip_addrs[i].family == IPADDR_INET6)
+ ip6++;
}
- initialise_io();
+ initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
/* Start sampling first source */
start_next_source();
#ifndef GOT_ACQUIRE_H
#define GOT_ACQUIRE_H
+#include "addressing.h"
+
typedef struct ACQ_SourceRecord *ACQ_Source;
extern void ACQ_Initialise(void);
extern void ACQ_Finalise(void);
-extern void ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int init_slew_threshold,
+extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold,
void (*after_hook)(void *), void *anything);
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);
#ifndef GOT_ADDRESSING_H
#define GOT_ADDRESSING_H
-/* This type is used to represent an IPv4 address and port
- number. Both parts are in HOST order, NOT network order. */
+#include "sysincl.h"
+
+/* This type is used to represent an IPv4 address or IPv6 address.
+ All parts are in HOST order, NOT network order. */
+
+#define IPADDR_UNSPEC 0
+#define IPADDR_INET4 1
+#define IPADDR_INET6 2
+
typedef struct {
- unsigned long ip_addr;
- unsigned long local_ip_addr;
+ union {
+ uint32_t in4;
+ uint8_t in6[16];
+ } addr;
+ uint16_t family;
+} IPAddr;
+
+typedef struct {
+ IPAddr ip_addr;
+ IPAddr local_ip_addr;
unsigned short port;
} NTP_Remote_Address;
-#if 0
-unsigned long NTP_IP_Address;
-#endif
-
#endif /* GOT_ADDRESSING_H */
} TableNode;
struct ADF_AuthTableInst {
- TableNode base;
+ TableNode base4; /* IPv4 node */
+ TableNode base6; /* IPv6 node */
};
/* ================================================== */
-inline static unsigned long
-get_subnet(unsigned long addr)
+static void
+split_ip6(IPAddr *ip, uint32_t *dst)
{
- return (addr >> (32-NBITS)) & ((1UL<<NBITS) - 1);
+ int i;
+
+ for (i = 0; i < 4; i++)
+ dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
+ ip->addr.in6[i * 4 + 1] << 16 |
+ ip->addr.in6[i * 4 + 2] << 8 |
+ ip->addr.in6[i * 4 + 3];
}
/* ================================================== */
-inline static unsigned long
-get_residual(unsigned long addr)
+inline static uint32_t
+get_subnet(uint32_t *addr, unsigned int where)
{
- return (addr << NBITS);
+ int off;
+
+ off = where / 32;
+ where %= 32;
+
+ return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
}
/* ================================================== */
result = MallocNew(struct ADF_AuthTableInst);
/* Default is that nothing is allowed */
- result->base.state = DENY;
- result->base.extended = NULL;
+ result->base4.state = DENY;
+ result->base4.extended = NULL;
+ result->base6.state = DENY;
+ result->base6.extended = NULL;
return result;
}
static ADF_Status
set_subnet(TableNode *start_node,
- unsigned long ip,
+ uint32_t *ip,
+ int ip_len,
int subnet_bits,
State new_state,
int delete_children)
{
- int bits_to_go;
- unsigned long residual;
- unsigned long subnet;
+ int bits_to_go, bits_consumed;
+ uint32_t subnet;
TableNode *node;
+ bits_consumed = 0;
bits_to_go = subnet_bits;
- residual = ip;
node = start_node;
if ((subnet_bits < 0) ||
- (subnet_bits > 32)) {
+ (subnet_bits > 32 * ip_len)) {
return ADF_BADSUBNET;
if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) {
- subnet = get_subnet(residual);
- residual = get_residual(residual);
+ subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
+ bits_consumed += NBITS;
}
if (delete_children) {
TableNode *this_node;
while (bits_to_go >= NBITS) {
- subnet = get_subnet(residual);
- residual = get_residual(residual);
+ subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
+ bits_consumed += NBITS;
}
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go);
- subnet = get_subnet(residual);
+ subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
/* ================================================== */
+static ADF_Status
+set_subnet_(ADF_AuthTable table,
+ IPAddr *ip_addr,
+ int subnet_bits,
+ State new_state,
+ int delete_children)
+{
+ uint32_t ip6[4];
+
+ switch (ip_addr->family) {
+ case IPADDR_INET4:
+ return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children);
+ case IPADDR_INET6:
+ split_ip6(ip_addr, ip6);
+ return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children);
+ case IPADDR_UNSPEC:
+ /* Apply to both, subnet_bits has to be 0 */
+ if (subnet_bits != 0)
+ return ADF_BADSUBNET;
+ memset(ip6, 0, sizeof (ip6));
+ if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS &&
+ set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS)
+ return ADF_SUCCESS;
+ break;
+ }
+
+ return ADF_BADSUBNET;
+}
+
ADF_Status
ADF_Allow(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits)
{
- return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 0);
+ return set_subnet_(table, ip, subnet_bits, ALLOW, 0);
}
/* ================================================== */
ADF_Status
ADF_AllowAll(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits)
{
- return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 1);
+ return set_subnet_(table, ip, subnet_bits, ALLOW, 1);
}
/* ================================================== */
ADF_Status
ADF_Deny(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits)
{
- return set_subnet(&(table->base), ip, subnet_bits, DENY, 0);
+ return set_subnet_(table, ip, subnet_bits, DENY, 0);
}
/* ================================================== */
ADF_Status
ADF_DenyAll(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits)
{
- return set_subnet(&(table->base), ip, subnet_bits, DENY, 1);
+ return set_subnet_(table, ip, subnet_bits, DENY, 1);
}
/* ================================================== */
void
ADF_DestroyTable(ADF_AuthTable table)
{
- close_node(&(table->base));
+ close_node(&table->base4);
+ close_node(&table->base6);
Free(table);
}
/* ================================================== */
static int
-check_ip_in_node(TableNode *start_node, unsigned long ip)
+check_ip_in_node(TableNode *start_node, uint32_t *ip)
{
- unsigned long residual, subnet;
+ uint32_t subnet;
+ int bits_consumed = 0;
int result = 0;
int finished = 0;
TableNode *node;
State state=DENY;
node = start_node;
- residual = ip;
do {
if (node->state != AS_PARENT) {
state = node->state;
}
if (node->extended) {
- subnet = get_subnet(residual);
- residual = get_residual(residual);
+ subnet = get_subnet(ip, bits_consumed);
node = &(node->extended[subnet]);
+ bits_consumed += NBITS;
} else {
/* Make decision on this node */
finished = 1;
int
ADF_IsAllowed(ADF_AuthTable table,
- unsigned long ip)
+ IPAddr *ip_addr)
{
+ uint32_t ip6[4];
+
+ switch (ip_addr->family) {
+ case IPADDR_INET4:
+ return check_ip_in_node(&table->base4, &ip_addr->addr.in4);
+ case IPADDR_INET6:
+ split_ip6(ip_addr, ip6);
+ return check_ip_in_node(&table->base6, ip6);
+ }
- return check_ip_in_node(&(table->base), ip);
-
+ return 0;
}
/* ================================================== */
#if defined TEST
-static void print_node(TableNode *node, unsigned long addr, int shift, int subnet_bits)
+static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
{
- unsigned long new_addr;
+ uint32_t new_addr[4];
int i;
TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' ');
- printf("%d.%d.%d.%d/%d : %s\n",
- ((addr >> 24) & 255),
- ((addr >> 16) & 255),
- ((addr >> 8) & 255),
- ((addr ) & 255),
+ if (ip_len == 1)
+ printf("%d.%d.%d.%d",
+ ((addr[0] >> 24) & 255),
+ ((addr[0] >> 16) & 255),
+ ((addr[0] >> 8) & 255),
+ ((addr[0] ) & 255));
+ else {
+ for (i=0; i<4; i++) {
+ if (addr[i])
+ printf("%d.%d.%d.%d",
+ ((addr[i] >> 24) & 255),
+ ((addr[i] >> 16) & 255),
+ ((addr[i] >> 8) & 255),
+ ((addr[i] ) & 255));
+ putchar(i < 3 ? ':' : '\0');
+ }
+ }
+ printf("/%d : %s\n",
subnet_bits,
(node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent");
if (node->extended) {
for (i=0; i<16; i++) {
- sub_node = &((*(node->extended))[i]);
- new_addr = addr | ((unsigned long) i << shift);
- print_node(sub_node, new_addr, shift - 4, subnet_bits + 4);
+ sub_node = &(node->extended[i]);
+ new_addr[0] = addr[0];
+ new_addr[1] = addr[1];
+ new_addr[2] = addr[2];
+ new_addr[3] = addr[3];
+ new_addr[ip_len - 1 - shift / 32] |= ((uint32_t)i << (shift % 32));
+ print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
}
}
return;
static void print_table(ADF_AuthTable table)
{
- unsigned long addr = 0;
- int shift = 28;
- int subnet_bits = 0;
+ uint32_t addr[4];
+
+ memset(addr, 0, sizeof (addr));
+ printf("IPv4 table:\n");
+ print_node(&table->base4, addr, 1, 28, 0);
- print_node(&table->base, addr, shift, subnet_bits);
+ memset(addr, 0, sizeof (addr));
+ printf("IPv6 table:\n");
+ print_node(&table->base6, addr, 4, 124, 0);
return;
}
int main (int argc, char **argv)
{
+ IPAddr ip;
ADF_AuthTable table;
table = ADF_CreateTable();
- ADF_Allow(table, 0x7e800000, 9);
- ADF_Deny(table, 0x7ecc0000, 14);
- /* ADF_Deny(table, 0x7f000001, 32); */
- /* ADF_Allow(table, 0x7f000000, 8); */
+ ip.family = IPADDR_INET4;
+
+ ip.addr.in4 = 0x7e800000;
+ ADF_Allow(table, &ip, 9);
+ ip.addr.in4 = 0x7ecc0000;
+ ADF_Deny(table, &ip, 14);
+#if 0
+ ip.addr.in4 = 0x7f000001;
+ ADF_Deny(table, &ip, 32);
+ ip.addr.in4 = 0x7f000000;
+ ADF_Allow(table, &ip, 8);
+#endif
+
+ printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+ ip.addr.in4 ^= 1;
+ printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+
+ ip.family = IPADDR_INET6;
+
+ memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
+ ADF_Deny(table, &ip, 66);
+ ADF_Allow(table, &ip, 59);
+
+ memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
+ ADF_Deny(table, &ip, 128);
+ ip.addr.in6[15] ^= 3;
+ ADF_Allow(table, &ip, 127);
+
+ printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+ ip.addr.in4 ^= 1;
+ printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
print_table(table);
#ifndef GOT_ADDRFILT_H
#define GOT_ADDRFILT_H
+#include "addressing.h"
+
typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum {
/* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
- unsigned long ip,
+ IPAddr *ip,
int subnet_bits);
/* Clear up the table */
/* Check whether a given IP address is allowed by the rules in
the table */
extern int ADF_IsAllowed(ADF_AuthTable table,
- unsigned long ip);
+ IPAddr *ip);
#endif /* GOT_ADDRFILT_H */
/* ================================================== */
void
-BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
+BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
{
if (max_destinations == n_destinations) {
/* Expand array */
}
}
- destinations[n_destinations].addr.ip_addr = addr;
- destinations[n_destinations].addr.local_ip_addr = 0;
+ destinations[n_destinations].addr.ip_addr = *addr;
+ destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval;
#ifndef GOT_BROADCAST_H
#define GOT_BROADCAST_H
+#include "addressing.h"
+
extern void BRD_Initialise(void);
extern void BRD_Finalise(void);
-extern void BRD_AddDestination(unsigned long addr, unsigned short port, int interval);
+extern void BRD_AddDestination(IPAddr *addr, unsigned short port, int interval);
#endif /* GOT_BROADCAST_H */
#define GOT_CANDM_H
#include "sysincl.h"
+#include "addressing.h"
/* This is the default port to use for CANDM, if no alternative is
defined */
transmitted for each packet type. */
typedef struct {
- uint32_t mask;
- uint32_t address;
+ IPAddr mask;
+ IPAddr address;
int32_t EOR;
} REQ_Online;
typedef struct {
- uint32_t mask;
- uint32_t address;
+ IPAddr mask;
+ IPAddr address;
int32_t EOR;
} REQ_Offline;
typedef struct {
- uint32_t mask;
- uint32_t address;
+ IPAddr mask;
+ IPAddr address;
int32_t n_good_samples;
int32_t n_total_samples;
int32_t EOR;
} REQ_Burst;
typedef struct {
- uint32_t address;
+ IPAddr address;
int32_t new_minpoll;
int32_t EOR;
} REQ_Modify_Minpoll;
typedef struct {
- uint32_t address;
+ IPAddr address;
int32_t new_maxpoll;
int32_t EOR;
} REQ_Modify_Maxpoll;
} REQ_Dump;
typedef struct {
- uint32_t address;
+ IPAddr address;
int32_t new_max_delay;
int32_t EOR;
} REQ_Modify_Maxdelay;
typedef struct {
- uint32_t address;
+ IPAddr address;
int32_t new_max_delay_ratio;
int32_t EOR;
} REQ_Modify_Maxdelayratio;
} REQ_Rekey;
typedef struct {
- uint32_t ip;
+ IPAddr ip;
int32_t subnet_bits;
int32_t EOR;
} REQ_Allow_Deny;
typedef struct {
- uint32_t ip;
+ IPAddr ip;
int32_t EOR;
} REQ_Ac_Check;
typedef struct {
- uint32_t ip_addr;
+ IPAddr ip_addr;
uint32_t port;
int32_t minpoll;
int32_t maxpoll;
} REQ_NTP_Source;
typedef struct {
- uint32_t ip_addr;
+ IPAddr ip_addr;
int32_t EOR;
} REQ_Del_Source;
} REQ_CycleLogs;
typedef struct {
- uint32_t ip;
+ IPAddr ip;
uint32_t bits_specd;
} REQ_SubnetsAccessed_Subnet;
/* This is based on the response size rather than the
request size */
-#define MAX_CLIENT_ACCESSES 16
+#define MAX_CLIENT_ACCESSES 8
typedef struct {
uint32_t n_clients;
- uint32_t client_ips[MAX_CLIENT_ACCESSES];
+ IPAddr client_ips[MAX_CLIENT_ACCESSES];
} REQ_ClientAccesses;
typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline)
+ Version 4 : IPv6 addressing added
+
*/
-#define PROTO_VERSION_NUMBER 3
+#define PROTO_VERSION_NUMBER 4
/* ================================================== */
#define STT_BADRTCFILE 14
#define STT_INACTIVE 15
#define STT_BADSAMPLE 16
+#define STT_INVALIDAF 17
typedef struct {
int32_t EOR;
#define RPY_SD_ST_OTHER 4
typedef struct {
- uint32_t ip_addr;
+ IPAddr ip_addr;
uint16_t poll;
uint16_t stratum;
uint16_t state;
} RPY_Tracking;
typedef struct {
- uint32_t ip_addr;
+ IPAddr ip_addr;
uint32_t n_samples;
uint32_t n_runs;
uint32_t span_seconds;
} RPY_ManualTimestamp;
typedef struct {
- uint32_t ip;
+ IPAddr ip;
uint32_t bits_specd;
uint32_t bitmap[8];
} RPY_SubnetsAccessed_Subnet;
} RPY_SubnetsAccessed;
typedef struct {
- uint32_t ip;
+ IPAddr ip;
uint32_t client_hits;
uint32_t peer_hits;
uint32_t cmd_hits_auth;
/* ================================================== */
+union sockaddr_in46 {
+ struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr u;
+};
+
static int sock_fd;
-struct sockaddr_in his_addr;
+union sockaddr_in46 his_addr;
static int on_terminal = 0;
}
/* ================================================== */
+/* Initialise the socket used to talk to the daemon */
-static unsigned long
-get_address(const char *hostname)
+static void
+open_io(const char *hostname, int port)
{
- char *address0;
- struct hostent *host;
- unsigned long result;
+ union sockaddr_in46 my_addr;
+ IPAddr ip;
/* Note, this call could block for a while */
- host = gethostbyname(hostname);
- if (host == NULL) {
+ if (!DNS_Name2IPAddress(hostname, &ip, 0)) {
fprintf(stderr, "Could not get IP address for %s\n", hostname);
exit(1);
- } else {
- address0 = host->h_addr_list[0];
- result = ((((unsigned long) address0[0] & 0xff) << 24) |
- (((unsigned long) address0[1] & 0xff) << 16) |
- (((unsigned long) address0[2] & 0xff) << 8) |
- (((unsigned long) address0[3] & 0xff)));
}
- return result;
+ memset(&my_addr, 0, sizeof (my_addr));
+ memset(&his_addr, 0, sizeof (his_addr));
-}
+ switch (ip.family) {
+ case IPADDR_INET4:
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
-/* ================================================== */
-/* Initialise the socket used to talk to the daemon */
+ my_addr.in4.sin_family = AF_INET;
+ my_addr.in4.sin_port = htons(INADDR_ANY);
+ my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
-static void
-open_io(const char *hostname, int port)
-{
- struct sockaddr_in my_addr;
+ his_addr.in4.sin_family = AF_INET;
+ his_addr.in4.sin_addr.s_addr = htonl(ip.addr.in4);
+ his_addr.in4.sin_port = htons(port);
+ break;
+#ifdef HAVE_IPV6
+ case IPADDR_INET6:
+ sock_fd = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ my_addr.in6.sin6_family = AF_INET6;
+ my_addr.in6.sin6_port = htons(INADDR_ANY);
+ my_addr.in6.sin6_addr = in6addr_any;
+
+ his_addr.in6.sin6_family = AF_INET6;
+ memcpy(his_addr.in6.sin6_addr.s6_addr, ip.addr.in6,
+ sizeof (his_addr.in6.sin6_addr.s6_addr));
+ his_addr.in6.sin6_port = htons(port);
+ break;
+#endif
+ default:
+ assert(0);
+ }
- sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
perror("Can't create socket");
exit(1);
}
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(INADDR_ANY);
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if(bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+ if(bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
perror("Can't bind socket");
exit(1);
}
- /* Build the socket address structure for sending packets */
- his_addr.sin_family = AF_INET;
- his_addr.sin_addr.s_addr = htonl(get_address(hostname));
-
- /* Eventually the port number needs to be a command line param */
- his_addr.sin_port = htons(port);
-
return;
}
/* ================================================== */
+static void
+bits_to_mask(int bits, int family, IPAddr *mask)
+{
+ int i;
+
+ mask->family = family;
+ switch (family) {
+ case IPADDR_INET4:
+ if (bits < 0)
+ bits = 32;
+ if (bits > 0) {
+ mask->addr.in4 = -1;
+ mask->addr.in4 <<= 32 - bits;
+ } else {
+ mask->addr.in4 = 0;
+ }
+ break;
+ case IPADDR_INET6:
+ if (bits > 128 || bits < 0)
+ bits = 128;
+ for (i = 0; i < bits / 8; i++)
+ mask->addr.in6[i] = 0xff;
+ if (i < 16)
+ mask->addr.in6[i++] = (0xff << (8 - bits % 8)) & 0xff;
+ for (; i < 16; i++)
+ mask->addr.in6[i] = 0x0;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+/* ================================================== */
+
static int
-read_mask_address(char *line, unsigned long *mask, unsigned long *address)
+read_mask_address(char *line, IPAddr *mask, IPAddr *address)
{
- unsigned int ma, mb, mc, md, aa, ab, ac, ad;
- int ok = 0;
- char *p;
+ unsigned int bits;
+ char *p, *q;
p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) {
- *mask = *address = 0;
- ok = 1;
+ mask->family = address->family = IPADDR_UNSPEC;
+ return 1;
} else {
-
- if (sscanf(line, "%u.%u.%u.%u/%u.%u.%u.%u",
- &ma, &mb, &mc, &md,
- &aa, &ab, &ac, &ad) != 8) {
- fprintf(stderr, "Invalid syntax for mask/address\n");
- ok = 0;
+ q = strchr(p, '/');
+ if (q) {
+ *q++ = 0;
+ if (UTI_StringToIP(p, mask)) {
+ p = q;
+ while (*q && !isspace((unsigned char)*q)) q++;
+ *q = 0;
+ if (UTI_StringToIP(p, address)) {
+ if (address->family == mask->family)
+ return 1;
+ } else if (sscanf(p, "%u", &bits) == 1) {
+ *address = *mask;
+ bits_to_mask(bits, address->family, mask);
+ return 1;
+ }
+ }
} else {
- *mask = (ma << 24) | (mb << 16) | (mc << 8) | md;
- *address = (aa << 24) | (ab << 16) | (ac << 8) | ad;
- ok = 1;
+ if (UTI_StringToIP(p, address)) {
+ bits_to_mask(-1, address->family, mask);
+ return 1;
+ }
}
}
- return ok;
-
+ fprintf(stderr, "Invalid syntax for mask/address\n");
+ return 0;
}
/* ================================================== */
static int
process_cmd_offline(CMD_Request *msg, char *line)
{
- unsigned long mask, address;
+ IPAddr mask, address;
int ok;
if (read_mask_address(line, &mask, &address)) {
- msg->data.offline.mask = htonl(mask);
- msg->data.offline.address = htonl(address);
+ UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
+ UTI_IPHostToNetwork(&address, &msg->data.offline.address);
msg->command = htons(REQ_OFFLINE);
ok = 1;
} else {
static int
process_cmd_online(CMD_Request *msg, char *line)
{
- unsigned long mask, address;
+ IPAddr mask, address;
int ok;
if (read_mask_address(line, &mask, &address)) {
- msg->data.online.mask = htonl(mask);
- msg->data.online.address = htonl(address);
+ UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
+ UTI_IPHostToNetwork(&address, &msg->data.online.address);
msg->command = htons(REQ_ONLINE);
ok = 1;
} else {
/* ================================================== */
static int
-read_address_integer(char *line, unsigned long *address, int *value)
+read_address_integer(char *line, IPAddr *address, int *value)
{
char hostname[2048];
int ok = 0;
fprintf(stderr, "Invalid syntax for address value\n");
ok = 0;
} else {
- *address = DNS_Name2IPAddress(hostname);
- if (*address == DNS_Failed_Address) {
+ if (!DNS_Name2IPAddress(hostname, address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
/* ================================================== */
static int
-read_address_double(char *line, unsigned long *address, double *value)
+read_address_double(char *line, IPAddr *address, double *value)
{
char hostname[2048];
int ok = 0;
fprintf(stderr, "Invalid syntax for address value\n");
ok = 0;
} else {
- *address = DNS_Name2IPAddress(hostname);
- if (*address == DNS_Failed_Address) {
+ if (!DNS_Name2IPAddress(hostname, address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
static int
process_cmd_minpoll(CMD_Request *msg, char *line)
{
- unsigned long address;
+ IPAddr address;
int minpoll;
int ok;
if (read_address_integer(line, &address, &minpoll)) {
- msg->data.modify_minpoll.address = htonl(address);
+ UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address);
msg->data.modify_minpoll.new_minpoll = htonl(minpoll);
msg->command = htons(REQ_MODIFY_MINPOLL);
ok = 1;
static int
process_cmd_maxpoll(CMD_Request *msg, char *line)
{
- unsigned long address;
+ IPAddr address;
int maxpoll;
int ok;
if (read_address_integer(line, &address, &maxpoll)) {
- msg->data.modify_maxpoll.address = htonl(address);
+ UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address);
msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll);
msg->command = htons(REQ_MODIFY_MAXPOLL);
ok = 1;
static int
process_cmd_maxdelay(CMD_Request *msg, char *line)
{
- unsigned long address;
+ IPAddr address;
double max_delay;
int ok;
if (read_address_double(line, &address, &max_delay)) {
- msg->data.modify_maxdelay.address = htonl(address);
+ UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay);
msg->command = htons(REQ_MODIFY_MAXDELAY);
ok = 1;
static int
process_cmd_maxdelayratio(CMD_Request *msg, char *line)
{
- unsigned long address;
+ IPAddr address;
double max_delay_ratio;
int ok;
if (read_address_double(line, &address, &max_delay_ratio)) {
- msg->data.modify_maxdelayratio.address = htonl(address);
+ UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio);
msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
ok = 1;
static int
process_cmd_burst(CMD_Request *msg, char *line)
{
- int ok;
int n_good_samples, n_total_samples;
- unsigned int ma, mb, mc, md, aa, ab, ac, ad;
int n_parsed;
+ char s[101];
+ IPAddr address, mask;
- n_parsed = sscanf(line, "%d/%d %u.%u.%u.%u/%u.%u.%u.%u",
- &n_good_samples,
- &n_total_samples,
- &ma, &mb, &mc, &md,
- &aa, &ab, &ac, &ad);
+ n_parsed = sscanf(line, "%d/%d %100s", &n_good_samples, &n_total_samples, s);
msg->command = htons(REQ_BURST);
msg->data.burst.n_good_samples = ntohl(n_good_samples);
msg->data.burst.n_total_samples = ntohl(n_total_samples);
- if (n_parsed == 10) {
- msg->data.burst.mask = htonl((ma << 24) | (mb << 16) | (mc << 8) | md);
- msg->data.burst.address = htonl((aa << 24) | (ab << 16) | (ac << 8) | ad);
- ok = 1;
- } else if (n_parsed == 2) {
- msg->data.burst.mask = 0;
- msg->data.burst.address = 0;
- ok = 1;
- } else {
- ok = 0;
+ mask.family = address.family = IPADDR_UNSPEC;
+
+ if (n_parsed < 2 || (n_parsed == 3 && !read_mask_address(s, &mask, &address))) {
fprintf(stderr, "Invalid syntax for burst command\n");
+ return 0;
}
- return ok;
+ UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
+ UTI_IPHostToNetwork(&address, &msg->data.burst.address);
+ return 1;
}
/* ================================================== */
static int
parse_allow_deny(CMD_Request *msg, char *line)
{
- unsigned long a, b, c, d, n, ip;
+ unsigned long a, b, c, d, n;
+ IPAddr ip;
char *p, *q;
p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) {
/* blank line - applies to all addresses */
- msg->data.allow_deny.ip = htonl(0);
+ ip.family = IPADDR_UNSPEC;
+ UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
msg->data.allow_deny.subnet_bits = htonl(0);
} else {
char *slashpos;
slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0;
- n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
+ n = 0;
+ if (!UTI_StringToIP(p, &ip) &&
+ (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {
- if (n == 0) {
/* Try to parse as the name of a machine */
q = p;
while (*q) {
if (*q == '\n') *q = 0;
q++;
}
- ip = DNS_Name2IPAddress(p);
- if (ip == DNS_Failed_Address) {
+ if (!DNS_Name2IPAddress(p, &ip, 0)) {
fprintf(stderr, "Could not read address\n");
return 0;
} else {
- msg->data.allow_deny.ip = htonl(ip);
- msg->data.allow_deny.subnet_bits = htonl(32);
+ UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
+ if (ip.family == IPADDR_INET6)
+ msg->data.allow_deny.subnet_bits = htonl(128);
+ else
+ msg->data.allow_deny.subnet_bits = htonl(32);
}
} else {
- a &= 0xff;
- b &= 0xff;
- c &= 0xff;
- d &= 0xff;
-
- switch (n) {
- case 1:
- msg->data.allow_deny.ip = htonl((a<<24));
- msg->data.allow_deny.subnet_bits = htonl(8);
- break;
- case 2:
- msg->data.allow_deny.ip = htonl((a<<24) | (b<<16));
- msg->data.allow_deny.subnet_bits = htonl(16);
- break;
- case 3:
- msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8));
- msg->data.allow_deny.subnet_bits = htonl(24);
- break;
- case 4:
- msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8) | d);
+ if (n == 0) {
+ if (ip.family == IPADDR_INET6)
+ msg->data.allow_deny.subnet_bits = htonl(128);
+ else
msg->data.allow_deny.subnet_bits = htonl(32);
- break;
- default:
- assert(0);
-
+ } else {
+ ip.family = IPADDR_INET4;
+
+ a &= 0xff;
+ b &= 0xff;
+ c &= 0xff;
+ d &= 0xff;
+
+ switch (n) {
+ case 1:
+ ip.addr.in4 = htonl((a<<24));
+ msg->data.allow_deny.subnet_bits = htonl(8);
+ break;
+ case 2:
+ ip.addr.in4 = htonl((a<<24) | (b<<16));
+ msg->data.allow_deny.subnet_bits = htonl(16);
+ break;
+ case 3:
+ ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8));
+ msg->data.allow_deny.subnet_bits = htonl(24);
+ break;
+ case 4:
+ ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8) | d);
+ msg->data.allow_deny.subnet_bits = htonl(32);
+ break;
+ default:
+ assert(0);
+ }
}
+ UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
+
if (slashpos) {
int specified_subnet_bits, n;
n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
/* ================================================== */
static int
-accheck_getaddr(char *line, unsigned long *addr)
+accheck_getaddr(char *line, IPAddr *addr)
{
- unsigned long a, b, c, d, ip;
+ unsigned long a, b, c, d;
+ IPAddr ip;
char *p, *q;
p = line;
while (*p && isspace(*p)) p++;
return 0;
} else {
if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) {
- *addr = (a<<24) | (b<<16) | (c<<8) | d;
+ addr->family = IPADDR_INET4;
+ addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
return 1;
} else {
q = p;
if (*q == '\n') *q = 0;
q++;
}
- ip = DNS_Name2IPAddress(p);
- if (ip == DNS_Failed_Address) {
+ if (!DNS_Name2IPAddress(p, &ip, 0)) {
return 0;
} else {
*addr = ip;
static int
process_cmd_accheck(CMD_Request *msg, char *line)
{
- unsigned long ip;
+ IPAddr ip;
msg->command = htons(REQ_ACCHECK);
if (accheck_getaddr(line, &ip)) {
- msg->data.ac_check.ip = htonl(ip);
+ UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1;
} else {
fprintf(stderr, "Could not read address\n");
static int
process_cmd_cmdaccheck(CMD_Request *msg, char *line)
{
- unsigned long ip;
+ IPAddr ip;
msg->command = htons(REQ_CMDACCHECK);
if (accheck_getaddr(line, &ip)) {
- msg->data.ac_check.ip = htonl(ip);
+ UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
return 1;
} else {
fprintf(stderr, "Could not read address\n");
switch (status) {
case CPS_Success:
msg->data.ntp_source.port = htonl((unsigned long) data.port);
- msg->data.ntp_source.ip_addr = htonl(data.ip_addr);
+ UTI_IPHostToNetwork(&data.ip_addr, &msg->data.ntp_source.ip_addr);
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
{
char hostname[2048];
int ok = 0;
- unsigned long address = 0UL;
+ IPAddr address;
msg->command = htons(REQ_DEL_SOURCE);
fprintf(stderr, "Invalid syntax for address\n");
ok = 0;
} else {
- address = DNS_Name2IPAddress(hostname);
- if (address == DNS_Failed_Address) {
+ if (!DNS_Name2IPAddress(hostname, &address, 0)) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
}
}
- msg->data.del_source.ip_addr = htonl(address);
+ UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr);
return ok;
{
unsigned long tx_sequence;
socklen_t where_from_len;
- struct sockaddr_in where_from;
+ union sockaddr_in46 where_from;
int bad_length, bad_sender, bad_sequence, bad_header;
int select_status;
int recvfrom_status;
#endif
if (sendto(sock_fd, (void *) request, command_length, 0,
- (struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) {
+ &his_addr.u, sizeof(his_addr)) < 0) {
#if 0
where_from_len = sizeof(where_from);
recvfrom_status = recvfrom(sock_fd, (void *) reply, sizeof(CMD_Reply), 0,
- (struct sockaddr *) &where_from, &where_from_len);
+ &where_from.u, &where_from_len);
#if 0
expected_length = PKL_ReplyLength(reply);
bad_length = (read_length != expected_length);
- bad_sender = ((where_from.sin_addr.s_addr != his_addr.sin_addr.s_addr) ||
- (where_from.sin_port != his_addr.sin_port));
+ bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
+ (where_from.u.sa_family == AF_INET &&
+ (where_from.in4.sin_addr.s_addr != his_addr.in4.sin_addr.s_addr ||
+ where_from.in4.sin_port != his_addr.in4.sin_port)) ||
+#ifdef HAVE_IPV6
+ (where_from.u.sa_family == AF_INET6 &&
+ (memcmp(where_from.in6.sin6_addr.s6_addr, his_addr.in6.sin6_addr.s6_addr,
+ sizeof (where_from.in6.sin6_addr.s6_addr)) != 0 ||
+ where_from.in6.sin6_port != his_addr.in6.sin6_port)) ||
+#endif
+ 0);
if (!bad_length) {
bad_sequence = (ntohl(reply->sequence) != tx_sequence);
int verbose = 0;
int32_t orig_latest_meas, latest_meas, est_offset;
- uint32_t ip_addr;
+ IPAddr ip_addr;
uint32_t latest_meas_err, est_offset_err;
uint32_t latest_meas_ago;
uint16_t poll, stratum;
uint16_t state, mode;
double resid_freq, resid_skew;
- const char *dns_lookup;
char hostname_buf[32];
uint16_t status;
if (submit_ok) {
if (ntohs(reply.status) == STT_SUCCESS) {
- ip_addr = ntohl(reply.data.source_data.ip_addr);
+ UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &ip_addr);
poll = ntohs(reply.data.source_data.poll);
stratum = ntohs(reply.data.source_data.stratum);
state = ntohs(reply.data.source_data.state);
resid_freq = (double) ((long) ntohl(reply.data.source_data.resid_freq)) * 1.0e-3;
resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
- hostname_buf[25] = 0;
if (mode == RPY_SD_MD_REF) {
- snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr));
+ snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr.addr.in4));
} else if (no_dns) {
- snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
+ snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
} else {
- dns_lookup = DNS_IPAddress2Name(ip_addr);
- strncpy(hostname_buf, dns_lookup, 25);
+ DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
+ hostname_buf[25] = 0;
}
switch (mode) {
int n_sources, i;
int verbose = 0;
- const char *dns_lookup;
char hostname_buf[32];
unsigned long n_samples, n_runs, span_seconds;
double resid_freq_ppm, skew_ppm;
unsigned long sd_us;
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned short status;
verbose = check_for_verbose_flag(line);
if (submit_ok) {
if (ntohs(reply.status) == STT_SUCCESS) {
- ip_addr = ntohl(reply.data.sourcestats.ip_addr);
+ UTI_IPNetworkToHost(&reply.data.sourcestats.ip_addr, &ip_addr);
n_samples = ntohl(reply.data.sourcestats.n_samples);
n_runs = ntohl(reply.data.sourcestats.n_runs);
span_seconds = ntohl(reply.data.sourcestats.span_seconds);
skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
sd_us = ntohl(reply.data.sourcestats.sd_us);
- hostname_buf[25] = 0;
if (no_dns) {
- snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
+ snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
} else {
- dns_lookup = DNS_IPAddress2Name(ip_addr);
- strncpy(hostname_buf, dns_lookup, 25);
+ DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
+ hostname_buf[25] = 0;
}
printf("%-25s %2lu %2lu ", hostname_buf, n_samples, n_runs);
b = (ref_id >> 16) & 0xff;
c = (ref_id >> 8) & 0xff;
d = (ref_id) & 0xff;
+
printf("Reference ID : %lu.%lu.%lu.%lu (%s)\n",
- a, b, c, d,
- (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id));
+ a, b, c, d, "");
+ //* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
printf("Stratum : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum));
ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s);
ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us);
unsigned long last_ntp_hit_ago;
unsigned long last_cmd_hit_ago;
char hostname_buf[32];
- const char *dns_lookup;
int n_replies;
snprintf(hostname_buf, sizeof(hostname_buf),
"%s", UTI_IPToDottedQuad(ip));
} else {
- dns_lookup = DNS_IPAddress2Name(ip);
+ DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
- strncpy(hostname_buf, dns_lookup, 25);
}
printf("%-25s %6d %6d %6d %6d %6d ",
hostname_buf,
int status;
unsigned long next_index;
int j;
- unsigned long ip;
+ IPAddr ip;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_auth;
unsigned long last_ntp_hit_ago;
unsigned long last_cmd_hit_ago;
char hostname_buf[32];
- const char *dns_lookup;
int n_replies;
int n_indices_in_table;
goto finished;
}
for (j=0; j<n_replies; j++) {
- ip = ntohl(reply.data.client_accesses_by_index.clients[j].ip);
- if (ip != 0UL) {
- /* ip == 0 implies that the node could not be found in
+ UTI_IPNetworkToHost(&reply.data.client_accesses_by_index.clients[j].ip, &ip);
+ if (ip.family != IPADDR_UNSPEC) {
+ /* UNSPEC implies that the node could not be found in
the daemon's tables; we shouldn't ever generate this
case, but ignore it if we do. (In future there might
be a protocol to reset the client logging; if another
if (no_dns) {
snprintf(hostname_buf, sizeof(hostname_buf),
- "%s", UTI_IPToDottedQuad(ip));
+ "%s", UTI_IPToString(&ip));
} else {
- dns_lookup = DNS_IPAddress2Name(ip);
+ DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
hostname_buf[25] = 0;
- strncpy(hostname_buf, dns_lookup, 25);
}
printf("%-25s %6ld %6ld %6ld %6ld %6ld ",
hostname_buf,
case STT_BADRTCFILE:
printf("514 Can't write RTC parameters");
break;
+ case STT_INVALIDAF:
+ printf("515 Invalid address family");
+ break;
}
if (reply_auth_ok) {
#define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node {
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_bad;
/* ================================================== */
-/* Table for the class A subnet */
-static Subnet top_subnet;
+/* Table for the IPv4 class A subnet */
+static Subnet top_subnet4;
+/* Table for IPv6 */
+static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been
allocated. */
/* ================================================== */
+static void
+split_ip6(IPAddr *ip, uint32_t *dst)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
+ ip->addr.in6[i * 4 + 1] << 16 |
+ ip->addr.in6[i * 4 + 2] << 8 |
+ ip->addr.in6[i * 4 + 3];
+}
+
+/* ================================================== */
+
+inline static uint32_t
+get_subnet(uint32_t *addr, unsigned int where)
+{
+ int off;
+
+ off = where / 32;
+ where %= 32;
+
+ return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
+}
+
+/* ================================================== */
+
+
static void
clear_subnet(Subnet *subnet)
{
void
CLG_Initialise(void)
{
- clear_subnet(&top_subnet);
+ clear_subnet(&top_subnet4);
+ clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) {
active = 0;
} else {
expanding subnet tables and node entries as we go if necessary. */
static void *
-find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
+find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{
- unsigned long this_subnet, new_subnet, mask, shift;
- unsigned long new_bits_left;
-
- shift = 32 - NBITS;
- mask = (1UL<<shift) - 1;
- this_subnet = addr >> shift;
- new_subnet = (addr & mask) << NBITS;
- new_bits_left = bits_left - NBITS;
-
-#if 0
- fprintf(stderr, "fs addr=%08lx bl=%d ma=%08lx this=%08lx newsn=%08lx nbl=%d\n",
- addr, bits_left, mask, this_subnet, new_subnet, new_bits_left);
-#endif
-
- if (new_bits_left > 0) {
+ uint32_t this_subnet;
+
+ this_subnet = get_subnet(addr, bits_consumed);
+ bits_consumed += NBITS;
+
+ if (bits_consumed < 32 * addr_len) {
if (!subnet->entry[this_subnet]) {
create_subnet(subnet, this_subnet);
}
- return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
+ return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
} else {
if (!subnet->entry[this_subnet]) {
create_node(subnet, this_subnet);
one of the parents does not exist - never open a node out */
static void *
-find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
+find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{
- unsigned long this_subnet, new_subnet, mask, shift;
- unsigned long new_bits_left;
+ uint32_t this_subnet;
- if (bits_left == 0) {
+ if (bits_consumed >= 32 * addr_len) {
return subnet;
} else {
- shift = 32 - NBITS;
- mask = (1UL<<shift) - 1;
- this_subnet = addr >> shift;
- new_subnet = (addr & mask) << NBITS;
- new_bits_left = bits_left - NBITS;
-
-#if 0
- fprintf(stderr, "fsdo addr=%08lx bl=%d this=%08lx newsn=%08lx nbl=%d\n",
- addr, bits_left, this_subnet, new_subnet, new_bits_left);
-#endif
-
+ this_subnet = get_subnet(addr, bits_consumed);
+ bits_consumed += NBITS;
+
if (!subnet->entry[this_subnet]) {
return NULL;
} else {
- return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
+ return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
}
}
}
/* ================================================== */
void
-CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
+CLG_LogNTPClientAccess (IPAddr *client, time_t now)
{
+ uint32_t ip6[4];
Node *node;
+
if (active) {
- node = (Node *) find_subnet(&top_subnet, client, 32);
- node->ip_addr = client;
+ switch (client->family) {
+ case IPADDR_INET4:
+ node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+ break;
+ case IPADDR_INET6:
+ split_ip6(client, ip6);
+ node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+ break;
+ default:
+ assert(0);
+ }
+
+ node->ip_addr = *client;
++node->client_hits;
node->last_ntp_hit = now;
}
/* ================================================== */
void
-CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
+CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
{
+ uint32_t ip6[4];
Node *node;
+
if (active) {
- node = (Node *) find_subnet(&top_subnet, client, 32);
- node->ip_addr = client;
+ switch (client->family) {
+ case IPADDR_INET4:
+ node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+ break;
+ case IPADDR_INET6:
+ split_ip6(client, ip6);
+ node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+ break;
+ default:
+ assert(0);
+ }
+
+ node->ip_addr = *client;
++node->peer_hits;
node->last_ntp_hit = now;
}
/* ================================================== */
void
-CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
+CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
{
+ uint32_t ip6[4];
Node *node;
+
if (active) {
- node = (Node *) find_subnet(&top_subnet, client, 32);
- node->ip_addr = client;
+ switch (client->family) {
+ case IPADDR_INET4:
+ node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+ break;
+ case IPADDR_INET6:
+ split_ip6(client, ip6);
+ node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+ break;
+ default:
+ assert(0);
+ }
+
+ node->ip_addr = *client;
node->last_cmd_hit = now;
switch (type) {
case CLG_CMD_AUTH:
/* ================================================== */
CLG_Status
-CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
+CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
{
Subnet *s;
+ uint32_t ip6[4];
unsigned long i;
unsigned long word, bit, mask;
- if ((bits == 0) || (bits == 8) || (bits == 16) || (bits == 24)) {
+ if (bits >= 0 && bits % 8 == 0) {
memset (result, 0, TABLE_SIZE/8);
if (active) {
- s = find_subnet_dont_open(&top_subnet, subnet, bits);
+ switch (subnet->family) {
+ case IPADDR_INET4:
+ if (bits >= 32)
+ return CLG_BADSUBNET;
+ s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
+ break;
+ case IPADDR_INET6:
+ if (bits >= 128)
+ return CLG_BADSUBNET;
+ split_ip6(subnet, ip6);
+ s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
+ break;
+ default:
+ return CLG_BADSUBNET;
+ }
+
if (s) {
for (i=0; i<256; i++) {
if (s->entry[i]) {
/* ================================================== */
CLG_Status
-CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now)
+CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now)
{
+ uint32_t ip6[4];
Node *node;
if (!active) {
return CLG_INACTIVE;
} else {
- node = (Node *) find_subnet_dont_open(&top_subnet, ip, 32);
-
+ switch (ip->family) {
+ case IPADDR_INET4:
+ node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
+ break;
+ case IPADDR_INET6:
+ split_ip6(ip, ip6);
+ node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
+ break;
+ default:
+ return CLG_EMPTYSUBNET;
+ }
+
if (!node) {
return CLG_EMPTYSUBNET;
} else {
#include "sysincl.h"
#include "reports.h"
-typedef unsigned long CLG_IP_Addr;
-
/* Enough to hold flags for 256 hosts in a class C */
typedef uint32_t CLG_Bitmap[8];
extern void CLG_Initialise(void);
extern void CLG_Finalise(void);
-extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now);
-extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now);
+extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
+extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
/* When logging command packets, there are several subtypes */
CLG_CMD_BAD_PKT /* bad version or packet length */
} CLG_Command_Type;
-extern void CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now);
+extern void CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now);
/* And some reporting functions, for use by chronyc. */
/* TBD */
known. For bits=24, flag which hosts in that subnet are known.
Other values, return 0 (failed) */
-extern CLG_Status CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result);
+extern CLG_Status CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result);
extern CLG_Status
-CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now);
+CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now);
CLG_Status
CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
that has accessed us since 'since'. */
extern void CLG_IterateNTPClients
-(void (*fn)(CLG_IP_Addr client, void *arb),
+(void (*fn)(IPAddr *client, void *arb),
void *arb,
time_t since);
/* ================================================== */
-/* File descriptor for command and monitoring socket */
-static int sock_fd;
+union sockaddr_in46 {
+ struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr u;
+};
+
+/* File descriptors for command and monitoring sockets */
+static int sock_fd4;
+#ifdef HAVE_IPV6
+static int sock_fd6;
+#endif
/* Flag indicating whether this module has been initialised or not */
static int initialised = 0;
/* ================================================== */
/* Forward prototypes */
+static int prepare_socket(int family);
static void read_from_cmd_socket(void *anything);
/* ================================================== */
-void
-CAM_Initialise(void)
+static int
+prepare_socket(int family)
{
- int port_number;
- struct sockaddr_in my_addr;
- unsigned long bind_address;
+ int port_number, sock_fd;
+ union sockaddr_in46 my_addr;
+ IPAddr bind_address;
int on_off = 1;
- if (initialised) {
- CROAK("Shouldn't be initialised");
- }
-
- initialised = 1;
-
- if ((sizeof(permissions)/sizeof(permissions[0])) != N_REQUEST_TYPES) {
- CROAK("Permissions table size wrong");
- }
-
- utoken = (unsigned long) time(NULL);
-
- issued_tokens = returned_tokens = issue_pointer = 0;
- token_base = 1; /* zero is the value used when the previous command was
- unauthenticated */
-
- free_replies = NULL;
- kept_replies.next = NULL;
-
port_number = CNF_GetCommandPort();
if (port_number < 0) {
port_number = DEFAULT_CANDM_PORT;
}
- sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) {
- LOG_FATAL(LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
+ LOG(LOGS_ERR, LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
+ return -1;
}
/* Allow reuse of port number */
LOG(LOGS_ERR, LOGF_CmdMon, "Could not set socket options");
/* Don't quit - we might survive anyway */
}
+#ifdef HAVE_IPV6
+ if (family == AF_INET6) {
+#ifdef IPV6_V6ONLY
+ /* Receive IPv6 packets only */
+ if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
+ }
+#endif
+ }
+#endif
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons((unsigned short) port_number);
+ memset(&my_addr, 0, sizeof (my_addr));
- CNF_GetBindCommandAddress(&bind_address);
+ switch (family) {
+ case AF_INET:
+ my_addr.in4.sin_family = family;
+ my_addr.in4.sin_port = htons((unsigned short)port_number);
- if (bind_address != 0UL) {
- my_addr.sin_addr.s_addr = htonl(bind_address);
- } else {
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ CNF_GetBindCommandAddress(IPADDR_INET4, &bind_address);
+
+ if (bind_address.family == IPADDR_INET4)
+ my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
+ else
+ my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ my_addr.in6.sin6_family = family;
+ my_addr.in6.sin6_port = htons((unsigned short)port_number);
+
+ CNF_GetBindCommandAddress(IPADDR_INET6, &bind_address);
+
+ if (bind_address.family == IPADDR_INET6)
+ memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
+ sizeof (my_addr.in6.sin6_addr.s6_addr));
+ else
+ my_addr.in6.sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ assert(0);
}
- if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+ if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_CmdMon, "Could not bind socket : %s", strerror(errno));
}
/* Register handler for read events on the socket */
- SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, NULL);
+ SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, (void *)(long)sock_fd);
+
+ return sock_fd;
+}
+
+/* ================================================== */
+
+void
+CAM_Initialise(void)
+{
+
+ if (initialised) {
+ CROAK("Shouldn't be initialised");
+ }
+
+ initialised = 1;
+
+ if ((sizeof(permissions)/sizeof(permissions[0])) != N_REQUEST_TYPES) {
+ CROAK("Permissions table size wrong");
+ }
+
+ utoken = (unsigned long) time(NULL);
+
+ issued_tokens = returned_tokens = issue_pointer = 0;
+ token_base = 1; /* zero is the value used when the previous command was
+ unauthenticated */
+
+ free_replies = NULL;
+ kept_replies.next = NULL;
+
+ sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+ sock_fd6 = prepare_socket(AF_INET6);
+#endif
+
+ if (sock_fd4 < 0
+#ifdef HAVE_IPV6
+ && sock_fd6 < 0
+#endif
+ ) {
+ LOG_FATAL(LOGF_CmdMon, "Could not open any command socket");
+ }
access_auth_table = ADF_CreateTable();
void
CAM_Finalise(void)
{
- SCH_RemoveInputFileHandler(sock_fd);
- close(sock_fd);
- sock_fd = -1;
+ if (sock_fd4 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd4);
+ close(sock_fd4);
+ }
+ sock_fd4 = -1;
+#ifdef HAVE_IPV6
+ if (sock_fd6 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd6);
+ close(sock_fd6);
+ }
+ sock_fd6 = -1;
+#endif
ADF_DestroyTable(access_auth_table);
/* ================================================== */
static void
-transmit_reply(CMD_Reply *msg, struct sockaddr_in *where_to)
+transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
{
int status;
int tx_message_length;
- unsigned long remote_ip;
- unsigned short remote_port;
+ int sock_fd;
+
+ switch (where_to->u.sa_family) {
+ case AF_INET:
+ sock_fd = sock_fd4;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ sock_fd = sock_fd6;
+ break;
+#endif
+ default:
+ assert(0);
+ }
tx_message_length = PKL_ReplyLength(msg);
status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
- (struct sockaddr *) where_to, sizeof(struct sockaddr_in));
+ &where_to->u, sizeof(union sockaddr_in46));
if (status < 0) {
- remote_ip = ntohl(where_to->sin_addr.s_addr);
- remote_port = ntohs(where_to->sin_port);
- LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
+ unsigned short port;
+ IPAddr ip;
+
+ switch (where_to->u.sa_family) {
+ case AF_INET:
+ ip.family = IPADDR_INET4;
+ ip.addr.in4 = ntohl(where_to->in4.sin_addr.s_addr);
+ port = ntohs(where_to->in4.sin_port);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ ip.family = IPADDR_INET6;
+ memcpy(ip.addr.in6, (where_to->in6.sin6_addr.s6_addr), sizeof(ip.addr.in6));
+ port = ntohs(where_to->in6.sin6_port);
+ break;
+#endif
+ default:
+ assert(0);
+ }
+
+ LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&ip), port);
}
return;
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_TakeSourcesOnline(ntohl(rx_message->data.online.mask), ntohl(rx_message->data.online.address));
+ IPAddr address, mask;
+ UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
+ UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
+ status = NSR_TakeSourcesOnline(&mask, &address);
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_TakeSourcesOffline(ntohl(rx_message->data.offline.mask), ntohl(rx_message->data.offline.address));
+ IPAddr address, mask;
+ UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
+ UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
+ status = NSR_TakeSourcesOffline(&mask, &address);
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
+ IPAddr address, mask;
+ UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
+ UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
ntohl(rx_message->data.burst.n_total_samples),
- ntohl(rx_message->data.burst.mask),
- ntohl(rx_message->data.burst.address));
+ &mask, &address);
if (status) {
tx_message->status = htons(STT_SUCCESS);
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_ModifyMinpoll(ntohl(rx_message->data.modify_minpoll.address),
+ IPAddr address;
+ UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
+ status = NSR_ModifyMinpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) {
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_ModifyMaxpoll(ntohl(rx_message->data.modify_minpoll.address),
+ IPAddr address;
+ UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
+ status = NSR_ModifyMaxpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) {
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_ModifyMaxdelay(ntohl(rx_message->data.modify_maxdelay.address),
+ IPAddr address;
+ UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
+ status = NSR_ModifyMaxdelay(&address,
WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay));
if (status) {
tx_message->status = htons(STT_SUCCESS);
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
- status = NSR_ModifyMaxdelayratio(ntohl(rx_message->data.modify_maxdelayratio.address),
+ IPAddr address;
+ UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
+ status = NSR_ModifyMaxdelayratio(&address,
WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
if (status) {
tx_message->status = htons(STT_SUCCESS);
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCE_DATA);
- tx_message->data.source_data.ip_addr = htonl(report.ip_addr);
+ UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
tx_message->data.source_data.stratum = htons(report.stratum);
tx_message->data.source_data.poll = htons(report.poll);
switch (report.state) {
static void
handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 0)) {
+ if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (NCR_AddAccessRestriction(ip, subnet_bits, 1, 1)) {
+ if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 0)) {
+ if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (NCR_AddAccessRestriction(ip, subnet_bits, 0, 1)) {
+ if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 0)) {
+ if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (CAM_AddAccessRestriction(ip, subnet_bits, 1, 1)) {
+ if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 0)) {
+ if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
- ip = ntohl(rx_message->data.allow_deny.ip);
+ UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
- if (CAM_AddAccessRestriction(ip, subnet_bits, 0, 1)) {
+ if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
static void
handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
- ip = ntohl(rx_message->data.ac_check.ip);
- if (NCR_CheckAccessRestriction(ip)) {
+ IPAddr ip;
+ UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
+ if (NCR_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED);
} else {
tx_message->status = htons(STT_ACCESSDENIED);
static void
handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- unsigned long ip;
- ip = ntohl(rx_message->data.ac_check.ip);
- if (CAM_CheckAccessRestriction(ip)) {
+ IPAddr ip;
+ UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
+ if (CAM_CheckAccessRestriction(&ip)) {
tx_message->status = htons(STT_ACCESSALLOWED);
} else {
tx_message->status = htons(STT_ACCESSDENIED);
SourceParameters params;
NSR_Status status;
- rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
- rem_addr.local_ip_addr = 0;
+ UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
+ rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
+ case NSR_InvalidAF:
+ tx_message->status = htons(STT_INVALIDAF);
+ break;
case NSR_NoSuchSource:
CROAK("Impossible");
break;
SourceParameters params;
NSR_Status status;
- rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
- rem_addr.local_ip_addr = 0;
+ UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
+ rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
+ case NSR_InvalidAF:
+ tx_message->status = htons(STT_INVALIDAF);
+ break;
case NSR_NoSuchSource:
CROAK("Impossible");
break;
NTP_Remote_Address rem_addr;
NSR_Status status;
- rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr);
- rem_addr.local_ip_addr = 0;
+ UTI_IPNetworkToHost(&rx_message->data.del_source.ip_addr, &rem_addr.ip_addr);
+ rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = 0;
status = NSR_RemoveSource(&rem_addr);
break;
case NSR_TooManySources:
case NSR_AlreadyInUse:
+ case NSR_InvalidAF:
CROAK("Impossible");
break;
}
if (status) {
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCESTATS);
- tx_message->data.sourcestats.ip_addr = htonl(report.ip_addr);
+ UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr);
tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int i, j;
- unsigned long ns;
- unsigned long ip, bits_specd;
+ unsigned long ns, bits_specd;
+ IPAddr ip;
CLG_Status result;
ns = ntohl(rx_message->data.subnets_accessed.n_subnets);
tx_message->data.subnets_accessed.n_subnets = htonl(ns);
for (i=0; i<ns; i++) {
- ip = ntohl(rx_message->data.subnets_accessed.subnets[i].ip);
+ UTI_IPNetworkToHost(&rx_message->data.subnets_accessed.subnets[i].ip, &ip);
bits_specd = ntohl(rx_message->data.subnets_accessed.subnets[i].bits_specd);
- tx_message->data.subnets_accessed.subnets[i].ip = htonl(ip);
+ UTI_IPHostToNetwork(&ip, &tx_message->data.subnets_accessed.subnets[i].ip);
tx_message->data.subnets_accessed.subnets[i].bits_specd = htonl(bits_specd);
- result = CLG_GetSubnetBitmap(ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
+ result = CLG_GetSubnetBitmap(&ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
switch (result) {
case CLG_SUCCESS:
case CLG_EMPTYSUBNET:
CLG_Status result;
RPT_ClientAccess_Report report;
unsigned long nc;
- unsigned long ip;
+ IPAddr ip;
int i;
struct timeval now;
double local_time_error;
printf("%d %d\n", (int)sizeof(RPY_ClientAccesses_Client), (int)offsetof(CMD_Reply, data.client_accesses.clients));
for (i=0; i<nc; i++) {
- ip = ntohl(rx_message->data.client_accesses.client_ips[i]);
- tx_message->data.client_accesses.clients[i].ip = htonl(ip);
+ UTI_IPNetworkToHost(&rx_message->data.client_accesses.client_ips[i], &ip);
+ UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
- result = CLG_GetClientAccessReportByIP(ip, &report, now.tv_sec);
+ result = CLG_GetClientAccessReportByIP(&ip, &report, now.tv_sec);
switch (result) {
case CLG_SUCCESS:
tx_message->data.client_accesses.clients[i].client_hits = htonl(report.client_hits);
tx_message->data.client_accesses.clients[i].cmd_hits_bad = htonl(report.cmd_hits_bad);
tx_message->data.client_accesses.clients[i].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
tx_message->data.client_accesses.clients[i].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
- printf("%08lx %lu %lu %lu %lu %lu %lu %lu\n", ip, report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
+ printf("%s %lu %lu %lu %lu %lu %lu %lu\n", UTI_IPToString(&ip), report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
break;
case CLG_EMPTYSUBNET:
/* Signal back to the client that this single client address
- was unknown, by specifying the zero ip address, which will
- always be invalid (hopefully) */
- tx_message->data.client_accesses.clients[i].ip = htonl(0);
+ was unknown */
+ ip.family = IPADDR_UNSPEC;
+ UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
break;
case CLG_INACTIVE:
tx_message->status = htons(STT_INACTIVE);
switch (result) {
case CLG_SUCCESS:
- tx_message->data.client_accesses_by_index.clients[j].ip = htonl(report.ip_addr);
+ UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.client_accesses_by_index.clients[j].ip);
tx_message->data.client_accesses_by_index.clients[j].client_hits = htonl(report.client_hits);
tx_message->data.client_accesses_by_index.clients[j].peer_hits = htonl(report.peer_hits);
tx_message->data.client_accesses_by_index.clients[j].cmd_hits_auth = htonl(report.cmd_hits_auth);
CMD_Request rx_message;
CMD_Reply tx_message, *prev_tx_message;
int rx_message_length, tx_message_length;
- struct sockaddr_in where_from;
+ int sock_fd;
+ union sockaddr_in46 where_from;
socklen_t from_length;
- unsigned long remote_ip;
+ IPAddr remote_ip;
unsigned short remote_port;
int md5_ok;
int utoken_ok, token_ok;
rx_message_length = sizeof(rx_message);
from_length = sizeof(where_from);
+ sock_fd = (long)anything;
status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, flags,
- (struct sockaddr *)&where_from, &from_length);
+ &where_from.u, &from_length);
if (status < 0) {
- LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket (IP=%s port=%d)",
- strerror(errno),
- UTI_IPToDottedQuad(ntohl(where_from.sin_addr.s_addr)),
- ntohs(where_from.sin_port));
+ LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d",
+ strerror(errno), sock_fd);
+ return;
}
read_length = status;
tx_message.token = htonl(0xffffffffUL);
memset(&tx_message.auth, 0, sizeof(tx_message.auth));
- remote_ip = ntohl(where_from.sin_addr.s_addr);
- remote_port = ntohs(where_from.sin_port);
-
- localhost = (remote_ip == 0x7f000001UL);
+ switch (where_from.u.sa_family) {
+ case AF_INET:
+ remote_ip.family = IPADDR_INET4;
+ remote_ip.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
+ remote_port = ntohs(where_from.in4.sin_port);
+ localhost = (remote_ip.addr.in4 == 0x7f000001UL);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ remote_ip.family = IPADDR_INET6;
+ memcpy(&remote_ip.addr.in6, where_from.in6.sin6_addr.s6_addr,
+ sizeof (remote_ip.addr.in6));
+ remote_port = ntohs(where_from.in6.sin6_port);
+ /* Check for ::1 */
+ for (localhost = 0; localhost < 16; localhost++)
+ if (remote_ip.addr.in6[localhost] != 0)
+ break;
+ localhost = (localhost == 15 && remote_ip.addr.in6[localhost] == 1);
+ break;
+#endif
+ default:
+ assert(0);
+ }
- if ((!ADF_IsAllowed(access_auth_table, remote_ip)) &&
+ if ((!ADF_IsAllowed(access_auth_table, &remote_ip)) &&
(!localhost)) {
/* The client is not allowed access, so don't waste any more time
on him. Note that localhost is always allowed access
hitting us with bad packets until our log file(s) fill up. */
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
- UTI_IPToDottedQuad(remote_ip),
+ UTI_IPToString(&remote_ip),
remote_port);
tx_message.status = htons(STT_NOHOSTACCESS);
if (read_length != expected_length) {
- LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
- CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
+ LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
+ CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
/* For now, just ignore the packet. We may want to send a reply
back eventually */
return;
(rx_message.res2 != 0)) {
/* We don't know how to process anything like this */
- CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
+ CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
return;
}
status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
(struct sockaddr *) &where_from, sizeof(where_from));
if (status < 0) {
- LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
+ LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
}
return;
}
authenticated = md5_ok & utoken_ok & token_ok;
if (authenticated) {
- CLG_LogCommandAccess(remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
+ CLG_LogCommandAccess(&remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
} else {
- CLG_LogCommandAccess(remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
+ CLG_LogCommandAccess(&remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
}
if (issue_token) {
if (!issue_token) {
LOG(LOGS_WARN, LOGF_CmdMon,
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
- UTI_IPToDottedQuad(remote_ip),
+ UTI_IPToString(&remote_ip),
remote_port,
md5_ok, valid_ts);
}
/* ================================================== */
int
-CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all)
+CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{
ADF_Status status;
/* ================================================== */
int
-CAM_CheckAccessRestriction(unsigned long ip_addr)
+CAM_CheckAccessRestriction(IPAddr *ip_addr)
{
return ADF_IsAllowed(access_auth_table, ip_addr);
}
#ifndef GOT_CMDMON_H
#define GOT_CMDMON_H
+#include "addressing.h"
+
extern void CAM_Initialise(void);
extern void CAM_Finalise(void);
-extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
-extern int CAM_CheckAccessRestriction(unsigned long ip_addr);
+extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
+extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
#endif /* GOT_CMDMON_H */
ok = 0;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
- src->ip_addr = DNS_Name2IPAddressRetry(hostname);
- if (src->ip_addr != DNS_Failed_Address) {
+ if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
ok = 1;
}
}
#define GOT_CMDPARSE_H
#include "srcparams.h"
+#include "addressing.h"
typedef enum {
CPS_Success,
} CPS_Status;
typedef struct {
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned short port;
SourceParameters params;
} CPS_NTP_Source;
#include "acquire.h"
#include "cmdparse.h"
#include "broadcast.h"
+#include "util.h"
/* ================================================== */
than this, slew instead of stepping */
static int init_slew_threshold = -1;
#define MAX_INIT_SRCS 8
-static unsigned long init_srcs_ip[MAX_INIT_SRCS];
+static IPAddr init_srcs_ip[MAX_INIT_SRCS];
static int enable_manual=0;
memory */
static int no_client_log = 0;
-/* IP address (host order) for binding the NTP socket to. 0 means INADDR_ANY
+/* IP addresses for binding the NTP socket to. UNSPEC family means INADDR_ANY
will be used */
-static unsigned long bind_address = 0UL;
+static IPAddr bind_address4, bind_address6;
-/* IP address (host order) for binding the command socket to. 0 means
+/* IP addresses for binding the command socket to. UNSPEC family means
use the value of bind_address */
-static unsigned long bind_cmd_address = 0UL;
+static IPAddr bind_cmd_address4, bind_cmd_address6;
/* Filename to use for storing pid of running chronyd, to prevent multiple
* chronyds being started. */
typedef struct {
NTP_Source_Type type;
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned short port;
SourceParameters params;
} NTP_Source;
typedef struct _AllowDeny {
struct _AllowDeny *next;
struct _AllowDeny *prev;
- unsigned long ip;
+ IPAddr ip;
int subnet_bits;
int all; /* 1 to override existing more specific defns */
int allow; /* 0 for deny, 1 for allow */
char hostname[HOSTNAME_LEN+1];
int n;
int threshold;
- unsigned long ip_addr;
+ IPAddr ip_addr;
n_init_srcs = 0;
p = line;
}
while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
- ip_addr = DNS_Name2IPAddressRetry(hostname);
- if (ip_addr != DNS_Failed_Address) {
+ if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs;
}
unsigned long a, b, c, d, n;
int all = 0;
AllowDeny *new_node = NULL;
- unsigned long ip_addr;
+ IPAddr ip_addr;
p = line;
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
- new_node->ip = 0UL;
+ new_node->ip.family = IPADDR_UNSPEC;
new_node->subnet_bits = 0;
} else {
char *slashpos;
slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0;
- n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
-
- if (n >= 1) {
+ n = 0;
+ if (UTI_StringToIP(p, &ip_addr) ||
+ (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
- a &= 0xff;
- b &= 0xff;
- c &= 0xff;
- d &= 0xff;
-
- switch (n) {
- case 1:
- new_node->ip = (a<<24);
- new_node->subnet_bits = 8;
- break;
- case 2:
- new_node->ip = (a<<24) | (b<<16);
- new_node->subnet_bits = 16;
- break;
- case 3:
- new_node->ip = (a<<24) | (b<<16) | (c<<8);
- new_node->subnet_bits = 24;
- break;
- case 4:
- new_node->ip = (a<<24) | (b<<16) | (c<<8) | d;
+ if (n == 0) {
+ new_node->ip = ip_addr;
+ if (ip_addr.family == IPADDR_INET6)
+ new_node->subnet_bits = 128;
+ else
new_node->subnet_bits = 32;
- break;
- default:
- assert(0);
-
+ } else {
+ new_node->ip.family = IPADDR_INET4;
+
+ a &= 0xff;
+ b &= 0xff;
+ c &= 0xff;
+ d &= 0xff;
+
+ switch (n) {
+ case 1:
+ new_node->ip.addr.in4 = (a<<24);
+ new_node->subnet_bits = 8;
+ break;
+ case 2:
+ new_node->ip.addr.in4 = (a<<24) | (b<<16);
+ new_node->subnet_bits = 16;
+ break;
+ case 3:
+ new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
+ new_node->subnet_bits = 24;
+ break;
+ case 4:
+ new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
+ new_node->subnet_bits = 32;
+ break;
+ default:
+ assert(0);
+ }
}
if (slashpos) {
}
} else {
- ip_addr = DNS_Name2IPAddressRetry(p);
- if (ip_addr != DNS_Failed_Address) {
+ if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
new_node->ip = ip_addr;
- new_node->subnet_bits = 32;
+ if (ip_addr.family == IPADDR_INET6)
+ new_node->subnet_bits = 128;
+ else
+ new_node->subnet_bits = 32;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number);
}
/* ================================================== */
-static unsigned long
-parse_an_address(const char *line, const char *errmsg)
-{
- unsigned long a, b, c, d;
- int n;
- n = sscanf(line, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
- if (n == 4) {
- return (((a&0xff)<<24) | ((b&0xff)<<16) |
- ((c&0xff)<<8) | (d&0xff));
- } else {
- LOG(LOGS_WARN, LOGF_Configure, errmsg, line_number);
- return 0UL;
- }
-}
-
-/* ================================================== */
-
static void
parse_bindaddress(const char *line)
{
- bind_address = parse_an_address(line, "Could not read bind address at line %d\n");
+ IPAddr ip;
+ char addr[51];
+
+ if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
+ if (ip.family == IPADDR_INET4)
+ bind_address4 = ip;
+ else if (ip.family == IPADDR_INET6)
+ bind_address6 = ip;
+ } else {
+ LOG(LOGS_WARN, LOGF_Configure, "Could not read bind address at line %d\n", line_number);
+ }
}
/* ================================================== */
static void
parse_bindcmdaddress(const char *line)
{
- bind_cmd_address = parse_an_address(line, "Could not read bind command address at line %d\n");
+ IPAddr ip;
+ char addr[51];
+
+ if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
+ if (ip.family == IPADDR_INET4)
+ bind_cmd_address4 = ip;
+ else if (ip.family == IPADDR_INET6)
+ bind_cmd_address6 = ip;
+ } else {
+ LOG(LOGS_WARN, LOGF_Configure, "Could not read bind command address at line %d\n", line_number);
+ }
}
/* ================================================== */
typedef struct {
/* Both in host (not necessarily network) order */
- unsigned long addr;
+ IPAddr addr;
unsigned short port;
int interval;
} NTP_Broadcast_Destination;
{
/* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
int port;
- unsigned int a, b, c, d;
int n;
int interval;
- unsigned long addr;
+ char addr[51];
+ IPAddr ip;
- n = sscanf(line, "%d %u.%u.%u.%u %d", &interval, &a, &b, &c, &d, &port);
- if (n < 5) {
+ n = sscanf(line, "%d %50s %d", &interval, addr, &port);
+ if (n < 2 || !UTI_StringToIP(addr, &ip)) {
LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
return;
- } else if (n == 5) {
+ } else if (n == 2) {
/* default port */
port = 123;
- } else if (n > 6) {
+ } else if (n > 3) {
LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number);
}
- addr = ((unsigned long) a << 24) |
- ((unsigned long) b << 16) |
- ((unsigned long) c << 8) |
- ((unsigned long) d );
-
if (max_broadcasts == n_broadcasts) {
/* Expand array */
max_broadcasts += 8;
}
}
- broadcasts[n_broadcasts].addr = addr;
+ broadcasts[n_broadcasts].addr = ip;
broadcasts[n_broadcasts].port = port;
broadcasts[n_broadcasts].interval = interval;
++n_broadcasts;
for (i=0; i<n_ntp_sources; i++) {
server.ip_addr = ntp_sources[i].ip_addr;
- server.local_ip_addr = 0;
+ memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
server.port = ntp_sources[i].port;
switch (ntp_sources[i].type) {
{
int i;
for (i=0; i<n_broadcasts; i++) {
- BRD_AddDestination(broadcasts[i].addr,
+ BRD_AddDestination(&broadcasts[i].addr,
broadcasts[i].port,
broadcasts[i].interval);
}
int status;
for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) {
- status = NCR_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all);
+ status = NCR_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
}
for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) {
- status = CAM_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all);
+ status = CAM_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
/* ================================================== */
void
-CNF_GetBindAddress(unsigned long *addr)
+CNF_GetBindAddress(int family, IPAddr *addr)
{
- *addr = bind_address;
+ if (family == IPADDR_INET4)
+ *addr = bind_address4;
+ else if (family == IPADDR_INET6)
+ *addr = bind_address6;
+ else
+ addr->family = IPADDR_UNSPEC;
}
/* ================================================== */
void
-CNF_GetBindCommandAddress(unsigned long *addr)
-{
- *addr = bind_cmd_address ? bind_cmd_address : bind_address;
+CNF_GetBindCommandAddress(int family, IPAddr *addr)
+{
+ if (family == IPADDR_INET4)
+ *addr = bind_cmd_address4.family != IPADDR_UNSPEC ? bind_cmd_address4 : bind_address4;
+ else if (family == IPADDR_INET6)
+ *addr = bind_cmd_address6.family != IPADDR_UNSPEC ? bind_cmd_address6 : bind_address6;
+ else
+ addr->family = IPADDR_UNSPEC;
}
/* ================================================== */
#ifndef GOT_CONF_H
#define GOT_CONF_H
+#include "addressing.h"
+
extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename);
extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void);
-extern void CNF_GetBindAddress(unsigned long *addr);
-extern void CNF_GetBindCommandAddress(unsigned long *addr);
+extern void CNF_GetBindAddress(int family, IPAddr *addr);
+extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void);
extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
echo $result
}
#}}}
+#{{{ test_for_ipv6
+test_for_ipv6 () {
+ cat >docheck.c <<EOF;
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int main(int argc, char **argv) {
+ struct sockaddr_in6 n;
+ char p[100];
+ n.sin6_addr = in6addr_any;
+ return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));
+}
+EOF
+
+ ${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
+ if [ $? -eq 0 ]
+ then
+ result=0
+ else
+ result=1
+ fi
+
+ rm -f docheck.c docheck.o
+ echo $result
+}
+#}}}
#{{{ usage
usage () {
cat <<EOF;
--readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is
+ --disable-ipv6 Disable IPv6 support
--disable-rtc Don't include RTC even on Linux
--enable-linuxcaps Enable Linux capabilities support
readline_lib=""
readline_inc=""
ncurses_lib=""
+feat_ipv6=1
SETINFODIR=""
SETMANDIR=""
--disable-rtc)
feat_rtc=0
;;
+ --disable-ipv6)
+ feat_ipv6=0
+ ;;
--enable-linuxcaps)
feat_linuxcaps=1
;;
printf "No\n"
fi
+printf "Checking for IPv6 support : "
+if [ $feat_ipv6 -eq 1 -a `test_for_ipv6` -eq 0 ]; then
+ printf "Yes\n"
+ SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
+else
+ printf "No\n"
+fi
+
if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
#include "sysincl.h"
#include "nameserv.h"
+#include "util.h"
#include <resolv.h>
/* ================================================== */
+#define MAXRETRIES 10
static unsigned int retries = 0;
-static unsigned long
-Name2IPAddress(const char *name, int retry)
+int
+DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
{
- struct hostent *host;
- unsigned char *address0;
- unsigned long result;
+#ifdef HAVE_IPV6
+ struct addrinfo hints, *res, *ai;
+ int result;
+
+ memset(&hints, 0, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+try_again:
+ result = getaddrinfo(name, NULL, &hints, &res);
+ if (result) {
+ if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
+ sleep(2 << retries);
+ retries++;
+ res_init();
+ goto try_again;
+ }
+ return 0;
+ }
+
+ for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
+ switch (ai->ai_family) {
+ case AF_INET:
+ addr->family = IPADDR_INET4;
+ addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
+ result = 1;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ addr->family = IPADDR_INET6;
+ memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
+ result = 1;
+ break;
+#endif
+ }
+ }
+
+ freeaddrinfo(res);
+ return result;
+#else
+ struct hostent *host;
+ char *address0;
+
try_again:
host = gethostbyname(name);
+
if (host == NULL) {
- if (retry && h_errno == TRY_AGAIN && retries < 10) {
+ if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
- result = DNS_Failed_Address;
} else {
+ addr->family = IPADDR_INET4;
address0 = host->h_addr_list[0];
- result = ((((unsigned long)address0[0])<<24) |
- (((unsigned long)address0[1])<<16) |
- (((unsigned long)address0[2])<<8) |
- (((unsigned long)address0[3])));
+ addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
+ (((unsigned long)address0[1])<<16) |
+ (((unsigned long)address0[2])<<8) |
+ (((unsigned long)address0[3])));
+ return 1;
}
- return result;
-}
-
-/* ================================================== */
-
-unsigned long
-DNS_Name2IPAddress(const char *name)
-{
- return Name2IPAddress(name, 0);
+ return 0;
+#endif
}
/* ================================================== */
-unsigned long
-DNS_Name2IPAddressRetry(const char *name)
+void
+DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
{
- return Name2IPAddress(name, 1);
-}
-
-/* ================================================== */
+#ifdef HAVE_IPV6
+ int result;
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+
+ switch (ip_addr->family) {
+ case IPADDR_INET4:
+ memset(&in4, 0, sizeof (in4));
+ in4.sin_family = AF_INET;
+ in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
+ result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
+ break;
+ case IPADDR_INET6:
+ memset(&in6, 0, sizeof (in6));
+ in6.sin6_family = AF_INET6;
+ memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
+ result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
+ break;
+ default:
+ result = 1;
+ }
-const char *
-DNS_IPAddress2Name(unsigned long ip_addr)
-{
+ if (result)
+ snprintf(name, len, "%s", UTI_IPToString(ip_addr));
+#else
struct hostent *host;
- static char buffer[16];
- unsigned int a, b, c, d;
uint32_t addr;
- addr = htonl(ip_addr);
- if (addr == 0UL) {
- /* Catch this as a special case that will never resolve to
- anything */
- strcpy(buffer, "0.0.0.0");
- return buffer;
- } else {
- host = gethostbyaddr((const char *) &addr, sizeof(ip_addr), AF_INET);
- if (!host) {
- a = (ip_addr >> 24) & 0xff;
- b = (ip_addr >> 16) & 0xff;
- c = (ip_addr >> 8) & 0xff;
- d = (ip_addr) & 0xff;
- snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", a, b, c, d);
- return buffer;
- } else {
- return host->h_name;
- }
+ switch (ip_addr->family) {
+ case IPADDR_INET4:
+ addr = htonl(ip_addr->addr.in4);
+ host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET);
+ break;
+#ifdef HAVE_IPV6
+ case IPADDR_INET6:
+ host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
+ break;
+#endif
+ default:
+ host = NULL;
}
+ snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
+#endif
}
/* ================================================== */
#ifndef GOT_NAMESERV_H
#define GOT_NAMESERV_H
-static const unsigned long DNS_Failed_Address = 0x0UL;
+#include "addressing.h"
-extern unsigned long DNS_Name2IPAddress(const char *name);
+extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
-extern unsigned long DNS_Name2IPAddressRetry(const char *name);
-
-const char *DNS_IPAddress2Name(unsigned long ip_addr);
+extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
#endif /* GOT_NAMESERV_H */
result->local_poll = params->minpoll;
/* Create a source instance for this NTP source */
- result->source = SRC_CreateNewInstance(remote_addr->ip_addr, SRC_NTP);
+ result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, &result->remote_addr.ip_addr);
result->local_rx.tv_sec = 0;
result->local_rx.tv_usec = 0;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]",
- UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->remote_addr.port);
+ UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port);
#endif
/* Check whether we need to 'warm up' the link to the other end by
message->lvm, message->stratum, message->poll, message->precision);
LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion);
- LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%s], ref_time=%08lx.%08lx [%s]",
- UTI_IPToDottedQuad(ntohl(message->reference_id)),
+ LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
+ ntohl(message->reference_id),
message->reference_ts.hi, message->reference_ts.lo,
UTI_TimestampToString(&message->reference_ts));
LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]",
inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll;
- LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->minpoll);
+ LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
/* Back off for a while */
delay_time += (double) (4 * (1UL << inst->minpoll));
fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n",
UTI_TimeToLogForm(sample_time.tv_sec),
- UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
+ UTI_IPToString(&inst->remote_addr.ip_addr),
sync_stats[pkt_leap],
message->stratum,
test1, test2, test3, test4,
one of the secondaries to flywheel it. The behaviour coded here
is required in the secondaries to make this possible. */
- if (ADF_IsAllowed(access_auth_table, inst->remote_addr.ip_addr)) {
+ if (ADF_IsAllowed(access_auth_table, &inst->remote_addr.ip_addr)) {
- CLG_LogNTPClientAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPClientAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
if (do_auth) {
auth_key_id = ntohl(message->auth_keyid);
} else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
- UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
+ UTI_IPToString(&inst->remote_addr.ip_addr),
inst->remote_addr.port);
}
switch(inst->mode) {
case MODE_ACTIVE:
/* Ordinary symmetric peering */
- CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth);
break;
case MODE_PASSIVE:
case MODE_CLIENT:
/* This is where we have the remote configured as a server and he has
us configured as a peer - fair enough. */
- CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth);
break;
case MODE_SERVER:
switch(inst->mode) {
case MODE_ACTIVE:
/* Slightly bizarre combination, but we can still process it */
- CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth);
break;
case MODE_PASSIVE:
case MODE_ACTIVE:
/* This would arise if we have the remote configured as a peer and
he does not have us configured */
- CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth);
break;
case MODE_PASSIVE:
NTP_Mode my_mode;
int my_poll;
- if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) {
+ if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) {
/* We are server */
my_mode = MODE_SERVER;
- CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE;
- CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else {
my_mode = MODE_UNDEFINED;
}
} else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
- UTI_IPToDottedQuad(remote_addr->ip_addr),
+ UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port);
}
int valid_key, valid_auth;
unsigned long key_id;
- if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) {
+ if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) {
/* We are server */
my_mode = MODE_SERVER;
- CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE;
- CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+ CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else {
my_mode = MODE_UNDEFINED;
case MD_OFFLINE:
if (!inst->timer_running) {
/* We are not already actively polling it */
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToDottedQuad(inst->remote_addr.ip_addr));
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
inst->local_poll = inst->minpoll;
inst->score = (ZONE_WIDTH >> 1);
inst->opmode = MD_ONLINE;
switch (inst->opmode) {
case MD_ONLINE:
if (inst->timer_running) {
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToDottedQuad(inst->remote_addr.ip_addr));
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
SCH_RemoveTimeout(inst->timeout_id);
inst->timer_running = 0;
inst->opmode = MD_OFFLINE;
NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
{
inst->minpoll = new_minpoll;
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_minpoll);
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
}
/* ================================================== */
NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
{
inst->maxpoll = new_maxpoll;
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_maxpoll);
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
}
/* ================================================== */
{
inst->max_delay = new_max_delay;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
- UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay);
+ UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
}
/* ================================================== */
{
inst->max_delay_ratio = new_max_delay_ratio;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
- UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay_ratio);
+ UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
}
/* ================================================== */
/* ================================================== */
int
-NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all)
+NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{
ADF_Status status;
/* ================================================== */
int
-NCR_CheckAccessRestriction(unsigned long ip_addr)
+NCR_CheckAccessRestriction(IPAddr *ip_addr)
{
return ADF_IsAllowed(access_auth_table, ip_addr);
}
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
-extern int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
-extern int NCR_CheckAccessRestriction(unsigned long ip_addr);
+extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
+extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void);
#include <fcntl.h>
-/* The file descriptor for the socket */
-static int sock_fd;
+union sockaddr_in46 {
+ struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr u;
+};
+
+/* The file descriptors for the IPv4 and IPv6 sockets */
+static int sock_fd4;
+#ifdef HAVE_IPV6
+static int sock_fd6;
+#endif
/* Flag indicating that we have been initialised */
static int initialised=0;
/* ================================================== */
/* Forward prototypes */
+static int prepare_socket(int family);
static void read_from_socket(void *anything);
/* ================================================== */
/* ================================================== */
-void
-NIO_Initialise(void)
+static int
+prepare_socket(int family)
{
- struct sockaddr_in my_addr;
+ union sockaddr_in46 my_addr;
+ int sock_fd;
unsigned short port_number;
- unsigned long bind_address;
+ IPAddr bind_address;
int on_off = 1;
- assert(!initialised);
- initialised = 1;
-
- do_size_checks();
-
port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */
#if 0
- sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
#else
- sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ sock_fd = socket(family, SOCK_DGRAM, 0);
#endif
+
if (sock_fd < 0) {
- LOG_FATAL(LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
+ return -1;
}
/* Make the socket capable of re-using an old address */
/* Don't quit - we might survive anyway */
}
- /* We want the local IP info too */
- if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
- LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
- /* Don't quit - we might survive anyway */
+ if (family == AF_INET) {
+ /* We want the local IP info too */
+ if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
+ /* Don't quit - we might survive anyway */
+ }
+ }
+#ifdef HAVE_IPV6
+ else if (family == AF_INET6) {
+#ifdef IPV6_V6ONLY
+ /* Receive IPv6 packets only */
+ if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
+ }
+#endif
}
+#endif
/* Bind the port */
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(port_number);
-
- CNF_GetBindAddress(&bind_address);
-
- if (bind_address != 0UL) {
- my_addr.sin_addr.s_addr = htonl(bind_address);
- } else {
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ memset(&my_addr, 0, sizeof (my_addr));
+
+ switch (family) {
+ case AF_INET:
+ my_addr.in4.sin_family = family;
+ my_addr.in4.sin_port = htons(port_number);
+
+ CNF_GetBindAddress(IPADDR_INET4, &bind_address);
+
+ if (bind_address.family == IPADDR_INET4)
+ my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
+ else
+ my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ my_addr.in6.sin6_family = family;
+ my_addr.in6.sin6_port = htons(port_number);
+
+ CNF_GetBindAddress(IPADDR_INET6, &bind_address);
+
+ if (bind_address.family == IPADDR_INET6)
+ memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
+ sizeof (my_addr.in6.sin6_addr.s6_addr));
+ else
+ my_addr.in6.sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ assert(0);
}
#if 0
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#endif
- if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+ if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno));
}
/* Register handler for read events on the socket */
- SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
+ SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
#if 0
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
}
#endif
+ return sock_fd;
+}
+
+void
+NIO_Initialise(void)
+{
+ assert(!initialised);
+ initialised = 1;
+
+ do_size_checks();
+
+ sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+ sock_fd6 = prepare_socket(AF_INET6);
+#endif
+
+ if (sock_fd4 < 0
+#ifdef HAVE_IPV6
+ && sock_fd6 < 0
+#endif
+ ) {
+ LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
+ }
return;
}
void
NIO_Finalise(void)
{
- if (sock_fd >= 0) {
- SCH_RemoveInputFileHandler(sock_fd);
- close(sock_fd);
+ if (sock_fd4 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd4);
+ close(sock_fd4);
}
- sock_fd = -1;
+ sock_fd4 = -1;
+#ifdef HAVE_IPV6
+ if (sock_fd6 >= 0) {
+ SCH_RemoveInputFileHandler(sock_fd6);
+ close(sock_fd6);
+ }
+ sock_fd6 = -1;
+#endif
initialised = 0;
return;
}
/* This should only be called when there is something
to read, otherwise it will block. */
- int status;
+ int status, sock_fd;
ReceiveBuffer message;
- struct sockaddr_in where_from;
+ union sockaddr_in46 where_from;
unsigned int flags = 0;
struct timeval now;
NTP_Remote_Address remote_addr;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0;
+ sock_fd = (long)anything;
status = recvmsg(sock_fd, &msg, flags);
/* Don't bother checking if read failed or why if it did. More
reponse on a subsequent recvfrom). */
if (status > 0) {
- remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
- remote_addr.local_ip_addr = 0;
- remote_addr.port = ntohs(where_from.sin_port);
+ memset(&remote_addr, 0, sizeof (remote_addr));
+
+ switch (where_from.u.sa_family) {
+ case AF_INET:
+ remote_addr.ip_addr.family = IPADDR_INET4;
+ remote_addr.ip_addr.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
+ remote_addr.port = ntohs(where_from.in4.sin_port);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ remote_addr.ip_addr.family = IPADDR_INET6;
+ memcpy(&remote_addr.ip_addr.addr.in6, where_from.in6.sin6_addr.s6_addr,
+ sizeof (remote_addr.ip_addr.addr.in6));
+ remote_addr.port = ntohs(where_from.in6.sin6_port);
+ break;
+#endif
+ default:
+ assert(0);
+ }
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
struct in_pktinfo ipi;
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
- remote_addr.local_ip_addr = ntohl(ipi.ipi_spec_dst.s_addr);
+ remote_addr.local_ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
+ remote_addr.local_ip_addr.family = IPADDR_INET4;
}
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
static void
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
{
- struct sockaddr_in remote;
+ union sockaddr_in46 remote;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
char cmsgbuf[256];
int cmsglen;
+ int sock_fd;
assert(initialised);
- remote.sin_family = AF_INET;
- remote.sin_port = htons(remote_addr->port);
- remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
+ memset(&remote, 0, sizeof (remote));
+ switch (remote_addr->ip_addr.family) {
+ case IPADDR_INET4:
+ remote.in4.sin_family = AF_INET;
+ remote.in4.sin_port = htons(remote_addr->port);
+ remote.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
+ sock_fd = sock_fd4;
+ break;
+#ifdef HAVE_IPV6
+ case IPADDR_INET6:
+ remote.in6.sin6_family = AF_INET6;
+ remote.in6.sin6_port = htons(remote_addr->port);
+ memcpy(&remote.in6.sin6_addr.s6_addr, &remote_addr->ip_addr.addr.in6,
+ sizeof (remote.in6.sin6_addr.s6_addr));
+ sock_fd = sock_fd6;
+ break;
+#endif
+ default:
+ return;
+ }
+
+ if (sock_fd < 0)
+ return;
iov.iov_base = packet;
iov.iov_len = packetlen;
- msg.msg_name = &remote;
+ msg.msg_name = &remote.u;
msg.msg_namelen = sizeof(remote);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
cmsglen = 0;
- if (remote_addr->local_ip_addr) {
+ if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
struct in_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
ipi = (struct in_pktinfo *) CMSG_DATA(cmsg);
- ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr);
+ ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr.addr.in4);
#if 0
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
- UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, UTI_IPToDottedQuad(remote_addr->local_ip_addr));
+ UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
#endif
}
if (sendmsg(sock_fd, &msg, 0) < 0) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
- UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+ UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
return;
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{
unsigned long hash;
- unsigned long ip = remote_addr->ip_addr;
- unsigned short port = remote_addr->port;
+ unsigned long ip;
+ unsigned short port;
+ uint8_t *ip6;
assert(N_RECORDS == 256);
+ switch (remote_addr->ip_addr.family) {
+ case IPADDR_INET6:
+ ip6 = remote_addr->ip_addr.addr.in6;
+ ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
+ (ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
+ (ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
+ (ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
+ break;
+ case IPADDR_INET4:
+ ip = remote_addr->ip_addr.addr.in4;
+ break;
+ default:
+ *found = *slot = 0;
+ return;
+ }
+
+ port = remote_addr->port;
/* Compute hash value just by xor'ing the 4 bytes of the address together */
hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff;
while ((records[hash].in_use) &&
- (records[hash].remote_addr.ip_addr != ip)) {
+ UTI_CompareIPs(&records[hash].remote_addr.ip_addr,
+ &remote_addr->ip_addr, NULL)) {
hash++;
if (hash == 256) hash = 0;
}
assert(initialised);
#if 0
- LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long)remote_addr->ip_addr, remote_addr->port);
+ LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif
/* Find empty bin & check that we don't have the address already */
} else {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
+ } else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
+ remote_addr->ip_addr.family != IPADDR_INET6) {
+ return NSR_InvalidAF;
} else {
n_sources++;
records[slot].remote_addr = *remote_addr;
assert(initialised);
#if 0
- LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long) remote_addr->ip_addr, remote_addr->port);
+ LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif
/* Find empty bin & check that we don't have the address already */
} else {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
+ } else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
+ remote_addr->ip_addr.family != IPADDR_INET6) {
+ return NSR_InvalidAF;
} else {
n_sources++;
records[slot].remote_addr = *remote_addr;
#if 0
LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s",
- UTI_IPToDottedQuad(remote_addr->ip_addr),
+ UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port, UTI_TimevalToString(now));
#endif
if (records[i].in_use) {
#if 0
LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f",
- UTI_IPToDottedQuad(records[i].remote_addr.ip_addr), dfreq, doffset);
+ UTI_IPToString(&records[i].remote_addr.ip_addr), dfreq, doffset);
#endif
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
/* ================================================== */
int
-NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
+NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
- unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
- ip = records[i].remote_addr.ip_addr;
- if ((ip & mask) == address) {
+ if (address->family == IPADDR_UNSPEC ||
+ !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOnline(records[i].data);
}
/* ================================================== */
int
-NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
+NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
- unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
- ip = records[i].remote_addr.ip_addr;
- if ((ip & mask) == address) {
+ if (address->family == IPADDR_UNSPEC ||
+ !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOffline(records[i].data);
}
/* ================================================== */
int
-NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
+NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
{
int slot, found;
NTP_Remote_Address addr;
- addr.ip_addr = address;
+ addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
/* ================================================== */
int
-NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
+NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
{
int slot, found;
NTP_Remote_Address addr;
- addr.ip_addr = address;
+ addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
/* ================================================== */
int
-NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
+NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
{
int slot, found;
NTP_Remote_Address addr;
- addr.ip_addr = address;
+ addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
/* ================================================== */
int
-NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
+NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
{
int slot, found;
NTP_Remote_Address addr;
- addr.ip_addr = address;
+ addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
- unsigned long mask, unsigned long address)
+ IPAddr *mask, IPAddr *address)
{
int i;
int any;
- unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
- ip = records[i].remote_addr.ip_addr;
- if ((ip & mask) == address) {
+ if (address->family == IPADDR_UNSPEC ||
+ !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
}
NSR_Success, /* Operation successful */
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
- NSR_TooManySources /* AddServer, AddPeer - too many sources already present */
+ NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
+ NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
} NSR_Status;
/* Procedure to add a new server source (to which this machine will be
/* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set online again. Returns a
flag indicating whether any hosts matched the address */
-extern int NSR_TakeSourcesOnline(unsigned long mask, unsigned long address);
+extern int NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address);
/* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set offline. Returns a flag
indicating whether any hosts matched the address */
-extern int NSR_TakeSourcesOffline(unsigned long mask, unsigned long address);
+extern int NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address);
-extern int NSR_ModifyMinpoll(unsigned long address, int new_minpoll);
+extern int NSR_ModifyMinpoll(IPAddr *address, int new_minpoll);
-extern int NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll);
+extern int NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll);
-extern int NSR_ModifyMaxdelay(unsigned long address, double new_max_delay);
+extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
-extern int NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio);
+extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
-extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, unsigned long mask, unsigned long address);
+extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
- inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK);
+ inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
}
int i;
unsigned long ref_id;
- ref_id = report->ip_addr;
+ assert(report->ip_addr.family == IPADDR_INET4);
+ ref_id = report->ip_addr.addr.in4;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
#define GOT_REPORTS_H
#include "sysincl.h"
+#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000
typedef struct {
- unsigned long ip_addr;
+ IPAddr ip_addr;
int stratum;
int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
} RPT_TrackingReport;
typedef struct {
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned long n_samples;
unsigned long n_runs;
unsigned long span_seconds;
} RPT_ClientAccess_Report;
typedef struct {
- unsigned long ip_addr;
+ IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_auth;
unsigned long ref_id; /* The reference ID of this source
(i.e. its IP address, NOT the
reference _it_ is sync'd to) */
+ IPAddr *ip_addr; /* Its IP address if NTP source */
/* Flag indicating that we are receiving packets with valid headers
from this source and can use it as a reference */
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
-SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
+SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
{
SRC_Instance result;
result->index = n_sources;
result->leap_status = LEAP_Normal;
result->ref_id = ref_id;
+ result->ip_addr = addr;
result->reachable = 0;
result->status = SRC_BAD_STATS;
result->type = type;
{
switch (inst->type) {
case SRC_NTP:
- return UTI_IPToDottedQuad(inst->ref_id);
+ return UTI_IPToString(inst->ip_addr);
case SRC_REFCLOCK:
return UTI_RefidToString(inst->ref_id);
default:
return 0;
} else {
src = sources[index];
- report->ip_addr = src->ref_id;
+
+ memset(&report->ip_addr, 0, sizeof (report->ip_addr));
+ if (src->ip_addr)
+ report->ip_addr = *src->ip_addr;
+ else {
+ /* Use refid as an address */
+ report->ip_addr.addr.in4 = src->ref_id;
+ report->ip_addr.family = IPADDR_INET4;
+ }
+
switch (src->status) {
case SRC_SYNC:
report->state = RPT_SYNC;
return 0;
} else {
src = sources[index];
- report->ip_addr = src->ref_id;
+ if (src->ip_addr)
+ report->ip_addr = *src->ip_addr;
+ else
+ report->ip_addr.family = IPADDR_UNSPEC;
SST_DoSourcestatsReport(src->stats, report);
return 1;
}
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
-extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type);
+extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr);
/* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this
#endif
+#ifdef HAVE_IPV6
+/* For inet_ntop() */
+#include <arpa/inet.h>
+#endif
+
#if defined (SOLARIS) || defined(SUNOS)
/* Only needed on these platforms, and doesn't exist on some Linux
versions. */
#include "sysincl.h"
#include "util.h"
+#include "md5.h"
/* ================================================== */
/* ================================================== */
+char *
+UTI_IPToString(IPAddr *addr)
+{
+ unsigned long a, b, c, d, ip;
+ uint8_t *ip6;
+ char *result;
+
+ result = NEXT_BUFFER;
+ switch (addr->family) {
+ case IPADDR_UNSPEC:
+ snprintf(result, BUFFER_LENGTH, "[UNSPEC]");
+ break;
+ case IPADDR_INET4:
+ ip = addr->addr.in4;
+ a = (ip>>24) & 0xff;
+ b = (ip>>16) & 0xff;
+ c = (ip>> 8) & 0xff;
+ d = (ip>> 0) & 0xff;
+ snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d);
+ break;
+ case IPADDR_INET6:
+ ip6 = addr->addr.in6;
+#ifdef HAVE_IPV6
+ inet_ntop(AF_INET6, ip6, result, BUFFER_LENGTH);
+#else
+ snprintf(result, BUFFER_LENGTH, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7],
+ ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]);
+#endif
+ break;
+ default:
+ snprintf(result, BUFFER_LENGTH, "[UNKNOWN]");
+ }
+ return result;
+}
+
+/* ================================================== */
+
+int
+UTI_StringToIP(const char *addr, IPAddr *ip)
+{
+#ifdef HAVE_IPV6
+ struct in_addr in4;
+ struct in6_addr in6;
+
+ if (inet_pton(AF_INET, addr, &in4) > 0) {
+ ip->family = IPADDR_INET4;
+ ip->addr.in4 = ntohl(in4.s_addr);
+ return 1;
+ }
+
+ if (inet_pton(AF_INET6, addr, &in6) > 0) {
+ ip->family = IPADDR_INET6;
+ memcpy(ip->addr.in6, in6.s6_addr, sizeof (ip->addr.in6));
+ return 1;
+ }
+#else
+ unsigned long a, b, c, d, n;
+
+ n = sscanf(addr, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
+ if (n == 4) {
+ ip->family = IPADDR_INET4;
+ ip->addr.in4 = ((a & 0xff) << 24) | ((b & 0xff) << 16) |
+ ((c & 0xff) << 8) | (d & 0xff);
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+/* ================================================== */
+
+unsigned long
+UTI_IPToRefid(IPAddr *ip)
+{
+ MD5_CTX ctx;
+
+ switch (ip->family) {
+ case IPADDR_INET4:
+ return ip->addr.in4;
+ case IPADDR_INET6:
+ MD5Init(&ctx);
+ MD5Update(&ctx, (unsigned const char *) ip->addr.in6, sizeof (ip->addr.in6));
+ MD5Final(&ctx);
+ return ctx.digest[0] << 24 | ctx.digest[1] << 16 | ctx.digest[2] << 8 | ctx.digest[3];
+ }
+ return 0;
+}
+
+/* ================================================== */
+
+void
+UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest)
+{
+ /* Don't send uninitialized bytes over network */
+ memset(dest, 0, sizeof (IPAddr));
+
+ dest->family = htons(src->family);
+
+ switch (src->family) {
+ case IPADDR_INET4:
+ dest->addr.in4 = htonl(src->addr.in4);
+ break;
+ case IPADDR_INET6:
+ memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
+ break;
+ }
+}
+
+/* ================================================== */
+
+void
+UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest)
+{
+ dest->family = ntohs(src->family);
+
+ switch (dest->family) {
+ case IPADDR_INET4:
+ dest->addr.in4 = ntohl(src->addr.in4);
+ break;
+ case IPADDR_INET6:
+ memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
+ break;
+ }
+}
+
+/* ================================================== */
+
+int
+UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask)
+{
+ int i, d;
+
+ if (a->family != b->family)
+ return a->family - b->family;
+
+ if (mask && mask->family != b->family)
+ mask = NULL;
+
+ switch (a->family) {
+ case IPADDR_UNSPEC:
+ return 0;
+ case IPADDR_INET4:
+ if (mask)
+ return (a->addr.in4 & mask->addr.in4) - (b->addr.in4 & mask->addr.in4);
+ else
+ return a->addr.in4 - b->addr.in4;
+ case IPADDR_INET6:
+ for (i = 0, d = 0; !d && i < 16; i++) {
+ if (mask)
+ d = (a->addr.in6[i] & mask->addr.in6[i]) -
+ (b->addr.in6[i] & mask->addr.in6[i]);
+ else
+ d = a->addr.in6[i] - b->addr.in6[i];
+ }
+ return d;
+ }
+ return 0;
+}
+
+/* ================================================== */
+
char *
UTI_TimeToLogForm(time_t t)
{
#include "sysincl.h"
+#include "addressing.h"
#include "ntp.h"
/* Convert a timeval into a floating point number of seconds */
/* Convert ref_id into a temporary string, for diagnostics */
extern char *UTI_RefidToString(unsigned long ref_id);
-/* Convert an IP address to dotted quad notation, for diagnostics */
+/* Convert an IP address to string, for diagnostics */
extern char *UTI_IPToDottedQuad(unsigned long ip);
+extern char *UTI_IPToString(IPAddr *ip);
+
+extern int UTI_StringToIP(const char *addr, IPAddr *ip);
+extern unsigned long UTI_IPToRefid(IPAddr *ip);
+extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
+extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
+extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
extern char *UTI_TimeToLogForm(time_t t);