github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/tcpip/header/ipv4.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package header 16 17 import ( 18 "encoding/binary" 19 20 "github.com/google/netstack/tcpip" 21 ) 22 23 const ( 24 versIHL = 0 25 tos = 1 26 // IPv4TotalLenOffset is the offset of the total length field in the 27 // IPv4 header. 28 IPv4TotalLenOffset = 2 29 id = 4 30 flagsFO = 6 31 ttl = 8 32 protocol = 9 33 checksum = 10 34 srcAddr = 12 35 dstAddr = 16 36 ) 37 38 // IPv4Fields contains the fields of an IPv4 packet. It is used to describe the 39 // fields of a packet that needs to be encoded. 40 type IPv4Fields struct { 41 // IHL is the "internet header length" field of an IPv4 packet. 42 IHL uint8 43 44 // TOS is the "type of service" field of an IPv4 packet. 45 TOS uint8 46 47 // TotalLength is the "total length" field of an IPv4 packet. 48 TotalLength uint16 49 50 // ID is the "identification" field of an IPv4 packet. 51 ID uint16 52 53 // Flags is the "flags" field of an IPv4 packet. 54 Flags uint8 55 56 // FragmentOffset is the "fragment offset" field of an IPv4 packet. 57 FragmentOffset uint16 58 59 // TTL is the "time to live" field of an IPv4 packet. 60 TTL uint8 61 62 // Protocol is the "protocol" field of an IPv4 packet. 63 Protocol uint8 64 65 // Checksum is the "checksum" field of an IPv4 packet. 66 Checksum uint16 67 68 // SrcAddr is the "source ip address" of an IPv4 packet. 69 SrcAddr tcpip.Address 70 71 // DstAddr is the "destination ip address" of an IPv4 packet. 72 DstAddr tcpip.Address 73 } 74 75 // IPv4 represents an ipv4 header stored in a byte array. 76 // Most of the methods of IPv4 access to the underlying slice without 77 // checking the boundaries and could panic because of 'index out of range'. 78 // Always call IsValid() to validate an instance of IPv4 before using other methods. 79 type IPv4 []byte 80 81 const ( 82 // IPv4MinimumSize is the minimum size of a valid IPv4 packet. 83 IPv4MinimumSize = 20 84 85 // IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given 86 // that there are only 4 bits to represents the header length in 32-bit 87 // units, the header cannot exceed 15*4 = 60 bytes. 88 IPv4MaximumHeaderSize = 60 89 90 // MinIPFragmentPayloadSize is the minimum number of payload bytes that 91 // the first fragment must carry when an IPv4 packet is fragmented. 92 MinIPFragmentPayloadSize = 8 93 94 // IPv4AddressSize is the size, in bytes, of an IPv4 address. 95 IPv4AddressSize = 4 96 97 // IPv4ProtocolNumber is IPv4's network protocol number. 98 IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800 99 100 // IPv4Version is the version of the ipv4 protocol. 101 IPv4Version = 4 102 103 // IPv4Broadcast is the broadcast address of the IPv4 procotol. 104 IPv4Broadcast tcpip.Address = "\xff\xff\xff\xff" 105 106 // IPv4Any is the non-routable IPv4 "any" meta address. 107 IPv4Any tcpip.Address = "\x00\x00\x00\x00" 108 109 // IPv4MinimumProcessableDatagramSize is the minimum size of an IP 110 // packet that every IPv4 capable host must be able to 111 // process/reassemble. 112 IPv4MinimumProcessableDatagramSize = 576 113 ) 114 115 // Flags that may be set in an IPv4 packet. 116 const ( 117 IPv4FlagMoreFragments = 1 << iota 118 IPv4FlagDontFragment 119 ) 120 121 // IPv4EmptySubnet is the empty IPv4 subnet. 122 var IPv4EmptySubnet = func() tcpip.Subnet { 123 subnet, err := tcpip.NewSubnet(IPv4Any, tcpip.AddressMask(IPv4Any)) 124 if err != nil { 125 panic(err) 126 } 127 return subnet 128 }() 129 130 // IPVersion returns the version of IP used in the given packet. It returns -1 131 // if the packet is not large enough to contain the version field. 132 func IPVersion(b []byte) int { 133 // Length must be at least offset+length of version field. 134 if len(b) < versIHL+1 { 135 return -1 136 } 137 return int(b[versIHL] >> 4) 138 } 139 140 // HeaderLength returns the value of the "header length" field of the ipv4 141 // header. 142 func (b IPv4) HeaderLength() uint8 { 143 return (b[versIHL] & 0xf) * 4 144 } 145 146 // ID returns the value of the identifier field of the ipv4 header. 147 func (b IPv4) ID() uint16 { 148 return binary.BigEndian.Uint16(b[id:]) 149 } 150 151 // Protocol returns the value of the protocol field of the ipv4 header. 152 func (b IPv4) Protocol() uint8 { 153 return b[protocol] 154 } 155 156 // Flags returns the "flags" field of the ipv4 header. 157 func (b IPv4) Flags() uint8 { 158 return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13) 159 } 160 161 // TTL returns the "TTL" field of the ipv4 header. 162 func (b IPv4) TTL() uint8 { 163 return b[ttl] 164 } 165 166 // FragmentOffset returns the "fragment offset" field of the ipv4 header. 167 func (b IPv4) FragmentOffset() uint16 { 168 return binary.BigEndian.Uint16(b[flagsFO:]) << 3 169 } 170 171 // TotalLength returns the "total length" field of the ipv4 header. 172 func (b IPv4) TotalLength() uint16 { 173 return binary.BigEndian.Uint16(b[IPv4TotalLenOffset:]) 174 } 175 176 // Checksum returns the checksum field of the ipv4 header. 177 func (b IPv4) Checksum() uint16 { 178 return binary.BigEndian.Uint16(b[checksum:]) 179 } 180 181 // SourceAddress returns the "source address" field of the ipv4 header. 182 func (b IPv4) SourceAddress() tcpip.Address { 183 return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize]) 184 } 185 186 // DestinationAddress returns the "destination address" field of the ipv4 187 // header. 188 func (b IPv4) DestinationAddress() tcpip.Address { 189 return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize]) 190 } 191 192 // TransportProtocol implements Network.TransportProtocol. 193 func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber { 194 return tcpip.TransportProtocolNumber(b.Protocol()) 195 } 196 197 // Payload implements Network.Payload. 198 func (b IPv4) Payload() []byte { 199 return b[b.HeaderLength():][:b.PayloadLength()] 200 } 201 202 // PayloadLength returns the length of the payload portion of the ipv4 packet. 203 func (b IPv4) PayloadLength() uint16 { 204 return b.TotalLength() - uint16(b.HeaderLength()) 205 } 206 207 // TOS returns the "type of service" field of the ipv4 header. 208 func (b IPv4) TOS() (uint8, uint32) { 209 return b[tos], 0 210 } 211 212 // SetTOS sets the "type of service" field of the ipv4 header. 213 func (b IPv4) SetTOS(v uint8, _ uint32) { 214 b[tos] = v 215 } 216 217 // SetTotalLength sets the "total length" field of the ipv4 header. 218 func (b IPv4) SetTotalLength(totalLength uint16) { 219 binary.BigEndian.PutUint16(b[IPv4TotalLenOffset:], totalLength) 220 } 221 222 // SetChecksum sets the checksum field of the ipv4 header. 223 func (b IPv4) SetChecksum(v uint16) { 224 binary.BigEndian.PutUint16(b[checksum:], v) 225 } 226 227 // SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the 228 // ipv4 header. 229 func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) { 230 v := (uint16(flags) << 13) | (offset >> 3) 231 binary.BigEndian.PutUint16(b[flagsFO:], v) 232 } 233 234 // SetID sets the identification field. 235 func (b IPv4) SetID(v uint16) { 236 binary.BigEndian.PutUint16(b[id:], v) 237 } 238 239 // SetSourceAddress sets the "source address" field of the ipv4 header. 240 func (b IPv4) SetSourceAddress(addr tcpip.Address) { 241 copy(b[srcAddr:srcAddr+IPv4AddressSize], addr) 242 } 243 244 // SetDestinationAddress sets the "destination address" field of the ipv4 245 // header. 246 func (b IPv4) SetDestinationAddress(addr tcpip.Address) { 247 copy(b[dstAddr:dstAddr+IPv4AddressSize], addr) 248 } 249 250 // CalculateChecksum calculates the checksum of the ipv4 header. 251 func (b IPv4) CalculateChecksum() uint16 { 252 return Checksum(b[:b.HeaderLength()], 0) 253 } 254 255 // Encode encodes all the fields of the ipv4 header. 256 func (b IPv4) Encode(i *IPv4Fields) { 257 b[versIHL] = (4 << 4) | ((i.IHL / 4) & 0xf) 258 b[tos] = i.TOS 259 b.SetTotalLength(i.TotalLength) 260 binary.BigEndian.PutUint16(b[id:], i.ID) 261 b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset) 262 b[ttl] = i.TTL 263 b[protocol] = i.Protocol 264 b.SetChecksum(i.Checksum) 265 copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr) 266 copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr) 267 } 268 269 // EncodePartial updates the total length and checksum fields of ipv4 header, 270 // taking in the partial checksum, which is the checksum of the header without 271 // the total length and checksum fields. It is useful in cases when similar 272 // packets are produced. 273 func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) { 274 b.SetTotalLength(totalLength) 275 checksum := Checksum(b[IPv4TotalLenOffset:IPv4TotalLenOffset+2], partialChecksum) 276 b.SetChecksum(^checksum) 277 } 278 279 // IsValid performs basic validation on the packet. 280 func (b IPv4) IsValid(pktSize int) bool { 281 if len(b) < IPv4MinimumSize { 282 return false 283 } 284 285 hlen := int(b.HeaderLength()) 286 tlen := int(b.TotalLength()) 287 if hlen < IPv4MinimumSize || hlen > tlen || tlen > pktSize { 288 return false 289 } 290 291 if IPVersion(b) != IPv4Version { 292 return false 293 } 294 295 return true 296 } 297 298 // IsV4MulticastAddress determines if the provided address is an IPv4 multicast 299 // address (range 224.0.0.0 to 239.255.255.255). The four most significant bits 300 // will be 1110 = 0xe0. 301 func IsV4MulticastAddress(addr tcpip.Address) bool { 302 if len(addr) != IPv4AddressSize { 303 return false 304 } 305 return (addr[0] & 0xf0) == 0xe0 306 }