LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ipv4 | 5 package ipv4 |
6 | 6 |
7 import ( | 7 import ( |
8 "errors" | 8 "errors" |
9 "fmt" | 9 "fmt" |
10 "net" | 10 "net" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 posTotalLen = 2 // packet total length | 43 posTotalLen = 2 // packet total length |
44 posID = 4 // identification | 44 posID = 4 // identification |
45 posFragOff = 6 // fragment offset | 45 posFragOff = 6 // fragment offset |
46 posTTL = 8 // time-to-live | 46 posTTL = 8 // time-to-live |
47 posProtocol = 9 // next protocol | 47 posProtocol = 9 // next protocol |
48 posChecksum = 10 // checksum | 48 posChecksum = 10 // checksum |
49 posSrc = 12 // source address | 49 posSrc = 12 // source address |
50 posDst = 16 // destination address | 50 posDst = 16 // destination address |
51 ) | 51 ) |
52 | 52 |
| 53 type HeaderFlags int |
| 54 |
| 55 const ( |
| 56 MoreFragments HeaderFlags = 1 << iota // more fragments flag |
| 57 DontFragment // don't fragment flag |
| 58 ) |
| 59 |
53 // A Header represents an IPv4 header. | 60 // A Header represents an IPv4 header. |
54 type Header struct { | 61 type Header struct { |
55 » Version int // protocol version | 62 » Version int // protocol version |
56 » Len int // header length | 63 » Len int // header length |
57 » TOS int // type-of-service | 64 » TOS int // type-of-service |
58 » TotalLen int // packet total length | 65 » TotalLen int // packet total length |
59 » ID int // identification | 66 » ID int // identification |
60 » FragOff int // fragment offset | 67 » Flags HeaderFlags // flags |
61 » TTL int // time-to-live | 68 » FragOff int // fragment offset |
62 » Protocol int // next protocol | 69 » TTL int // time-to-live |
63 » Checksum int // checksum | 70 » Protocol int // next protocol |
64 » Src net.IP // source address | 71 » Checksum int // checksum |
65 » Dst net.IP // destination address | 72 » Src net.IP // source address |
66 » Options []byte // options, extension headers | 73 » Dst net.IP // destination address |
| 74 » Options []byte // options, extension headers |
67 } | 75 } |
68 | 76 |
69 func (h *Header) String() string { | 77 func (h *Header) String() string { |
70 if h == nil { | 78 if h == nil { |
71 return "<nil>" | 79 return "<nil>" |
72 } | 80 } |
73 » return fmt.Sprintf("ver: %v, hdrlen: %v, tos: %#x, totallen: %v, id: %#x
, fragoff: %#x, ttl: %v, proto: %v, cksum: %#x, src: %v, dst: %v", h.Version, h.
Len, h.TOS, h.TotalLen, h.ID, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h
.Dst) | 81 » return fmt.Sprintf("ver: %v, hdrlen: %v, tos: %#x, totallen: %v, id: %#x
, flags: %#x, fragoff: %#x, ttl: %v, proto: %v, cksum: %#x, src: %v, dst: %v", h
.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.Flags, h.FragOff, h.TTL, h.Protocol,
h.Checksum, h.Src, h.Dst) |
74 } | 82 } |
75 | 83 |
76 // Please refer to the online manual; IP(4) on Darwin, FreeBSD and | 84 // Please refer to the online manual; IP(4) on Darwin, FreeBSD and |
77 // OpenBSD. IP(7) on Linux. | 85 // OpenBSD. IP(7) on Linux. |
78 const supportsNewIPInput = runtime.GOOS == "linux" || runtime.GOOS == "openbsd" | 86 const supportsNewIPInput = runtime.GOOS == "linux" || runtime.GOOS == "openbsd" |
79 | 87 |
80 // Marshal returns the binary encoding of the IPv4 header h. | 88 // Marshal returns the binary encoding of the IPv4 header h. |
81 func (h *Header) Marshal() ([]byte, error) { | 89 func (h *Header) Marshal() ([]byte, error) { |
82 if h == nil { | 90 if h == nil { |
83 return nil, syscall.EINVAL | 91 return nil, syscall.EINVAL |
84 } | 92 } |
85 if h.Len < HeaderLen { | 93 if h.Len < HeaderLen { |
86 return nil, errHeaderTooShort | 94 return nil, errHeaderTooShort |
87 } | 95 } |
88 hdrlen := HeaderLen + len(h.Options) | 96 hdrlen := HeaderLen + len(h.Options) |
89 b := make([]byte, hdrlen) | 97 b := make([]byte, hdrlen) |
90 b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f)) | 98 b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f)) |
91 b[posTOS] = byte(h.TOS) | 99 b[posTOS] = byte(h.TOS) |
| 100 flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13) |
92 if supportsNewIPInput { | 101 if supportsNewIPInput { |
93 b[posTotalLen], b[posTotalLen+1] = byte(h.TotalLen>>8), byte(h.T
otalLen) | 102 b[posTotalLen], b[posTotalLen+1] = byte(h.TotalLen>>8), byte(h.T
otalLen) |
94 » » b[posFragOff], b[posFragOff+1] = byte(h.FragOff>>8), byte(h.Frag
Off) | 103 » » b[posFragOff], b[posFragOff+1] = byte(flagsAndFragOff>>8), byte(
flagsAndFragOff) |
95 } else { | 104 } else { |
96 *(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])) =
uint16(h.TotalLen) | 105 *(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])) =
uint16(h.TotalLen) |
97 » » *(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])) = u
int16(h.FragOff) | 106 » » *(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])) = u
int16(flagsAndFragOff) |
98 } | 107 } |
99 b[posID], b[posID+1] = byte(h.ID>>8), byte(h.ID) | 108 b[posID], b[posID+1] = byte(h.ID>>8), byte(h.ID) |
100 b[posTTL] = byte(h.TTL) | 109 b[posTTL] = byte(h.TTL) |
101 b[posProtocol] = byte(h.Protocol) | 110 b[posProtocol] = byte(h.Protocol) |
102 b[posChecksum], b[posChecksum+1] = byte(h.Checksum>>8), byte(h.Checksum) | 111 b[posChecksum], b[posChecksum+1] = byte(h.Checksum>>8), byte(h.Checksum) |
103 if ip := h.Src.To4(); ip != nil { | 112 if ip := h.Src.To4(); ip != nil { |
104 copy(b[posSrc:posSrc+net.IPv4len], ip[:net.IPv4len]) | 113 copy(b[posSrc:posSrc+net.IPv4len], ip[:net.IPv4len]) |
105 } | 114 } |
106 if ip := h.Dst.To4(); ip != nil { | 115 if ip := h.Dst.To4(); ip != nil { |
107 copy(b[posDst:posDst+net.IPv4len], ip[:net.IPv4len]) | 116 copy(b[posDst:posDst+net.IPv4len], ip[:net.IPv4len]) |
(...skipping 20 matching lines...) Expand all Loading... |
128 h.Len = hdrlen | 137 h.Len = hdrlen |
129 h.TOS = int(b[posTOS]) | 138 h.TOS = int(b[posTOS]) |
130 if supportsNewIPInput { | 139 if supportsNewIPInput { |
131 h.TotalLen = int(b[posTotalLen])<<8 | int(b[posTotalLen+1]) | 140 h.TotalLen = int(b[posTotalLen])<<8 | int(b[posTotalLen+1]) |
132 h.FragOff = int(b[posFragOff])<<8 | int(b[posFragOff+1]) | 141 h.FragOff = int(b[posFragOff])<<8 | int(b[posFragOff+1]) |
133 } else { | 142 } else { |
134 h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[posTotalLen : posT
otalLen+1][0]))) | 143 h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[posTotalLen : posT
otalLen+1][0]))) |
135 h.TotalLen += hdrlen | 144 h.TotalLen += hdrlen |
136 h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[posFragOff : posFra
gOff+1][0]))) | 145 h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[posFragOff : posFra
gOff+1][0]))) |
137 } | 146 } |
| 147 h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13 |
| 148 h.FragOff = h.FragOff & 0x1fff |
138 h.ID = int(b[posID])<<8 | int(b[posID+1]) | 149 h.ID = int(b[posID])<<8 | int(b[posID+1]) |
139 h.TTL = int(b[posTTL]) | 150 h.TTL = int(b[posTTL]) |
140 h.Protocol = int(b[posProtocol]) | 151 h.Protocol = int(b[posProtocol]) |
141 h.Checksum = int(b[posChecksum])<<8 | int(b[posChecksum+1]) | 152 h.Checksum = int(b[posChecksum])<<8 | int(b[posChecksum+1]) |
142 h.Src = net.IPv4(b[posSrc], b[posSrc+1], b[posSrc+2], b[posSrc+3]) | 153 h.Src = net.IPv4(b[posSrc], b[posSrc+1], b[posSrc+2], b[posSrc+3]) |
143 h.Dst = net.IPv4(b[posDst], b[posDst+1], b[posDst+2], b[posDst+3]) | 154 h.Dst = net.IPv4(b[posDst], b[posDst+1], b[posDst+2], b[posDst+3]) |
144 if hdrlen-HeaderLen > 0 { | 155 if hdrlen-HeaderLen > 0 { |
145 h.Options = make([]byte, hdrlen-HeaderLen) | 156 h.Options = make([]byte, hdrlen-HeaderLen) |
146 copy(h.Options, b[HeaderLen:]) | 157 copy(h.Options, b[HeaderLen:]) |
147 } | 158 } |
148 return h, nil | 159 return h, nil |
149 } | 160 } |
LEFT | RIGHT |