@@ -40,18 +40,6 @@ const (
40
40
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
41
41
)
42
42
43
- const (
44
- posTOS = 1 // type-of-service
45
- posTotalLen = 2 // packet total length
46
- posID = 4 // identification
47
- posFragOff = 6 // fragment offset
48
- posTTL = 8 // time-to-live
49
- posProtocol = 9 // next protocol
50
- posChecksum = 10 // checksum
51
- posSrc = 12 // source address
52
- posDst = 16 // destination address
53
- )
54
-
55
43
type HeaderFlags int
56
44
57
45
const (
@@ -83,10 +71,6 @@ func (h *Header) String() string {
83
71
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 )
84
72
}
85
73
86
- // Please refer to the online manual; IP(4) on Darwin, FreeBSD and
87
- // OpenBSD. IP(7) on Linux.
88
- const supportsNewIPInput = runtime .GOOS == "linux" || runtime .GOOS == "openbsd"
89
-
90
74
// Marshal returns the binary encoding of the IPv4 header h.
91
75
func (h * Header ) Marshal () ([]byte , error ) {
92
76
if h == nil {
@@ -98,25 +82,26 @@ func (h *Header) Marshal() ([]byte, error) {
98
82
hdrlen := HeaderLen + len (h .Options )
99
83
b := make ([]byte , hdrlen )
100
84
b [0 ] = byte (Version << 4 | (hdrlen >> 2 & 0x0f ))
101
- b [posTOS ] = byte (h .TOS )
85
+ b [1 ] = byte (h .TOS )
102
86
flagsAndFragOff := (h .FragOff & 0x1fff ) | int (h .Flags << 13 )
103
- if supportsNewIPInput {
104
- b [posTotalLen ], b [posTotalLen + 1 ] = byte (h .TotalLen >> 8 ), byte (h .TotalLen )
105
- b [posFragOff ], b [posFragOff + 1 ] = byte (flagsAndFragOff >> 8 ), byte (flagsAndFragOff )
106
- } else {
87
+ switch runtime .GOOS {
88
+ case "darwin" , "dragonfly" , "freebsd" , "netbsd" :
107
89
// TODO(mikio): fix potential misaligned memory access
108
- * (* uint16 )(unsafe .Pointer (& b [posTotalLen : posTotalLen + 1 ][0 ])) = uint16 (h .TotalLen )
109
- * (* uint16 )(unsafe .Pointer (& b [posFragOff : posFragOff + 1 ][0 ])) = uint16 (flagsAndFragOff )
90
+ * (* uint16 )(unsafe .Pointer (& b [2 :3 ][0 ])) = uint16 (h .TotalLen )
91
+ * (* uint16 )(unsafe .Pointer (& b [6 :7 ][0 ])) = uint16 (flagsAndFragOff )
92
+ default :
93
+ b [2 ], b [3 ] = byte (h .TotalLen >> 8 ), byte (h .TotalLen )
94
+ b [6 ], b [7 ] = byte (flagsAndFragOff >> 8 ), byte (flagsAndFragOff )
110
95
}
111
- b [posID ], b [posID + 1 ] = byte (h .ID >> 8 ), byte (h .ID )
112
- b [posTTL ] = byte (h .TTL )
113
- b [posProtocol ] = byte (h .Protocol )
114
- b [posChecksum ], b [posChecksum + 1 ] = byte (h .Checksum >> 8 ), byte (h .Checksum )
96
+ b [4 ], b [5 ] = byte (h .ID >> 8 ), byte (h .ID )
97
+ b [8 ] = byte (h .TTL )
98
+ b [9 ] = byte (h .Protocol )
99
+ b [10 ], b [11 ] = byte (h .Checksum >> 8 ), byte (h .Checksum )
115
100
if ip := h .Src .To4 (); ip != nil {
116
- copy (b [posSrc : posSrc + net . IPv4len ], ip [:net .IPv4len ])
101
+ copy (b [12 : 16 ], ip [:net .IPv4len ])
117
102
}
118
103
if ip := h .Dst .To4 (); ip != nil {
119
- copy (b [posDst : posDst + net . IPv4len ], ip [:net .IPv4len ])
104
+ copy (b [16 : 20 ], ip [:net .IPv4len ])
120
105
} else {
121
106
return nil , errMissingAddress
122
107
}
@@ -138,30 +123,37 @@ func ParseHeader(b []byte) (*Header, error) {
138
123
if hdrlen > len (b ) {
139
124
return nil , errBufferTooShort
140
125
}
141
- h := & Header {}
142
- h .Version = int (b [0 ] >> 4 )
143
- h .Len = hdrlen
144
- h .TOS = int (b [posTOS ])
145
- if supportsNewIPInput {
146
- h .TotalLen = int (b [posTotalLen ])<< 8 | int (b [posTotalLen + 1 ])
147
- h .FragOff = int (b [posFragOff ])<< 8 | int (b [posFragOff + 1 ])
148
- } else {
126
+ h := & Header {
127
+ Version : int (b [0 ] >> 4 ),
128
+ Len : hdrlen ,
129
+ TOS : int (b [1 ]),
130
+ ID : int (b [4 ])<< 8 | int (b [5 ]),
131
+ TTL : int (b [8 ]),
132
+ Protocol : int (b [9 ]),
133
+ Checksum : int (b [10 ])<< 8 | int (b [11 ]),
134
+ Src : net .IPv4 (b [12 ], b [13 ], b [14 ], b [15 ]),
135
+ Dst : net .IPv4 (b [16 ], b [17 ], b [18 ], b [19 ]),
136
+ }
137
+ switch runtime .GOOS {
138
+ case "darwin" , "dragonfly" , "netbsd" :
139
+ // TODO(mikio): fix potential misaligned memory access
140
+ h .TotalLen = int (* (* uint16 )(unsafe .Pointer (& b [2 :3 ][0 ]))) + hdrlen
141
+ // TODO(mikio): fix potential misaligned memory access
142
+ h .FragOff = int (* (* uint16 )(unsafe .Pointer (& b [6 :7 ][0 ])))
143
+ case "freebsd" :
149
144
// TODO(mikio): fix potential misaligned memory access
150
- h .TotalLen = int (* (* uint16 )(unsafe .Pointer (& b [posTotalLen : posTotalLen + 1 ][0 ])))
151
- if runtime . GOOS != "freebsd" || freebsdVersion < 1000000 {
145
+ h .TotalLen = int (* (* uint16 )(unsafe .Pointer (& b [2 : 3 ][0 ])))
146
+ if freebsdVersion < 1000000 {
152
147
h .TotalLen += hdrlen
153
148
}
154
149
// TODO(mikio): fix potential misaligned memory access
155
- h .FragOff = int (* (* uint16 )(unsafe .Pointer (& b [posFragOff : posFragOff + 1 ][0 ])))
150
+ h .FragOff = int (* (* uint16 )(unsafe .Pointer (& b [6 :7 ][0 ])))
151
+ default :
152
+ h .TotalLen = int (b [2 ])<< 8 | int (b [3 ])
153
+ h .FragOff = int (b [6 ])<< 8 | int (b [7 ])
156
154
}
157
155
h .Flags = HeaderFlags (h .FragOff & 0xe000 ) >> 13
158
156
h .FragOff = h .FragOff & 0x1fff
159
- h .ID = int (b [posID ])<< 8 | int (b [posID + 1 ])
160
- h .TTL = int (b [posTTL ])
161
- h .Protocol = int (b [posProtocol ])
162
- h .Checksum = int (b [posChecksum ])<< 8 | int (b [posChecksum + 1 ])
163
- h .Src = net .IPv4 (b [posSrc ], b [posSrc + 1 ], b [posSrc + 2 ], b [posSrc + 3 ])
164
- h .Dst = net .IPv4 (b [posDst ], b [posDst + 1 ], b [posDst + 2 ], b [posDst + 3 ])
165
157
if hdrlen - HeaderLen > 0 {
166
158
h .Options = make ([]byte , hdrlen - HeaderLen )
167
159
copy (h .Options , b [HeaderLen :])
0 commit comments