Skip to content
Snippets Groups Projects
Commit c169b4b1 authored by Leonid Evdokimov's avatar Leonid Evdokimov Committed by Johannes 'fish' Ziemke
Browse files

Add metrics from SNTPv4 packet to ntp collector & add ntpd sanity check (#655)

* Add metrics from SNTPv4 packet to ntp collector & add ntpd sanity check

1. Checking local clock against remote NTP daemon is bad idea, local
ntpd acting as a  client should do it better and avoid excessive load on
remote NTP server so the collector is refactored to query local NTP
server.

2. Checking local clock against remote one does not check local ntpd
itself. Local ntpd may be down or out of sync due to network issues, but
clock will be OK.

3. Checking NTP server using sanity of it's response is tricky and
depends on ntpd implementation, that's why common `node_ntp_sanity`
variable is exported.

* `govendor add golang.org/x/net/ipv4`, it is dependency of github.com/beevik/ntp

* Update github.com/beevik/ntp to include boring SNTP fix

* Use variable name from RFC5905

* ntp: move code to make export of raw metrics more explicit

* Move NTP math to `github.com/beevik/ntp`

* Make `golint` happy

* Add some brief docs explaining `ntp` #655 and `timex` #664 modules

* ntp: drop XXX comment that got its decision

* ntp: add `_seconds` suffix to relevant metrics

* Better `node_ntp_leap` comment

* s/node_ntp_reftime/node_ntp_reference_timestamp_seconds/ as requested by @discordianfish

* Extract subsystem name to const as suggested by @superq
parent b0d5c008
No related branches found
No related tags found
No related merge requests found
Showing
with 1268 additions and 61 deletions
Loading
Loading
@@ -64,6 +64,7 @@ logind | Exposes session counts from [logind](http://www.freedesktop.org/wiki/So
meminfo\_numa | Exposes memory statistics from `/proc/meminfo_numa`. | Linux
mountstats | Exposes filesystem statistics from `/proc/self/mountstats`. Exposes detailed NFS client statistics. | Linux
nfs | Exposes NFS client statistics from `/proc/net/rpc/nfs`. This is the same information as `nfsstat -c`. | Linux
ntp | Exposes local NTP daemon health to check [time](./docs/TIME.md) | _any_
qdisc | Exposes [queuing discipline](https://en.wikipedia.org/wiki/Network_scheduler#Linux_kernel) statistics | Linux
runit | Exposes service status from [runit](http://smarden.org/runit/). | _any_
supervisord | Exposes service status from [supervisord](http://supervisord.org/). | _any_
Loading
Loading
@@ -78,7 +79,6 @@ Name | Description | OS
---------|-------------|----
gmond | Exposes statistics from Ganglia. | _any_
megacli | Exposes RAID statistics from MegaCLI. | Linux
ntp | Exposes time drift from an NTP server. | _any_
 
### Textfile Collector
 
Loading
Loading
Loading
Loading
@@ -17,62 +17,146 @@ package collector
 
import (
"fmt"
"net"
"time"
 
"github.com/beevik/ntp"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
 
const (
hour24 = 24 * time.Hour // `time` does not export `Day` as Day != 24h because of DST
ntpSubsystem = "ntp"
)
var (
ntpServer = kingpin.Flag("collector.ntp.server", "NTP server to use for ntp collector.").Default("").String()
ntpServer = kingpin.Flag("collector.ntp.server", "NTP server to use for ntp collector").Default("127.0.0.1").String()
ntpProtocolVersion = kingpin.Flag("collector.ntp.protocol-version", "NTP protocol version").Default("4").Int()
ntpServerIsLocal = kingpin.Flag("collector.ntp.server-is-local", "Certify that collector.ntp.server address is the same local host as this collector.").Default("false").Bool()
ntpIPTTL = kingpin.Flag("collector.ntp.ip-ttl", "IP TTL to use while sending NTP query").Default("1").Int()
// 3.46608s ~ 1.5s + PHI * (1 << maxPoll), where 1.5s is MAXDIST from ntp.org, it is 1.0 in RFC5905
// max-distance option is used as-is without phi*(1<<poll)
ntpMaxDistance = kingpin.Flag("collector.ntp.max-distance", "Max accumulated distance to the root").Default("3.46608s").Duration()
ntpOffsetTolerance = kingpin.Flag("collector.ntp.local-offset-tolerance", "Offset between local clock and local ntpd time to tolerate").Default("1ms").Duration()
leapMidnight time.Time
)
 
type ntpCollector struct {
drift, stratum typedDesc
stratum, leap, rtt, offset, reftime, rootDelay, rootDispersion, sanity typedDesc
}
 
func init() {
Factories["ntp"] = NewNtpCollector
}
 
// NewNtpCollector returns a new Collector exposing the offset between ntp and
// the current system time.
// NewNtpCollector returns a new Collector exposing sanity of local NTP server.
// Default definition of "local" is:
// - collector.ntp.server address is a loopback address (or collector.ntp.server-is-mine flag is turned on)
// - the server is reachable with outgoin IP_TTL = 1
func NewNtpCollector() (Collector, error) {
warnDeprecated("ntp")
if *ntpServer == "" {
return nil, fmt.Errorf("no NTP server specified, see -collector.ntp.server")
ipaddr := net.ParseIP(*ntpServer)
if !*ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) {
return nil, fmt.Errorf("only IP address of local NTP server is valid for -collector.ntp.server")
}
if *ntpProtocolVersion < 2 || *ntpProtocolVersion > 4 {
return nil, fmt.Errorf("invalid NTP protocol version %d; must be 2, 3, or 4", *ntpProtocolVersion)
}
 
if *ntpOffsetTolerance < 0 {
return nil, fmt.Errorf("Offset tolerance must be non-negative")
}
return &ntpCollector{
drift: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "ntp", "drift_seconds"),
"Time between system time and ntp time.",
stratum: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "stratum"),
"NTPD stratum.",
nil, nil,
), prometheus.GaugeValue},
stratum: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "ntp", "stratum"),
"NTP server stratum.",
leap: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "leap"),
"NTPD leap second indicator, 2 bits.",
nil, nil,
), prometheus.GaugeValue},
rtt: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "rtt_seconds"),
"RTT to NTPD.",
nil, nil,
), prometheus.GaugeValue},
offset: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "offset_seconds"),
"ClockOffset between NTP and local clock.",
nil, nil,
), prometheus.GaugeValue},
reftime: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "reference_timestamp_seconds"),
"NTPD ReferenceTime, UNIX timestamp.",
nil, nil,
), prometheus.GaugeValue},
rootDelay: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "root_delay_seconds"),
"NTPD RootDelay.",
nil, nil,
), prometheus.GaugeValue},
rootDispersion: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "root_dispersion_seconds"),
"NTPD RootDispersion.",
nil, nil,
), prometheus.GaugeValue},
sanity: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(Namespace, ntpSubsystem, "sanity"),
"NTPD sanity according to RFC5905 heuristics and configured limits.",
nil, nil,
), prometheus.GaugeValue},
}, nil
}
 
func (c *ntpCollector) Update(ch chan<- prometheus.Metric) error {
resp, err := ntp.Query(*ntpServer, *ntpProtocolVersion)
resp, err := ntp.QueryWithOptions(*ntpServer, ntp.QueryOptions{
Version: *ntpProtocolVersion,
TTL: *ntpIPTTL,
Timeout: time.Second, // default `ntpdate` timeout
})
if err != nil {
return fmt.Errorf("couldn't get NTP drift: %s", err)
return fmt.Errorf("couldn't get SNTP reply: %s", err)
}
ch <- c.stratum.mustNewConstMetric(float64(resp.Stratum))
ch <- c.leap.mustNewConstMetric(float64(resp.Leap))
ch <- c.rtt.mustNewConstMetric(resp.RTT.Seconds())
ch <- c.offset.mustNewConstMetric(resp.ClockOffset.Seconds())
if resp.ReferenceTime.Unix() > 0 {
// Go Zero is 0001-01-01 00:00:00 UTC
// NTP Zero is 1900-01-01 00:00:00 UTC
// UNIX Zero is 1970-01-01 00:00:00 UTC
// so let's keep ALL ancient `reftime` values as zero
ch <- c.reftime.mustNewConstMetric(float64(resp.ReferenceTime.UnixNano()) / 1e9)
} else {
ch <- c.reftime.mustNewConstMetric(0)
}
ch <- c.rootDelay.mustNewConstMetric(resp.RootDelay.Seconds())
ch <- c.rootDispersion.mustNewConstMetric(resp.RootDispersion.Seconds())
// Here is SNTP packet sanity check that is exposed to move burden of
// configuration from node_exporter user to the developer.
maxerr := *ntpOffsetTolerance
if resp.Leap == ntp.LeapAddSecond || resp.Leap == ntp.LeapDelSecond {
// state of leapMidnight is cached as leap flag is dropped right after midnight
leapMidnight = resp.Time.Truncate(hour24).Add(hour24)
}
if leapMidnight.Add(-hour24).Before(resp.Time) && resp.Time.Before(leapMidnight.Add(hour24)) {
// tolerate leap smearing
maxerr += time.Second
}
if resp.Validate() && resp.RootDistance <= *ntpMaxDistance && resp.CausalityViolation <= maxerr {
ch <- c.sanity.mustNewConstMetric(1)
} else {
ch <- c.sanity.mustNewConstMetric(0)
}
driftSeconds := resp.ClockOffset.Seconds()
log.Debugf("Set ntp_drift_seconds: %f", driftSeconds)
ch <- c.drift.mustNewConstMetric(driftSeconds)
 
stratum := float64(resp.Stratum)
log.Debugf("Set ntp_stratum: %f", stratum)
ch <- c.stratum.mustNewConstMetric(stratum)
return nil
}
# Monitoring time sync with node_exporter
## `ntp` collector
This collector is intended for usage with local NTPD like [ntp.org](http://ntp.org/), [chrony](https://chrony.tuxfamily.org/comparison.html) or [OpenNTPD](http://www.openntpd.org/).
Note, some chrony packages have `local stratum 10` configuration value making chrony a valid server when it it is unsynchronised. This configuration makes one of `node_ntp_sanity` heuristics unreliable.
Note, OpenNTPD does not listen for SNTP queries by default, you should add `listen on 127.0.0.1` configuration line to use this collector with OpenNTPD.
### `node_ntp_stratum`
This metric shows [stratum](https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_strata) of local NTPD.
Stratum `16` means that clock are unsynchronised. See also aforementioned note about default local stratum in chrony.
### `node_ntp_leap`
Raw leap flag value. 0 – OK, 1 – add leap second at UTC midnight, 2 – delete leap second at UTC midnight, 3 – unsynchronised.
OpenNTPD ignores leap seconds and never sets leap flag to `1` or `2`.
### `node_ntp_rtt`
RTT (round-trip time) from node_exporter collector to local NTPD. This value is
used in sanity check as part of causality violation estimate.
### `node_ntp_offset`
[Clock offset](https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_synchronization_algorithm) between local time and NTPD time.
ntp.org always sets NTPD time to local clock instead of relaying remote NTP
time, so this offset is irrelevant for this NTPD.
This value is used in sanity check as part of causality violation estimate.
### `node_ntp_reference_timestamp_seconds`
Reference Time. This field show time when the last adjustment was made, but
implementation details vary from "**local** wall-clock time" to "Reference Time
field in incoming SNTP packet".
`time() - node_ntp_reference_timestamp_seconds` and
`node_time - node_ntp_reference_timestamp_seconds` represent some estimate of
"freshness" of synchronization.
### `node_ntp_root_delay` and `node_ntp_root_dispersion`
These values are used to calculate synchronization distance that is limited by
`collector.ntp.max-distance`.
ntp.org adds known local offset to announced root dispersion and linearly
increases dispersion in case of NTP connectivity problems, OpenNTPD does not
account dispersion at all and always reports `0`.
### `node_ntp_sanity`
Aggregate NTPD health including stratum, leap flag, sane freshness, root
distance being less than `collector.ntp.max-distance` and causality violation
being less than `collector.ntp.local-offset-tolerance`.
Causality violation is lower bound estimate of clock error done using SNTP,
it's calculated as positive portion of `abs(node_ntp_offset) - node_ntp_rtt / 2`.
## `timex` collector
This collector exports state of kernel time synchronization flag that should be
maintained by time-keeping daemon and is eventually raised by Linux kernel if
time-keeping daemon does not update it regularly.
Unfortunately some daemons do not handle this flag properly, e.g. chrony-1.30
from Debian/jessie clears `STA_UNSYNC` flag during daemon initialisation and
does not indicate clock synchronization status using this flag. Modern chrony
versions should work better. All chrony versions require `rtcsync` option to
maintain this flag. OpenNTPD does not touch this flag at all till
OpenNTPD-5.9p1.
On the other hand combination of `sync_status` and `offset` exported by `timex`
module is the way to monitor if systemd-timesyncd does its job.
Loading
Loading
@@ -2,3 +2,5 @@ Brett Vickers (beevik)
Mikhail Salosin (AlphaB)
Anton Tolchanov (knyar)
Christopher Batey (chbatey)
Meng Zhuo (mengzhuo)
Leonid Evdokimov (darkk)
Loading
Loading
@@ -7,14 +7,18 @@ ntp
The ntp package is an implementation of a simple NTP client. It allows you
to connect to a remote NTP server and request the current time.
 
To request the current time using version 4 of the NTP protocol, simply do the
following:
To request the current time, simply do the following:
```go
time, err := ntp.Time("0.pool.ntp.org")
time, err := ntp.Time("0.beevik-ntp.pool.ntp.org")
```
 
To request the current time along with additional metadata, use the Query
function:
```go
response, err := ntp.Query("0.pool.ntp.org", 4)
response, err := ntp.Query("0.beevik-ntp.pool.ntp.org")
```
NB: if you want to use the NTP Pool in your software you should request your
own [vendor zone](http://www.pool.ntp.org/en/vendors.html). You **must
absolutely not use the default pool.ntp.org zone names** as the default
configuration in your application or appliance.
Loading
Loading
@@ -11,8 +11,11 @@ package ntp
 
import (
"encoding/binary"
"errors"
"net"
"time"
"golang.org/x/net/ipv4"
)
 
type mode uint8
Loading
Loading
@@ -28,13 +31,39 @@ const (
reservedPrivate
)
 
// The LeapIndicator is used to warn if a leap second should be inserted
// or deleted in the last minute of the current month.
type LeapIndicator uint8
const (
// LeapNoWarning indicates no impending leap second
LeapNoWarning LeapIndicator = 0
// LeapAddSecond indicates the last minute of the day has 61 seconds
LeapAddSecond = 1
// LeapDelSecond indicates the last minute of the day has 59 seconds
LeapDelSecond = 2
// LeapNotInSync indicates an unsynchronized leap second.
LeapNotInSync = 3
)
const (
maxStratum = 16
// MaxStratum is the largest allowable NTP stratum value
MaxStratum = 16
nanoPerSec = 1000000000
defaultNtpVersion = 4
maxPoll = 17 // log2 max poll interval (~36 h)
maxDispersion = 16 // aka MAXDISP
)
 
var (
timeout = 5 * time.Second
defaultTimeout = 5 * time.Second
ntpEpoch = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
)
 
Loading
Loading
@@ -72,8 +101,9 @@ type ntpTimeShort uint32
// Duration interprets the fixed-point ntpTimeShort as a number of elapsed
// seconds and returns the corresponding time.Duration value.
func (t ntpTimeShort) Duration() time.Duration {
sec := (t >> 16) * nanoPerSec
frac := (t & 0xffff) * nanoPerSec >> 16
t64 := uint64(t)
sec := (t64 >> 16) * nanoPerSec
frac := (t64 & 0xffff) * nanoPerSec >> 16
return time.Duration(sec + frac)
}
 
Loading
Loading
@@ -102,6 +132,25 @@ func (m *msg) setMode(md mode) {
m.LiVnMode = (m.LiVnMode & 0xf8) | uint8(md)
}
 
// setLeapIndicator modifies the leap indicator on the message.
func (m *msg) setLeapIndicator(li LeapIndicator) {
m.LiVnMode = (m.LiVnMode & 0x3f) | uint8(li)<<6
}
// getLeapIndicator returns the leap indicator on the message.
func (m *msg) getLeapIndicator() LeapIndicator {
return LeapIndicator((m.LiVnMode >> 6) & 0x03)
}
// QueryOptions contains the list of configurable options that may be used with
// the QueryWithOptions function.
type QueryOptions struct {
Timeout time.Duration // defaults to 5 seconds
Version int // NTP protocol version, defaults to 4
Port int // NTP Server port for UDPAddr.Port, defaults to 123
TTL int // IP TTL to use for outgoing UDP packets, defaults to system default
}
// A Response contains time data, some of which is returned by the NTP server
// and some of which is calculated by the client.
type Response struct {
Loading
Loading
@@ -112,92 +161,253 @@ type Response struct {
Precision time.Duration // precision of server's system clock
Stratum uint8 // stratum level of NTP server's clock
ReferenceID uint32 // server's reference ID
ReferenceTime time.Time // server's time of last clock update
RootDelay time.Duration // server's RTT to the reference clock
RootDispersion time.Duration // server's dispersion to the reference clock
Leap LeapIndicator // server's leap second indicator; see RFC 5905
// RootDistance is the single-packet estimate of the root synchronization
// distance. Some SNTP clients limit-check this value before using the
// response. For example, systemd-timesyncd uses 5.0s as an upper bound. See
// https://tools.ietf.org/html/rfc5905#appendix-A.5.5.2
RootDistance time.Duration
// CausalityViolation is a time duration representing the amount of
// causality violation between two sets of timestamps. It may be used as a
// lower bound on current time synchronization error betwen local and NTP
// clock. A leap second may contribute as much as 1 second of causality violation.
CausalityViolation time.Duration
}
 
// Query returns the current time from the remote server host using the
// requested version of the NTP protocol. It also returns additional
// information about the exchanged time information. The version may be 2, 3,
// or 4; although 4 is most typically used.
func Query(host string, version int) (*Response, error) {
m, err := getTime(host, version)
now := toNtpTime(time.Now())
// Validate checks if the response is valid for the purposes of time
// synchronization.
func (r *Response) Validate() bool {
// Reference Timestamp: Time when the system clock was last set or
// corrected. Semantics of this value seems to vary across NTP server
// implementations: it may be both NTP-clock time and system wall-clock
// time of this event. :-( So (T3 - ReferenceTime) is not true
// "freshness" as it may be actually NEGATIVE sometimes.
freshness := r.Time.Sub(r.ReferenceTime)
// (Lambda := RootDelay/2 + RootDispersion) check against MAXDISP (16s)
// is required as ntp.org ntpd may report sane other fields while
// giving quite erratic clock. The check is declared in packet() at
// https://tools.ietf.org/html/rfc5905#appendix-A.5.1.1.
lambda := r.RootDelay/2 + r.RootDispersion
// `r.RTT > 0` check is not included as it does not depend on the
// packet itself, but also depends on clock _speed_. It's indicator
// that local clock run faster than remote one, so (T4-T1) < (T3-T2),
// but it may be local clock issue.
// E.g. T1/T2/T3/T4 = 0/10/20/1 leads to RTT = -9s.
return r.Leap != LeapNotInSync && // RFC5905, packet()
0 < r.Stratum && r.Stratum < MaxStratum && // RFC5905, packet()
lambda < maxDispersion*time.Second && // RFC5905, packet()
!r.Time.Before(r.ReferenceTime) && // RFC5905, packet(), reftime <= xmt ~~ !(xmt < reftime)
freshness <= (1<<maxPoll)*time.Second && // ntpdate uses 24h as a heuristics instead of ~36h derived from MAXPOLL
ntpEpoch.Before(r.Time) && // sanity
ntpEpoch.Before(r.ReferenceTime) // sanity
}
func (r *Response) rootDistance() time.Duration {
// RFC5905 suggests more strict check against _peer_ in fit(), that
// root_dist should be less than MAXDIST + PHI * LOG2D(s.poll).
// MAXPOLL is 17, so it is approximately at most (1s + 15e-6 * 2**17) =
// 2.96608 s, but MAXDIST and MAXPOLL are confugurable values in the
// reference implementation, so only MAXDISP check has hardcoded value
// in Validate().
//
// root_dist should also have following summands
// + Dispersion towards the peer
// + jitter of the link to the peer
// + PHI * (current_uptime - peer->uptime_of_last_update)
// but all these values are 0 if only single NTP packet was sent.
rtt := r.RTT
if rtt < 0 {
rtt = 0
}
return (rtt+r.RootDelay)/2 + r.RootDispersion
}
func (r *Response) causalityViolation() time.Duration {
// SNTP query has four timestamps for consecutive events: T1, T2, T3
// and T4. T1 and T4 use local clock, T2 and T3 use NTP clock.
// RTT = (T4 - T1) - (T3 - T2) = T4 - T3 + T2 - T1
// Offset = (T2 + T3)/2 - (T4 + T1)/2 = (-T4 + T3 + T2 - T1) / 2
// => T2 - T1 = RTT/2 + Offset && T4 - T3 = RTT/2 - Offset
// If system wall-clock is synced to NTP-clock then T2 >= T1 && T4 >= T3.
// This check may be useful against chrony NTP daemon as it starts
// relaying sane NTP clock before system wall-clock is actually adjusted.
violation := r.RTT / 2
if r.ClockOffset > 0 {
violation -= r.ClockOffset
} else {
violation += r.ClockOffset
}
if violation < 0 {
return -violation
}
return time.Duration(0)
}
// Query returns the current time from the remote server host. It also returns
// additional information about the exchanged time information.
func Query(host string) (*Response, error) {
return QueryWithOptions(host, QueryOptions{})
}
// QueryWithOptions returns the current time from the remote server host.
// It also returns additional information about the exchanged time
// information. It allows the specification of additional query options.
func QueryWithOptions(host string, opt QueryOptions) (*Response, error) {
m, now, err := getTime(host, opt)
if err != nil {
return nil, err
}
return parseTime(m, now), nil
}
 
// parseTime parses SNTP packet paired with the packet arrival time (dst) and
// returns Response having SNTP packet data converted to go types.
func parseTime(m *msg, dst ntpTime) *Response {
r := &Response{
Time: m.ReceiveTime.Time(),
RTT: rtt(m.OriginTime, m.ReceiveTime, m.TransmitTime, now),
ClockOffset: offset(m.OriginTime, m.ReceiveTime, m.TransmitTime, now),
Time: m.TransmitTime.Time(),
RTT: rtt(m.OriginTime, m.ReceiveTime, m.TransmitTime, dst),
ClockOffset: offset(m.OriginTime, m.ReceiveTime, m.TransmitTime, dst),
Poll: toInterval(m.Poll),
Precision: toInterval(m.Precision),
Stratum: m.Stratum,
ReferenceID: m.ReferenceID,
ReferenceTime: m.ReferenceTime.Time(),
RootDelay: m.RootDelay.Duration(),
RootDispersion: m.RootDispersion.Duration(),
Leap: m.getLeapIndicator(),
}
 
// these are exported as values to preserve API style consistency
r.RootDistance = r.rootDistance()
r.CausalityViolation = r.causalityViolation()
// https://tools.ietf.org/html/rfc5905#section-7.3
if r.Stratum == 0 {
r.Stratum = maxStratum
r.Stratum = MaxStratum
}
 
return r, nil
return r
}
 
// getTime returns the "receive time" from the remote NTP server host.
func getTime(host string, version int) (*msg, error) {
if version < 2 || version > 4 {
// getTime returns SNTP packet & DestinationTime timestamp.
func getTime(host string, opt QueryOptions) (*msg, ntpTime, error) {
if opt.Version == 0 {
opt.Version = defaultNtpVersion
}
if opt.Version < 2 || opt.Version > 4 {
panic("ntp: invalid version number")
}
 
if opt.Timeout == 0 {
opt.Timeout = defaultTimeout
}
raddr, err := net.ResolveUDPAddr("udp", host+":123")
if err != nil {
return nil, err
return nil, 0, err
}
if opt.Port != 0 {
raddr.Port = opt.Port
}
 
con, err := net.DialUDP("udp", nil, raddr)
if err != nil {
return nil, err
return nil, 0, err
}
defer con.Close()
con.SetDeadline(time.Now().Add(timeout))
if opt.TTL != 0 {
ipcon := ipv4.NewConn(con)
err = ipcon.SetTTL(opt.TTL)
if err != nil {
return nil, 0, err
}
}
con.SetDeadline(time.Now().Add(opt.Timeout))
 
m := new(msg)
m.setMode(client)
m.setVersion(version)
m.TransmitTime = toNtpTime(time.Now())
m.setVersion(opt.Version)
m.setLeapIndicator(LeapNotInSync)
xmtTime := time.Now()
xmt := toNtpTime(xmtTime)
m.TransmitTime = xmt
 
err = binary.Write(con, binary.BigEndian, m)
if err != nil {
return nil, err
return nil, 0, err
}
 
err = binary.Read(con, binary.BigEndian, m)
if err != nil {
return nil, err
return nil, 0, err
}
 
return m, nil
delta := time.Since(xmtTime) // uses monotonic clock @ Go 1.9+, NB: delta != RTT
dst := toNtpTime(xmtTime.Add(delta))
// It's possible to use random uint64 as client's `TransmitTime` field,
// it has better privacy (clock of the node is not disclosed in
// plain-text), better UDP packet spoofing resistance (blind attacker
// has to guess both port and the uint64 value), and OpenNTPD behaves
// like that. But math/rand is not secure enough for the purpose,
// crypto/rand takes 64 bits of entropy for every outgoing packet and
// CSPRNG from crypto/rand/rand_unix is not available: see
// https://github.com/golang/go/issues/13820
// A packet is bogus if the origin timestamp t1 in the packet does not
// match the xmt state variable T1.
// -- https://tools.ietf.org/html/rfc5905#section-8
if m.OriginTime != xmt {
return nil, 0, errors.New("response OriginTime != query TransmitTime") // spoofed packet?
}
if m.OriginTime > dst { // Go 1.9 has monotonic clock preventing that, but 1.8 has not, so it's not panic()
return nil, 0, errors.New("client clock tick backwards")
}
if m.ReceiveTime > m.TransmitTime {
return nil, 0, errors.New("server clock tick backwards")
}
return m, dst, nil
}
 
// TimeV returns the current time from the remote server host using the
// requested version of the NTP protocol. The version may be 2, 3, or 4;
// although 4 is most typically used.
// requested version of the NTP protocol. On error, it returns the local time.
// The version may be 2, 3, or 4.
func TimeV(host string, version int) (time.Time, error) {
m, err := getTime(host, version)
m, dst, err := getTime(host, QueryOptions{Version: version})
if err != nil {
return time.Now(), err
}
return m.ReceiveTime.Time().Local(), nil
r := parseTime(m, dst)
if !r.Validate() {
return time.Now(), errors.New("invalid SNTP reply")
}
// An SNTP client implementing the on-wire protocol has a single server
// and no dependent clients. It can operate with any subset of the NTP
// on-wire protocol, the simplest approach using only the transmit
// timestamp of the server packet and ignoring all other fields.
// -- https://tools.ietf.org/html/rfc5905#section-14
return time.Now().Add(r.ClockOffset), nil
}
 
// Time returns the current time from the remote server host using version 4
// of the NTP protocol.
// Time returns the current time from the remote server host using version 4 of
// the NTP protocol. On error, it returns the local time.
func Time(host string) (time.Time, error) {
return TimeV(host, 4)
return TimeV(host, defaultNtpVersion)
}
 
func rtt(t1, t2, t3, t4 ntpTime) time.Duration {
Loading
Loading
// go generate gen.go
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
package iana // import "golang.org/x/net/internal/iana"
// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12
const (
DiffServCS0 = 0x0 // CS0
DiffServCS1 = 0x20 // CS1
DiffServCS2 = 0x40 // CS2
DiffServCS3 = 0x60 // CS3
DiffServCS4 = 0x80 // CS4
DiffServCS5 = 0xa0 // CS5
DiffServCS6 = 0xc0 // CS6
DiffServCS7 = 0xe0 // CS7
DiffServAF11 = 0x28 // AF11
DiffServAF12 = 0x30 // AF12
DiffServAF13 = 0x38 // AF13
DiffServAF21 = 0x48 // AF21
DiffServAF22 = 0x50 // AF22
DiffServAF23 = 0x58 // AF23
DiffServAF31 = 0x68 // AF31
DiffServAF32 = 0x70 // AF32
DiffServAF33 = 0x78 // AF33
DiffServAF41 = 0x88 // AF41
DiffServAF42 = 0x90 // AF42
DiffServAF43 = 0x98 // AF43
DiffServEF = 0xb8 // EF
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
)
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
const (
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
CongestionExperienced = 0x3 // CE (Congestion Experienced)
)
// Protocol Numbers, Updated: 2016-06-22
const (
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
ProtocolICMP = 1 // Internet Control Message
ProtocolIGMP = 2 // Internet Group Management
ProtocolGGP = 3 // Gateway-to-Gateway
ProtocolIPv4 = 4 // IPv4 encapsulation
ProtocolST = 5 // Stream
ProtocolTCP = 6 // Transmission Control
ProtocolCBT = 7 // CBT
ProtocolEGP = 8 // Exterior Gateway Protocol
ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
ProtocolNVPII = 11 // Network Voice Protocol
ProtocolPUP = 12 // PUP
ProtocolEMCON = 14 // EMCON
ProtocolXNET = 15 // Cross Net Debugger
ProtocolCHAOS = 16 // Chaos
ProtocolUDP = 17 // User Datagram
ProtocolMUX = 18 // Multiplexing
ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
ProtocolHMP = 20 // Host Monitoring
ProtocolPRM = 21 // Packet Radio Measurement
ProtocolXNSIDP = 22 // XEROX NS IDP
ProtocolTRUNK1 = 23 // Trunk-1
ProtocolTRUNK2 = 24 // Trunk-2
ProtocolLEAF1 = 25 // Leaf-1
ProtocolLEAF2 = 26 // Leaf-2
ProtocolRDP = 27 // Reliable Data Protocol
ProtocolIRTP = 28 // Internet Reliable Transaction
ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
ProtocolMFENSP = 31 // MFE Network Services Protocol
ProtocolMERITINP = 32 // MERIT Internodal Protocol
ProtocolDCCP = 33 // Datagram Congestion Control Protocol
Protocol3PC = 34 // Third Party Connect Protocol
ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
ProtocolXTP = 36 // XTP
ProtocolDDP = 37 // Datagram Delivery Protocol
ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
ProtocolTPPP = 39 // TP++ Transport Protocol
ProtocolIL = 40 // IL Transport Protocol
ProtocolIPv6 = 41 // IPv6 encapsulation
ProtocolSDRP = 42 // Source Demand Routing Protocol
ProtocolIPv6Route = 43 // Routing Header for IPv6
ProtocolIPv6Frag = 44 // Fragment Header for IPv6
ProtocolIDRP = 45 // Inter-Domain Routing Protocol
ProtocolRSVP = 46 // Reservation Protocol
ProtocolGRE = 47 // Generic Routing Encapsulation
ProtocolDSR = 48 // Dynamic Source Routing Protocol
ProtocolBNA = 49 // BNA
ProtocolESP = 50 // Encap Security Payload
ProtocolAH = 51 // Authentication Header
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
ProtocolNARP = 54 // NBMA Address Resolution Protocol
ProtocolMOBILE = 55 // IP Mobility
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
ProtocolSKIP = 57 // SKIP
ProtocolIPv6ICMP = 58 // ICMP for IPv6
ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
ProtocolIPv6Opts = 60 // Destination Options for IPv6
ProtocolCFTP = 62 // CFTP
ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
ProtocolKRYPTOLAN = 65 // Kryptolan
ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
ProtocolIPPC = 67 // Internet Pluribus Packet Core
ProtocolSATMON = 69 // SATNET Monitoring
ProtocolVISA = 70 // VISA Protocol
ProtocolIPCV = 71 // Internet Packet Core Utility
ProtocolCPNX = 72 // Computer Protocol Network Executive
ProtocolCPHB = 73 // Computer Protocol Heart Beat
ProtocolWSN = 74 // Wang Span Network
ProtocolPVP = 75 // Packet Video Protocol
ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
ProtocolWBMON = 78 // WIDEBAND Monitoring
ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
ProtocolISOIP = 80 // ISO Internet Protocol
ProtocolVMTP = 81 // VMTP
ProtocolSECUREVMTP = 82 // SECURE-VMTP
ProtocolVINES = 83 // VINES
ProtocolTTP = 84 // Transaction Transport Protocol
ProtocolIPTM = 84 // Internet Protocol Traffic Manager
ProtocolNSFNETIGP = 85 // NSFNET-IGP
ProtocolDGP = 86 // Dissimilar Gateway Protocol
ProtocolTCF = 87 // TCF
ProtocolEIGRP = 88 // EIGRP
ProtocolOSPFIGP = 89 // OSPFIGP
ProtocolSpriteRPC = 90 // Sprite RPC Protocol
ProtocolLARP = 91 // Locus Address Resolution Protocol
ProtocolMTP = 92 // Multicast Transport Protocol
ProtocolAX25 = 93 // AX.25 Frames
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
ProtocolENCAP = 98 // Encapsulation Header
ProtocolGMTP = 100 // GMTP
ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
ProtocolPNNI = 102 // PNNI over IP
ProtocolPIM = 103 // Protocol Independent Multicast
ProtocolARIS = 104 // ARIS
ProtocolSCPS = 105 // SCPS
ProtocolQNX = 106 // QNX
ProtocolAN = 107 // Active Networks
ProtocolIPComp = 108 // IP Payload Compression Protocol
ProtocolSNP = 109 // Sitara Networks Protocol
ProtocolCompaqPeer = 110 // Compaq Peer Protocol
ProtocolIPXinIP = 111 // IPX in IP
ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
ProtocolPGM = 113 // PGM Reliable Transport Protocol
ProtocolL2TP = 115 // Layer Two Tunneling Protocol
ProtocolDDX = 116 // D-II Data Exchange (DDX)
ProtocolIATP = 117 // Interactive Agent Transfer Protocol
ProtocolSTP = 118 // Schedule Transfer Protocol
ProtocolSRP = 119 // SpectraLink Radio Protocol
ProtocolUTI = 120 // UTI
ProtocolSMP = 121 // Simple Message Protocol
ProtocolPTP = 123 // Performance Transparency Protocol
ProtocolISIS = 124 // ISIS over IPv4
ProtocolFIRE = 125 // FIRE
ProtocolCRTP = 126 // Combat Radio Transport Protocol
ProtocolCRUDP = 127 // Combat Radio User Datagram
ProtocolSSCOPMCE = 128 // SSCOPMCE
ProtocolIPLT = 129 // IPLT
ProtocolSPS = 130 // Secure Packet Shield
ProtocolPIPE = 131 // Private IP Encapsulation within IP
ProtocolSCTP = 132 // Stream Control Transmission Protocol
ProtocolFC = 133 // Fibre Channel
ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
ProtocolMobilityHeader = 135 // Mobility Header
ProtocolUDPLite = 136 // UDPLite
ProtocolMPLSinIP = 137 // MPLS-in-IP
ProtocolMANET = 138 // MANET Protocols
ProtocolHIP = 139 // Host Identity Protocol
ProtocolShim6 = 140 // Shim6 Protocol
ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
ProtocolROHC = 142 // Robust Header Compression
ProtocolReserved = 255 // Reserved
)
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
//go:generate go run gen.go
// This program generates internet protocol constants and tables by
// reading IANA protocol registries.
package main
import (
"bytes"
"encoding/xml"
"fmt"
"go/format"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
)
var registries = []struct {
url string
parse func(io.Writer, io.Reader) error
}{
{
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
parseDSCPRegistry,
},
{
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
parseTOSTCByte,
},
{
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
parseProtocolNumbers,
},
}
func main() {
var bb bytes.Buffer
fmt.Fprintf(&bb, "// go generate gen.go\n")
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
for _, r := range registries {
resp, err := http.Get(r.url)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
os.Exit(1)
}
if err := r.parse(&bb, resp.Body); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Fprintf(&bb, "\n")
}
b, err := format.Source(bb.Bytes())
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var dr dscpRegistry
if err := dec.Decode(&dr); err != nil {
return err
}
drs := dr.escape()
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
fmt.Fprintf(w, "const (\n")
for _, dr := range drs {
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
fmt.Fprintf(w, "// %s\n", dr.OrigName)
}
fmt.Fprintf(w, ")\n")
return nil
}
type dscpRegistry struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
Note string `xml:"note"`
RegTitle string `xml:"registry>title"`
PoolRecords []struct {
Name string `xml:"name"`
Space string `xml:"space"`
} `xml:"registry>record"`
Records []struct {
Name string `xml:"name"`
Space string `xml:"space"`
} `xml:"registry>registry>record"`
}
type canonDSCPRecord struct {
OrigName string
Name string
Value int
}
func (drr *dscpRegistry) escape() []canonDSCPRecord {
drs := make([]canonDSCPRecord, len(drr.Records))
sr := strings.NewReplacer(
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, dr := range drr.Records {
s := strings.TrimSpace(dr.Name)
drs[i].OrigName = s
drs[i].Name = sr.Replace(s)
n, err := strconv.ParseUint(dr.Space, 2, 8)
if err != nil {
continue
}
drs[i].Value = int(n) << 2
}
return drs
}
func parseTOSTCByte(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var ttb tosTCByte
if err := dec.Decode(&ttb); err != nil {
return err
}
trs := ttb.escape()
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
fmt.Fprintf(w, "const (\n")
for _, tr := range trs {
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
}
fmt.Fprintf(w, ")\n")
return nil
}
type tosTCByte struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
Note string `xml:"note"`
RegTitle string `xml:"registry>title"`
Records []struct {
Binary string `xml:"binary"`
Keyword string `xml:"keyword"`
} `xml:"registry>record"`
}
type canonTOSTCByteRecord struct {
OrigKeyword string
Keyword string
Value int
}
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
sr := strings.NewReplacer(
"Capable", "",
"(", "",
")", "",
"+", "",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, tr := range ttb.Records {
s := strings.TrimSpace(tr.Keyword)
trs[i].OrigKeyword = s
ss := strings.Split(s, " ")
if len(ss) > 1 {
trs[i].Keyword = strings.Join(ss[1:], " ")
} else {
trs[i].Keyword = ss[0]
}
trs[i].Keyword = sr.Replace(trs[i].Keyword)
n, err := strconv.ParseUint(tr.Binary, 2, 8)
if err != nil {
continue
}
trs[i].Value = int(n)
}
return trs
}
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
dec := xml.NewDecoder(r)
var pn protocolNumbers
if err := dec.Decode(&pn); err != nil {
return err
}
prs := pn.escape()
prs = append([]canonProtocolRecord{{
Name: "IP",
Descr: "IPv4 encapsulation, pseudo protocol number",
Value: 0,
}}, prs...)
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
fmt.Fprintf(w, "const (\n")
for _, pr := range prs {
if pr.Name == "" {
continue
}
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
s := pr.Descr
if s == "" {
s = pr.OrigName
}
fmt.Fprintf(w, "// %s\n", s)
}
fmt.Fprintf(w, ")\n")
return nil
}
type protocolNumbers struct {
XMLName xml.Name `xml:"registry"`
Title string `xml:"title"`
Updated string `xml:"updated"`
RegTitle string `xml:"registry>title"`
Note string `xml:"registry>note"`
Records []struct {
Value string `xml:"value"`
Name string `xml:"name"`
Descr string `xml:"description"`
} `xml:"registry>record"`
}
type canonProtocolRecord struct {
OrigName string
Name string
Descr string
Value int
}
func (pn *protocolNumbers) escape() []canonProtocolRecord {
prs := make([]canonProtocolRecord, len(pn.Records))
sr := strings.NewReplacer(
"-in-", "in",
"-within-", "within",
"-over-", "over",
"+", "P",
"-", "",
"/", "",
".", "",
" ", "",
)
for i, pr := range pn.Records {
if strings.Contains(pr.Name, "Deprecated") ||
strings.Contains(pr.Name, "deprecated") {
continue
}
prs[i].OrigName = pr.Name
s := strings.TrimSpace(pr.Name)
switch pr.Name {
case "ISIS over IPv4":
prs[i].Name = "ISIS"
case "manet":
prs[i].Name = "MANET"
default:
prs[i].Name = sr.Replace(s)
}
ss := strings.Split(pr.Descr, "\n")
for i := range ss {
ss[i] = strings.TrimSpace(ss[i])
}
if len(ss) > 1 {
prs[i].Descr = strings.Join(ss, " ")
} else {
prs[i].Descr = ss[0]
}
prs[i].Value, _ = strconv.Atoi(pr.Value)
}
return prs
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package socket
func (h *cmsghdr) len() int { return int(h.Len) }
func (h *cmsghdr) lvl() int { return int(h.Level) }
func (h *cmsghdr) typ() int { return int(h.Type) }
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm mips mipsle 386
// +build linux
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build linux
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint64(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64
// +build solaris
package socket
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
h.Type = int32(typ)
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket
type cmsghdr struct{}
const sizeofCmsghdr = 0
func (h *cmsghdr) len() int { return 0 }
func (h *cmsghdr) lvl() int { return 0 }
func (h *cmsghdr) typ() int { return 0 }
func (h *cmsghdr) set(l, lvl, typ int) {}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <linux/in.h>
#include <linux/in6.h>
#define _GNU_SOURCE
#include <sys/socket.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type mmsghdr C.struct_mmsghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type mmsghdr C.struct_mmsghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofMmsghdr = C.sizeof_struct_mmsghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
package socket
/*
#include <sys/socket.h>
#include <netinet/in.h>
*/
import "C"
const (
sysAF_UNSPEC = C.AF_UNSPEC
sysAF_INET = C.AF_INET
sysAF_INET6 = C.AF_INET6
sysSOCK_RAW = C.SOCK_RAW
)
type iovec C.struct_iovec
type msghdr C.struct_msghdr
type cmsghdr C.struct_cmsghdr
type sockaddrInet C.struct_sockaddr_in
type sockaddrInet6 C.struct_sockaddr_in6
const (
sizeofIovec = C.sizeof_struct_iovec
sizeofMsghdr = C.sizeof_struct_msghdr
sizeofCmsghdr = C.sizeof_struct_cmsghdr
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment