apply icmp patch
authorCraig Dowell <craigdo@ee.washington.edu>
Wed, 29 Oct 2008 11:18:39 -0700
changeset 3820 c04ecfdce1ef
parent 3819 37b316422064
child 3821 9ea825f066a2
apply icmp patch
bindings/python/ns3_module_core.py
bindings/python/ns3_module_internet_stack.py
bindings/python/ns3_module_node.py
src/internet-stack/arp-ipv4-interface.cc
src/internet-stack/icmpv4-l4-protocol.cc
src/internet-stack/icmpv4-l4-protocol.h
src/internet-stack/icmpv4.cc
src/internet-stack/icmpv4.h
src/internet-stack/internet-stack.cc
src/internet-stack/ipv4-end-point-demux.cc
src/internet-stack/ipv4-end-point-demux.h
src/internet-stack/ipv4-end-point.cc
src/internet-stack/ipv4-end-point.h
src/internet-stack/ipv4-l3-protocol.cc
src/internet-stack/ipv4-l3-protocol.h
src/internet-stack/ipv4-l4-protocol.cc
src/internet-stack/ipv4-l4-protocol.h
src/internet-stack/ipv4-raw-socket-factory-impl.cc
src/internet-stack/ipv4-raw-socket-factory-impl.h
src/internet-stack/ipv4-raw-socket-impl.cc
src/internet-stack/ipv4-raw-socket-impl.h
src/internet-stack/nsc-tcp-l4-protocol.cc
src/internet-stack/nsc-tcp-l4-protocol.h
src/internet-stack/tcp-l4-protocol.cc
src/internet-stack/tcp-l4-protocol.h
src/internet-stack/udp-l4-protocol.cc
src/internet-stack/udp-l4-protocol.h
src/internet-stack/udp-socket-impl.cc
src/internet-stack/udp-socket-impl.h
src/internet-stack/wscript
src/node/ipv4-raw-socket-factory.cc
src/node/ipv4-raw-socket-factory.h
src/node/socket.cc
src/node/socket.h
src/node/udp-socket.cc
src/node/udp-socket.h
src/node/wscript
--- a/bindings/python/ns3_module_core.py	Mon Oct 27 15:12:00 2008 -0400
+++ b/bindings/python/ns3_module_core.py	Wed Oct 29 11:18:39 2008 -0700
@@ -2025,6 +2025,10 @@
     module.add_function('MakeStringChecker', 
                         'ns3::Ptr< ns3::AttributeChecker const >', 
                         [])
+    ## type-id.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::MakeTypeIdChecker() [free function]
+    module.add_function('MakeTypeIdChecker', 
+                        'ns3::Ptr< ns3::AttributeChecker const >', 
+                        [])
     ## ptr.h: extern ns3::Ptr<ns3::PointerValue> ns3::Create() [free function]
     module.add_function('Create', 
                         'ns3::Ptr< ns3::PointerValue >', 
@@ -2039,10 +2043,6 @@
     module.add_function('LogComponentEnableAll', 
                         'void', 
                         [param('ns3::LogLevel', 'level')])
-    ## type-id.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::MakeTypeIdChecker() [free function]
-    module.add_function('MakeTypeIdChecker', 
-                        'ns3::Ptr< ns3::AttributeChecker const >', 
-                        [])
     ## object-factory.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::MakeObjectFactoryChecker() [free function]
     module.add_function('MakeObjectFactoryChecker', 
                         'ns3::Ptr< ns3::AttributeChecker const >', 
--- a/bindings/python/ns3_module_internet_stack.py	Mon Oct 27 15:12:00 2008 -0400
+++ b/bindings/python/ns3_module_internet_stack.py	Wed Oct 29 11:18:39 2008 -0700
@@ -3,6 +3,20 @@
 def register_types(module):
     root_module = module.get_root()
     
+    ## icmpv4.h: ns3::Icmpv4DestinationUnreachable [class]
+    module.add_class('Icmpv4DestinationUnreachable', parent=root_module['ns3::Header'])
+    ## icmpv4.h: ns3::Icmpv4DestinationUnreachable [enumeration]
+    module.add_enum('', ['NET_UNREACHABLE', 'HOST_UNREACHABLE', 'PROTOCOL_UNREACHABLE', 'PORT_UNREACHABLE', 'FRAG_NEEDED', 'SOURCE_ROUTE_FAILED'], outer_class=root_module['ns3::Icmpv4DestinationUnreachable'])
+    ## icmpv4.h: ns3::Icmpv4Echo [class]
+    module.add_class('Icmpv4Echo', parent=root_module['ns3::Header'])
+    ## icmpv4.h: ns3::Icmpv4Header [class]
+    module.add_class('Icmpv4Header', parent=root_module['ns3::Header'])
+    ## icmpv4.h: ns3::Icmpv4Header [enumeration]
+    module.add_enum('', ['ECHO_REPLY', 'DEST_UNREACH', 'ECHO', 'TIME_EXCEEDED'], outer_class=root_module['ns3::Icmpv4Header'])
+    ## icmpv4.h: ns3::Icmpv4TimeExceeded [class]
+    module.add_class('Icmpv4TimeExceeded', parent=root_module['ns3::Header'])
+    ## icmpv4.h: ns3::Icmpv4TimeExceeded [enumeration]
+    module.add_enum('', ['TIME_TO_LIVE', 'FRAGMENT_REASSEMBLY'], outer_class=root_module['ns3::Icmpv4TimeExceeded'])
     ## tcp-header.h: ns3::TcpHeader [class]
     module.add_class('TcpHeader', parent=root_module['ns3::Header'])
     ## tcp-header.h: ns3::TcpHeader::Flags_t [enumeration]
@@ -57,6 +71,10 @@
     
 
 def register_methods(root_module):
+    register_Ns3Icmpv4DestinationUnreachable_methods(root_module, root_module['ns3::Icmpv4DestinationUnreachable'])
+    register_Ns3Icmpv4Echo_methods(root_module, root_module['ns3::Icmpv4Echo'])
+    register_Ns3Icmpv4Header_methods(root_module, root_module['ns3::Icmpv4Header'])
+    register_Ns3Icmpv4TimeExceeded_methods(root_module, root_module['ns3::Icmpv4TimeExceeded'])
     register_Ns3TcpHeader_methods(root_module, root_module['ns3::TcpHeader'])
     register_Ns3UdpHeader_methods(root_module, root_module['ns3::UdpHeader'])
     register_Ns3Ipv4Interface_methods(root_module, root_module['ns3::Ipv4Interface'])
@@ -64,6 +82,248 @@
     register_Ns3Ipv4StaticRouting_methods(root_module, root_module['ns3::Ipv4StaticRouting'])
     return
 
+def register_Ns3Icmpv4DestinationUnreachable_methods(root_module, cls):
+    ## icmpv4.h: ns3::Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable(ns3::Icmpv4DestinationUnreachable const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Icmpv4DestinationUnreachable const &', 'arg0')])
+    ## icmpv4.h: static ns3::TypeId ns3::Icmpv4DestinationUnreachable::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## icmpv4.h: ns3::Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable() [constructor]
+    cls.add_constructor([])
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetNextHopMtu(uint16_t mtu) [member function]
+    cls.add_method('SetNextHopMtu', 
+                   'void', 
+                   [param('uint16_t', 'mtu')])
+    ## icmpv4.h: uint16_t ns3::Icmpv4DestinationUnreachable::GetNextHopMtu() const [member function]
+    cls.add_method('GetNextHopMtu', 
+                   'uint16_t', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetData(ns3::Ptr<const ns3::Packet> data) [member function]
+    cls.add_method('SetData', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'data')])
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetHeader(ns3::Ipv4Header header) [member function]
+    cls.add_method('SetHeader', 
+                   'void', 
+                   [param('ns3::Ipv4Header', 'header')])
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::GetData(uint8_t * payload) const [member function]
+    cls.add_method('GetData', 
+                   'void', 
+                   [param('uint8_t *', 'payload')], 
+                   is_const=True)
+    ## icmpv4.h: ns3::Ipv4Header ns3::Icmpv4DestinationUnreachable::GetHeader() const [member function]
+    cls.add_method('GetHeader', 
+                   'ns3::Ipv4Header', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: ns3::TypeId ns3::Icmpv4DestinationUnreachable::GetInstanceTypeId() const [member function]
+    cls.add_method('GetInstanceTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_const=True, visibility='private', is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4DestinationUnreachable::GetSerializedSize() const [member function]
+    cls.add_method('GetSerializedSize', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, visibility='private', is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::Serialize(ns3::Buffer::Iterator start) const [member function]
+    cls.add_method('Serialize', 
+                   'void', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_const=True, visibility='private', is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4DestinationUnreachable::Deserialize(ns3::Buffer::Iterator start) [member function]
+    cls.add_method('Deserialize', 
+                   'uint32_t', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   visibility='private', is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::Print(std::ostream & os) const [member function]
+    cls.add_method('Print', 
+                   'void', 
+                   [param('std::ostream &', 'os')], 
+                   is_const=True, visibility='private', is_virtual=True)
+    return
+
+def register_Ns3Icmpv4Echo_methods(root_module, cls):
+    ## icmpv4.h: ns3::Icmpv4Echo::Icmpv4Echo(ns3::Icmpv4Echo const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Icmpv4Echo const &', 'arg0')])
+    ## icmpv4.h: void ns3::Icmpv4Echo::SetIdentifier(uint16_t id) [member function]
+    cls.add_method('SetIdentifier', 
+                   'void', 
+                   [param('uint16_t', 'id')])
+    ## icmpv4.h: void ns3::Icmpv4Echo::SetSequenceNumber(uint16_t seq) [member function]
+    cls.add_method('SetSequenceNumber', 
+                   'void', 
+                   [param('uint16_t', 'seq')])
+    ## icmpv4.h: void ns3::Icmpv4Echo::SetData(ns3::Ptr<const ns3::Packet> data) [member function]
+    cls.add_method('SetData', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'data')])
+    ## icmpv4.h: uint16_t ns3::Icmpv4Echo::GetIdentifier() const [member function]
+    cls.add_method('GetIdentifier', 
+                   'uint16_t', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: uint16_t ns3::Icmpv4Echo::GetSequenceNumber() const [member function]
+    cls.add_method('GetSequenceNumber', 
+                   'uint16_t', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: ns3::Ptr<const ns3::Packet> ns3::Icmpv4Echo::GetData() const [member function]
+    cls.add_method('GetData', 
+                   'ns3::Ptr< ns3::Packet const >', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: static ns3::TypeId ns3::Icmpv4Echo::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## icmpv4.h: ns3::Icmpv4Echo::Icmpv4Echo() [constructor]
+    cls.add_constructor([])
+    ## icmpv4.h: ns3::TypeId ns3::Icmpv4Echo::GetInstanceTypeId() const [member function]
+    cls.add_method('GetInstanceTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4Echo::GetSerializedSize() const [member function]
+    cls.add_method('GetSerializedSize', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4Echo::Serialize(ns3::Buffer::Iterator start) const [member function]
+    cls.add_method('Serialize', 
+                   'void', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4Echo::Deserialize(ns3::Buffer::Iterator start) [member function]
+    cls.add_method('Deserialize', 
+                   'uint32_t', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4Echo::Print(std::ostream & os) const [member function]
+    cls.add_method('Print', 
+                   'void', 
+                   [param('std::ostream &', 'os')], 
+                   is_const=True, is_virtual=True)
+    return
+
+def register_Ns3Icmpv4Header_methods(root_module, cls):
+    ## icmpv4.h: ns3::Icmpv4Header::Icmpv4Header(ns3::Icmpv4Header const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Icmpv4Header const &', 'arg0')])
+    ## icmpv4.h: void ns3::Icmpv4Header::EnableChecksum() [member function]
+    cls.add_method('EnableChecksum', 
+                   'void', 
+                   [])
+    ## icmpv4.h: void ns3::Icmpv4Header::SetType(uint8_t type) [member function]
+    cls.add_method('SetType', 
+                   'void', 
+                   [param('uint8_t', 'type')])
+    ## icmpv4.h: void ns3::Icmpv4Header::SetCode(uint8_t code) [member function]
+    cls.add_method('SetCode', 
+                   'void', 
+                   [param('uint8_t', 'code')])
+    ## icmpv4.h: uint8_t ns3::Icmpv4Header::GetType() const [member function]
+    cls.add_method('GetType', 
+                   'uint8_t', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: uint8_t ns3::Icmpv4Header::GetCode() const [member function]
+    cls.add_method('GetCode', 
+                   'uint8_t', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: static ns3::TypeId ns3::Icmpv4Header::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## icmpv4.h: ns3::Icmpv4Header::Icmpv4Header() [constructor]
+    cls.add_constructor([])
+    ## icmpv4.h: ns3::TypeId ns3::Icmpv4Header::GetInstanceTypeId() const [member function]
+    cls.add_method('GetInstanceTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4Header::GetSerializedSize() const [member function]
+    cls.add_method('GetSerializedSize', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4Header::Serialize(ns3::Buffer::Iterator start) const [member function]
+    cls.add_method('Serialize', 
+                   'void', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4Header::Deserialize(ns3::Buffer::Iterator start) [member function]
+    cls.add_method('Deserialize', 
+                   'uint32_t', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4Header::Print(std::ostream & os) const [member function]
+    cls.add_method('Print', 
+                   'void', 
+                   [param('std::ostream &', 'os')], 
+                   is_const=True, is_virtual=True)
+    return
+
+def register_Ns3Icmpv4TimeExceeded_methods(root_module, cls):
+    ## icmpv4.h: ns3::Icmpv4TimeExceeded::Icmpv4TimeExceeded(ns3::Icmpv4TimeExceeded const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Icmpv4TimeExceeded const &', 'arg0')])
+    ## icmpv4.h: void ns3::Icmpv4TimeExceeded::SetData(ns3::Ptr<const ns3::Packet> data) [member function]
+    cls.add_method('SetData', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'data')])
+    ## icmpv4.h: void ns3::Icmpv4TimeExceeded::SetHeader(ns3::Ipv4Header header) [member function]
+    cls.add_method('SetHeader', 
+                   'void', 
+                   [param('ns3::Ipv4Header', 'header')])
+    ## icmpv4.h: void ns3::Icmpv4TimeExceeded::GetData(uint8_t * payload) const [member function]
+    cls.add_method('GetData', 
+                   'void', 
+                   [param('uint8_t *', 'payload')], 
+                   is_const=True)
+    ## icmpv4.h: ns3::Ipv4Header ns3::Icmpv4TimeExceeded::GetHeader() const [member function]
+    cls.add_method('GetHeader', 
+                   'ns3::Ipv4Header', 
+                   [], 
+                   is_const=True)
+    ## icmpv4.h: static ns3::TypeId ns3::Icmpv4TimeExceeded::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## icmpv4.h: ns3::Icmpv4TimeExceeded::Icmpv4TimeExceeded() [constructor]
+    cls.add_constructor([])
+    ## icmpv4.h: ns3::TypeId ns3::Icmpv4TimeExceeded::GetInstanceTypeId() const [member function]
+    cls.add_method('GetInstanceTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4TimeExceeded::GetSerializedSize() const [member function]
+    cls.add_method('GetSerializedSize', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4TimeExceeded::Serialize(ns3::Buffer::Iterator start) const [member function]
+    cls.add_method('Serialize', 
+                   'void', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_const=True, is_virtual=True)
+    ## icmpv4.h: uint32_t ns3::Icmpv4TimeExceeded::Deserialize(ns3::Buffer::Iterator start) [member function]
+    cls.add_method('Deserialize', 
+                   'uint32_t', 
+                   [param('ns3::Buffer::Iterator', 'start')], 
+                   is_virtual=True)
+    ## icmpv4.h: void ns3::Icmpv4TimeExceeded::Print(std::ostream & os) const [member function]
+    cls.add_method('Print', 
+                   'void', 
+                   [param('std::ostream &', 'os')], 
+                   is_const=True, is_virtual=True)
+    return
+
 def register_Ns3TcpHeader_methods(root_module, cls):
     ## tcp-header.h: ns3::TcpHeader::TcpHeader(ns3::TcpHeader const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::TcpHeader const &', 'arg0')])
@@ -354,6 +614,14 @@
     cls.add_method('SetNode', 
                    'void', 
                    [param('ns3::Ptr< ns3::Node >', 'node')])
+    ## ipv4-l3-protocol.h: ns3::Ptr<ns3::Socket> ns3::Ipv4L3Protocol::CreateRawSocket() [member function]
+    cls.add_method('CreateRawSocket', 
+                   'ns3::Ptr< ns3::Socket >', 
+                   [])
+    ## ipv4-l3-protocol.h: void ns3::Ipv4L3Protocol::DeleteRawSocket(ns3::Ptr<ns3::Socket> socket) [member function]
+    cls.add_method('DeleteRawSocket', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Socket >', 'socket')])
     ## ipv4-l3-protocol.h: void ns3::Ipv4L3Protocol::Insert(ns3::Ptr<ns3::Ipv4L4Protocol> protocol) [member function]
     cls.add_method('Insert', 
                    'void', 
--- a/bindings/python/ns3_module_node.py	Mon Oct 27 15:12:00 2008 -0400
+++ b/bindings/python/ns3_module_node.py	Wed Oct 29 11:18:39 2008 -0700
@@ -67,6 +67,8 @@
     module.add_class('SocketFactory', parent=root_module['ns3::Object'])
     ## socket.h: ns3::SocketIpTtlTag [class]
     module.add_class('SocketIpTtlTag', parent=root_module['ns3::Tag'])
+    ## socket.h: ns3::SocketSetDontFragmentTag [class]
+    module.add_class('SocketSetDontFragmentTag', parent=root_module['ns3::Tag'])
     ## tcp-socket.h: ns3::TcpSocket [class]
     module.add_class('TcpSocket', parent=root_module['ns3::Socket'])
     ## tcp-socket-factory.h: ns3::TcpSocketFactory [class]
@@ -91,6 +93,8 @@
     module.add_class('EthernetTrailer', parent=root_module['ns3::Trailer'])
     ## ipv4.h: ns3::Ipv4 [class]
     module.add_class('Ipv4', parent=root_module['ns3::Object'])
+    ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory [class]
+    module.add_class('Ipv4RawSocketFactory', parent=root_module['ns3::SocketFactory'])
     ## ipv4.h: ns3::Ipv4RoutingProtocol [class]
     module.add_class('Ipv4RoutingProtocol', parent=root_module['ns3::Object'])
     ## net-device.h: ns3::NetDevice [class]
@@ -172,6 +176,7 @@
     register_Ns3SocketAddressTag_methods(root_module, root_module['ns3::SocketAddressTag'])
     register_Ns3SocketFactory_methods(root_module, root_module['ns3::SocketFactory'])
     register_Ns3SocketIpTtlTag_methods(root_module, root_module['ns3::SocketIpTtlTag'])
+    register_Ns3SocketSetDontFragmentTag_methods(root_module, root_module['ns3::SocketSetDontFragmentTag'])
     register_Ns3TcpSocket_methods(root_module, root_module['ns3::TcpSocket'])
     register_Ns3TcpSocketFactory_methods(root_module, root_module['ns3::TcpSocketFactory'])
     register_Ns3UdpSocket_methods(root_module, root_module['ns3::UdpSocket'])
@@ -184,6 +189,7 @@
     register_Ns3EthernetHeader_methods(root_module, root_module['ns3::EthernetHeader'])
     register_Ns3EthernetTrailer_methods(root_module, root_module['ns3::EthernetTrailer'])
     register_Ns3Ipv4_methods(root_module, root_module['ns3::Ipv4'])
+    register_Ns3Ipv4RawSocketFactory_methods(root_module, root_module['ns3::Ipv4RawSocketFactory'])
     register_Ns3Ipv4RoutingProtocol_methods(root_module, root_module['ns3::Ipv4RoutingProtocol'])
     register_Ns3NetDevice_methods(root_module, root_module['ns3::NetDevice'])
     register_Ns3Node_methods(root_module, root_module['ns3::Node'])
@@ -1507,6 +1513,56 @@
                    is_const=True, is_virtual=True)
     return
 
+def register_Ns3SocketSetDontFragmentTag_methods(root_module, cls):
+    ## socket.h: ns3::SocketSetDontFragmentTag::SocketSetDontFragmentTag(ns3::SocketSetDontFragmentTag const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::SocketSetDontFragmentTag const &', 'arg0')])
+    ## socket.h: ns3::SocketSetDontFragmentTag::SocketSetDontFragmentTag() [constructor]
+    cls.add_constructor([])
+    ## socket.h: void ns3::SocketSetDontFragmentTag::Enable() [member function]
+    cls.add_method('Enable', 
+                   'void', 
+                   [])
+    ## socket.h: void ns3::SocketSetDontFragmentTag::Disable() [member function]
+    cls.add_method('Disable', 
+                   'void', 
+                   [])
+    ## socket.h: bool ns3::SocketSetDontFragmentTag::IsEnabled() const [member function]
+    cls.add_method('IsEnabled', 
+                   'bool', 
+                   [], 
+                   is_const=True)
+    ## socket.h: static ns3::TypeId ns3::SocketSetDontFragmentTag::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## socket.h: ns3::TypeId ns3::SocketSetDontFragmentTag::GetInstanceTypeId() const [member function]
+    cls.add_method('GetInstanceTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## socket.h: uint32_t ns3::SocketSetDontFragmentTag::GetSerializedSize() const [member function]
+    cls.add_method('GetSerializedSize', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## socket.h: void ns3::SocketSetDontFragmentTag::Serialize(ns3::TagBuffer i) const [member function]
+    cls.add_method('Serialize', 
+                   'void', 
+                   [param('ns3::TagBuffer', 'i')], 
+                   is_const=True, is_virtual=True)
+    ## socket.h: void ns3::SocketSetDontFragmentTag::Deserialize(ns3::TagBuffer i) [member function]
+    cls.add_method('Deserialize', 
+                   'void', 
+                   [param('ns3::TagBuffer', 'i')], 
+                   is_virtual=True)
+    ## socket.h: void ns3::SocketSetDontFragmentTag::Print(std::ostream & os) const [member function]
+    cls.add_method('Print', 
+                   'void', 
+                   [param('std::ostream &', 'os')], 
+                   is_const=True, is_virtual=True)
+    return
+
 def register_Ns3TcpSocket_methods(root_module, cls):
     ## tcp-socket.h: ns3::TcpSocket::TcpSocket(ns3::TcpSocket const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::TcpSocket const &', 'arg0')])
@@ -1661,6 +1717,16 @@
                    'uint32_t', 
                    [], 
                    is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: void ns3::UdpSocket::SetMtuDiscover(bool discover) [member function]
+    cls.add_method('SetMtuDiscover', 
+                   'void', 
+                   [param('bool', 'discover')], 
+                   is_pure_virtual=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: bool ns3::UdpSocket::GetMtuDiscover() const [member function]
+    cls.add_method('GetMtuDiscover', 
+                   'bool', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
     return
 
 def register_Ns3UdpSocketFactory_methods(root_module, cls):
@@ -2167,6 +2233,18 @@
                    is_virtual=True)
     return
 
+def register_Ns3Ipv4RawSocketFactory_methods(root_module, cls):
+    ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory::Ipv4RawSocketFactory(ns3::Ipv4RawSocketFactory const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4RawSocketFactory const &', 'arg0')])
+    ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory::Ipv4RawSocketFactory() [constructor]
+    cls.add_constructor([])
+    ## ipv4-raw-socket-factory.h: static ns3::TypeId ns3::Ipv4RawSocketFactory::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    return
+
 def register_Ns3Ipv4RoutingProtocol_methods(root_module, cls):
     ## ipv4.h: ns3::Ipv4RoutingProtocol::IF_INDEX_ANY [variable]
     cls.add_static_attribute('IF_INDEX_ANY', 'uint32_t const', is_const=True)
--- a/src/internet-stack/arp-ipv4-interface.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/arp-ipv4-interface.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -65,7 +65,6 @@
 ArpIpv4Interface::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
-  m_node = 0;
   m_device = 0;
   m_cache = 0;
   Ipv4Interface::DoDispose ();
@@ -107,6 +106,17 @@
   NS_LOG_FUNCTION (this << p << dest);
 
   NS_ASSERT (GetDevice () != 0);
+  if (dest == GetAddress ())
+    {
+      Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+        
+      ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, 
+                     GetDevice ()->GetBroadcast (),
+                     GetDevice ()->GetBroadcast (),
+                     NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
+                     );
+      return;
+    }
   if (m_device->NeedsArp ())
     {
       NS_LOG_LOGIC ("Needs ARP");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv4-l4-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,223 @@
+#include "icmpv4-l4-protocol.h"
+#include "ipv4-interface.h"
+#include "ipv4-l3-protocol.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/boolean.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("Icmpv4L4Protocol");
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv4L4Protocol);
+
+  // see rfc 792
+enum {
+ ICMP_PROTOCOL = 1
+};
+
+TypeId 
+Icmpv4L4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol")
+    .SetParent<Ipv4L4Protocol> ()
+    .AddConstructor<Icmpv4L4Protocol> ()
+    .AddAttribute ("CalcChecksum", 
+		   "Control whether the icmp header checksum is calculated and stored in outgoing icmpv4 headers",
+		   BooleanValue (false),
+		   MakeBooleanAccessor (&Icmpv4L4Protocol::m_calcChecksum),
+		   MakeBooleanChecker ())
+    ;
+  return tid;
+}
+
+Icmpv4L4Protocol::Icmpv4L4Protocol ()
+  : m_node (0)
+{}
+Icmpv4L4Protocol::~Icmpv4L4Protocol ()
+{
+  NS_ASSERT (m_node == 0);
+}
+
+void 
+Icmpv4L4Protocol::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+uint16_t 
+Icmpv4L4Protocol::GetStaticProtocolNumber (void)
+{
+  return ICMP_PROTOCOL;
+}
+
+int 
+Icmpv4L4Protocol::GetProtocolNumber (void) const
+{
+  return ICMP_PROTOCOL;
+}
+void
+Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
+{
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  uint32_t i;
+  if (!ipv4->GetIfIndexForDestination (dest, i))
+    {
+      NS_LOG_WARN ("drop icmp message");
+      return;
+    }
+  Ipv4Address source = ipv4->GetAddress (i);
+  SendMessage (packet, source, dest, type, code);
+}
+
+void
+Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code)
+{
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  Icmpv4Header icmp;
+  icmp.SetType (type);
+  icmp.SetCode (code);
+  if (m_calcChecksum)
+    {
+      icmp.EnableChecksum ();
+    }
+  packet->AddHeader (icmp);
+  ipv4->Send (packet, source, dest, ICMP_PROTOCOL);
+}
+void 
+Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header, 
+					     Ptr<const Packet> orgData, 
+					     uint16_t nextHopMtu)
+{
+  NS_LOG_FUNCTION (this << header << *orgData << nextHopMtu);
+  SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::FRAG_NEEDED, nextHopMtu);
+}
+void 
+Icmpv4L4Protocol::SendDestUnreachPort (Ipv4Header header, 
+				       Ptr<const Packet> orgData)
+{
+  NS_LOG_FUNCTION (this << header << *orgData);
+  SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::PORT_UNREACHABLE, 0);
+}
+void 
+Icmpv4L4Protocol::SendDestUnreach (Ipv4Header header, Ptr<const Packet> orgData, 
+				   uint8_t code, uint16_t nextHopMtu)
+{
+  NS_LOG_FUNCTION (this << header << *orgData << (uint32_t) code << nextHopMtu);
+  Ptr<Packet> p = Create<Packet> ();
+  Icmpv4DestinationUnreachable unreach;
+  unreach.SetNextHopMtu (nextHopMtu);
+  unreach.SetHeader (header);
+  unreach.SetData (orgData);
+  p->AddHeader (unreach);
+  SendMessage (p, header.GetSource (), Icmpv4Header::DEST_UNREACH, code);
+}
+
+void 
+Icmpv4L4Protocol::SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData)
+{
+  NS_LOG_FUNCTION (this << header << *orgData);
+  Ptr<Packet> p = Create<Packet> ();
+  Icmpv4TimeExceeded time;
+  time.SetHeader (header);
+  time.SetData (orgData);
+  p->AddHeader (time);
+  SendMessage (p, header.GetSource (), Icmpv4Header::TIME_EXCEEDED, Icmpv4TimeExceeded::TIME_TO_LIVE);
+}
+
+void
+Icmpv4L4Protocol::HandleEcho (Ptr<Packet> p,
+			      Icmpv4Header header, 
+			      Ipv4Address source,
+			      Ipv4Address destination)
+{
+  NS_LOG_FUNCTION (this << p << header << source << destination);
+
+  Ptr<Packet> reply = Create<Packet> ();
+  Icmpv4Echo echo;
+  p->RemoveHeader (echo);
+  reply->AddHeader (echo);
+  SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0);
+}
+void
+Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp,
+			   uint32_t info, Ipv4Header ipHeader,
+			   const uint8_t payload[8])
+{
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  Ptr<Ipv4L4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
+  if (l4 != 0)
+    {
+      l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (),
+		       info, ipHeader.GetSource (), ipHeader.GetDestination (), payload);
+    }
+}
+void
+Icmpv4L4Protocol::HandleDestUnreach (Ptr<Packet> p,
+				     Icmpv4Header icmp, 
+				     Ipv4Address source,
+				     Ipv4Address destination)
+{
+  NS_LOG_FUNCTION (this << p << icmp << source << destination);
+
+  Icmpv4DestinationUnreachable unreach;
+  p->PeekHeader (unreach);
+  uint8_t payload[8];
+  unreach.GetData (payload);
+  Ipv4Header ipHeader = unreach.GetHeader ();
+  Forward (source, icmp, unreach.GetNextHopMtu (), ipHeader, payload);
+}
+void
+Icmpv4L4Protocol::HandleTimeExceeded (Ptr<Packet> p,
+				      Icmpv4Header icmp, 
+				      Ipv4Address source,
+				      Ipv4Address destination)
+{
+  NS_LOG_FUNCTION (this << p << icmp << source << destination);
+
+  Icmpv4TimeExceeded time;
+  p->PeekHeader (time);
+  uint8_t payload[8];
+  time.GetData (payload);
+  Ipv4Header ipHeader = time.GetHeader ();
+  // info field is zero for TimeExceeded on linux
+  Forward (source, icmp, 0, ipHeader, payload);
+}
+
+enum Ipv4L4Protocol::RxStatus
+Icmpv4L4Protocol::Receive(Ptr<Packet> p, 
+			  Ipv4Address const &source,
+			  Ipv4Address const &destination,
+			  Ptr<Ipv4Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION (this << p << source << destination << incomingInterface);
+
+  Icmpv4Header icmp;
+  p->RemoveHeader (icmp);
+  switch (icmp.GetType ()) {
+  case Icmpv4Header::ECHO:
+    HandleEcho (p, icmp, source, destination);
+    break;
+  case Icmpv4Header::DEST_UNREACH:
+    HandleDestUnreach (p, icmp, source, destination);
+    break;
+  case Icmpv4Header::TIME_EXCEEDED:
+    HandleTimeExceeded (p, icmp, source, destination);
+    break;
+  default:
+    NS_LOG_DEBUG (icmp << " " << *p);
+    break;
+  }
+  return Ipv4L4Protocol::RX_OK;
+}
+void 
+Icmpv4L4Protocol::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  Ipv4L4Protocol::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv4-l4-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,62 @@
+#ifndef ICMPV4_L4_PROTOCOL_H
+#define ICMPV4_L4_PROTOCOL_H
+
+#include "ipv4-l4-protocol.h"
+#include "icmpv4.h"
+#include "ns3/ipv4-address.h"
+
+namespace ns3 {
+
+class Node;
+class Ipv4Interface;
+
+class Icmpv4L4Protocol : public Ipv4L4Protocol
+{
+public:
+  static TypeId GetTypeId (void);
+  Icmpv4L4Protocol ();
+  virtual ~Icmpv4L4Protocol ();
+
+  void SetNode (Ptr<Node> node);
+
+  static uint16_t GetStaticProtocolNumber (void);
+  virtual int GetProtocolNumber (void) const;
+  virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr<Packet> p, 
+						const Ipv4Address &source,
+						const Ipv4Address &destination,
+						Ptr<Ipv4Interface> incomingInterface);
+
+  void SendDestUnreachFragNeeded (Ipv4Header header, Ptr<const Packet> orgData, uint16_t nextHopMtu);
+  void SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData);
+  void SendDestUnreachPort (Ipv4Header header, Ptr<const Packet> orgData);
+
+private:
+  void HandleEcho (Ptr<Packet> p,
+		   Icmpv4Header header, 
+		   Ipv4Address source,
+		   Ipv4Address destination);
+  void HandleDestUnreach (Ptr<Packet> p,
+			  Icmpv4Header header, 
+			  Ipv4Address source,
+			  Ipv4Address destination);
+  void HandleTimeExceeded (Ptr<Packet> p,
+			   Icmpv4Header icmp, 
+			   Ipv4Address source,
+			   Ipv4Address destination);
+  void SendDestUnreach (Ipv4Header header, Ptr<const Packet> orgData, 
+			uint8_t code, uint16_t nextHopMtu);
+  void SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code);
+  void SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code);
+  void Forward (Ipv4Address source, Icmpv4Header icmp,
+		uint32_t info, Ipv4Header ipHeader,
+		const uint8_t payload[8]);
+
+  virtual void DoDispose (void);
+
+  Ptr<Node> m_node;
+  bool m_calcChecksum;
+};
+
+} // namespace ns3
+
+#endif /* ICMPV4_L4_PROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv4.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,387 @@
+#include "icmpv4.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+/********************************************************
+ *        Icmpv4Header
+ ********************************************************/
+
+TypeId 
+Icmpv4Header::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Icmpv4Header")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv4Header> ()
+    ;
+  return tid;
+}
+Icmpv4Header::Icmpv4Header ()
+  : m_type (0),
+    m_code (0),
+    m_calcChecksum (false)
+{}
+Icmpv4Header::~Icmpv4Header ()
+{}
+void 
+Icmpv4Header::EnableChecksum (void)
+{
+  m_calcChecksum = true;
+}
+TypeId 
+Icmpv4Header::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+Icmpv4Header::GetSerializedSize (void) const
+{
+  return 4;
+}
+void 
+Icmpv4Header::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (m_type);
+  i.WriteU8 (m_code);
+  i.WriteHtonU16 (0);
+  if (m_calcChecksum)
+    {
+      i = start;
+      uint16_t checksum = i.CalculateIpChecksum (i.GetSize ());
+      i = start;
+      i.Next (2);
+      i.WriteU16 (checksum);
+    }
+  
+}
+uint32_t 
+Icmpv4Header::Deserialize (Buffer::Iterator start)
+{
+  m_type = start.ReadU8 ();
+  m_code = start.ReadU8 ();
+  uint16_t checksum;
+  checksum = start.ReadNtohU16 ();
+  return 4;
+}
+void 
+Icmpv4Header::Print (std::ostream &os) const
+{
+  os << "type=" << (uint32_t)m_type << ", code=" << (uint32_t)m_code;
+}
+
+void 
+Icmpv4Header::SetType (uint8_t type)
+{
+  m_type = type;
+}
+void 
+Icmpv4Header::SetCode (uint8_t code)
+{
+  m_code = code;
+}
+uint8_t 
+Icmpv4Header::GetType (void) const
+{
+  return m_type;
+}
+uint8_t 
+Icmpv4Header::GetCode (void) const
+{
+  return m_code;
+}
+
+/********************************************************
+ *        Icmpv4Echo
+ ********************************************************/
+
+void 
+Icmpv4Echo::SetIdentifier (uint16_t id)
+{
+  m_identifier = id;
+}
+void 
+Icmpv4Echo::SetSequenceNumber (uint16_t seq)
+{
+  m_sequence = seq;
+}
+void 
+Icmpv4Echo::SetData (Ptr<const Packet> data)
+{
+  m_data = data->Copy ();
+}
+uint16_t 
+Icmpv4Echo::GetIdentifier (void) const
+{
+  return m_identifier;
+}
+uint16_t 
+Icmpv4Echo::GetSequenceNumber (void) const
+{
+  return m_sequence;
+}
+Ptr<const Packet> 
+Icmpv4Echo::GetData (void) const
+{
+  return m_data->Copy ();
+}
+
+
+TypeId 
+Icmpv4Echo::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Icmpv4Echo")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv4Echo> ()
+    ;
+  return tid;
+}
+Icmpv4Echo::Icmpv4Echo ()
+  : m_identifier (0),
+    m_sequence (0),
+    m_data (0)
+{}
+Icmpv4Echo::~Icmpv4Echo ()
+{}
+TypeId 
+Icmpv4Echo::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+Icmpv4Echo::GetSerializedSize (void) const
+{
+  return 4 + m_data->GetSize ();
+}
+void 
+Icmpv4Echo::Serialize (Buffer::Iterator start) const
+{
+  start.WriteHtonU16 (m_identifier);
+  start.WriteHtonU16 (m_sequence);
+  start.Write (m_data->PeekData (), m_data->GetSize ());
+}
+uint32_t 
+Icmpv4Echo::Deserialize (Buffer::Iterator start)
+{
+  m_identifier = start.ReadNtohU16 ();
+  m_sequence = start.ReadNtohU16 ();
+  NS_ASSERT (start.GetSize () >= 4);
+  uint32_t size = start.GetSize () - 4;
+  uint8_t *buffer = new uint8_t[size] ();
+  start.Read (buffer, size);
+  m_data = Create<Packet> (buffer, size);
+  delete[] buffer;
+  return start.GetSize ();
+}
+void 
+Icmpv4Echo::Print (std::ostream &os) const
+{
+  os << "identifier=" << m_identifier << ", sequence="  << m_sequence;
+}
+
+
+/********************************************************
+ *        Icmpv4DestinationUnreachable
+ ********************************************************/
+
+TypeId 
+Icmpv4DestinationUnreachable::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Icmpv4DestinationUnreachable")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv4DestinationUnreachable> ()
+    ;
+  return tid;
+}
+Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable ()
+{
+  // make sure that thing is initialized to get initialized bytes
+  // when the ip payload's size is smaller than 8 bytes.
+  for (uint8_t j = 0; j < 8; j++)
+    {
+      m_data[j] = 0;
+    }
+}
+
+void 
+Icmpv4DestinationUnreachable::SetNextHopMtu (uint16_t mtu)
+{
+  m_nextHopMtu = mtu;
+}
+uint16_t 
+Icmpv4DestinationUnreachable::GetNextHopMtu (void) const
+{
+  return m_nextHopMtu;
+}
+
+void 
+Icmpv4DestinationUnreachable::SetData (Ptr<const Packet> data)
+{
+  data->CopyData (m_data, 8);
+}
+void 
+Icmpv4DestinationUnreachable::SetHeader (Ipv4Header header)
+{
+  m_header = header;
+}
+void 
+Icmpv4DestinationUnreachable::GetData (uint8_t payload[8]) const
+{
+  memcpy (payload, m_data, 8);
+}
+Ipv4Header 
+Icmpv4DestinationUnreachable::GetHeader (void) const
+{
+  return m_header;
+}
+
+
+Icmpv4DestinationUnreachable::~Icmpv4DestinationUnreachable ()
+{}
+TypeId 
+Icmpv4DestinationUnreachable::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+Icmpv4DestinationUnreachable::GetSerializedSize (void) const
+{
+  return 4 + m_header.GetSerializedSize () + 8;
+}
+void 
+Icmpv4DestinationUnreachable::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU16 (0);
+  start.WriteHtonU16 (m_nextHopMtu);
+  uint32_t size = m_header.GetSerializedSize ();
+  m_header.Serialize (start);
+  start.Next (size);
+  start.Write (m_data, 8);
+}
+  
+uint32_t 
+Icmpv4DestinationUnreachable::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  i.Next (2);
+  m_nextHopMtu = i.ReadNtohU16 ();
+  uint32_t read = m_header.Deserialize (i);
+  i.Next (read);
+  for (uint8_t j = 0; j < 8; j++)
+    {
+      m_data[j] = i.ReadU8 ();
+    }
+  return i.GetDistanceFrom (start);
+}
+void 
+Icmpv4DestinationUnreachable::Print (std::ostream &os) const
+{
+  m_header.Print (os);
+  os << " org data=";
+  for (uint8_t i = 0; i < 8; i++)
+    {
+      os << (uint32_t) m_data[i];
+      if (i != 8)
+	{
+	  os << " ";
+	}
+    }
+}
+
+/********************************************************
+ *        Icmpv4TimeExceeded
+ ********************************************************/
+
+TypeId 
+Icmpv4TimeExceeded::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Icmpv4TimeExceeded")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv4TimeExceeded> ()
+    ;
+  return tid;
+}
+Icmpv4TimeExceeded::Icmpv4TimeExceeded ()
+{
+  // make sure that thing is initialized to get initialized bytes
+  // when the ip payload's size is smaller than 8 bytes.
+  for (uint8_t j = 0; j < 8; j++)
+    {
+      m_data[j] = 0;
+    }
+}
+
+
+void 
+Icmpv4TimeExceeded::SetData (Ptr<const Packet> data)
+{
+  data->CopyData (m_data, 8);
+}
+void 
+Icmpv4TimeExceeded::SetHeader (Ipv4Header header)
+{
+  m_header = header;
+}
+void 
+Icmpv4TimeExceeded::GetData (uint8_t payload[8]) const
+{
+  memcpy (payload, m_data, 8);
+}
+Ipv4Header 
+Icmpv4TimeExceeded::GetHeader (void) const
+{
+  return m_header;
+}
+
+
+Icmpv4TimeExceeded::~Icmpv4TimeExceeded ()
+{}
+TypeId 
+Icmpv4TimeExceeded::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+Icmpv4TimeExceeded::GetSerializedSize (void) const
+{
+  return 4 + m_header.GetSerializedSize () + 8;
+}
+void 
+Icmpv4TimeExceeded::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU32 (0);
+  uint32_t size = m_header.GetSerializedSize ();
+  m_header.Serialize (start);
+  start.Next (size);
+  start.Write (m_data, 8);
+}
+  
+uint32_t 
+Icmpv4TimeExceeded::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  i.Next (4);
+  uint32_t read = m_header.Deserialize (i);
+  i.Next (read);
+  for (uint8_t j = 0; j < 8; j++)
+    {
+      m_data[j] = i.ReadU8 ();
+    }
+  return i.GetDistanceFrom (start);
+}
+void 
+Icmpv4TimeExceeded::Print (std::ostream &os) const
+{
+  m_header.Print (os);
+  os << " org data=";
+  for (uint8_t i = 0; i < 8; i++)
+    {
+      os << (uint32_t) m_data[i];
+      if (i != 8)
+	{
+	  os << " ";
+	}
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv4.h	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,137 @@
+#ifndef ICMPV4_H
+#define ICMPV4_H
+
+#include "ns3/header.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-header.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class Packet;
+
+class Icmpv4Header : public Header
+{
+public:
+  enum {
+    ECHO_REPLY = 0,
+    DEST_UNREACH = 3,
+    ECHO = 8,
+    TIME_EXCEEDED = 11
+  };
+
+  void EnableChecksum (void);
+  void SetType (uint8_t type);
+  void SetCode (uint8_t code);
+
+  uint8_t GetType (void) const;
+  uint8_t GetCode (void) const;
+
+  static TypeId GetTypeId (void);
+  Icmpv4Header ();
+  virtual ~Icmpv4Header ();
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+
+private:
+  uint8_t m_type;
+  uint8_t m_code;
+  bool m_calcChecksum;
+};
+
+class Icmpv4Echo : public Header
+{
+public:
+  void SetIdentifier (uint16_t id);
+  void SetSequenceNumber (uint16_t seq);
+  void SetData (Ptr<const Packet> data);
+  uint16_t GetIdentifier (void) const;
+  uint16_t GetSequenceNumber (void) const;
+  Ptr<const Packet> GetData (void) const;
+
+
+  static TypeId GetTypeId (void);
+  Icmpv4Echo ();
+  virtual ~Icmpv4Echo ();
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+private:
+  uint16_t m_identifier;
+  uint16_t m_sequence;
+  Ptr<Packet> m_data;
+};
+
+class Icmpv4DestinationUnreachable : public Header
+{
+public:
+  enum {
+    NET_UNREACHABLE = 0,
+    HOST_UNREACHABLE = 1,
+    PROTOCOL_UNREACHABLE = 2,
+    PORT_UNREACHABLE = 3,
+    FRAG_NEEDED = 4,
+    SOURCE_ROUTE_FAILED = 5
+  };
+  static TypeId GetTypeId (void);
+  Icmpv4DestinationUnreachable ();
+  virtual ~Icmpv4DestinationUnreachable ();
+
+  void SetNextHopMtu (uint16_t mtu);
+  uint16_t GetNextHopMtu (void) const;
+
+  void SetData (Ptr<const Packet> data);
+  void SetHeader (Ipv4Header header);
+
+  void GetData (uint8_t payload[8]) const;
+  Ipv4Header GetHeader (void) const;
+
+private:
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+private:
+  uint16_t m_nextHopMtu;
+  Ipv4Header m_header;
+  uint8_t m_data[8];
+};
+
+
+class Icmpv4TimeExceeded : public Header
+{
+public:
+  enum {
+    TIME_TO_LIVE = 0,
+    FRAGMENT_REASSEMBLY = 1
+  };
+
+  void SetData (Ptr<const Packet> data);
+  void SetHeader (Ipv4Header header);
+
+  void GetData (uint8_t payload[8]) const;
+  Ipv4Header GetHeader (void) const;
+
+  static TypeId GetTypeId (void);
+  Icmpv4TimeExceeded ();
+  virtual ~Icmpv4TimeExceeded ();
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+
+private:
+  Ipv4Header m_header;
+  uint8_t m_data[8];
+};
+
+} // namespace ns3
+
+#endif /* ICMPV4_H */
--- a/src/internet-stack/internet-stack.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/internet-stack.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -30,6 +30,8 @@
 #include "udp-socket-factory-impl.h"
 #include "tcp-socket-factory-impl.h"
 #include "ipv4-impl.h"
+#include "ipv4-raw-socket-factory-impl.h"
+#include "icmpv4-l4-protocol.h"
 #ifdef NETWORK_SIMULATION_CRADLE
 #include "nsc-tcp-socket-factory-impl.h"
 #include "nsc-tcp-l4-protocol.h"
@@ -58,12 +60,25 @@
 }
 
 static void
