diff --git a/scapy/base_classes.py b/scapy/base_classes.py
index 2f40f61ccf71a10f983e6648d1bcd21935a5cd8a..6d36053c021c16386dc593b9037da18273863ae6 100644
--- a/scapy/base_classes.py
+++ b/scapy/base_classes.py
@@ -189,7 +189,7 @@ class NewDefaultValues(Packet_metaclass):
         except:
             f,l="??",-1
             raise
-        log_loading.warning("Deprecated use of NewDefaultValues  (%s l. %i)." % (f,l))
+        log_loading.warning("Deprecated (no more needed) use of NewDefaultValues  (%s l. %i)." % (f,l))
         
         return super(NewDefaultValues, cls).__new__(cls, name, bases, dct)
 
diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py
index 702d50d9fc971e2c9a9eac6f12d1d92212f660c8..769c3966934ad709c2fbdb3ef15fd0d76f3ee449 100644
--- a/scapy/layers/inet.py
+++ b/scapy/layers/inet.py
@@ -34,18 +34,160 @@ class IPTools:
         return self.ottl()-self.ttl-1 
 
 
+_ip_options_names = { 0: "end_of_list",
+                      1: "nop",
+                      2: "security",
+                      3: "loose_source_route",
+                      4: "timestamp",
+                      5: "extended_security",
+                      6: "commercial_security",
+                      7: "record_route",
+                      8: "stream_id",
+                      9: "strict_source_route",
+                      10: "experimental_measurement",
+                      11: "mtu_probe",
+                      12: "mtu_reply",
+                      13: "flow_control",
+                      14: "access_control",
+                      15: "encode",
+                      16: "imi_traffic_descriptor",
+                      17: "extended_IP",
+                      18: "traceroute",
+                      19: "address_extension",
+                      20: "router_alert",
+                      21: "selective_directed_broadcast_mode",
+                      23: "dynamic_packet_state",
+                      24: "upstream_multicast_packet",
+                      25: "quick_start",
+                      30: "rfc4727_experiment", 
+                      }
+                      
+
+class _IPOption_HDR(Packet):
+    fields_desc = [ BitField("copy_flag",0, 1),
+                    BitEnumField("optclass",0,2,{0:"control",2:"debug"}),
+                    BitEnumField("option",0,5, _ip_options_names) ]
+    
+class IPOption(Packet):
+    fields_desc = [ _IPOption_HDR,
+                    FieldLenField("length", None, fmt="B",  # Only option 0 and 1 have no length and value
+                                  length_of="value", adjust=lambda pkt,l:l+2),
+                    StrLenField("value", "",length_from=lambda pkt:pkt.length-2) ]
+    
+    def extract_padding(self, p):
+        return "",p
+
+    registered_ip_options = {}
+    @classmethod
+    def register_variant(cls):
+        cls.registered_ip_options[cls.option.default] = cls
+    @classmethod
+    def dispatch_hook(cls, pkt=None, *args, **kargs):
+        if pkt:
+            opt = ord(pkt[0])&0x1f
+            if opt in cls.registered_ip_options:
+                return cls.registered_ip_options[opt]
+        return cls
+
+class IPOption_EOL(IPOption):
+    option = 0
+    fields_desc = [ _IPOption_HDR ]
+    
 
-class IPoptionsField(StrField):
-    def i2m(self, pkt, x):
-        return x+"\x00"*(3-((len(x)+3)%4))
-    def getfield(self, pkt, s):
-        opsz = (pkt.ihl-5)*4
-        if opsz < 0:
-            warning("bad ihl (%i). Assuming ihl=5"%pkt.ihl)
-            opsz = 0
-        return s[opsz:],s[:opsz]
-    def randval(self):
-        return RandBin(RandNum(0,39))
+class IPOption_NOP(IPOption):
+    option=1
+    fields_desc = [ _IPOption_HDR ]
+
+class IPOption_Security(IPOption):
+    copy_flag = 1
+    option = 2
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 11),
+                    ShortField("security",0),
+                    ShortField("compartment",0),
+                    ShortField("handling_restrictions",0),
+                    StrFixedLenField("transmission_control_code","xxx",3),
+                    ]
+    
+class IPOption_LSRR(IPOption):
+    name = "IP Option Loose Source and Record Route"
+    copy_flag = 1
+    option = 3
+    fields_desc = [ _IPOption_HDR,
+                    FieldLenField("length", None, fmt="B",
+                                  length_of="routers", adjust=lambda pkt,l:l+3),
+                    ByteField("pointer",4), # 4 is first IP
+                    FieldListField("routers",[],IPField("","0.0.0.0"), 
+                                   length_from=lambda pkt:pkt.length-3)
+                    ]
+    def get_current_router(self):
+        return self.routers[self.pointer/4-1]
+
+class IPOption_RR(IPOption_LSRR):
+    name = "IP Option Record Route"
+    option = 7
+
+class IPOption_SSRR(IPOption_LSRR):
+    name = "IP Option Strict Source and Record Route"
+    option = 9
+
+class IPOption_Stream_Id(IPOption):
+    name = "IP Option Stream ID"
+    option = 8
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 4),
+                    ShortField("security",0), ]
+                    
+class IPOption_MTU_Probe(IPOption):
+    name = "IP Option MTU Probe"
+    option = 11
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 4),
+                    ShortField("mtu",0), ]
+
+class IPOption_MTU_Reply(IPOption_MTU_Probe):
+    name = "IP Option MTU Reply"
+    option = 12
+
+class IPOption_Traceroute(IPOption):
+    copy_flag = 1
+    option = 18
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 12),
+                    ShortField("id",0),
+                    ShortField("outbound_hops",0),
+                    ShortField("return_hops",0),
+                    IPField("originator_ip","0.0.0.0") ]
+
+class IPOption_Address_Extension(IPOption):
+    name = "IP Option Address Extension"
+    copy_flag = 1
+    option = 19
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 10),
+                    IPField("src_ext","0.0.0.0"),
+                    IPField("dst_ext","0.0.0.0") ]
+
+class IPOption_Router_Alert(IPOption):
+    name = "IP Option Router Alert"
+    copy_flag = 1
+    option = 20
+    fields_desc = [ _IPOption_HDR,
+                    ByteField("length", 4),
+                    ShortEnumField("alert",0, {0:"router_shall_examine_packet"}), ]
+
+
+class IPOption_SDBM(IPOption):
+    name = "IP Option Selective Directed Broadcast Mode"
+    copy_flag = 1
+    option = 21
+    fields_desc = [ _IPOption_HDR,
+                    FieldLenField("length", None, fmt="B",
+                                  length_of="addresses", adjust=lambda pkt,l:l+2),
+                    FieldListField("addresses",[],IPField("","0.0.0.0"), 
+                                   length_from=lambda pkt:pkt.length-2)
+                    ]
+    
 
 
 TCPOptions = (
@@ -181,9 +323,10 @@ class IP(Packet, IPTools):
                     #IPField("src", "127.0.0.1"),
                     Emph(SourceIPField("src","dst")),
                     Emph(IPField("dst", "127.0.0.1")),
-                    IPoptionsField("options", "") ]
+                    PacketListField("options", [], IPOption, length_from=lambda p:p.ihl*4-20) ]
     def post_build(self, p, pay):
         ihl = self.ihl
+        p += "\0"*((-len(p))%4) # pad IP options if needed
         if ihl is None:
             ihl = len(p)/4
             p = chr(((self.version&0xf)<<4) | ihl&0x0f)+p[1:]