+* [Bug 1215] unpeer by association ID
(4.2.5p181) 2009/06/06 Released by Harlan Stenn <stenn@ntp.org>
* [Bug 1206] Required compiler changes for Windows
* [Bug 1084] PPSAPI for ntpd on Windows with DLL backends
};
struct unpeer_node {
- struct address_node *addr;
+ u_int assocID;
+ struct address_node * addr;
};
struct auth_node {
/* Structure for holding a remote configuration command */
struct REMOTE_CONFIG_INFO {
- char buffer[MAXLINE];
- char err_msg[MAXLINE];
- int pos;
- int err_pos;
- int no_errors;
+ char buffer[MAXLINE];
+ char err_msg[MAXLINE];
+ int pos;
+ int err_pos;
+ int no_errors;
};
#include "iosignal.h"
#include <isc/list.h>
+
+
+#ifdef DEBUG
+static void uninit_recvbuff(void);
+#endif
+
/*
* Memory allocation
*/
static u_long volatile total_recvbufs; /* total recvbufs currently in use */
static u_long volatile lowater_adds; /* number of times we have added memory */
static u_long volatile buffer_shortfall;/* number of missed free receive buffers
- between replenishments */
+ between replenishments */
static ISC_LIST(recvbuf_t) full_recv_list; /* Currently used recv buffers */
static ISC_LIST(recvbuf_t) free_recv_list; /* Currently unused buffers */
abuf = nbufs + buffer_shortfall;
buffer_shortfall = 0;
- bufp = (recvbuf_t *) emalloc(abuf*sizeof(recvbuf_t));
+#ifndef DEBUG
+ bufp = emalloc(abuf * sizeof(*bufp));
+#endif
- for (i = 0; i < abuf; i++)
- {
- memset((char *) bufp, 0, sizeof(recvbuf_t));
+ for (i = 0; i < abuf; i++) {
+#ifdef DEBUG
+ /*
+ * Allocate each buffer individually so they can be
+ * free()d during ntpd shutdown on DEBUG builds to
+ * keep them out of heap leak reports.
+ */
+ bufp = emalloc(sizeof(*bufp));
+#endif
+ memset(bufp, 0, sizeof(*bufp));
ISC_LIST_APPEND(free_recv_list, bufp, link);
bufp++;
free_recvbufs++;
InitializeCriticalSection(&RecvLock);
#endif
+#ifdef DEBUG
+ atexit(&uninit_recvbuff);
+#endif
+}
+
+
+#ifdef DEBUG
+static void
+uninit_recvbuff(void)
+{
+ recvbuf_t * rb;
+
+ for (rb = ISC_LIST_HEAD(full_recv_list);
+ rb != NULL;
+ rb = ISC_LIST_HEAD(full_recv_list)) {
+
+ ISC_LIST_DEQUEUE(full_recv_list, rb, link);
+ free(rb);
+ }
+
+ for (rb = ISC_LIST_HEAD(free_recv_list);
+ rb != NULL;
+ rb = ISC_LIST_HEAD(free_recv_list)) {
+
+ ISC_LIST_DEQUEUE(free_recv_list, rb, link);
+ free(rb);
+ }
}
+#endif /* DEBUG */
+
/*
* freerecvbuf - make a single recvbuf available for reuse
struct address_node *addr
)
{
- struct unpeer_node* my_node;
+ struct unpeer_node * my_node;
+ char * pch;
- my_node = get_node(sizeof *my_node);
+ my_node = get_node(sizeof(*my_node));
- my_node->addr = addr;
+ /*
+ * From the parser's perspective an association ID fits into
+ * its generic T_String definition of a name/address "address".
+ * We treat all valid 16-bit numbers as association IDs.
+ */
+ pch = addr->address;
+ while (*pch && isdigit(*pch))
+ pch++;
+
+ if (!*pch
+ && 1 == sscanf(addr->address, "%u", &my_node->assocID)
+ && my_node->assocID <= USHRT_MAX) {
+
+ destroy_address_node(addr);
+ my_node->addr = NULL;
+ } else {
+ my_node->assocID = 0;
+ my_node->addr = addr;
+ }
return my_node;
}
while (!empty(my_config.unpeers)) {
curr_unpeer = (struct unpeer_node *) dequeue(my_config.unpeers);
- /* Attempt to resolve the address */
+ /*
+ * Either AssocID will be zero, and we unpeer by name/
+ * address addr, or it is nonzero and addr NULL.
+ */
+ if (curr_unpeer->assocID) {
+ peer = findpeerbyassoc((u_int)curr_unpeer->assocID);
+ if (peer != NULL) {
+ peer_clear(peer, "GONE");
+ unpeer(peer);
+ }
+
+ /* Ok, everything done. Free up peer node memory */
+ free_node(curr_unpeer);
+ continue;
+ }
+
+ /* Attempt to resolve the name or address */
memset((char *)&peeraddr, 0, sizeof(peeraddr));
peeraddr.ss_family = (u_short)curr_unpeer->addr->type;
- status = get_multiple_netnums(curr_unpeer->addr->address, &peeraddr, &res, 0, t_UNK);
+ status = get_multiple_netnums(
+ curr_unpeer->addr->address, &peeraddr, &res, 0,
+ t_UNK);
/* I don't know why getnetnum would return -1.
* The old code had this test, so I guess it must be
}
/* Ok, everything done. Free up peer node memory */
- free(curr_unpeer->addr->address);
- free_node(curr_unpeer->addr);
+ destroy_address_node(curr_unpeer->addr);
free_node(curr_unpeer);
}
}
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
+/* #define MALLOC_LINT */ /* ntservice.c */
#endif
/*
SERIAL_WRITE
};
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 201) /* nonstd extension nameless union */
+#endif
typedef struct IoCompletionInfo {
- OVERLAPPED overlapped;
- int request_type;
+ OVERLAPPED overlapped; /* must be first */
+ int request_type;
union {
- recvbuf_t *rbuf;
- transmitbuf_t *tbuf;
- } buff_space;
+ recvbuf_t * recv_buf;
+ transmitbuf_t * trans_buf;
+ };
+#ifdef DEBUG
+ ISC_LINK(struct IoCompletionInfo) link;
+#endif
} IoCompletionInfo;
-#define recv_buf buff_space.rbuf
-#define trans_buf buff_space.tbuf
-
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
/*
* local function definitions
static int OnSerialReadComplete(ULONG_PTR, IoCompletionInfo *, DWORD, int);
static int OnWriteComplete(ULONG_PTR, IoCompletionInfo *, DWORD, int);
+/* keep a list to traverse to free memory on debug builds */
+#ifdef DEBUG
+static void free_io_completion_port_mem(void);
+ISC_LIST(IoCompletionInfo) compl_info_list;
+CRITICAL_SECTION compl_info_lock;
+#define LOCK_COMPL() EnterCriticalSection(&compl_info_lock);
+#define UNLOCK_COMPL() LeaveCriticalSection(&compl_info_lock);
+#endif
+
/* #define USE_HEAP */
#ifdef USE_HEAP
#endif
DPRINTF(3, ("Allocation %d memory for %s, ptr %x\n", sizeof(IoCompletionInfo), fromfunc, lpo));
+#ifdef DEBUG
+ LOCK_COMPL();
+ ISC_LIST_APPEND(compl_info_list, lpo, link);
+ UNLOCK_COMPL();
+#endif
+
return (lpo);
}
{
DPRINTF(3, ("Freeing memory for %s, ptr %x\n", fromfunc, lpo));
+#ifdef DEBUG
+ LOCK_COMPL();
+ ISC_LIST_DEQUEUE(compl_info_list, lpo, link);
+ UNLOCK_COMPL();
+#endif
+
#ifdef USE_HEAP
HeapFree(hHeapHandle, 0, lpo);
#else
unsigned tid;
HANDLE thread;
+#ifdef DEBUG
+ ISC_LIST_INIT(compl_info_list);
+ InitializeCriticalSection(&compl_info_lock);
+ atexit(&free_io_completion_port_mem);
+#endif
+
#ifdef USE_HEAP
/*
* Create a handle to the Heap
/*
* Initialize the Wait Handles
*/
- WaitHandles[0] = get_io_event();
- WaitHandles[1] = get_exit_event(); /* exit request */
+ WaitHandles[0] = WaitableIoEventHandle;
+ WaitHandles[1] = WaitableExitEventHandle; /* exit request */
WaitHandles[2] = get_timer_handle();
/* Have one thread servicing I/O - there were 4, but this would
}
+#ifdef DEBUG
+static void
+free_io_completion_port_mem(
+ void
+ )
+{
+ IoCompletionInfo * pci;
+
+ LOCK_COMPL();
+ for (pci = ISC_LIST_HEAD(compl_info_list);
+ pci != NULL;
+ pci = ISC_LIST_HEAD(compl_info_list)) {
+
+ /* this handles both xmit and recv buffs */
+ if (pci->recv_buf != NULL)
+ free(pci->recv_buf);
+
+ FreeHeap(pci, "free_io_completion_port_mem");
+ /* FreeHeap() removed this item from compl_info_list */
+ }
+ UNLOCK_COMPL()
+}
+#endif /* DEBUG */
+
+
void
uninit_io_completion_port(
void
if (errstatus == WSA_OPERATION_ABORTED)
{
freerecvbuf(buff);
+ lpo->recv_buf = NULL;
FreeHeap(lpo, "OnSocketRecv: Socket Closed");
return (1);
}
buff = lpo->trans_buf;
free_trans_buf(buff);
+ lpo->trans_buf = NULL;
if (SOCK_SEND == lpo->request_type) {
switch (errstatus) {
* Something bad happened
*/
default :
- netsyslog(LOG_ERR, "WSASendTo - error sending message: %m");
+ msyslog(LOG_ERR, "WSASendTo - error sending message: %m");
free_trans_buf(buff);
+ lpo->trans_buf = NULL;
FreeHeap(lpo, "io_completion_port_sendto");
break;
}
if (! buff || ! lpo) {
if (buff) {
free_trans_buf(buff);
-#ifdef DEBUG
- if (debug)
- printf("async_write: out of memory, \n");
-#endif
- } else {
+ DPRINTF(1, ("async_write: out of memory\n"));
+ } else
msyslog(LOG_ERR, "No more transmit buffers left - data discarded");
- }
errno = ENOMEM;
return -1;
lpo->trans_buf = buff;
memcpy(&buff->pkt, data, count);
- if (! WriteFile((HANDLE)_get_osfhandle(fd), buff->pkt, count, &BytesWritten, (LPOVERLAPPED) lpo) &&
- ERROR_IO_PENDING != GetLastError()) {
+ if (!WriteFile((HANDLE)_get_osfhandle(fd), buff->pkt, count,
+ &BytesWritten, (LPOVERLAPPED)lpo)
+ && ERROR_IO_PENDING != GetLastError()) {
msyslog(LOG_ERR, "async_write - error %m");
free_trans_buf(buff);
+ lpo->trans_buf = NULL;
FreeHeap(lpo, "async_write");
errno = EBADF;
return -1;