+AddIcmpStack (Ptr<Node> node)
+{
+  Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
+  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
+  icmp->SetNode (node);
+  ipv4->Insert (icmp);
+  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
+  node->AggregateObject (rawFactory);
+}
+
+static void
 AddTcpStack(Ptr<Node> node)
 {
   Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
   Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
   tcp->SetNode (node);
+
   ipv4->Insert (tcp);
+
   Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
   tcpFactory->SetTcp (tcp);
   node->AggregateObject (tcpFactory);
@@ -85,6 +100,7 @@
 {
   AddArpStack (node);
   AddIpv4Stack (node);
+  AddIcmpStack (node);
   AddUdpStack (node);
   AddTcpStack (node);
 }
@@ -109,7 +125,7 @@
 {
   AddArpStack (node);
   AddIpv4Stack (node);
-
+  AddIcmpStack (node);
   AddUdpStack (node);
   AddNscStack (node, soname);
 }
--- a/src/internet-stack/ipv4-end-point-demux.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-end-point-demux.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -287,6 +287,47 @@
   return retval1;  // might be empty if no matches
 }
 
+Ipv4EndPoint *
+Ipv4EndPointDemux::SimpleLookup (Ipv4Address daddr, 
+                                 uint16_t dport, 
+                                 Ipv4Address saddr, 
+                                 uint16_t sport)
+{
+  // this code is a copy/paste version of an old BSD ip stack lookup
+  // function.
+  uint32_t genericity = 3;
+  Ipv4EndPoint *generic = 0;
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+    {
+      if ((*i)->GetLocalPort () != dport) 
+        {
+          continue;
+        }
+      if ((*i)->GetLocalAddress () == daddr &&
+          (*i)->GetPeerPort () == sport &&
+          (*i)->GetPeerAddress () == saddr) 
+        {
+          /* this is an exact match. */
+          return *i;
+        }
+      uint32_t tmp = 0;
+      if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ()) 
+        {
+          tmp ++;
+        }
+      if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ()) 
+        {
+          tmp ++;
+        }
+      if (tmp < genericity) 
+        {
+          generic = (*i);
+          genericity = tmp;
+        }
+    }
+  return generic;
+}
+
 uint16_t
 Ipv4EndPointDemux::AllocateEphemeralPort (void)
 {
--- a/src/internet-stack/ipv4-end-point-demux.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-end-point-demux.h	Wed Oct 29 11:18:39 2008 -0700
@@ -57,6 +57,11 @@
                     uint16_t sport,
                     Ptr<Ipv4Interface> incomingInterface);
 
+  Ipv4EndPoint *SimpleLookup (Ipv4Address daddr, 
+                              uint16_t dport, 
+                              Ipv4Address saddr, 
+                              uint16_t sport);
+
   Ipv4EndPoint *Allocate (void);
   Ipv4EndPoint *Allocate (Ipv4Address address);
   Ipv4EndPoint *Allocate (uint16_t port);
--- a/src/internet-stack/ipv4-end-point.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-end-point.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -20,6 +20,9 @@
 
 #include "ipv4-end-point.h"
 #include "ns3/packet.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4EndPoint");
 
 namespace ns3 {
 
@@ -76,6 +79,11 @@
 {
   m_rxCallback = callback;
 }
+void 
+Ipv4EndPoint::SetIcmpCallback (Callback<void,Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> callback)
+{
+  m_icmpCallback = callback;
+}
 
 void 
 Ipv4EndPoint::SetDestroyCallback (Callback<void> callback)
@@ -92,6 +100,17 @@
   }
 }
 
-
+void 
+Ipv4EndPoint::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
+                           uint8_t icmpType, uint8_t icmpCode,
+                           uint32_t icmpInfo)
+{
+  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
+                   (uint32_t)icmpCode << icmpInfo);
+  if (!m_icmpCallback.IsNull ())
+    {
+      m_icmpCallback (icmpSource,icmpTtl,icmpType,icmpCode,icmpInfo);
+    }
+}
 
 }; // namespace ns3
--- a/src/internet-stack/ipv4-end-point.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-end-point.h	Wed Oct 29 11:18:39 2008 -0700
@@ -54,10 +54,19 @@
 
   void SetPeer (Ipv4Address address, uint16_t port);
 
+  // Called from socket implementations to get notified about important events.
   void SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> callback);
+  void SetIcmpCallback (Callback<void,Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> callback);
   void SetDestroyCallback (Callback<void> callback);
 
+  // Called from an L4Protocol implementation to notify an endpoint of a
+  // packet reception.
   void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, uint16_t sport);
+  // Called from an L4Protocol implementation to notify an endpoint of
+  // an icmp message reception.
+  void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
+                    uint8_t icmpType, uint8_t icmpCode,
+                    uint32_t icmpInfo);
 
 private:
   Ipv4Address m_localAddr;
@@ -65,6 +74,7 @@
   Ipv4Address m_peerAddr;
   uint16_t m_peerPort;
   Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> m_rxCallback;
+  Callback<void,Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
   Callback<void> m_destroyCallback;
 };
 
--- a/src/internet-stack/ipv4-l3-protocol.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -35,9 +35,11 @@
 
 #include "ipv4-l3-protocol.h"
 #include "ipv4-l4-protocol.h"
+#include "icmpv4-l4-protocol.h"
 #include "ipv4-interface.h"
 #include "ipv4-loopback-interface.h"
 #include "arp-ipv4-interface.h"
+#include "ipv4-raw-socket-impl.h"
 
 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
 
@@ -120,6 +122,30 @@
   SetupLoopback ();
 }
 
+Ptr<Socket> 
+Ipv4L3Protocol::CreateRawSocket (void)
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
+  socket->SetNode (m_node);
+  m_sockets.push_back (socket);
+  return socket;
+}
+void 
+Ipv4L3Protocol::DeleteRawSocket (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
+    {
+      if ((*i) == socket)
+        {
+          m_sockets.erase (i);
+          return;
+        }
+    }
+  return;
+}
+
 void 
 Ipv4L3Protocol::DoDispose (void)
 {
@@ -514,6 +540,12 @@
       return;
     }
 
+  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
+    {
+      Ptr<Ipv4RawSocketImpl> socket = *i;
+      socket->ForwardUp (packet, ipHeader, device);
+    }
+
   if (Forwarding (index, packet, ipHeader, device)) 
     {
       return;
@@ -522,6 +554,25 @@
   ForwardUp (packet, ipHeader, ipv4Interface);
 }
 
+Ptr<Icmpv4L4Protocol> 
+Ipv4L3Protocol::GetIcmp (void) const
+{
+  Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
+  if (prot != 0)
+    {
+      return prot->GetObject<Icmpv4L4Protocol> ();
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+bool
+Ipv4L3Protocol::IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const
+{
+  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
+}
 
 void 
 Ipv4L3Protocol::Send (Ptr<Packet> packet, 
@@ -542,16 +593,29 @@
   ipHeader.SetDestination (destination);
   ipHeader.SetProtocol (protocol);
   ipHeader.SetPayloadSize (packet->GetSize ());
-  ipHeader.SetTtl (m_defaultTtl);
-  ipHeader.SetMayFragment ();
   ipHeader.SetIdentification (m_identification);
 
   m_identification ++;
 
+  SocketSetDontFragmentTag dfTag;
+  bool found = packet->FindFirstMatchingTag (dfTag);
+  if (found)
+    {
+      if (dfTag.IsEnabled ())
+        {
+          ipHeader.SetDontFragment ();
+        }
+      else
+        {
+          ipHeader.SetMayFragment ();
+        }
+    }
+  
+
   // Set TTL to 1 if it is a broadcast packet of any type.  Otherwise,
   // possibly override the default TTL if the packet is tagged
   SocketIpTtlTag tag;
-  bool found = packet->FindFirstMatchingTag (tag);
+  found = packet->FindFirstMatchingTag (tag);
 
   if (destination.IsBroadcast ()) 
     {
@@ -564,6 +628,7 @@
     }
   else
     {
+      ipHeader.SetTtl (m_defaultTtl);
       uint32_t ifaceIndex = 0;
       for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
            ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
@@ -585,10 +650,28 @@
           Ptr<Ipv4Interface> outInterface = *ifaceIter;
           Ptr<Packet> packetCopy = packet->Copy ();
 
-          NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
           packetCopy->AddHeader (ipHeader);
-          m_txTrace (packetCopy, ifaceIndex);
-          outInterface->Send (packetCopy, destination);
+          if (packetCopy->GetSize () > outInterface->GetMtu () &&
+              ipHeader.IsDontFragment () &&
+              IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ()))
+            {
+              Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
+              NS_ASSERT (icmp != 0);
+              icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ());
+              m_dropTrace (packetCopy);
+            }
+          else if (packet->GetSize () > outInterface->GetMtu () &&
+                   !ipHeader.IsDontFragment ())
+            {
+              NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
+              m_dropTrace (packet);
+            }
+          else
+            {
+              NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
+              m_txTrace (packetCopy, ifaceIndex);
+              outInterface->Send (packetCopy, destination);
+            }
         }
     }
   else
