IPv4/6 reassembly
[vpp.git] / test / patches / scapy-2.3.3 / inet6.py.patch
1 diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
2 index 03b80ec..06ef27f 100644
3 --- a/scapy/layers/inet6.py
4 +++ b/scapy/layers/inet6.py
5 @@ -369,6 +369,8 @@ class _IPv6GuessPayload:
6              return Raw
7          elif self.nh == 135 and len(p) > 3: # Mobile IPv6
8              return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic)
9 +        elif self.nh == 43 and ord(p[2]) == 4:  # Segment Routing header
10 +            return IPv6ExtHdrSegmentRouting
11          else:
12              return get_cls(ipv6nhcls.get(self.nh,"Raw"), "Raw")
13  
14 @@ -430,6 +432,14 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools):
15                      sd = strxor(sd, a)
16                  sd = inet_ntop(socket.AF_INET6, sd)
17  
18 +        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):
19 +            # With segment routing header (rh == 4), the destination is
20 +            # the first address of the IPv6 addresses list
21 +            try:
22 +                sd = self.addresses[0]
23 +            except IndexError:
24 +                sd = self.dst
25 +
26          if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
27              nh = self.payload.nh 
28  
29 @@ -489,6 +499,8 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools):
30              return self.payload.answers(other.payload.payload) 
31          elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
32              return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
33 +        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):
34 +            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting
35          elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
36              return self.payload.payload.answers(other.payload.payload)
37          elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
38 @@ -919,6 +931,148 @@ class IPv6ExtHdrRouting(_IPv6ExtHdr):
39              pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
40          return _IPv6ExtHdr.post_build(self, pkt, pay)
41  
42 +######################### Segment Routing Header ############################
43 +
44 +# This implementation is based on draft 06, available at:
45 +# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06
46 +
47 +class IPv6ExtHdrSegmentRoutingTLV(Packet):
48 +    name = "IPv6 Option Header Segment Routing - Generic TLV"
49 +    fields_desc = [ ByteField("type", 0),
50 +                    ByteField("len", 0),
51 +                    ByteField("reserved", 0),
52 +                    ByteField("flags", 0),
53 +                    StrLenField("value", "", length_from=lambda pkt: pkt.len) ]
54 +
55 +    def extract_padding(self, p):
56 +        return "",p
57 +
58 +    registered_sr_tlv = {}
59 +    @classmethod
60 +    def register_variant(cls):
61 +        cls.registered_sr_tlv[cls.type.default] = cls
62 +
63 +    @classmethod
64 +    def dispatch_hook(cls, pkt=None, *args, **kargs):
65 +        if pkt:
66 +            tmp_type = ord(pkt[0])
67 +            return cls.registered_sr_tlv.get(tmp_type, cls)
68 +        return cls
69 +
70 +
71 +class IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):
72 +    name = "IPv6 Option Header Segment Routing - Ingress Node TLV"
73 +    fields_desc = [ ByteField("type", 1),
74 +                    ByteField("len", 18),
75 +                    ByteField("reserved", 0),
76 +                    ByteField("flags", 0),
77 +                    IP6Field("ingress_node", "::1") ]
78 +
79 +
80 +class IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):
81 +    name = "IPv6 Option Header Segment Routing - Egress Node TLV"
82 +    fields_desc = [ ByteField("type", 2),
83 +                    ByteField("len", 18),
84 +                    ByteField("reserved", 0),
85 +                    ByteField("flags", 0),
86 +                    IP6Field("egress_node", "::1") ]
87 +
88 +
89 +class IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV):
90 +    name = "IPv6 Option Header Segment Routing - Padding TLV"
91 +    fields_desc = [ ByteField("type", 4),
92 +                    FieldLenField("len", None, length_of="padding", fmt="B"),
93 +                    StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ]
94 +
95 +
96 +class IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):
97 +    # 0                   1                   2                   3
98 +    # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
99 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 +    #| Next Header   |  Hdr Ext Len  | Routing Type  | Segments Left |
101 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 +    #|  Last Entry   |     Flags     |              Tag              |
103 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 +    #|                                                               |
105 +    #|            Segment List[0] (128 bits IPv6 address)            |
106 +    #|                                                               |
107 +    #|                                                               |
108 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 +    #|                                                               |
110 +    #|                                                               |
111 +    #                              ...
112 +    #|                                                               |
113 +    #|                                                               |
114 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 +    #|                                                               |
116 +    #|            Segment List[n] (128 bits IPv6 address)            |
117 +    #|                                                               |
118 +    #|                                                               |
119 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 +    #//                                                             //
121 +    #//         Optional Type Length Value objects (variable)       //
122 +    #//                                                             //
123 +    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 +    #
125 +    #      0 1 2 3 4 5 6 7
126 +    #     +-+-+-+-+-+-+-+-+
127 +    #     |U|P|O|A|H|  U  |
128 +    #     +-+-+-+-+-+-+-+-+
129 +
130 +    name = "IPv6 Segment Routing Extension Header"
131 +    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
132 +                    ByteField("len", None),
133 +                    ByteField("type", 4),
134 +                    ByteField("segleft", None),
135 +                    ByteField("lastentry", None),
136 +                    BitField("unused1", 0, 1),
137 +                    BitField("protected", 0, 1),
138 +                    BitField("oam", 0, 1),
139 +                    BitField("alert", 0, 1),
140 +                    BitField("hmac", 0, 1),
141 +                    BitField("unused2", 0, 3),
142 +                    ShortField("tag", 0),
143 +                    IP6ListField("addresses", ["::1"],
144 +                        count_from=lambda pkt: pkt.lastentry+1),
145 +                    PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV,
146 +                        length_from=lambda pkt: 8*pkt.len - 16*(pkt.lastentry+1)) ]
147 +
148 +    overload_fields = { IPv6: { "nh": 43 } }
149 +
150 +    def post_build(self, pkt, pay):
151 +
152 +        if self.len is None:
153 +
154 +            # The extension must be align on 8 bytes
155 +            tmp_mod = (len(pkt) - 8) % 8
156 +            if tmp_mod == 1:
157 +                warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !")
158 +            elif tmp_mod >= 2:
159 +                #Add the padding extension
160 +                tmp_pad = b"\x00" * (tmp_mod-2)
161 +                tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad)
162 +                pkt += str(tlv)
163 +
164 +            tmp_len = (len(pkt) - 8) / 8
165 +            pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:]
166 +
167 +        if self.segleft is None:
168 +            tmp_len = len(self.addresses)
169 +            if tmp_len:
170 +                tmp_len -= 1
171 +            pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:]
172 +
173 +        if self.lastentry is None:
174 +            #km - changed to contain n-1
175 +            tmp_len = len(self.addresses)
176 +            if tmp_len:
177 +                tmp_len -= 1
178 +            #pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:]
179 +            pkt = pkt[:4] + struct.pack("B", tmp_len) + pkt[5:]
180 +
181 +        return _IPv6ExtHdr.post_build(self, pkt, pay)
182 +
183 +
184  ########################### Fragmentation Header ############################
185
186  class IPv6ExtHdrFragment(_IPv6ExtHdr):
187 diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
188 index 20afedf..ae3c4dd 100644
189 --- a/scapy/layers/inet6.py
190 +++ b/scapy/layers/inet6.py
191 @@ -3888,3 +3888,4 @@ bind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
192  bind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
193  bind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
194  bind_layers(IPv6,      IP,       nh = socket.IPPROTO_IPIP )
195 +bind_layers(IPv6,      GRE,      nh = socket.IPPROTO_GRE )