-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathntp_header.go
114 lines (93 loc) · 2.37 KB
/
ntp_header.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"encoding/binary"
"fmt"
"net"
)
type NtpLeap uint8
const (
NtpLeapNoWarn NtpLeap = 0
NtpLeap61 NtpLeap = 1
NtpLeap59 NtpLeap = 2
NtpLeapUnknown NtpLeap = 3
)
type NtpMode uint8
const (
NtpModeReserved NtpMode = 0
NtpModeSymmetricActive NtpMode = 1
NtpModeSymmetricPassive NtpMode = 2
NtpModeClient NtpMode = 3
NtpModeServer NtpMode = 4
NtpModeBroadcast NtpMode = 5
NtpModeControl NtpMode = 6
NtpModePrivate NtpMode = 7
)
type NtpHeader struct {
Leap NtpLeap
Version uint8
Mode NtpMode
Stratum uint8
Poll int8
Precision int32
Rootdelay uint32
Rootdisp uint32
Refid uint32
Refts uint64
Orgts uint64
Rects uint64
Xmtts uint64
Dstts uint64
}
func (n *NtpHeader) Marshal() ([]byte, error) {
b := make([]byte, 48)
b[0] |= (uint8(n.Leap<<6) & 0xc0)
b[0] |= (uint8(n.Version<<3) & 0x38)
b[0] |= uint8(n.Mode) & 0x7
b[1] = n.Stratum
b[2] = byte(n.Poll)
b[3] = byte(n.Precision)
binary.BigEndian.PutUint32(b[4:8], n.Rootdelay)
binary.BigEndian.PutUint32(b[8:12], n.Rootdisp)
binary.BigEndian.PutUint32(b[12:16], n.Refid)
binary.BigEndian.PutUint64(b[16:24], n.Refts)
binary.BigEndian.PutUint64(b[24:32], n.Orgts)
binary.BigEndian.PutUint64(b[32:40], n.Rects)
binary.BigEndian.PutUint64(b[40:48], n.Xmtts)
return b, nil
}
func (n *NtpHeader) Unmarshal(b []byte) error {
if len(b) < 48 {
return fmt.Errorf("invaild ntp length: %d", len(b))
}
n.Leap = NtpLeap((b[0] >> 6) & 0x3)
n.Version = uint8((b[0] >> 3) & 0x7)
n.Mode = NtpMode(b[0] & 0x7)
n.Stratum = b[1]
n.Poll = int8(b[2])
n.Precision = int32(b[3])
n.Rootdelay = binary.BigEndian.Uint32(b[4:8])
n.Rootdisp = binary.BigEndian.Uint32(b[8:12])
n.Refid = binary.BigEndian.Uint32(b[12:16])
n.Refts = binary.BigEndian.Uint64(b[16:24])
n.Orgts = binary.BigEndian.Uint64(b[24:32])
n.Rects = binary.BigEndian.Uint64(b[32:40])
n.Xmtts = binary.BigEndian.Uint64(b[40:48])
return nil
}
func (n *NtpHeader) RefidStr() string {
s := ""
if n.Stratum == 1 {
s += string((n.Refid >> 24) & 0xff)
s += string((n.Refid >> 16) & 0xff)
s += string((n.Refid >> 8) & 0xff)
s += string(n.Refid & 0xff)
} else if n.Stratum > 1 {
return net.IPv4(
byte((n.Refid>>24)&0xff),
byte((n.Refid>>16)&0xff),
byte((n.Refid>>8)&0xff),
byte(n.Refid&0xff),
).String()
}
return s
}