@@ -625,17 +708,38 @@
   NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
 
   Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
-  NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
-  m_txTrace (packet, route.GetInterface ());
-  if (route.IsGateway ()) 
+  if (packet->GetSize () > outInterface->GetMtu () &&
+      ipHeader.IsDontFragment () &&
+      IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ()))
+    {
+      NS_LOG_LOGIC ("Too big: need fragmentation but not allowed");
+      Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
+      NS_ASSERT (icmp != 0);
+      Ptr<Packet> copyNoHeader = packet->Copy ();
+      Ipv4Header tmp;
+      copyNoHeader->RemoveHeader (tmp);
+      icmp->SendDestUnreachFragNeeded (ipHeader, copyNoHeader, outInterface->GetMtu ());
+      m_dropTrace (packet);
+    }
+  else if (packet->GetSize () > outInterface->GetMtu () &&
+           !ipHeader.IsDontFragment ())
     {
-      NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
-      outInterface->Send (packet, route.GetGateway ());
-    } 
-  else 
+      NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
+      m_dropTrace (packet);
+    }
+  else
     {
-      NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
-      outInterface->Send (packet, ipHeader.GetDestination ());
+      m_txTrace (packet, route.GetInterface ());
+      if (route.IsGateway ()) 
+        {
+          NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
+          outInterface->Send (packet, route.GetGateway ());
+        } 
+      else 
+        {
+          NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
+          outInterface->Send (packet, ipHeader.GetDestination ());
+        }
     }
 }
 
@@ -685,17 +789,6 @@
       NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
       return false;
     }
-
-  if (ipHeader.GetTtl () == 1) 
-    {
-      // Should send ttl expired here
-      // XXX
-      NS_LOG_LOGIC ("Not for me (TTL expired).  Drop");
-      m_dropTrace (packet);
-      return true;
-    }
-  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
-
 //  
 // If this is a to a multicast address and this node is a member of the 
 // indicated group we need to return false so the multicast is forwarded up.
@@ -710,18 +803,39 @@
           // We forward with a packet copy, since forwarding may change
           // the packet, affecting our local delivery
           NS_LOG_LOGIC ("Forwarding (multicast).");
-          Lookup (ifIndex, ipHeader, packet->Copy (),
-          MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+          DoForward (ifIndex, packet->Copy (), ipHeader);
           return false;
         }   
-    }     
+    }
+
+  DoForward (ifIndex, packet, ipHeader);
+  return true;
+}
+
+void
+Ipv4L3Protocol::DoForward (uint32_t ifIndex, 
+                           Ptr<Packet> packet, 
+                           Ipv4Header ipHeader)
+{
+  NS_LOG_FUNCTION (this << ifIndex << packet << ipHeader);
+
+  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
+  if (ipHeader.GetTtl () == 0)
+    {
+      if (IsUnicast (ipHeader.GetDestination (), GetInterface (ifIndex)->GetNetworkMask ()))
+        {
+          Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
+          icmp->SendTimeExceededTtl (ipHeader, packet);
+        }
+      m_dropTrace (packet);
+      return;
+    }  
   NS_LOG_LOGIC ("Not for me, forwarding.");
   Lookup (ifIndex, ipHeader, packet,
-  MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
-  
-  return true;
+          MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
 }
 
+
 void
 Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
                            Ptr<Ipv4Interface> incomingInterface)
@@ -729,7 +843,26 @@
   NS_LOG_FUNCTION (this << p << &ip);
 
   Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
-  protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
+  if (protocol != 0)
+    {
+      // we need to make a copy in the unlikely event we hit the
+      // RX_ENDPOINT_UNREACH codepath
+      Ptr<Packet> copy = p->Copy ();
+      enum Ipv4L4Protocol::RxStatus status = 
+        protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
+      switch (status) {
+      case Ipv4L4Protocol::RX_OK:
+        // fall through
+      case Ipv4L4Protocol::RX_CSUM_FAILED:
+        break;
+      case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
+        if (IsUnicast (ip.GetDestination (), incomingInterface->GetNetworkMask ()))
+          {
+            GetIcmp ()->SendDestUnreachPort (ip, copy);
+          }
+        break;
+      }
+    }
 }
 
 void 
--- a/src/internet-stack/ipv4-l3-protocol.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-l3-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -40,7 +40,11 @@
 class Ipv4Header;
 class Ipv4Route;
 class Node;
+class Socket;
+class Ipv4RawSocketImpl;
 class Ipv4L4Protocol;
+class Ipv4L4Protocol;
+class Icmpv4L4Protocol;
 
 
 /**
@@ -60,6 +64,9 @@
 
   void SetNode (Ptr<Node> node);
 
+  Ptr<Socket> CreateRawSocket (void);
+  void DeleteRawSocket (Ptr<Socket> socket);
+
   /**
    * \param protocol a template for the protocol to add to this L4 Demux.
    * \returns the L4Protocol effectively added.
@@ -201,6 +208,8 @@
   virtual void DoDispose (void);
 
 private:
+  Ipv4L3Protocol(const Ipv4L3Protocol &);
+  Ipv4L3Protocol &operator = (const Ipv4L3Protocol &);
   void Lookup (uint32_t ifIndex,
                Ipv4Header const &ipHeader,
                Ptr<Packet> packet,
@@ -217,15 +226,19 @@
   void ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, Ptr<Ipv4Interface> incomingInterface);
   uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
   void SetupLoopback (void);
-  Ipv4L3Protocol(const Ipv4L3Protocol &);
-  Ipv4L3Protocol &operator = (const Ipv4L3Protocol &);
+  Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
+  bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const;
+  void DoForward (uint32_t ifIndex, 
+                  Ptr<Packet> packet, 
+                  Ipv4Header ipHeader);
+
 
   typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
-  typedef std::list<std::pair<Ipv4Address, Ipv4Address> > 
-    Ipv4MulticastGroupList;
+  typedef std::list<std::pair<Ipv4Address, Ipv4Address> > Ipv4MulticastGroupList;
   typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
+  typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
+  typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
 
-  typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
   L4List_t m_protocols;
   Ipv4InterfaceList m_interfaces;
   uint32_t m_nInterfaces;
@@ -241,6 +254,8 @@
 
   Ptr<Ipv4StaticRouting> m_staticRouting;
   Ipv4MulticastGroupList m_multicastGroups;
+
+  SocketList m_sockets;
 };
 
 } // Namespace ns3
--- a/src/internet-stack/ipv4-l4-protocol.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-l4-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -44,4 +44,11 @@
 Ipv4L4Protocol::~Ipv4L4Protocol ()
 {}
 
+void 
+Ipv4L4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                             Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                             const uint8_t payload[8])
+{}
+
 }//namespace ns3
--- a/src/internet-stack/ipv4-l4-protocol.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/ipv4-l4-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -25,12 +25,13 @@
 #define IPV4_L4_PROTOCOL_H
 
 #include "ns3/object.h"
-#include "ipv4-interface.h"
+#include "ns3/ipv4-header.h"
 
 namespace ns3 {
 
 class Packet;
 class Ipv4Address;
+class Ipv4Interface;
 
 /**
  * \brief L4 Protocol abstract base class 
@@ -41,6 +42,12 @@
 class Ipv4L4Protocol : public Object
 {
 public:
+  enum RxStatus {
+    RX_OK,
+    RX_CSUM_FAILED,
+    RX_ENDPOINT_UNREACH
+  };
+
   static TypeId GetTypeId (void);
 
   virtual ~Ipv4L4Protocol ();
@@ -59,10 +66,29 @@
    * Called from lower-level layers to send the packet up
    * in the stack. 
    */
-  virtual void Receive(Ptr<Packet> p, 
-                       Ipv4Address const &source,
-                       Ipv4Address const &destination,
-                       Ptr<Ipv4Interface> incomingInterface) = 0;
+  virtual enum RxStatus Receive(Ptr<Packet> p, 
+                                Ipv4Address const &source,
+                                Ipv4Address const &destination,
+                                Ptr<Ipv4Interface> incomingInterface) = 0;
+
+  /**
+   * \param icmpSouce the source address of the icmp message
+   * \param icmpTtl the ttl of the icmp message
+   * \param icmpType the 'type' field of the icmp message
+   * \param icmpCode the 'code' field of the icmp message
+   * \param icmpInfo extra information dependent on the icmp message
+   *        generated by Icmpv4L4Protocol
+   * \param payloadSource the source address of the packet which triggered
+   *        the icmp message
+   * \param payloadDestination the destination address of the packet which
+   *        triggered the icmp message.
+   * \param payload the first 8 bytes of the udp header of the packet
+   *        which triggered the icmp message.
+   */
+  virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource, Ipv4Address payloadDestination,
+                            const uint8_t payload[8]);
 };
 
 } // Namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-raw-socket-factory-impl.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,16 @@
+#include "ipv4-raw-socket-factory-impl.h"
+#include "ipv4-l3-protocol.h"
+#include "ns3/socket.h"
+
+namespace ns3 {
+
+
+Ptr<Socket> 
+Ipv4RawSocketFactoryImpl::CreateSocket (void)
+{
+  Ptr<Ipv4L3Protocol> ipv4 = GetObject<Ipv4L3Protocol> ();
+  Ptr<Socket> socket = ipv4->CreateRawSocket ();
+  return socket;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-raw-socket-factory-impl.h	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,17 @@
+#ifndef IPV4_RAW_SOCKET_FACTORY_IMPL_H
+#define IPV4_RAW_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/ipv4-raw-socket-factory.h"
+
+namespace ns3 {
+
+class Ipv4RawSocketFactoryImpl : public Ipv4RawSocketFactory
+{
+public:
+  virtual Ptr<Socket> CreateSocket (void);
+};
+
+
+} // namespace ns3
+
+#endif /* IPV4_RAW_SOCKET_FACTORY_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-raw-socket-impl.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,269 @@
+#include "ipv4-raw-socket-impl.h"
+#include "ipv4-l3-protocol.h"
+#include "icmpv4.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4RawSocketImpl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketImpl);
+
+TypeId 
+Ipv4RawSocketImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4RawSocketImpl")
+    .SetParent<Socket> ()
+    .AddAttribute ("Protocol", "Protocol number to match.",
+		   UintegerValue (0),
+		   MakeUintegerAccessor (&Ipv4RawSocketImpl::m_protocol),
+		   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("IcmpFilter", 
+		   "Any icmp header whose type field matches a bit in this filter is dropped.",
+		   UintegerValue (0),
+		   MakeUintegerAccessor (&Ipv4RawSocketImpl::m_icmpFilter),
+		   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+Ipv4RawSocketImpl::Ipv4RawSocketImpl ()
+{
+  NS_LOG_FUNCTION (this);
+  m_err = Socket::ERROR_NOTERROR;
+  m_node = 0;
+  m_src = Ipv4Address::GetAny ();
+  m_dst = Ipv4Address::GetAny ();
+  m_protocol = 0;
+  m_shutdownSend = false;
+  m_shutdownRecv = false;
+}
+
+void 
+Ipv4RawSocketImpl::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+void
+Ipv4RawSocketImpl::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  Socket::DoDispose ();
+}
+
+enum Socket::SocketErrno 
+Ipv4RawSocketImpl::GetErrno (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_err;
+}
+Ptr<Node> 
+Ipv4RawSocketImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_node;
+}
+int 
+Ipv4RawSocketImpl::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION (this << address);
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      m_err = Socket::ERROR_INVAL;
+      return -1;
+    }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (address);
+  m_src = ad.GetIpv4 ();
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::Bind (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_src = Ipv4Address::GetAny ();
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::GetSockName (Address &address) const
+{
+  address = InetSocketAddress (m_src, 0);
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::Close (void)
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  if (ipv4 != 0)
+    {
+      ipv4->DeleteRawSocket (this);
+    }
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_shutdownSend = true;
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_shutdownRecv = true;
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::Connect (const Address &address)
+{
+  NS_LOG_FUNCTION (this << address);
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      m_err = Socket::ERROR_INVAL;
+      return -1;
+    }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (address);
+  m_dst = ad.GetIpv4 ();
+  return 0;
+}
+int 
+Ipv4RawSocketImpl::Listen (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_err = Socket::ERROR_OPNOTSUPP;
+  return -1;
+}
+uint32_t 
+Ipv4RawSocketImpl::GetTxAvailable (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return 0xffffffff;
+}
+int 
+Ipv4RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << p << flags);
+  InetSocketAddress to = InetSocketAddress (m_dst, m_protocol);
+  return SendTo (p, flags, to);
+}
+int 
+Ipv4RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, 
+			   const Address &toAddress)
+{
+  NS_LOG_FUNCTION (this << p << flags << toAddress);
+  if (!InetSocketAddress::IsMatchingType (toAddress))
+    {
+      m_err = Socket::ERROR_INVAL;
+      return -1;
+    }
+  if (m_shutdownSend)
+    {
+      return 0;
+    }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  Ipv4Address dst = ad.GetIpv4 ();
+  uint32_t localIfIndex;
+  if (ipv4->GetIfIndexForDestination(dst, localIfIndex))
+    {
+      ipv4->Send (p, ipv4->GetAddress (localIfIndex), dst, m_protocol);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("dropped because no outgoing route.");
+    }
+  return 0;
+}
+uint32_t 
+Ipv4RawSocketImpl::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION (this);
+  uint32_t rx = 0;
+  for (std::list<Data>::const_iterator i = m_recv.begin (); i != m_recv.end (); ++i)
+    {
+      rx += (i->packet)->GetSize ();
+    }
+  return rx;
+}
+Ptr<Packet> 
+Ipv4RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags);
+  Address tmp;
+  return RecvFrom (maxSize, flags, tmp);
+}
+Ptr<Packet> 
+Ipv4RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,  
+			     Address &fromAddress)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
+  if (m_recv.empty ())
+    {
+      return 0;
+    }
+  struct Data data = m_recv.front ();
+  m_recv.pop_front ();
+  if (data.packet->GetSize () > maxSize)
+    {
+      Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
+      data.packet->RemoveAtStart (maxSize);
+      m_recv.push_front (data);
+      return first;
+    }
+  InetSocketAddress inet = InetSocketAddress (data.fromIp, data.fromProtocol);
+  fromAddress = inet;
+  return data.packet;
+}
+
+void 
+Ipv4RawSocketImpl::SetProtocol (uint16_t protocol)
+{
+  NS_LOG_FUNCTION (this << protocol);
+  m_protocol = protocol;
+}
+
+bool 
+Ipv4RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << *p << ipHeader << device);
+  if (m_shutdownRecv)
+    {
+      return false;
+    }
+  if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) &&
+      (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) &&
+      ipHeader.GetProtocol () == m_protocol)
+    {
+      Ptr<Packet> copy = p->Copy ();
+      if (m_protocol == 1)
+	{
+	  Icmpv4Header icmpHeader;
+	  copy->PeekHeader (icmpHeader);
+	  uint8_t type = icmpHeader.GetType ();
+	  if (type < 32 && 
+	      ((1 << type) & m_icmpFilter))
+	    {
+	      // filter out icmp packet.
+	      return false;
+	    }
+	}
+      copy->AddHeader (ipHeader);
+      struct Data data;
+      data.packet = copy;
+      data.fromIp = ipHeader.GetSource ();
+      data.fromProtocol = ipHeader.GetProtocol ();
+      m_recv.push_back (data);
+      NotifyDataRecv ();
+      return true;
+    }
+  return false;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-raw-socket-impl.h	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,65 @@
+#ifndef IPV4_RAW_SOCKET_IMPL_H
+#define IPV4_RAW_SOCKET_IMPL_H
+
+#include "ns3/socket.h"
+#include "ns3/ipv4-header.h"
+#include <list>
+
+namespace ns3 {
+
+class NetDevice;
+class Node;
+
+class Ipv4RawSocketImpl : public Socket
+{
+public:
+  static TypeId GetTypeId (void);
+
+  Ipv4RawSocketImpl ();
+
+  void SetNode (Ptr<Node> node);
+
+  virtual enum Socket::SocketErrno GetErrno (void) const;
+  virtual Ptr<Node> GetNode (void) const;
+  virtual int Bind (const Address &address);
+  virtual int Bind ();
+  virtual int GetSockName (Address &address) const; 
+  virtual int Close (void);
+  virtual int ShutdownSend (void);
+  virtual int ShutdownRecv (void);
+  virtual int Connect (const Address &address);
+  virtual int Listen (void);
+  virtual uint32_t GetTxAvailable (void) const;
+  virtual int Send (Ptr<Packet> p, uint32_t flags);
+  virtual int SendTo (Ptr<Packet> p, uint32_t flags, 
+		      const Address &toAddress);
+  virtual uint32_t GetRxAvailable (void) const;
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,  
+				Address &fromAddress);
+
+  void SetProtocol (uint16_t protocol);
+  bool ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device);
+private:
+  virtual void DoDispose (void);
+
+  struct Data {
+    Ptr<Packet> packet;
+    Ipv4Address fromIp;
+    uint16_t fromProtocol;
+  };
+
+  enum Socket::SocketErrno m_err;
+  Ptr<Node> m_node;
+  Ipv4Address m_src;
+  Ipv4Address m_dst;
+  uint16_t m_protocol;
+  std::list<struct Data> m_recv;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  uint32_t m_icmpFilter;
+};
+
+} // namespace ns3
+
+#endif /* IPV4_RAW_SOCKET_IMPL_H */
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -220,7 +220,7 @@
   // NSC m_endPoints->DeAllocate (endPoint);
 }
 
-void
+Ipv4L4Protocol::RxStatus
 NscTcpL4Protocol::Receive (Ptr<Packet> packet,
              Ipv4Address const &source,
              Ipv4Address const &destination,
@@ -251,6 +251,7 @@
   // deliver complete packet to the NSC network stack
   m_nscStack->if_receive_packet(0, data, packetSize);
   wakeup ();
+  return Ipv4L4Protocol::RX_OK;
 }
 
 void NscTcpL4Protocol::SoftInterrupt (void)
--- a/src/internet-stack/nsc-tcp-l4-protocol.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -80,10 +80,10 @@
    * \param destination The destinations Ipv4Address
    * \param incomingInterface The Ipv4Interface it was received on
    */
-  virtual void Receive (Ptr<Packet> p,
-                       Ipv4Address const &source,
-                       Ipv4Address const &destination,
-                       Ptr<Ipv4Interface> incomingInterface);
+  virtual Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                            Ipv4Address const &source,
+                                            Ipv4Address const &destination,
+                                            Ptr<Ipv4Interface> incomingInterface);
 
   // NSC callbacks.
   // NSC invokes these hooks to interact with the simulator.
--- a/src/internet-stack/tcp-l4-protocol.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/tcp-l4-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -431,7 +431,7 @@
   m_endPoints->DeAllocate (endPoint);
 }
 
-void 
+enum Ipv4L4Protocol::RxStatus
 TcpL4Protocol::Receive (Ptr<Packet> packet,
              Ipv4Address const &source,
              Ipv4Address const &destination,
@@ -457,7 +457,7 @@
   if(!tcpHeader.IsChecksumOk ())
   {
     NS_LOG_INFO("Bad checksum, dropping packet!");
-    return;
+    return Ipv4L4Protocol::RX_CSUM_FAILED;
   }
 
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
@@ -474,11 +474,12 @@
     source.Print (oss);
     oss<<" source port: "<<tcpHeader.GetSourcePort ();
     NS_LOG_LOGIC (oss.str ());
-    return;
+    return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
   }
   NS_ASSERT_MSG (endPoints.size() == 1 , "Demux returned more than one endpoint");
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
   (*endPoints.begin ())->ForwardUp (packet, source, tcpHeader.GetSourcePort ());
+  return Ipv4L4Protocol::RX_OK;
 }
 
 void
--- a/src/internet-stack/tcp-l4-protocol.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/tcp-l4-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -101,10 +101,10 @@
    * \param destination The destinations Ipv4Address
    * \param incomingInterface The Ipv4Interface it was received on
    */
-  virtual void Receive (Ptr<Packet> p,
-                       Ipv4Address const &source,
-                       Ipv4Address const &destination,
-                       Ptr<Ipv4Interface> incomingInterface);
+  virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv4Address const &source,
+                                                 Ipv4Address const &destination,
+                                                 Ptr<Ipv4Interface> incomingInterface);
 
 protected:
   virtual void DoDispose (void);
--- a/src/internet-stack/udp-l4-protocol.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/udp-l4-protocol.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -146,6 +146,33 @@
 }
 
 void 
+UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                            const uint8_t payload[8])
+{
+  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo 
+                   << payloadSource << payloadDestination);
+  uint16_t src, dst;
+  src = payload[0] << 8;
+  src |= payload[1];
+  dst = payload[2] << 8;
+  dst |= payload[3];
+
+  Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst);
+  if (endPoint != 0)
+    {
+      endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
+                    ", destination="<<payloadDestination<<
+                    ", src=" << src << ", dst=" << dst);
+    }
+}
+
+enum Ipv4L4Protocol::RxStatus
 UdpL4Protocol::Receive(Ptr<Packet> packet, 
                        Ipv4Address const &source,
                        Ipv4Address const &destination,
@@ -165,17 +192,22 @@
   if(!udpHeader.IsChecksumOk ())
   {
     NS_LOG_INFO("Bad checksum : dropping packet!");
-    return;
+    return Ipv4L4Protocol::RX_CSUM_FAILED;
   }
 
   Ipv4EndPointDemux::EndPoints endPoints =
     m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (),
                          source, udpHeader.GetSourcePort (), interface);
+  if (endPoints.empty ())
+    {
+      return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
+    }
   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
        endPoint != endPoints.end (); endPoint++)
     {
       (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ());
     }
+  return Ipv4L4Protocol::RX_OK;
 }
 
 void
--- a/src/internet-stack/udp-l4-protocol.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/udp-l4-protocol.h	Wed Oct 29 11:18:39 2008 -0700
@@ -84,10 +84,15 @@
    * \param interface the interface from which the packet is coming.
    */
   // inherited from Ipv4L4Protocol
-  virtual void Receive(Ptr<Packet> p, 
-                       Ipv4Address const &source,
-                       Ipv4Address const &destination,
+  virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr<Packet> p, 
+                                                Ipv4Address const &source,
+                                                Ipv4Address const &destination,
                        Ptr<Ipv4Interface> interface);
+
+  virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                            const uint8_t payload[8]);
 protected:
   virtual void DoDispose (void);
 private:
--- a/src/internet-stack/udp-socket-impl.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/udp-socket-impl.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -25,8 +25,6 @@
 #include "ns3/ipv4.h"
 #include "ns3/udp-socket-factory.h"
 #include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-#include "ns3/boolean.h"
 #include "udp-socket-impl.h"
 #include "udp-l4-protocol.h"
 #include "ipv4-end-point.h"
@@ -47,6 +45,10 @@
     .AddConstructor<UdpSocketImpl> ()
     .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
                      MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
+    .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
+                   CallbackValue (),
+                   MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
+                   MakeCallbackChecker ())
     ;
   return tid;
 }
@@ -134,6 +136,7 @@
       return -1;
     }
   m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
+  m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
   m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
   return 0;
 }
@@ -328,6 +331,22 @@
       tag.SetTtl (m_ipTtl);
       p->AddTag (tag);
     }
+  {
+    SocketSetDontFragmentTag tag;
+    bool found = p->FindFirstMatchingTag (tag);
+    if (!found)
+      {
+        if (m_mtuDiscover)
+          {
+            tag.Enable ();
+          }
+        else
+          {
+            tag.Disable ();
+          }
+        p->AddTag (tag);
+      }
+  }
   //
   // If dest is sent to the limited broadcast address (all ones),
   // convert it to send a copy of the packet out of every interface
@@ -405,6 +424,7 @@
   NS_LOG_FUNCTION (this << maxSize << flags);
   if (m_deliveryQueue.empty() )
     {
+      m_errno = ERROR_AGAIN;
       return 0;
     }
   Ptr<Packet> p = m_deliveryQueue.front ();
@@ -483,6 +503,19 @@
     }
 }
 
+void
+UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
+                            uint8_t icmpType, uint8_t icmpCode,
+                            uint32_t icmpInfo)
+{
+  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
+                   (uint32_t)icmpCode << icmpInfo);
+  if (!m_icmpCallback.IsNull ())
+    {
+      m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+}
+
 
 void 
 UdpSocketImpl::SetRcvBufSize (uint32_t size)
@@ -520,6 +553,18 @@
   return m_ipMulticastTtl;
 }
 
+void 
+UdpSocketImpl::SetMtuDiscover (bool discover)
+{
+  m_mtuDiscover = discover;
+}
+bool 
+UdpSocketImpl::GetMtuDiscover (void) const
+{
+  return m_mtuDiscover;
+}
+
+
 } //namespace ns3
 
 
--- a/src/internet-stack/udp-socket-impl.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/udp-socket-impl.h	Wed Oct 29 11:18:39 2008 -0700
@@ -28,6 +28,7 @@
 #include "ns3/ptr.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/udp-socket.h"
+#include "icmpv4.h"
 
 namespace ns3 {
 
@@ -83,6 +84,9 @@
   virtual uint32_t GetIpTtl (void) const;
   virtual void SetIpMulticastTtl (uint32_t ipTtl);
   virtual uint32_t GetIpMulticastTtl (void) const;
+  virtual void SetMtuDiscover (bool discover);
+  virtual bool GetMtuDiscover (void) const;
+
 
   friend class UdpSocketFactory;
   // invoked by Udp class
@@ -92,6 +96,9 @@
   int DoSend (Ptr<Packet> p);
   int DoSendTo (Ptr<Packet> p, const Address &daddr);
   int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+  void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
+                    uint8_t icmpType, uint8_t icmpCode,
+                    uint32_t icmpInfo);
 
   Ipv4EndPoint *m_endPoint;
   Ptr<Node> m_node;
@@ -114,7 +121,8 @@
   uint32_t m_rcvBufSize;
   uint32_t m_ipTtl;
   uint32_t m_ipMulticastTtl;
-
+  bool m_mtuDiscover;
+  Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
 };
 
 }//namespace ns3
--- a/src/internet-stack/wscript	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/internet-stack/wscript	Wed Oct 29 11:18:39 2008 -0700
@@ -148,6 +148,10 @@
         'pending-data.cc',
         'sequence-number.cc',
         'rtt-estimator.cc',
+        'ipv4-raw-socket-factory-impl.cc',
+        'ipv4-raw-socket-impl.cc',
+        'icmpv4.cc',
+        'icmpv4-l4-protocol.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -160,6 +164,7 @@
         'ipv4-interface.h',
         'ipv4-l3-protocol.h',
         'ipv4-static-routing.h',
+        'icmpv4.h',
         ]
 
     if bld.env()['NSC_ENABLED']:        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-raw-socket-factory.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,35 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ipv4-raw-socket-factory.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketFactory);
+
+TypeId Ipv4RawSocketFactory::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4RawSocketFactory")
+    .SetParent<SocketFactory> ()
+    ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-raw-socket-factory.h	Wed Oct 29 11:18:39 2008 -0700
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV4_RAW_SOCKET_FACTORY_H
+#define IPV4_RAW_SOCKET_FACTORY_H
+
+#include "socket-factory.h"
+
+namespace ns3 {
+
+class Socket;
+
+/**
+ * \ingroup socket
+ *
+ * \brief API to create RAW socket instances 
+ *
+ * This abstract class defines the API for RAW socket factory.
+ * 
+ */
+class Ipv4RawSocketFactory : public SocketFactory
+{
+public:
+  static TypeId GetTypeId (void);
+
+};
+
+} // namespace ns3
+
+#endif /* IPV4_RAW_SOCKET_FACTORY_H */
--- a/src/node/socket.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/node/socket.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -362,4 +362,57 @@
 }
 
 
+SocketSetDontFragmentTag::SocketSetDontFragmentTag ()
+{}
+void 
+SocketSetDontFragmentTag::Enable (void)
+{
+  m_dontFragment = true;
+}
+void 
+SocketSetDontFragmentTag::Disable (void)
+{
+  m_dontFragment = false;
+}
+bool 
+SocketSetDontFragmentTag::IsEnabled (void) const
+{
+  return m_dontFragment;
+}
+
+TypeId 
+SocketSetDontFragmentTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SocketSetDontFragmentTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SocketSetDontFragmentTag> ()
+    ;
+  return tid;
+}
+TypeId 
+SocketSetDontFragmentTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+SocketSetDontFragmentTag::GetSerializedSize (void) const
+{
+  return 1;
+}
+void 
+SocketSetDontFragmentTag::Serialize (TagBuffer i) const
+{
+  i.WriteU8 (m_dontFragment?1:0);
+}
+void 
+SocketSetDontFragmentTag::Deserialize (TagBuffer i)
+{
+  m_dontFragment = (i.ReadU8 () == 1)?true:false;
+}
+void 
+SocketSetDontFragmentTag::Print (std::ostream &os) const
+{
+  os << (m_dontFragment?"true":"false");
+}
+
 }//namespace ns3
--- a/src/node/socket.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/node/socket.h	Wed Oct 29 11:18:39 2008 -0700
@@ -336,9 +336,9 @@
    * not preserved.  
    * 
    * The flags argument is formed by or'ing one or more of the values:     
-   *        MSG_OOB        process out-of-band data
-   *        MSG_PEEK       peek at incoming message
-   * These flags are _unsupported_ as of ns-3.1.  
+   *        MSG_OOB             process out-of-band data
+   *        MSG_PEEK            peek at incoming message
+   * None of these flags are supported for now.
    *
    * Some variants of Recv() are supported as additional API,
    * including RecvFrom(), overloaded Recv() without arguments,
@@ -555,6 +555,29 @@
   uint8_t m_ttl;
 };
 
+
+/**
+ * \brief indicated whether packets should be sent out with
+ * the DF flag set.
+ */
+class SocketSetDontFragmentTag : public Tag
+{
+public:
+  SocketSetDontFragmentTag ();
+  void Enable (void);
+  void Disable (void);
+  bool IsEnabled (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+private:
+  bool m_dontFragment;
+};
+
 } //namespace ns3
 
 #endif /* SOCKET_H */
--- a/src/node/udp-socket.cc	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/node/udp-socket.cc	Wed Oct 29 11:18:39 2008 -0700
@@ -21,6 +21,7 @@
 #include "ns3/object.h"
 #include "ns3/log.h"
 #include "ns3/uinteger.h"
+#include "ns3/boolean.h"
 #include "ns3/trace-source-accessor.h"
 #include "udp-socket.h"
 
@@ -53,6 +54,11 @@
                    MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl,
                                          &UdpSocket::SetIpMulticastTtl),
                    MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&UdpSocket::SetMtuDiscover,
+                                        &UdpSocket::GetMtuDiscover),
+                   MakeBooleanChecker ())
     ;
   return tid;
 }
--- a/src/node/udp-socket.h	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/node/udp-socket.h	Wed Oct 29 11:18:39 2008 -0700
@@ -58,7 +58,8 @@
   virtual uint32_t GetIpTtl (void) const = 0;
   virtual void SetIpMulticastTtl (uint32_t ipTtl) = 0;
   virtual uint32_t GetIpMulticastTtl (void) const = 0;
-  
+  virtual void SetMtuDiscover (bool discover) = 0;
+  virtual bool GetMtuDiscover (void) const = 0;
 };
 
 } //namespace ns3
--- a/src/node/wscript	Mon Oct 27 15:12:00 2008 -0400
+++ b/src/node/wscript	Wed Oct 29 11:18:39 2008 -0700
@@ -34,6 +34,7 @@
         'application.cc',
         'simple-channel.cc',
         'simple-net-device.cc',
+        'ipv4-raw-socket-factory.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -69,4 +70,5 @@
         'application.h',
         'simple-channel.h',
         'simple-net-device.h',
+        'ipv4-raw-socket-factory.h',
         ]