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 @SuperQpull/648/merge
parent
b0d5c00832
commit
c169b4b1c5
@ -0,0 +1,79 @@ |
||||
# 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. |
||||
@ -0,0 +1,180 @@ |
||||
// 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
|
||||
) |
||||
@ -0,0 +1,293 @@ |
||||
// 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 |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
// 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) } |
||||
@ -0,0 +1,13 @@ |
||||
// 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) |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
// 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) |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
// 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) |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
// 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) |
||||
} |
||||
@ -0,0 +1,17 @@ |
||||
// 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) {} |
||||
@ -0,0 +1,44 @@ |
||||
// 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,0 +1,44 @@ |
||||
// 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,0 +1,44 @@ |
||||
// 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,0 +1,49 @@ |
||||
// 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 |
||||
) |
||||
@ -0,0 +1,47 @@ |
||||
// 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 |
||||
) |
||||
@ -0,0 +1,44 @@ |
||||
// 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,0 +1,44 @@ |
||||
// 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,0 +1,31 @@ |
||||
// 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 |
||||
|
||||
import "syscall" |
||||
|
||||
var ( |
||||
errEAGAIN error = syscall.EAGAIN |
||||
errEINVAL error = syscall.EINVAL |
||||
errENOENT error = syscall.ENOENT |
||||
) |
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||
// at runtime.
|
||||
func errnoErr(errno syscall.Errno) error { |
||||
switch errno { |
||||
case 0: |
||||
return nil |
||||
case syscall.EAGAIN: |
||||
return errEAGAIN |
||||
case syscall.EINVAL: |
||||
return errEINVAL |
||||
case syscall.ENOENT: |
||||
return errENOENT |
||||
} |
||||
return errno |
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import "syscall" |
||||
|
||||
var ( |
||||
errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING |
||||
errEINVAL error = syscall.EINVAL |
||||
) |
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||
// at runtime.
|
||||
func errnoErr(errno syscall.Errno) error { |
||||
switch errno { |
||||
case 0: |
||||
return nil |
||||
case syscall.ERROR_IO_PENDING: |
||||
return errERROR_IO_PENDING |
||||
case syscall.EINVAL: |
||||
return errEINVAL |
||||
} |
||||
return errno |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
// 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 darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package socket |
||||
|
||||
import "unsafe" |
||||
|
||||
func (v *iovec) set(b []byte) { |
||||
v.Base = (*byte)(unsafe.Pointer(&b[0])) |
||||
v.Len = uint32(len(b)) |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
// 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 darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package socket |
||||
|
||||
import "unsafe" |
||||
|
||||
func (v *iovec) set(b []byte) { |
||||
v.Base = (*byte)(unsafe.Pointer(&b[0])) |
||||
v.Len = uint64(len(b)) |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
// 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 |
||||
|
||||
import "unsafe" |
||||
|
||||
func (v *iovec) set(b []byte) { |
||||
v.Base = (*int8)(unsafe.Pointer(&b[0])) |
||||
v.Len = uint64(len(b)) |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
// 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 iovec struct{} |
||||
|
||||
func (v *iovec) set(b []byte) {} |
||||
@ -0,0 +1,21 @@ |
||||
// 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 !linux,!netbsd
|
||||
|
||||
package socket |
||||
|
||||
import "net" |
||||
|
||||
type mmsghdr struct{} |
||||
|
||||
type mmsghdrs []mmsghdr |
||||
|
||||
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error { |
||||
return nil |
||||
} |
||||
|
||||
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error { |
||||
return nil |
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
// 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 linux netbsd
|
||||
|
||||
package socket |
||||
|
||||
import "net" |
||||
|
||||
type mmsghdrs []mmsghdr |
||||
|
||||
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error { |
||||
for i := range hs { |
||||
vs := make([]iovec, len(ms[i].Buffers)) |
||||
var sa []byte |
||||
if parseFn != nil { |
||||
sa = make([]byte, sizeofSockaddrInet6) |
||||
} |
||||
if marshalFn != nil { |
||||
sa = marshalFn(ms[i].Addr) |
||||
} |
||||
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error { |
||||
for i := range hs { |
||||
ms[i].N = int(hs[i].Len) |
||||
ms[i].NN = hs[i].Hdr.controllen() |
||||
ms[i].Flags = hs[i].Hdr.flags() |
||||
if parseFn != nil { |
||||
var err error |
||||
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
// 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 |
||||
|
||||
import "unsafe" |
||||
|
||||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { |
||||
for i := range vs { |
||||
vs[i].set(bs[i]) |
||||
} |
||||
h.setIov(vs) |
||||
if len(oob) > 0 { |
||||
h.Control = (*byte)(unsafe.Pointer(&oob[0])) |
||||
h.Controllen = uint32(len(oob)) |
||||
} |
||||
if sa != nil { |
||||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) |
||||
h.Namelen = uint32(len(sa)) |
||||
} |
||||
} |
||||
|
||||
func (h *msghdr) name() []byte { |
||||
if h.Name != nil && h.Namelen > 0 { |
||||
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen] |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (h *msghdr) controllen() int { |
||||
return int(h.Controllen) |
||||
} |
||||
|
||||
func (h *msghdr) flags() int { |
||||
return int(h.Flags) |
||||
} |
||||
@ -0,0 +1,12 @@ |
||||
// 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
|
||||
|
||||
package socket |
||||
|
||||
func (h *msghdr) setIov(vs []iovec) { |
||||
h.Iov = &vs[0] |
||||
h.Iovlen = int32(len(vs)) |
||||
} |
||||
@ -0,0 +1,36 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import "unsafe" |
||||
|
||||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { |
||||
for i := range vs { |
||||
vs[i].set(bs[i]) |
||||
} |
||||
h.setIov(vs) |
||||
if len(oob) > 0 { |
||||
h.setControl(oob) |
||||
} |
||||
if sa != nil { |
||||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) |
||||
h.Namelen = uint32(len(sa)) |
||||
} |
||||
} |
||||
|
||||
func (h *msghdr) name() []byte { |
||||
if h.Name != nil && h.Namelen > 0 { |
||||
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen] |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (h *msghdr) controllen() int { |
||||
return int(h.Controllen) |
||||
} |
||||
|
||||
func (h *msghdr) flags() int { |
||||
return int(h.Flags) |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
// 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 |
||||
|
||||
import "unsafe" |
||||
|
||||
func (h *msghdr) setIov(vs []iovec) { |
||||
h.Iov = &vs[0] |
||||
h.Iovlen = uint32(len(vs)) |
||||
} |
||||
|
||||
func (h *msghdr) setControl(b []byte) { |
||||
h.Control = (*byte)(unsafe.Pointer(&b[0])) |
||||
h.Controllen = uint32(len(b)) |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
// 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 |
||||
|
||||
import "unsafe" |
||||
|
||||
func (h *msghdr) setIov(vs []iovec) { |
||||
h.Iov = &vs[0] |
||||
h.Iovlen = uint64(len(vs)) |
||||
} |
||||
|
||||
func (h *msghdr) setControl(b []byte) { |
||||
h.Control = (*byte)(unsafe.Pointer(&b[0])) |
||||
h.Controllen = uint64(len(b)) |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
func (h *msghdr) setIov(vs []iovec) { |
||||
h.Iov = &vs[0] |
||||
h.Iovlen = uint32(len(vs)) |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
// 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 |
||||
|
||||
import "unsafe" |
||||
|
||||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { |
||||
for i := range vs { |
||||
vs[i].set(bs[i]) |
||||
} |
||||
h.Iov = &vs[0] |
||||
h.Iovlen = int32(len(vs)) |
||||
if len(oob) > 0 { |
||||
h.Accrights = (*int8)(unsafe.Pointer(&oob[0])) |
||||
h.Accrightslen = int32(len(oob)) |
||||
} |
||||
if sa != nil { |
||||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) |
||||
h.Namelen = uint32(len(sa)) |
||||
} |
||||
} |
||||
|
||||
func (h *msghdr) controllen() int { |
||||
return int(h.Accrightslen) |
||||
} |
||||
|
||||
func (h *msghdr) flags() int { |
||||
return int(NativeEndian.Uint32(h.Pad_cgo_2[:])) |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
// 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 msghdr struct{} |
||||
|
||||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {} |
||||
func (h *msghdr) name() []byte { return nil } |
||||
func (h *msghdr) controllen() int { return 0 } |
||||
func (h *msghdr) flags() int { return 0 } |
||||
@ -0,0 +1,66 @@ |
||||
// 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 go1.9
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"errors" |
||||
"net" |
||||
"os" |
||||
"syscall" |
||||
) |
||||
|
||||
// A Conn represents a raw connection.
|
||||
type Conn struct { |
||||
network string |
||||
c syscall.RawConn |
||||
} |
||||
|
||||
// NewConn returns a new raw connection.
|
||||
func NewConn(c net.Conn) (*Conn, error) { |
||||
var err error |
||||
var cc Conn |
||||
switch c := c.(type) { |
||||
case *net.TCPConn: |
||||
cc.network = "tcp" |
||||
cc.c, err = c.SyscallConn() |
||||
case *net.UDPConn: |
||||
cc.network = "udp" |
||||
cc.c, err = c.SyscallConn() |
||||
case *net.IPConn: |
||||
cc.network = "ip" |
||||
cc.c, err = c.SyscallConn() |
||||
default: |
||||
return nil, errors.New("unknown connection type") |
||||
} |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &cc, nil |
||||
} |
||||
|
||||
func (o *Option) get(c *Conn, b []byte) (int, error) { |
||||
var operr error |
||||
var n int |
||||
fn := func(s uintptr) { |
||||
n, operr = getsockopt(s, o.Level, o.Name, b) |
||||
} |
||||
if err := c.c.Control(fn); err != nil { |
||||
return 0, err |
||||
} |
||||
return n, os.NewSyscallError("getsockopt", operr) |
||||
} |
||||
|
||||
func (o *Option) set(c *Conn, b []byte) error { |
||||
var operr error |
||||
fn := func(s uintptr) { |
||||
operr = setsockopt(s, o.Level, o.Name, b) |
||||
} |
||||
if err := c.c.Control(fn); err != nil { |
||||
return err |
||||
} |
||||
return os.NewSyscallError("setsockopt", operr) |
||||
} |
||||
@ -0,0 +1,74 @@ |
||||
// 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 go1.9
|
||||
// +build linux
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"net" |
||||
"os" |
||||
"syscall" |
||||
) |
||||
|
||||
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { |
||||
hs := make(mmsghdrs, len(ms)) |
||||
var parseFn func([]byte, string) (net.Addr, error) |
||||
if c.network != "tcp" { |
||||
parseFn = parseInetAddr |
||||
} |
||||
if err := hs.pack(ms, parseFn, nil); err != nil { |
||||
return 0, err |
||||
} |
||||
var operr error |
||||
var n int |
||||
fn := func(s uintptr) bool { |
||||
n, operr = recvmmsg(s, hs, flags) |
||||
if operr == syscall.EAGAIN { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
if err := c.c.Read(fn); err != nil { |
||||
return n, err |
||||
} |
||||
if operr != nil { |
||||
return n, os.NewSyscallError("recvmmsg", operr) |
||||
} |
||||
if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil { |
||||
return n, err |
||||
} |
||||
return n, nil |
||||
} |
||||
|
||||
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { |
||||
hs := make(mmsghdrs, len(ms)) |
||||
var marshalFn func(net.Addr) []byte |
||||
if c.network != "tcp" { |
||||
marshalFn = marshalInetAddr |
||||
} |
||||
if err := hs.pack(ms, nil, marshalFn); err != nil { |
||||
return 0, err |
||||
} |
||||
var operr error |
||||
var n int |
||||
fn := func(s uintptr) bool { |
||||
n, operr = sendmmsg(s, hs, flags) |
||||
if operr == syscall.EAGAIN { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
if err := c.c.Write(fn); err != nil { |
||||
return n, err |
||||
} |
||||
if operr != nil { |
||||
return n, os.NewSyscallError("sendmmsg", operr) |
||||
} |
||||
if err := hs[:n].unpack(ms[:n], nil, ""); err != nil { |
||||
return n, err |
||||
} |
||||
return n, nil |
||||
} |
||||
@ -0,0 +1,77 @@ |
||||
// 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 go1.9
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"os" |
||||
"syscall" |
||||
) |
||||
|
||||
func (c *Conn) recvMsg(m *Message, flags int) error { |
||||
var h msghdr |
||||
vs := make([]iovec, len(m.Buffers)) |
||||
var sa []byte |
||||
if c.network != "tcp" { |
||||
sa = make([]byte, sizeofSockaddrInet6) |
||||
} |
||||
h.pack(vs, m.Buffers, m.OOB, sa) |
||||
var operr error |
||||
var n int |
||||
fn := func(s uintptr) bool { |
||||
n, operr = recvmsg(s, &h, flags) |
||||
if operr == syscall.EAGAIN { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
if err := c.c.Read(fn); err != nil { |
||||
return err |
||||
} |
||||
if operr != nil { |
||||
return os.NewSyscallError("recvmsg", operr) |
||||
} |
||||
if c.network != "tcp" { |
||||
var err error |
||||
m.Addr, err = parseInetAddr(sa[:], c.network) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
m.N = n |
||||
m.NN = h.controllen() |
||||
m.Flags = h.flags() |
||||
return nil |
||||
} |
||||
|
||||
func (c *Conn) sendMsg(m *Message, flags int) error { |
||||
var h msghdr |
||||
vs := make([]iovec, len(m.Buffers)) |
||||
var sa []byte |
||||
if m.Addr != nil { |
||||
sa = marshalInetAddr(m.Addr) |
||||
} |
||||
h.pack(vs, m.Buffers, m.OOB, sa) |
||||
var operr error |
||||
var n int |
||||
fn := func(s uintptr) bool { |
||||
n, operr = sendmsg(s, &h, flags) |
||||
if operr == syscall.EAGAIN { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
if err := c.c.Write(fn); err != nil { |
||||
return err |
||||
} |
||||
if operr != nil { |
||||
return os.NewSyscallError("sendmsg", operr) |
||||
} |
||||
m.N = n |
||||
m.NN = len(m.OOB) |
||||
return nil |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
// 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 go1.9
|
||||
// +build !linux
|
||||
|
||||
package socket |
||||
|
||||
import "errors" |
||||
|
||||
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
// 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 go1.9
|
||||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
|
||||
|
||||
package socket |
||||
|
||||
import "errors" |
||||
|
||||
func (c *Conn) recvMsg(m *Message, flags int) error { |
||||
return errors.New("not implemented") |
||||
} |
||||
|
||||
func (c *Conn) sendMsg(m *Message, flags int) error { |
||||
return errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
// 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 !go1.9
|
||||
|
||||
package socket |
||||
|
||||
import "errors" |
||||
|
||||
func (c *Conn) recvMsg(m *Message, flags int) error { |
||||
return errors.New("not implemented") |
||||
} |
||||
|
||||
func (c *Conn) sendMsg(m *Message, flags int) error { |
||||
return errors.New("not implemented") |
||||
} |
||||
|
||||
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,62 @@ |
||||
// 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 !go1.9
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"errors" |
||||
"net" |
||||
"os" |
||||
"reflect" |
||||
"runtime" |
||||
) |
||||
|
||||
// A Conn represents a raw connection.
|
||||
type Conn struct { |
||||
c net.Conn |
||||
} |
||||
|
||||
// NewConn returns a new raw connection.
|
||||
func NewConn(c net.Conn) (*Conn, error) { |
||||
return &Conn{c: c}, nil |
||||
} |
||||
|
||||
func (o *Option) get(c *Conn, b []byte) (int, error) { |
||||
s, err := socketOf(c.c) |
||||
if err != nil { |
||||
return 0, err |
||||
} |
||||
n, err := getsockopt(s, o.Level, o.Name, b) |
||||
return n, os.NewSyscallError("getsockopt", err) |
||||
} |
||||
|
||||
func (o *Option) set(c *Conn, b []byte) error { |
||||
s, err := socketOf(c.c) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b)) |
||||
} |
||||
|
||||
func socketOf(c net.Conn) (uintptr, error) { |
||||
switch c.(type) { |
||||
case *net.TCPConn, *net.UDPConn, *net.IPConn: |
||||
v := reflect.ValueOf(c) |
||||
switch e := v.Elem(); e.Kind() { |
||||
case reflect.Struct: |
||||
fd := e.FieldByName("conn").FieldByName("fd") |
||||
switch e := fd.Elem(); e.Kind() { |
||||
case reflect.Struct: |
||||
sysfd := e.FieldByName("sysfd") |
||||
if runtime.GOOS == "windows" { |
||||
return uintptr(sysfd.Uint()), nil |
||||
} |
||||
return uintptr(sysfd.Int()), nil |
||||
} |
||||
} |
||||
} |
||||
return 0, errors.New("invalid type") |
||||
} |
||||
@ -0,0 +1,285 @@ |
||||
// 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.
|
||||
|
||||
// Package socket provides a portable interface for socket system
|
||||
// calls.
|
||||
package socket // import "golang.org/x/net/internal/socket"
|
||||
|
||||
import ( |
||||
"errors" |
||||
"net" |
||||
"unsafe" |
||||
) |
||||
|
||||
// An Option represents a sticky socket option.
|
||||
type Option struct { |
||||
Level int // level
|
||||
Name int // name; must be equal or greater than 1
|
||||
Len int // length of value in bytes; must be equal or greater than 1
|
||||
} |
||||
|
||||
// Get reads a value for the option from the kernel.
|
||||
// It returns the number of bytes written into b.
|
||||
func (o *Option) Get(c *Conn, b []byte) (int, error) { |
||||
if o.Name < 1 || o.Len < 1 { |
||||
return 0, errors.New("invalid option") |
||||
} |
||||
if len(b) < o.Len { |
||||
return 0, errors.New("short buffer") |
||||
} |
||||
return o.get(c, b) |
||||
} |
||||
|
||||
// GetInt returns an integer value for the option.
|
||||
//
|
||||
// The Len field of Option must be either 1 or 4.
|
||||
func (o *Option) GetInt(c *Conn) (int, error) { |
||||
if o.Len != 1 && o.Len != 4 { |
||||
return 0, errors.New("invalid option") |
||||
} |
||||
var b []byte |
||||
var bb [4]byte |
||||
if o.Len == 1 { |
||||
b = bb[:1] |
||||
} else { |
||||
b = bb[:4] |
||||
} |
||||
n, err := o.get(c, b) |
||||
if err != nil { |
||||
return 0, err |
||||
} |
||||
if n != o.Len { |
||||
return 0, errors.New("invalid option length") |
||||
} |
||||
if o.Len == 1 { |
||||
return int(b[0]), nil |
||||
} |
||||
return int(NativeEndian.Uint32(b[:4])), nil |
||||
} |
||||
|
||||
// Set writes the option and value to the kernel.
|
||||
func (o *Option) Set(c *Conn, b []byte) error { |
||||
if o.Name < 1 || o.Len < 1 { |
||||
return errors.New("invalid option") |
||||
} |
||||
if len(b) < o.Len { |
||||
return errors.New("short buffer") |
||||
} |
||||
return o.set(c, b) |
||||
} |
||||
|
||||
// SetInt writes the option and value to the kernel.
|
||||
//
|
||||
// The Len field of Option must be either 1 or 4.
|
||||
func (o *Option) SetInt(c *Conn, v int) error { |
||||
if o.Len != 1 && o.Len != 4 { |
||||
return errors.New("invalid option") |
||||
} |
||||
var b []byte |
||||
if o.Len == 1 { |
||||
b = []byte{byte(v)} |
||||
} else { |
||||
var bb [4]byte |
||||
NativeEndian.PutUint32(bb[:o.Len], uint32(v)) |
||||
b = bb[:4] |
||||
} |
||||
return o.set(c, b) |
||||
} |
||||
|
||||
func controlHeaderLen() int { |
||||
return roundup(sizeofCmsghdr) |
||||
} |
||||
|
||||
func controlMessageLen(dataLen int) int { |
||||
return roundup(sizeofCmsghdr) + dataLen |
||||
} |
||||
|
||||
// ControlMessageSpace returns the whole length of control message.
|
||||
func ControlMessageSpace(dataLen int) int { |
||||
return roundup(sizeofCmsghdr) + roundup(dataLen) |
||||
} |
||||
|
||||
// A ControlMessage represents the head message in a stream of control
|
||||
// messages.
|
||||
//
|
||||
// A control message comprises of a header, data and a few padding
|
||||
// fields to conform to the interface to the kernel.
|
||||
//
|
||||
// See RFC 3542 for further information.
|
||||
type ControlMessage []byte |
||||
|
||||
// Data returns the data field of the control message at the head on
|
||||
// w.
|
||||
func (m ControlMessage) Data(dataLen int) []byte { |
||||
l := controlHeaderLen() |
||||
if len(m) < l || len(m) < l+dataLen { |
||||
return nil |
||||
} |
||||
return m[l : l+dataLen] |
||||
} |
||||
|
||||
// Next returns the control message at the next on w.
|
||||
//
|
||||
// Next works only for standard control messages.
|
||||
func (m ControlMessage) Next(dataLen int) ControlMessage { |
||||
l := ControlMessageSpace(dataLen) |
||||
if len(m) < l { |
||||
return nil |
||||
} |
||||
return m[l:] |
||||
} |
||||
|
||||
// MarshalHeader marshals the header fields of the control message at
|
||||
// the head on w.
|
||||
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error { |
||||
if len(m) < controlHeaderLen() { |
||||
return errors.New("short message") |
||||
} |
||||
h := (*cmsghdr)(unsafe.Pointer(&m[0])) |
||||
h.set(controlMessageLen(dataLen), lvl, typ) |
||||
return nil |
||||
} |
||||
|
||||
// ParseHeader parses and returns the header fields of the control
|
||||
// message at the head on w.
|
||||
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) { |
||||
l := controlHeaderLen() |
||||
if len(m) < l { |
||||
return 0, 0, 0, errors.New("short message") |
||||
} |
||||
h := (*cmsghdr)(unsafe.Pointer(&m[0])) |
||||
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil |
||||
} |
||||
|
||||
// Marshal marshals the control message at the head on w, and returns
|
||||
// the next control message.
|
||||
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) { |
||||
l := len(data) |
||||
if len(m) < ControlMessageSpace(l) { |
||||
return nil, errors.New("short message") |
||||
} |
||||
h := (*cmsghdr)(unsafe.Pointer(&m[0])) |
||||
h.set(controlMessageLen(l), lvl, typ) |
||||
if l > 0 { |
||||
copy(m.Data(l), data) |
||||
} |
||||
return m.Next(l), nil |
||||
} |
||||
|
||||
// Parse parses w as a single or multiple control messages.
|
||||
//
|
||||
// Parse works for both standard and compatible messages.
|
||||
func (m ControlMessage) Parse() ([]ControlMessage, error) { |
||||
var ms []ControlMessage |
||||
for len(m) >= controlHeaderLen() { |
||||
h := (*cmsghdr)(unsafe.Pointer(&m[0])) |
||||
l := h.len() |
||||
if l <= 0 { |
||||
return nil, errors.New("invalid header length") |
||||
} |
||||
if uint64(l) < uint64(controlHeaderLen()) { |
||||
return nil, errors.New("invalid message length") |
||||
} |
||||
if uint64(l) > uint64(len(m)) { |
||||
return nil, errors.New("short buffer") |
||||
} |
||||
// On message reception:
|
||||
//
|
||||
// |<- ControlMessageSpace --------------->|
|
||||
// |<- controlMessageLen ---------->| |
|
||||
// |<- controlHeaderLen ->| | |
|
||||
// +---------------+------+---------+------+
|
||||
// | Header | PadH | Data | PadD |
|
||||
// +---------------+------+---------+------+
|
||||
//
|
||||
// On compatible message reception:
|
||||
//
|
||||
// | ... |<- controlMessageLen ----------->|
|
||||
// | ... |<- controlHeaderLen ->| |
|
||||
// +-----+---------------+------+----------+
|
||||
// | ... | Header | PadH | Data |
|
||||
// +-----+---------------+------+----------+
|
||||
ms = append(ms, ControlMessage(m[:l])) |
||||
ll := l - controlHeaderLen() |
||||
if len(m) >= ControlMessageSpace(ll) { |
||||
m = m[ControlMessageSpace(ll):] |
||||
} else { |
||||
m = m[controlMessageLen(ll):] |
||||
} |
||||
} |
||||
return ms, nil |
||||
} |
||||
|
||||
// NewControlMessage returns a new stream of control messages.
|
||||
func NewControlMessage(dataLen []int) ControlMessage { |
||||
var l int |
||||
for i := range dataLen { |
||||
l += ControlMessageSpace(dataLen[i]) |
||||
} |
||||
return make([]byte, l) |
||||
} |
||||
|
||||
// A Message represents an IO message.
|
||||
type Message struct { |
||||
// When writing, the Buffers field must contain at least one
|
||||
// byte to write.
|
||||
// When reading, the Buffers field will always contain a byte
|
||||
// to read.
|
||||
Buffers [][]byte |
||||
|
||||
// OOB contains protocol-specific control or miscellaneous
|
||||
// ancillary data known as out-of-band data.
|
||||
OOB []byte |
||||
|
||||
// Addr specifies a destination address when writing.
|
||||
// It can be nil when the underlying protocol of the raw
|
||||
// connection uses connection-oriented communication.
|
||||
// After a successful read, it may contain the source address
|
||||
// on the received packet.
|
||||
Addr net.Addr |
||||
|
||||
N int // # of bytes read or written from/to Buffers
|
||||
NN int // # of bytes read or written from/to OOB
|
||||
Flags int // protocol-specific information on the received message
|
||||
} |
||||
|
||||
// RecvMsg wraps recvmsg system call.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_PEEK.
|
||||
func (c *Conn) RecvMsg(m *Message, flags int) error { |
||||
return c.recvMsg(m, flags) |
||||
} |
||||
|
||||
// SendMsg wraps sendmsg system call.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_DONTROUTE.
|
||||
func (c *Conn) SendMsg(m *Message, flags int) error { |
||||
return c.sendMsg(m, flags) |
||||
} |
||||
|
||||
// RecvMsgs wraps recvmmsg system call.
|
||||
//
|
||||
// It returns the number of processed messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_PEEK.
|
||||
//
|
||||
// Only Linux supports this.
|
||||
func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) { |
||||
return c.recvMsgs(ms, flags) |
||||
} |
||||
|
||||
// SendMsgs wraps sendmmsg system call.
|
||||
//
|
||||
// It returns the number of processed messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_DONTROUTE.
|
||||
//
|
||||
// Only Linux supports this.
|
||||
func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) { |
||||
return c.sendMsgs(ms, flags) |
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"unsafe" |
||||
) |
||||
|
||||
var ( |
||||
// NativeEndian is the machine native endian implementation of
|
||||
// ByteOrder.
|
||||
NativeEndian binary.ByteOrder |
||||
|
||||
kernelAlign int |
||||
) |
||||
|
||||
func init() { |
||||
i := uint32(1) |
||||
b := (*[4]byte)(unsafe.Pointer(&i)) |
||||
if b[0] == 1 { |
||||
NativeEndian = binary.LittleEndian |
||||
} else { |
||||
NativeEndian = binary.BigEndian |
||||
} |
||||
kernelAlign = probeProtocolStack() |
||||
} |
||||
|
||||
func roundup(l int) int { |
||||
return (l + kernelAlign - 1) & ^(kernelAlign - 1) |
||||
} |
||||
@ -0,0 +1,17 @@ |
||||
// 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 openbsd
|
||||
|
||||
package socket |
||||
|
||||
import "errors" |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
// 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 freebsd netbsd openbsd
|
||||
|
||||
package socket |
||||
|
||||
import "unsafe" |
||||
|
||||
func probeProtocolStack() int { |
||||
var p uintptr |
||||
return int(unsafe.Sizeof(p)) |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
func probeProtocolStack() int { return 4 } |
||||
@ -0,0 +1,7 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
func probeProtocolStack() int { return 4 } |
||||
@ -0,0 +1,27 @@ |
||||
// 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 linux,!s390x,!386
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func probeProtocolStack() int { |
||||
var p uintptr |
||||
return int(unsafe.Sizeof(p)) |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall6(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func probeProtocolStack() int { return 4 } |
||||
|
||||
const ( |
||||
sysSETSOCKOPT = 0xe |
||||
sysGETSOCKOPT = 0xf |
||||
sysSENDMSG = 0x10 |
||||
sysRECVMSG = 0x11 |
||||
sysRECVMMSG = 0x13 |
||||
sysSENDMMSG = 0x14 |
||||
) |
||||
|
||||
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) |
||||
func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
l := uint32(len(b)) |
||||
_, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) |
||||
return int(l), errnoErr(errno) |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
_, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) |
||||
return errnoErr(errno) |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
// Copyright 2014 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. |
||||
|
||||
#include "textflag.h" |
||||
|
||||
TEXT ·socketcall(SB),NOSPLIT,$0-36 |
||||
JMP syscall·socketcall(SB) |
||||
|
||||
TEXT ·rawsocketcall(SB),NOSPLIT,$0-36 |
||||
JMP syscall·rawsocketcall(SB) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x12b |
||||
sysSENDMMSG = 0x133 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x16d |
||||
sysSENDMMSG = 0x176 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0xf3 |
||||
sysSENDMMSG = 0x10d |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x10ef |
||||
sysSENDMMSG = 0x10f7 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x14ae |
||||
sysSENDMMSG = 0x14b6 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x14ae |
||||
sysSENDMMSG = 0x14b6 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x10ef |
||||
sysSENDMMSG = 0x10f7 |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x157 |
||||
sysSENDMMSG = 0x15d |
||||
) |
||||
@ -0,0 +1,10 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x157 |
||||
sysSENDMMSG = 0x15d |
||||
) |
||||
@ -0,0 +1,55 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func probeProtocolStack() int { return 8 } |
||||
|
||||
const ( |
||||
sysSETSOCKOPT = 0xe |
||||
sysGETSOCKOPT = 0xf |
||||
sysSENDMSG = 0x10 |
||||
sysRECVMSG = 0x11 |
||||
sysRECVMMSG = 0x13 |
||||
sysSENDMMSG = 0x14 |
||||
) |
||||
|
||||
func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) |
||||
func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
l := uint32(len(b)) |
||||
_, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) |
||||
return int(l), errnoErr(errno) |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
_, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) |
||||
return errnoErr(errno) |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, errno := socketcall(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
// 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. |
||||
|
||||
#include "textflag.h" |
||||
|
||||
TEXT ·socketcall(SB),NOSPLIT,$0-72 |
||||
JMP syscall·socketcall(SB) |
||||
|
||||
TEXT ·rawsocketcall(SB),NOSPLIT,$0-72 |
||||
JMP syscall·rawsocketcall(SB) |
||||
@ -0,0 +1,25 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
const ( |
||||
sysRECVMMSG = 0x1db |
||||
sysSENDMMSG = 0x1dc |
||||
) |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall6(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
@ -0,0 +1,168 @@ |
||||
// 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 go1.9
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"errors" |
||||
"net" |
||||
"runtime" |
||||
"strconv" |
||||
"sync" |
||||
"time" |
||||
) |
||||
|
||||
func marshalInetAddr(a net.Addr) []byte { |
||||
switch a := a.(type) { |
||||
case *net.TCPAddr: |
||||
return marshalSockaddr(a.IP, a.Port, a.Zone) |
||||
case *net.UDPAddr: |
||||
return marshalSockaddr(a.IP, a.Port, a.Zone) |
||||
case *net.IPAddr: |
||||
return marshalSockaddr(a.IP, 0, a.Zone) |
||||
default: |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
func marshalSockaddr(ip net.IP, port int, zone string) []byte { |
||||
if ip4 := ip.To4(); ip4 != nil { |
||||
b := make([]byte, sizeofSockaddrInet) |
||||
switch runtime.GOOS { |
||||
case "linux", "solaris", "windows": |
||||
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET)) |
||||
default: |
||||
b[0] = sizeofSockaddrInet |
||||
b[1] = sysAF_INET |
||||
} |
||||
binary.BigEndian.PutUint16(b[2:4], uint16(port)) |
||||
copy(b[4:8], ip4) |
||||
return b |
||||
} |
||||
if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil { |
||||
b := make([]byte, sizeofSockaddrInet6) |
||||
switch runtime.GOOS { |
||||
case "linux", "solaris", "windows": |
||||
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6)) |
||||
default: |
||||
b[0] = sizeofSockaddrInet6 |
||||
b[1] = sysAF_INET6 |
||||
} |
||||
binary.BigEndian.PutUint16(b[2:4], uint16(port)) |
||||
copy(b[8:24], ip6) |
||||
if zone != "" { |
||||
NativeEndian.PutUint32(b[24:28], uint32(zoneCache.index(zone))) |
||||
} |
||||
return b |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func parseInetAddr(b []byte, network string) (net.Addr, error) { |
||||
if len(b) < 2 { |
||||
return nil, errors.New("invalid address") |
||||
} |
||||
var af int |
||||
switch runtime.GOOS { |
||||
case "linux", "solaris", "windows": |
||||
af = int(NativeEndian.Uint16(b[:2])) |
||||
default: |
||||
af = int(b[1]) |
||||
} |
||||
var ip net.IP |
||||
var zone string |
||||
if af == sysAF_INET { |
||||
if len(b) < sizeofSockaddrInet { |
||||
return nil, errors.New("short address") |
||||
} |
||||
ip = make(net.IP, net.IPv4len) |
||||
copy(ip, b[4:8]) |
||||
} |
||||
if af == sysAF_INET6 { |
||||
if len(b) < sizeofSockaddrInet6 { |
||||
return nil, errors.New("short address") |
||||
} |
||||
ip = make(net.IP, net.IPv6len) |
||||
copy(ip, b[8:24]) |
||||
if id := int(NativeEndian.Uint32(b[24:28])); id > 0 { |
||||
zone = zoneCache.name(id) |
||||
} |
||||
} |
||||
switch network { |
||||
case "tcp", "tcp4", "tcp6": |
||||
return &net.TCPAddr{IP: ip, Port: int(binary.BigEndian.Uint16(b[2:4])), Zone: zone}, nil |
||||
case "udp", "udp4", "udp6": |
||||
return &net.UDPAddr{IP: ip, Port: int(binary.BigEndian.Uint16(b[2:4])), Zone: zone}, nil |
||||
default: |
||||
return &net.IPAddr{IP: ip, Zone: zone}, nil |
||||
} |
||||
} |
||||
|
||||
// An ipv6ZoneCache represents a cache holding partial network
|
||||
// interface information. It is used for reducing the cost of IPv6
|
||||
// addressing scope zone resolution.
|
||||
//
|
||||
// Multiple names sharing the index are managed by first-come
|
||||
// first-served basis for consistency.
|
||||
type ipv6ZoneCache struct { |
||||
sync.RWMutex // guard the following
|
||||
lastFetched time.Time // last time routing information was fetched
|
||||
toIndex map[string]int // interface name to its index
|
||||
toName map[int]string // interface index to its name
|
||||
} |
||||
|
||||
var zoneCache = ipv6ZoneCache{ |
||||
toIndex: make(map[string]int), |
||||
toName: make(map[int]string), |
||||
} |
||||
|
||||
func (zc *ipv6ZoneCache) update(ift []net.Interface) { |
||||
zc.Lock() |
||||
defer zc.Unlock() |
||||
now := time.Now() |
||||
if zc.lastFetched.After(now.Add(-60 * time.Second)) { |
||||
return |
||||
} |
||||
zc.lastFetched = now |
||||
if len(ift) == 0 { |
||||
var err error |
||||
if ift, err = net.Interfaces(); err != nil { |
||||
return |
||||
} |
||||
} |
||||
zc.toIndex = make(map[string]int, len(ift)) |
||||
zc.toName = make(map[int]string, len(ift)) |
||||
for _, ifi := range ift { |
||||
zc.toIndex[ifi.Name] = ifi.Index |
||||
if _, ok := zc.toName[ifi.Index]; !ok { |
||||
zc.toName[ifi.Index] = ifi.Name |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (zc *ipv6ZoneCache) name(zone int) string { |
||||
zoneCache.update(nil) |
||||
zoneCache.RLock() |
||||
defer zoneCache.RUnlock() |
||||
name, ok := zoneCache.toName[zone] |
||||
if !ok { |
||||
name = strconv.Itoa(zone) |
||||
} |
||||
return name |
||||
} |
||||
|
||||
func (zc *ipv6ZoneCache) index(zone string) int { |
||||
zoneCache.update(nil) |
||||
zoneCache.RLock() |
||||
defer zoneCache.RUnlock() |
||||
index, ok := zoneCache.toIndex[zone] |
||||
if !ok { |
||||
index, _ = strconv.Atoi(zone) |
||||
} |
||||
return index |
||||
} |
||||
@ -0,0 +1,71 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"errors" |
||||
"runtime" |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func probeProtocolStack() int { |
||||
switch runtime.GOARCH { |
||||
case "amd64": |
||||
return 4 |
||||
default: |
||||
var p uintptr |
||||
return int(unsafe.Sizeof(p)) |
||||
} |
||||
} |
||||
|
||||
//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
|
||||
//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
|
||||
//go:cgo_import_dynamic libc___xnet_recvmsg __xnet_recvmsg "libsocket.so"
|
||||
//go:cgo_import_dynamic libc___xnet_sendmsg __xnet_sendmsg "libsocket.so"
|
||||
|
||||
//go:linkname procGetsockopt libc___xnet_getsockopt
|
||||
//go:linkname procSetsockopt libc_setsockopt
|
||||
//go:linkname procRecvmsg libc___xnet_recvmsg
|
||||
//go:linkname procSendmsg libc___xnet_sendmsg
|
||||
|
||||
var ( |
||||
procGetsockopt uintptr |
||||
procSetsockopt uintptr |
||||
procRecvmsg uintptr |
||||
procSendmsg uintptr |
||||
) |
||||
|
||||
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno) |
||||
func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno) |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
l := uint32(len(b)) |
||||
_, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procGetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) |
||||
return int(l), errnoErr(errno) |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
_, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) |
||||
return errnoErr(errno) |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procRecvmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSendmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
// Copyright 2016 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. |
||||
|
||||
#include "textflag.h" |
||||
|
||||
TEXT ·sysvicall6(SB),NOSPLIT,$0-88 |
||||
JMP syscall·sysvicall6(SB) |
||||
|
||||
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88 |
||||
JMP syscall·rawSysvicall6(SB) |
||||
@ -0,0 +1,64 @@ |
||||
// 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,!windows
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"errors" |
||||
"net" |
||||
"runtime" |
||||
"unsafe" |
||||
) |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
func probeProtocolStack() int { |
||||
switch runtime.GOARCH { |
||||
case "amd64p32", "mips64p32": |
||||
return 4 |
||||
default: |
||||
var p uintptr |
||||
return int(unsafe.Sizeof(p)) |
||||
} |
||||
} |
||||
|
||||
func marshalInetAddr(ip net.IP, port int, zone string) []byte { |
||||
return nil |
||||
} |
||||
|
||||
func parseInetAddr(b []byte, network string) (net.Addr, error) { |
||||
return nil, errors.New("not implemented") |
||||
} |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
return errors.New("not implemented") |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
// 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,!s390x,!386 netbsd openbsd
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
l := uint32(len(b)) |
||||
_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) |
||||
return int(l), errnoErr(errno) |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
_, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) |
||||
return errnoErr(errno) |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) |
||||
return int(n), errnoErr(errno) |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
// 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.
|
||||
|
||||
package socket |
||||
|
||||
import ( |
||||
"errors" |
||||
"syscall" |
||||
"unsafe" |
||||
) |
||||
|
||||
func probeProtocolStack() int { |
||||
var p uintptr |
||||
return int(unsafe.Sizeof(p)) |
||||
} |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x17 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
|
||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) { |
||||
l := uint32(len(b)) |
||||
err := syscall.Getsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(unsafe.Pointer(&b[0])), (*int32)(unsafe.Pointer(&l))) |
||||
return int(l), err |
||||
} |
||||
|
||||
func setsockopt(s uintptr, level, name int, b []byte) error { |
||||
return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(unsafe.Pointer(&b[0])), int32(len(b))) |
||||
} |
||||
|
||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
|
||||
func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) { |
||||
return 0, errors.New("not implemented") |
||||
} |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_darwin.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1e |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,61 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_darwin.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1e |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Pad_cgo_1 [4]byte |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_darwin.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1e |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,61 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_dragonfly.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1c |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Pad_cgo_1 [4]byte |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_freebsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1c |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,61 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_freebsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1c |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Pad_cgo_1 [4]byte |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_freebsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1c |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,63 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofMmsghdr = 0x20 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,63 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofMmsghdr = 0x20 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,63 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofMmsghdr = 0x20 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,63 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofMmsghdr = 0x20 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,66 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_linux.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0xa |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint64 |
||||
Control *byte |
||||
Controllen uint64 |
||||
Flags int32 |
||||
Pad_cgo_1 [4]byte |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint64 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
X__pad [8]uint8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x38 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0x10 |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,65 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_netbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofMmsghdr = 0x20 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,68 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_netbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Pad_cgo_1 [4]byte |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type mmsghdr struct { |
||||
Hdr msghdr |
||||
Len uint32 |
||||
Pad_cgo_0 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofMmsghdr = 0x40 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_netbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_openbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,61 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_openbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Pad_cgo_1 [4]byte |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,59 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_openbsd.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x18 |
||||
|
||||
sysSOCK_RAW = 0x3 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *byte |
||||
Len uint32 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Iov *iovec |
||||
Iovlen uint32 |
||||
Control *byte |
||||
Controllen uint32 |
||||
Flags int32 |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Len uint8 |
||||
Family uint8 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x8 |
||||
sizeofMsghdr = 0x1c |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x1c |
||||
) |
||||
@ -0,0 +1,60 @@ |
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs defs_solaris.go
|
||||
|
||||
package socket |
||||
|
||||
const ( |
||||
sysAF_UNSPEC = 0x0 |
||||
sysAF_INET = 0x2 |
||||
sysAF_INET6 = 0x1a |
||||
|
||||
sysSOCK_RAW = 0x4 |
||||
) |
||||
|
||||
type iovec struct { |
||||
Base *int8 |
||||
Len uint64 |
||||
} |
||||
|
||||
type msghdr struct { |
||||
Name *byte |
||||
Namelen uint32 |
||||
Pad_cgo_0 [4]byte |
||||
Iov *iovec |
||||
Iovlen int32 |
||||
Pad_cgo_1 [4]byte |
||||
Accrights *int8 |
||||
Accrightslen int32 |
||||
Pad_cgo_2 [4]byte |
||||
} |
||||
|
||||
type cmsghdr struct { |
||||
Len uint32 |
||||
Level int32 |
||||
Type int32 |
||||
} |
||||
|
||||
type sockaddrInet struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Addr [4]byte /* in_addr */ |
||||
Zero [8]int8 |
||||
} |
||||
|
||||
type sockaddrInet6 struct { |
||||
Family uint16 |
||||
Port uint16 |
||||
Flowinfo uint32 |
||||
Addr [16]byte /* in6_addr */ |
||||
Scope_id uint32 |
||||
X__sin6_src_id uint32 |
||||
} |
||||
|
||||
const ( |
||||
sizeofIovec = 0x10 |
||||
sizeofMsghdr = 0x30 |
||||
sizeofCmsghdr = 0xc |
||||
|
||||
sizeofSockaddrInet = 0x10 |
||||
sizeofSockaddrInet6 = 0x20 |
||||
) |
||||
@ -0,0 +1,191 @@ |
||||
// 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 go1.9
|
||||
|
||||
package ipv4 |
||||
|
||||
import ( |
||||
"net" |
||||
"runtime" |
||||
"syscall" |
||||
|
||||
"golang.org/x/net/internal/socket" |
||||
) |
||||
|
||||
// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
|
||||
// PacketConn are not implemented.
|
||||
|
||||
// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
|
||||
// RawConn are not implemented.
|
||||
|
||||
// A Message represents an IO message.
|
||||
//
|
||||
// type Message struct {
|
||||
// Buffers [][]byte
|
||||
// OOB []byte
|
||||
// Addr net.Addr
|
||||
// N int
|
||||
// NN int
|
||||
// Flags int
|
||||
// }
|
||||
//
|
||||
// The Buffers fields represents a list of contiguous buffers, which
|
||||
// can be used for vectored IO, for example, putting a header and a
|
||||
// payload in each slice.
|
||||
// When writing, the Buffers field must contain at least one byte to
|
||||
// write.
|
||||
// When reading, the Buffers field will always contain a byte to read.
|
||||
//
|
||||
// The OOB field contains protocol-specific control or miscellaneous
|
||||
// ancillary data known as out-of-band data.
|
||||
// It can be nil when not required.
|
||||
//
|
||||
// The Addr field specifies a destination address when writing.
|
||||
// It can be nil when the underlying protocol of the endpoint uses
|
||||
// connection-oriented communication.
|
||||
// After a successful read, it may contain the source address on the
|
||||
// received packet.
|
||||
//
|
||||
// The N field indicates the number of bytes read or written from/to
|
||||
// Buffers.
|
||||
//
|
||||
// The NN field indicates the number of bytes read or written from/to
|
||||
// OOB.
|
||||
//
|
||||
// The Flags field contains protocol-specific information on the
|
||||
// received message.
|
||||
type Message = socket.Message |
||||
|
||||
// ReadBatch reads a batch of messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_PEEK.
|
||||
//
|
||||
// On a successful read it returns the number of messages received, up
|
||||
// to len(ms).
|
||||
//
|
||||
// On Linux, a batch read will be optimized.
|
||||
// On other platforms, this method will read only a single message.
|
||||
//
|
||||
// Unlike the ReadFrom method, it doesn't strip the IPv4 header
|
||||
// followed by option headers from the received IPv4 datagram when the
|
||||
// underlying transport is net.IPConn. Each Buffers field of Message
|
||||
// must be large enough to accommodate an IPv4 header and option
|
||||
// headers.
|
||||
func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { |
||||
if !c.ok() { |
||||
return 0, syscall.EINVAL |
||||
} |
||||
switch runtime.GOOS { |
||||
case "linux": |
||||
n, err := c.RecvMsgs([]socket.Message(ms), flags) |
||||
if err != nil { |
||||
err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
default: |
||||
n := 1 |
||||
err := c.RecvMsg(&ms[0], flags) |
||||
if err != nil { |
||||
n = 0 |
||||
err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
} |
||||
} |
||||
|
||||
// WriteBatch writes a batch of messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_DONTROUTE.
|
||||
//
|
||||
// It returns the number of messages written on a successful write.
|
||||
//
|
||||
// On Linux, a batch write will be optimized.
|
||||
// On other platforms, this method will write only a single message.
|
||||
func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) { |
||||
if !c.ok() { |
||||
return 0, syscall.EINVAL |
||||
} |
||||
switch runtime.GOOS { |
||||
case "linux": |
||||
n, err := c.SendMsgs([]socket.Message(ms), flags) |
||||
if err != nil { |
||||
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
default: |
||||
n := 1 |
||||
err := c.SendMsg(&ms[0], flags) |
||||
if err != nil { |
||||
n = 0 |
||||
err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
} |
||||
} |
||||
|
||||
// ReadBatch reads a batch of messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_PEEK.
|
||||
//
|
||||
// On a successful read it returns the number of messages received, up
|
||||
// to len(ms).
|
||||
//
|
||||
// On Linux, a batch read will be optimized.
|
||||
// On other platforms, this method will read only a single message.
|
||||
func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) { |
||||
if !c.ok() { |
||||
return 0, syscall.EINVAL |
||||
} |
||||
switch runtime.GOOS { |
||||
case "linux": |
||||
n, err := c.RecvMsgs([]socket.Message(ms), flags) |
||||
if err != nil { |
||||
err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
default: |
||||
n := 1 |
||||
err := c.RecvMsg(&ms[0], flags) |
||||
if err != nil { |
||||
n = 0 |
||||
err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
} |
||||
} |
||||
|
||||
// WriteBatch writes a batch of messages.
|
||||
//
|
||||
// The provided flags is a set of platform-dependent flags, such as
|
||||
// syscall.MSG_DONTROUTE.
|
||||
//
|
||||
// It returns the number of messages written on a successful write.
|
||||
//
|
||||
// On Linux, a batch write will be optimized.
|
||||
// On other platforms, this method will write only a single message.
|
||||
func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) { |
||||
if !c.ok() { |
||||
return 0, syscall.EINVAL |
||||
} |
||||
switch runtime.GOOS { |
||||
case "linux": |
||||
n, err := c.SendMsgs([]socket.Message(ms), flags) |
||||
if err != nil { |
||||
err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
default: |
||||
n := 1 |
||||
err := c.SendMsg(&ms[0], flags) |
||||
if err != nil { |
||||
n = 0 |
||||
err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} |
||||
} |
||||
return n, err |
||||
} |
||||
} |
||||
@ -0,0 +1,144 @@ |
||||
// Copyright 2012 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.
|
||||
|
||||
package ipv4 |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net" |
||||
"sync" |
||||
|
||||
"golang.org/x/net/internal/iana" |
||||
"golang.org/x/net/internal/socket" |
||||
) |
||||
|
||||
type rawOpt struct { |
||||
sync.RWMutex |
||||
cflags ControlFlags |
||||
} |
||||
|
||||
func (c *rawOpt) set(f ControlFlags) { c.cflags |= f } |
||||
func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f } |
||||
func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 } |
||||
|
||||
type ControlFlags uint |
||||
|
||||
const ( |
||||
FlagTTL ControlFlags = 1 << iota // pass the TTL on the received packet
|
||||
FlagSrc // pass the source address on the received packet
|
||||
FlagDst // pass the destination address on the received packet
|
||||
FlagInterface // pass the interface index on the received packet
|
||||
) |
||||
|
||||
// A ControlMessage represents per packet basis IP-level socket options.
|
||||
type ControlMessage struct { |
||||
// Receiving socket options: SetControlMessage allows to
|
||||
// receive the options from the protocol stack using ReadFrom
|
||||
// method of PacketConn or RawConn.
|
||||
//
|
||||
// Specifying socket options: ControlMessage for WriteTo
|
||||
// method of PacketConn or RawConn allows to send the options
|
||||
// to the protocol stack.
|
||||
//
|
||||
TTL int // time-to-live, receiving only
|
||||
Src net.IP // source address, specifying only
|
||||
Dst net.IP // destination address, receiving only
|
||||
IfIndex int // interface index, must be 1 <= value when specifying
|
||||
} |
||||
|
||||
func (cm *ControlMessage) String() string { |
||||
if cm == nil { |
||||
return "<nil>" |
||||
} |
||||
return fmt.Sprintf("ttl=%d src=%v dst=%v ifindex=%d", cm.TTL, cm.Src, cm.Dst, cm.IfIndex) |
||||
} |
||||
|
||||
// Marshal returns the binary encoding of cm.
|
||||
func (cm *ControlMessage) Marshal() []byte { |
||||
if cm == nil { |
||||
return nil |
||||
} |
||||
var m socket.ControlMessage |
||||
if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To4() != nil || cm.IfIndex > 0) { |
||||
m = socket.NewControlMessage([]int{ctlOpts[ctlPacketInfo].length}) |
||||
} |
||||
if len(m) > 0 { |
||||
ctlOpts[ctlPacketInfo].marshal(m, cm) |
||||
} |
||||
return m |
||||
} |
||||
|
||||
// Parse parses b as a control message and stores the result in cm.
|
||||
func (cm *ControlMessage) Parse(b []byte) error { |
||||
ms, err := socket.ControlMessage(b).Parse() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
for _, m := range ms { |
||||
lvl, typ, l, err := m.ParseHeader() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
if lvl != iana.ProtocolIP { |
||||
continue |
||||
} |
||||
switch { |
||||
case typ == ctlOpts[ctlTTL].name && l >= ctlOpts[ctlTTL].length: |
||||
ctlOpts[ctlTTL].parse(cm, m.Data(l)) |
||||
case typ == ctlOpts[ctlDst].name && l >= ctlOpts[ctlDst].length: |
||||
ctlOpts[ctlDst].parse(cm, m.Data(l)) |
||||
case typ == ctlOpts[ctlInterface].name && l >= ctlOpts[ctlInterface].length: |
||||
ctlOpts[ctlInterface].parse(cm, m.Data(l)) |
||||
case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length: |
||||
ctlOpts[ctlPacketInfo].parse(cm, m.Data(l)) |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// NewControlMessage returns a new control message.
|
||||
//
|
||||
// The returned message is large enough for options specified by cf.
|
||||
func NewControlMessage(cf ControlFlags) []byte { |
||||
opt := rawOpt{cflags: cf} |
||||
var l int |
||||
if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 { |
||||
l += socket.ControlMessageSpace(ctlOpts[ctlTTL].length) |
||||
} |
||||
if ctlOpts[ctlPacketInfo].name > 0 { |
||||
if opt.isset(FlagSrc | FlagDst | FlagInterface) { |
||||
l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length) |
||||
} |
||||
} else { |
||||
if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 { |
||||
l += socket.ControlMessageSpace(ctlOpts[ctlDst].length) |
||||
} |
||||
if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 { |
||||
l += socket.ControlMessageSpace(ctlOpts[ctlInterface].length) |
||||
} |
||||
} |
||||
var b []byte |
||||
if l > 0 { |
||||
b = make([]byte, l) |
||||
} |
||||
return b |
||||
} |
||||
|
||||
// Ancillary data socket options
|
||||
const ( |
||||
ctlTTL = iota // header field
|
||||
ctlSrc // header field
|
||||
ctlDst // header field
|
||||
ctlInterface // inbound or outbound interface
|
||||
ctlPacketInfo // inbound or outbound packet path
|
||||
ctlMax |
||||
) |
||||
|
||||
// A ctlOpt represents a binding for ancillary data socket option.
|
||||
type ctlOpt struct { |
||||
name int // option name, must be equal or greater than 1
|
||||
length int // option length
|
||||
marshal func([]byte, *ControlMessage) []byte |
||||
parse func(*ControlMessage, []byte) |
||||
} |
||||
@ -0,0 +1,40 @@ |
||||
// Copyright 2012 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 ipv4 |
||||
|
||||
import ( |
||||
"net" |
||||
"syscall" |
||||
"unsafe" |
||||
|
||||
"golang.org/x/net/internal/iana" |
||||
"golang.org/x/net/internal/socket" |
||||
) |
||||
|
||||
func marshalDst(b []byte, cm *ControlMessage) []byte { |
||||
m := socket.ControlMessage(b) |
||||
m.MarshalHeader(iana.ProtocolIP, sysIP_RECVDSTADDR, net.IPv4len) |
||||
return m.Next(net.IPv4len) |
||||
} |
||||
|
||||
func parseDst(cm *ControlMessage, b []byte) { |
||||
if len(cm.Dst) < net.IPv4len { |
||||
cm.Dst = make(net.IP, net.IPv4len) |
||||
} |
||||
copy(cm.Dst, b[:net.IPv4len]) |
||||
} |
||||
|
||||
func marshalInterface(b []byte, cm *ControlMessage) []byte { |
||||
m := socket.ControlMessage(b) |
||||
m.MarshalHeader(iana.ProtocolIP, sysIP_RECVIF, syscall.SizeofSockaddrDatalink) |
||||
return m.Next(syscall.SizeofSockaddrDatalink) |
||||
} |
||||
|
||||
func parseInterface(cm *ControlMessage, b []byte) { |
||||
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0])) |
||||
cm.IfIndex = int(sadl.Index) |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
// Copyright 2014 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 linux solaris
|
||||
|
||||
package ipv4 |
||||
|
||||
import ( |
||||
"net" |
||||
"unsafe" |
||||
|
||||
"golang.org/x/net/internal/iana" |
||||
"golang.org/x/net/internal/socket" |
||||
) |
||||
|
||||
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte { |
||||
m := socket.ControlMessage(b) |
||||
m.MarshalHeader(iana.ProtocolIP, sysIP_PKTINFO, sizeofInetPktinfo) |
||||
if cm != nil { |
||||
pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0])) |
||||
if ip := cm.Src.To4(); ip != nil { |
||||
copy(pi.Spec_dst[:], ip) |
||||
} |
||||
if cm.IfIndex > 0 { |
||||
pi.setIfindex(cm.IfIndex) |
||||
} |
||||
} |
||||
return m.Next(sizeofInetPktinfo) |
||||
} |
||||
|
||||
func parsePacketInfo(cm *ControlMessage, b []byte) { |
||||
pi := (*inetPktinfo)(unsafe.Pointer(&b[0])) |
||||
cm.IfIndex = int(pi.Ifindex) |
||||
if len(cm.Dst) < net.IPv4len { |
||||
cm.Dst = make(net.IP, net.IPv4len) |
||||
} |
||||
copy(cm.Dst, pi.Addr[:]) |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue