I have a simple Python script that uses the socket module to send a UDP packet. The script works fine on my Windows box, but on my Ubuntu Linux PC the packet it sends is slightly different. On Windows the flags field in the IP header is zero, but using the same code on Linux created a packet with the flags field set to 4. I'd like to modify my script so it has consistent behavior on Windows and Linux.
Is there a method for controlling the flags field in the socket module? Or, is this a setting I have to change in Linux?
Here's the route I ended up taking. I followed the link posted by SashaN in the comments of D.Shwley's answer and learned a little bit about why the "don't fragment" bit is set in Linux's UDP packets. Turns out it has something to do with PMTU discovery. Long story short, you can clear the don't fragment bit from your UDP packets in Python by using the setsockopts function in the socket object.
import socket
IP_MTU_DISCOVER = 10
IP_PMTUDISC_DONT = 0 # Never send DF frames.
IP_PMTUDISC_WANT = 1 # Use per route hints.
IP_PMTUDISC_DO = 2 # Always DF.
IP_PMTUDISC_PROBE = 3 # Ignore dst pmtu.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("10.0.0.1", 8000))
s.send("Hello World!") # DF bit is set in this packet
s.setsockopt(socket.SOL_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT)
s.send("Hello World!") # DF bit is cleared in this packet
I'm guessing that the flags field is actually set to 2 = b010 instead of 4 - flags equal to 4 is an invalid IP packet. Remember that flags is a 3 bit value in the IP Header. I would expect to see UDP datagrams with a flags value of 2 which means "Don't fragment".
As for your question, I don't believe there is a way to set the IP flags directly without going all of the way to using raw sockets. I wouldn't worry about it since most applications don't really have a good reason to muck with IP or even UDP/TCP headers directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With