1c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 2c0b746e5SOllivier Robert # include <config.h> 3c0b746e5SOllivier Robert #endif 4c0b746e5SOllivier Robert 5c0b746e5SOllivier Robert #include <stdio.h> 6c0b746e5SOllivier Robert #include "ntp_machine.h" 7c0b746e5SOllivier Robert #include "ntp_fp.h" 8c0b746e5SOllivier Robert #include "ntp_syslog.h" 9224ba2bdSOllivier Robert #include "ntp_stdlib.h" 10c0b746e5SOllivier Robert #include "ntp_io.h" 11c0b746e5SOllivier Robert #include "recvbuff.h" 12c0b746e5SOllivier Robert #include "iosignal.h" 13c0b746e5SOllivier Robert 14ea906c41SOllivier Robert #include <isc/list.h> 15c0b746e5SOllivier Robert /* 16c0b746e5SOllivier Robert * Memory allocation 17c0b746e5SOllivier Robert */ 18c0b746e5SOllivier Robert static u_long volatile full_recvbufs; /* number of recvbufs on fulllist */ 19c0b746e5SOllivier Robert static u_long volatile free_recvbufs; /* number of recvbufs on freelist */ 20c0b746e5SOllivier Robert static u_long volatile total_recvbufs; /* total recvbufs currently in use */ 21c0b746e5SOllivier Robert static u_long volatile lowater_adds; /* number of times we have added memory */ 22ea906c41SOllivier Robert static u_long volatile buffer_shortfall;/* number of missed free receive buffers 23ea906c41SOllivier Robert between replenishments */ 24c0b746e5SOllivier Robert 25ea906c41SOllivier Robert static ISC_LIST(recvbuf_t) full_recv_list; /* Currently used recv buffers */ 26ea906c41SOllivier Robert static ISC_LIST(recvbuf_t) free_recv_list; /* Currently unused buffers */ 27c0b746e5SOllivier Robert 28ea906c41SOllivier Robert #if defined(SYS_WINNT) 29ea906c41SOllivier Robert 30ea906c41SOllivier Robert /* 31ea906c41SOllivier Robert * For Windows we need to set up a lock to manipulate the 32ea906c41SOllivier Robert * recv buffers to prevent corruption. We keep it lock for as 33ea906c41SOllivier Robert * short a time as possible 34ea906c41SOllivier Robert */ 35ea906c41SOllivier Robert static CRITICAL_SECTION RecvLock; 36ea906c41SOllivier Robert # define LOCK() EnterCriticalSection(&RecvLock) 37ea906c41SOllivier Robert # define UNLOCK() LeaveCriticalSection(&RecvLock) 38c0b746e5SOllivier Robert #else 39ea906c41SOllivier Robert # define LOCK() 40ea906c41SOllivier Robert # define UNLOCK() 41c0b746e5SOllivier Robert #endif 42c0b746e5SOllivier Robert 43c0b746e5SOllivier Robert u_long 44c0b746e5SOllivier Robert free_recvbuffs (void) 45c0b746e5SOllivier Robert { 46c0b746e5SOllivier Robert return free_recvbufs; 47c0b746e5SOllivier Robert } 48c0b746e5SOllivier Robert 49c0b746e5SOllivier Robert u_long 50c0b746e5SOllivier Robert full_recvbuffs (void) 51c0b746e5SOllivier Robert { 52ea906c41SOllivier Robert return full_recvbufs; 53c0b746e5SOllivier Robert } 54c0b746e5SOllivier Robert 55c0b746e5SOllivier Robert u_long 56c0b746e5SOllivier Robert total_recvbuffs (void) 57c0b746e5SOllivier Robert { 58ea906c41SOllivier Robert return total_recvbufs; 59c0b746e5SOllivier Robert } 60c0b746e5SOllivier Robert 61c0b746e5SOllivier Robert u_long 62c0b746e5SOllivier Robert lowater_additions(void) 63c0b746e5SOllivier Robert { 64c0b746e5SOllivier Robert return lowater_adds; 65c0b746e5SOllivier Robert } 66c0b746e5SOllivier Robert 67c0b746e5SOllivier Robert static void 68ea906c41SOllivier Robert initialise_buffer(recvbuf_t *buff) 69c0b746e5SOllivier Robert { 70ea906c41SOllivier Robert memset((char *) buff, 0, sizeof(recvbuf_t)); 71c0b746e5SOllivier Robert 72ea906c41SOllivier Robert #if defined SYS_WINNT 73c0b746e5SOllivier Robert buff->wsabuff.len = RX_BUFF_SIZE; 74c0b746e5SOllivier Robert buff->wsabuff.buf = (char *) buff->recv_buffer; 75c0b746e5SOllivier Robert #endif 76c0b746e5SOllivier Robert } 77c0b746e5SOllivier Robert 78c0b746e5SOllivier Robert static void 79ea906c41SOllivier Robert create_buffers(int nbufs) 80c0b746e5SOllivier Robert { 81ea906c41SOllivier Robert register recvbuf_t *bufp; 82ea906c41SOllivier Robert int i, abuf; 83c0b746e5SOllivier Robert 84ea906c41SOllivier Robert abuf = nbufs + buffer_shortfall; 85ea906c41SOllivier Robert buffer_shortfall = 0; 86ea906c41SOllivier Robert 87ea906c41SOllivier Robert bufp = (recvbuf_t *) emalloc(abuf*sizeof(recvbuf_t)); 88ea906c41SOllivier Robert 89ea906c41SOllivier Robert for (i = 0; i < abuf; i++) 90ea906c41SOllivier Robert { 91ea906c41SOllivier Robert memset((char *) bufp, 0, sizeof(recvbuf_t)); 92ea906c41SOllivier Robert ISC_LIST_APPEND(free_recv_list, bufp, link); 93ea906c41SOllivier Robert bufp++; 94ea906c41SOllivier Robert free_recvbufs++; 95ea906c41SOllivier Robert total_recvbufs++; 96ea906c41SOllivier Robert } 97c0b746e5SOllivier Robert lowater_adds++; 98c0b746e5SOllivier Robert } 99c0b746e5SOllivier Robert 100c0b746e5SOllivier Robert void 101c0b746e5SOllivier Robert init_recvbuff(int nbufs) 102c0b746e5SOllivier Robert { 103c0b746e5SOllivier Robert 104c0b746e5SOllivier Robert /* 105c0b746e5SOllivier Robert * Init buffer free list and stat counters 106c0b746e5SOllivier Robert */ 107ea906c41SOllivier Robert ISC_LIST_INIT(full_recv_list); 108ea906c41SOllivier Robert ISC_LIST_INIT(free_recv_list); 109ea906c41SOllivier Robert free_recvbufs = total_recvbufs = 0; 110c0b746e5SOllivier Robert full_recvbufs = lowater_adds = 0; 111c0b746e5SOllivier Robert 112ea906c41SOllivier Robert create_buffers(nbufs); 113ea906c41SOllivier Robert 114ea906c41SOllivier Robert #if defined(SYS_WINNT) 115ea906c41SOllivier Robert InitializeCriticalSection(&RecvLock); 116c0b746e5SOllivier Robert #endif 117c0b746e5SOllivier Robert 118c0b746e5SOllivier Robert } 119c0b746e5SOllivier Robert 120c0b746e5SOllivier Robert /* 121c0b746e5SOllivier Robert * freerecvbuf - make a single recvbuf available for reuse 122c0b746e5SOllivier Robert */ 123c0b746e5SOllivier Robert void 124ea906c41SOllivier Robert freerecvbuf(recvbuf_t *rb) 125c0b746e5SOllivier Robert { 126ea906c41SOllivier Robert if (rb == NULL) { 127ea906c41SOllivier Robert msyslog(LOG_ERR, "freerecvbuff received NULL buffer"); 128ea906c41SOllivier Robert return; 129ea906c41SOllivier Robert } 130ea906c41SOllivier Robert 131ea906c41SOllivier Robert LOCK(); 132ea906c41SOllivier Robert (rb->used)--; 133ea906c41SOllivier Robert if (rb->used != 0) 134ea906c41SOllivier Robert msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used); 135ea906c41SOllivier Robert ISC_LIST_APPEND(free_recv_list, rb, link); 136ea906c41SOllivier Robert #if defined SYS_WINNT 137ea906c41SOllivier Robert rb->wsabuff.len = RX_BUFF_SIZE; 138ea906c41SOllivier Robert rb->wsabuff.buf = (char *) rb->recv_buffer; 139ea906c41SOllivier Robert #endif 140c0b746e5SOllivier Robert free_recvbufs++; 141ea906c41SOllivier Robert UNLOCK(); 142c0b746e5SOllivier Robert } 143c0b746e5SOllivier Robert 144c0b746e5SOllivier Robert 145c0b746e5SOllivier Robert void 146ea906c41SOllivier Robert add_full_recv_buffer(recvbuf_t *rb) 147c0b746e5SOllivier Robert { 148ea906c41SOllivier Robert if (rb == NULL) { 149ea906c41SOllivier Robert msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer"); 150ea906c41SOllivier Robert return; 151c0b746e5SOllivier Robert } 152ea906c41SOllivier Robert LOCK(); 153ea906c41SOllivier Robert ISC_LIST_APPEND(full_recv_list, rb, link); 154c0b746e5SOllivier Robert full_recvbufs++; 155ea906c41SOllivier Robert UNLOCK(); 156c0b746e5SOllivier Robert } 157c0b746e5SOllivier Robert 158ea906c41SOllivier Robert recvbuf_t * 159c0b746e5SOllivier Robert get_free_recv_buffer(void) 160c0b746e5SOllivier Robert { 161ea906c41SOllivier Robert recvbuf_t * buffer = NULL; 162ea906c41SOllivier Robert LOCK(); 163ea906c41SOllivier Robert buffer = ISC_LIST_HEAD(free_recv_list); 164ea906c41SOllivier Robert if (buffer != NULL) 165c0b746e5SOllivier Robert { 166ea906c41SOllivier Robert ISC_LIST_DEQUEUE(free_recv_list, buffer, link); 167ea906c41SOllivier Robert free_recvbufs--; 168ea906c41SOllivier Robert initialise_buffer(buffer); 169ea906c41SOllivier Robert (buffer->used)++; 170c0b746e5SOllivier Robert } 171c0b746e5SOllivier Robert else 172c0b746e5SOllivier Robert { 173ea906c41SOllivier Robert buffer_shortfall++; 174c0b746e5SOllivier Robert } 175ea906c41SOllivier Robert UNLOCK(); 176ea906c41SOllivier Robert return (buffer); 177c0b746e5SOllivier Robert } 178c0b746e5SOllivier Robert 179ea906c41SOllivier Robert #ifdef HAVE_IO_COMPLETION_PORT 180ea906c41SOllivier Robert recvbuf_t * 181ea906c41SOllivier Robert get_free_recv_buffer_alloc(void) 182c0b746e5SOllivier Robert { 183ea906c41SOllivier Robert recvbuf_t * buffer = get_free_recv_buffer(); 184ea906c41SOllivier Robert if (buffer == NULL) 185ea906c41SOllivier Robert { 186ea906c41SOllivier Robert create_buffers(RECV_INC); 187ea906c41SOllivier Robert buffer = get_free_recv_buffer(); 188c0b746e5SOllivier Robert } 189ea906c41SOllivier Robert return (buffer); 190c0b746e5SOllivier Robert } 191ea906c41SOllivier Robert #endif 192c0b746e5SOllivier Robert 193ea906c41SOllivier Robert recvbuf_t * 194c0b746e5SOllivier Robert get_full_recv_buffer(void) 195c0b746e5SOllivier Robert { 196ea906c41SOllivier Robert recvbuf_t *rbuf; 197ea906c41SOllivier Robert LOCK(); 198ea906c41SOllivier Robert 199ea906c41SOllivier Robert #ifdef HAVE_SIGNALED_IO 200ea906c41SOllivier Robert /* 201ea906c41SOllivier Robert * make sure there are free buffers when we 202ea906c41SOllivier Robert * wander off to do lengthy paket processing with 203ea906c41SOllivier Robert * any buffer we grab from the full list. 204ea906c41SOllivier Robert * 205ea906c41SOllivier Robert * fixes malloc() interrupted by SIGIO risk 206ea906c41SOllivier Robert * (Bug 889) 207ea906c41SOllivier Robert */ 208ea906c41SOllivier Robert rbuf = ISC_LIST_HEAD(free_recv_list); 209ea906c41SOllivier Robert if (rbuf == NULL || buffer_shortfall > 0) { 210ea906c41SOllivier Robert /* 211ea906c41SOllivier Robert * try to get us some more buffers 212ea906c41SOllivier Robert */ 213ea906c41SOllivier Robert create_buffers(RECV_INC); 214c0b746e5SOllivier Robert } 215ea906c41SOllivier Robert #endif 216ea906c41SOllivier Robert 217ea906c41SOllivier Robert /* 218ea906c41SOllivier Robert * try to grab a full buffer 219ea906c41SOllivier Robert */ 220ea906c41SOllivier Robert rbuf = ISC_LIST_HEAD(full_recv_list); 221ea906c41SOllivier Robert if (rbuf != NULL) 222ea906c41SOllivier Robert { 223ea906c41SOllivier Robert ISC_LIST_DEQUEUE(full_recv_list, rbuf, link); 224ea906c41SOllivier Robert --full_recvbufs; 225ea906c41SOllivier Robert } 226ea906c41SOllivier Robert else 227ea906c41SOllivier Robert { 228ea906c41SOllivier Robert /* 229ea906c41SOllivier Robert * Make sure we reset the full count to 0 230ea906c41SOllivier Robert */ 231ea906c41SOllivier Robert full_recvbufs = 0; 232ea906c41SOllivier Robert } 233ea906c41SOllivier Robert UNLOCK(); 234ea906c41SOllivier Robert return (rbuf); 235ea906c41SOllivier Robert } 236ea906c41SOllivier Robert 237ea906c41SOllivier Robert /* 238ea906c41SOllivier Robert * Checks to see if there are buffers to process 239ea906c41SOllivier Robert */ 240ea906c41SOllivier Robert isc_boolean_t has_full_recv_buffer(void) 241ea906c41SOllivier Robert { 242ea906c41SOllivier Robert if (ISC_LIST_HEAD(full_recv_list) != NULL) 243ea906c41SOllivier Robert return (ISC_TRUE); 244ea906c41SOllivier Robert else 245ea906c41SOllivier Robert return (ISC_FALSE); 246c0b746e5SOllivier Robert } 247