]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1215] unpeer by association ID
authorDave Hart <hart@ntp.org>
Mon, 8 Jun 2009 17:51:47 +0000 (17:51 +0000)
committerDave Hart <hart@ntp.org>
Mon, 8 Jun 2009 17:51:47 +0000 (17:51 +0000)
bk: 4a2d4fb3kdzZQDuQhvSoAyiRuI4Nzw

ChangeLog
include/ntp_config.h
libntp/recvbuff.c
ntpd/ntp_config.c
ports/winnt/include/config.h
ports/winnt/ntpd/ntp_iocompletionport.c

index e8a4ade80c93acb37257c925ad90f0203a46ce0e..d0b0af19ffcac7da9f04688578e6476c406cd198 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+* [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
index ba5c2bbc2f19fbc71c141e5d0c3f0967a84f1238..d29d5945d3d3bf7c4d00ed2ea1154b128b06686b 100644 (file)
@@ -84,7 +84,8 @@ struct peer_node {
 };
 
 struct unpeer_node {
-    struct address_node *addr;
+       u_int                   assocID;
+       struct address_node *   addr;
 };
 
 struct auth_node {
@@ -166,11 +167,11 @@ struct config_tree {
 
 /* 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;
 };
 
 
index 71581b5e01613fdc61cd1575c910c6b319c9c887..5f05bdaa73198288b8904db8f516321628a855c1 100644 (file)
 #include "iosignal.h"
 
 #include <isc/list.h>
+
+
+#ifdef DEBUG
+static void uninit_recvbuff(void);
+#endif
+
 /*
  * Memory allocation
  */
@@ -21,7 +27,7 @@ static u_long volatile free_recvbufs; /* number of recvbufs on freelist */
 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 */
@@ -80,11 +86,20 @@ create_buffers(int nbufs)
        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++;
@@ -111,7 +126,36 @@ init_recvbuff(int nbufs)
        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
index 00d4f98e232718edf8cbc65b1b1770483b2cdabe..951cb2cc84a2c93c785175cd31af7e79f09b2cea 100644 (file)
@@ -626,11 +626,30 @@ create_unpeer_node(
        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;
 }
@@ -2059,11 +2078,29 @@ config_unpeers(void)
        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
@@ -2114,8 +2151,7 @@ config_unpeers(void)
                }
 
                /* 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);
        }
 }
index f08a6995c2ec4ca90a18e7766a10409ef8db3efc..8960cb1b29d4740b59ef2a02082ab8cbe5e17da0 100644 (file)
@@ -33,6 +33,7 @@
 #define _CRTDBG_MAP_ALLOC
 #include <stdlib.h>
 #include <crtdbg.h>
+/* #define MALLOC_LINT */      /* ntservice.c */
 #endif
 
 /*
index 5be1071694238052972edf0fa945f29655093027..b87f02eae85e53a6367da4aaff08773cdebef7b8 100644 (file)
@@ -34,19 +34,26 @@ enum {
        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
@@ -58,6 +65,15 @@ static int OnSerialWaitComplete(ULONG_PTR, IoCompletionInfo *, DWORD, int);
 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
@@ -92,6 +108,12 @@ GetHeapAlloc(char *fromfunc)
 #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);
 }
 
@@ -100,6 +122,12 @@ FreeHeap(IoCompletionInfo *lpo, char *fromfunc)
 {
        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
@@ -257,6 +285,12 @@ init_io_completion_port(
        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
@@ -301,8 +335,8 @@ init_io_completion_port(
        /*
         * 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 
@@ -320,6 +354,31 @@ init_io_completion_port(
 }
        
 
+#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
@@ -618,6 +677,7 @@ OnSocketRecv(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus)
        if (errstatus == WSA_OPERATION_ABORTED)
        {
                freerecvbuf(buff);
+               lpo->recv_buf = NULL;
                FreeHeap(lpo, "OnSocketRecv: Socket Closed");
                return (1);
        }
@@ -717,6 +777,7 @@ OnWriteComplete(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus)
        buff = lpo->trans_buf;
 
        free_trans_buf(buff);
+       lpo->trans_buf = NULL;
 
        if (SOCK_SEND == lpo->request_type) {
                switch (errstatus) {
@@ -802,8 +863,9 @@ io_completion_port_sendto(
                         * 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;
                        }
@@ -854,13 +916,9 @@ async_write(
        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;
@@ -870,11 +928,13 @@ async_write(
        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;