From 2f558854b7e844fa9d61c16edd6785544216714d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 8 Aug 2019 18:31:20 +1000 Subject: [PATCH] implement maxudp under windows --- bin/named/main.c | 3 ++ lib/isc/include/isc/socket.h | 2 +- lib/isc/unix/socket.c | 11 +++-- lib/isc/win32/socket.c | 78 +++++++++++++++++++++++++----------- 4 files changed, 65 insertions(+), 29 deletions(-) diff --git a/bin/named/main.c b/bin/named/main.c index 09842fd472..565dfe1253 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -646,6 +646,9 @@ parse_T_opt(char *option) { maxudp = 1460; } else if (!strncmp(option, "maxudp=", 7)) { maxudp = atoi(option + 7); + if (maxudp <= 0) { + named_main_earlyfatal("bad maxudp"); + } } else if (!strncmp(option, "mkeytimers=", 11)) { p = strtok_r(option + 11, "/", &last); if (p == NULL) { diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index a69222d253..7291387338 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -1002,7 +1002,7 @@ isc_socketmgr_setreserved(isc_socketmgr_t *mgr, uint32_t); */ void -isc_socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp); +isc_socketmgr_maxudp(isc_socketmgr_t *mgr, unsigned int maxudp); /*%< * Test interface. Drop UDP packet > 'maxudp'. */ diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index be8716ef7c..efdb16b955 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -386,7 +386,7 @@ struct isc__socketmgr { ISC_LIST(isc__socket_t) socklist; int reserved; /* unlocked */ isc_condition_t shutdown_ok; - int maxudp; + size_t maxudp; }; struct isc__socketthread { @@ -1592,8 +1592,11 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { * Simulate a firewall blocking UDP responses bigger than * 'maxudp' bytes. */ - if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp) + if (sock->manager->maxudp != 0 && + cc > (int)sock->manager->maxudp) + { return (DOIO_SOFT); + } } socket_log(sock, &dev->address, IOEVENT, @@ -1666,7 +1669,7 @@ doio_send(isc__socket_t *sock, isc_socketevent_t *dev) { resend: if (sock->type == isc_sockettype_udp && sock->manager->maxudp != 0 && - write_count > (size_t)sock->manager->maxudp) + write_count > sock->manager->maxudp) cc = write_count; else cc = sendmsg(sock->fd, &msghdr, 0); @@ -3521,7 +3524,7 @@ isc_socketmgr_setreserved(isc_socketmgr_t *manager0, uint32_t reserved) { } void -isc_socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) { +isc_socketmgr_maxudp(isc_socketmgr_t *manager0, unsigned int maxudp) { isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; REQUIRE(VALID_MANAGER(manager)); diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index b754fce824..4ef5c031ec 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -308,19 +308,20 @@ typedef struct IoCompletionInfo { struct isc_socketmgr { /* Not locked. */ - unsigned int magic; - isc_mem_t *mctx; - isc_mutex_t lock; - isc_stats_t *stats; + unsigned int magic; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_stats_t *stats; /* Locked by manager lock. */ - ISC_LIST(isc_socket_t) socklist; + ISC_LIST(isc_socket_t) socklist; bool bShutdown; - isc_condition_t shutdown_ok; - HANDLE hIoCompletionPort; - int maxIOCPThreads; - HANDLE hIOCPThreads[MAX_IOCPTHREADS]; - DWORD dwIOCPThreadIds[MAX_IOCPTHREADS]; + isc_condition_t shutdown_ok; + HANDLE hIoCompletionPort; + int maxIOCPThreads; + HANDLE hIOCPThreads[MAX_IOCPTHREADS]; + DWORD dwIOCPThreadIds[MAX_IOCPTHREADS]; + size_t maxudp; /* * Debugging. @@ -1133,12 +1134,23 @@ fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) { sock->recvbuf.from_addr_len); if (isc_sockaddr_getport(&dev->address) == 0) { if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { - socket_log(__LINE__, sock, &dev->address, IOEVENT, + socket_log(__LINE__, sock, &dev->address, + IOEVENT, "dropping source port zero packet"); } sock->recvbuf.remaining = 0; return; } + /* + * Simulate a firewall blocking UDP responses bigger than + * 'maxudp' bytes. + */ + if (sock->manager->maxudp != 0 && + sock->recvbuf.remaining > sock->manager->maxudp) + { + sock->recvbuf.remaining = 0; + return; + } } else if (sock->type == isc_sockettype_tcp) { dev->address = sock->address; } @@ -1247,6 +1259,18 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, int status; struct msghdr *mh; + /* + * Simulate a firewall blocking UDP responses bigger than + * 'maxudp' bytes. + */ + if (sock->type == isc_sockettype_udp && + sock->manager->maxudp != 0 && + dev->region.length - dev->n > sock->manager->maxudp) + { + *nbytes = dev->region.length - dev->n; + return (DOIO_SUCCESS); + } + lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(IoCompletionInfo)); @@ -2100,9 +2124,11 @@ internal_recv(isc_socket_t *sock, int nbytes) "internal_recv: %d bytes received", nbytes); /* - * If we got here, the I/O operation succeeded. However, we might still have removed this - * event from our notification list (or never placed it on it due to immediate completion.) - * Handle the reference counting here, and handle the cancellation event just after. + * If we got here, the I/O operation succeeded. However, we might + * still have removed this event from our notification list (or never + * placed it on it due to immediate completion.) + * Handle the reference counting here, and handle the cancellation + * event just after. */ INSIST(sock->pending_iocp > 0); sock->pending_iocp--; @@ -2110,13 +2136,15 @@ internal_recv(isc_socket_t *sock, int nbytes) sock->pending_recv--; /* - * The only way we could have gotten here is that our I/O has successfully completed. - * Update our pointers, and move on. The only odd case here is that we might not - * have received enough data on a TCP stream to satisfy the minimum requirements. If - * this is the case, we will re-issue the recv() call for what we need. + * The only way we could have gotten here is that our I/O has + * successfully completed. Update our pointers, and move on. + * The only odd case here is that we might not have received + * enough data on a TCP stream to satisfy the minimum requirements. + * If this is the case, we will re-issue the recv() call for what + * we need. * - * We do check for a recv() of 0 bytes on a TCP stream. This means the remote end - * has closed. + * We do check for a recv() of 0 bytes on a TCP stream. This + * means the remote end has closed. */ if (nbytes == 0 && sock->type == isc_sockettype_tcp) { send_recvdone_abort(sock, ISC_R_EOF); @@ -2508,6 +2536,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, manager->bShutdown = false; manager->totalSockets = 0; manager->iocp_total = 0; + manager->maxudp = 0; *managerp = manager; @@ -3870,9 +3899,10 @@ isc_socketmgr_createinctx(isc_mem_t *mctx, isc_socketmgr_t **managerp) return (result); } -/* Not implemented for win32 */ void -isc_socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) { - UNUSED(manager); - UNUSED(maxudp); +isc_socketmgr_maxudp(isc_socketmgr_t *manager, unsigned int maxudp) { + + REQUIRE(VALID_MANAGER(manager)); + + manager->maxudp = maxudp; }