diff --git a/lib/constants.py b/lib/constants.py index fddb30c6febd85247857798505524fe6ddf19cbd..123994826803eed7273ee6f99bbe8e82198406d6 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -681,3 +681,10 @@ CONFD_CONFIG_RELOAD_TIMEOUT = 60 # polling every RATELIMIT seconds, rather than relying on inotify, to be able # to serve more requests. CONFD_CONFIG_RELOAD_RATELIMIT = 2 + +# Maximum UDP datagram size. +# On IPv4: 64K - 20 (ip header size) - 8 (udp header size) = 65507 +# On IPv6: 64K - 40 (ip6 header size) - 8 (udp header size) = 65487 +# (assuming we can't use jumbo frames) +# We just set this to 60K, which should be enough +MAX_UDP_DATA_SIZE = 61440 diff --git a/lib/daemon.py b/lib/daemon.py index 9467bb97b5c98eb31bcea5c38a66e052fcb6b684..ac250cd1d8d9cf5a23e57ac6a0333802476685ce 100644 --- a/lib/daemon.py +++ b/lib/daemon.py @@ -95,7 +95,7 @@ class AsyncUDPSocket(asyncore.dispatcher): def handle_read(self): try: try: - payload, address = self.recvfrom(4096) + payload, address = self.recvfrom(constants.MAX_UDP_DATA_SIZE) except socket.error, err: if err.errno == errno.EINTR: # we got a signal while trying to read. no need to do anything, @@ -148,6 +148,9 @@ class AsyncUDPSocket(asyncore.dispatcher): """Enqueue a datagram to be sent when possible """ + if len(payload) > constants.MAX_UDP_DATA_SIZE: + raise errors.UdpDataSizeError('Packet too big: %s > %s' % (len(payload), + constants.MAX_UDP_DATA_SIZE)) self._out_queue.append((ip, port, payload)) diff --git a/lib/errors.py b/lib/errors.py index ec154f738ab938d76499b297ec58f05fa6249138..663bc02f3c6facda20cddd1111ca4de13d44833e 100644 --- a/lib/errors.py +++ b/lib/errors.py @@ -297,6 +297,12 @@ class ConfdRequestError(GenericError): """ +class UdpDataSizeError(GenericError): + """UDP payload too big. + + """ + + # errors should be added above