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