1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package socket provides a portable interface for socket system 6// calls. 7package socket // import "golang.org/x/net/internal/socket" 8 9import ( 10 "errors" 11 "net" 12 "runtime" 13 "unsafe" 14) 15 16var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH) 17 18// An Option represents a sticky socket option. 19type Option struct { 20 Level int // level 21 Name int // name; must be equal or greater than 1 22 Len int // length of value in bytes; must be equal or greater than 1 23} 24 25// Get reads a value for the option from the kernel. 26// It returns the number of bytes written into b. 27func (o *Option) Get(c *Conn, b []byte) (int, error) { 28 if o.Name < 1 || o.Len < 1 { 29 return 0, errors.New("invalid option") 30 } 31 if len(b) < o.Len { 32 return 0, errors.New("short buffer") 33 } 34 return o.get(c, b) 35} 36 37// GetInt returns an integer value for the option. 38// 39// The Len field of Option must be either 1 or 4. 40func (o *Option) GetInt(c *Conn) (int, error) { 41 if o.Len != 1 && o.Len != 4 { 42 return 0, errors.New("invalid option") 43 } 44 var b []byte 45 var bb [4]byte 46 if o.Len == 1 { 47 b = bb[:1] 48 } else { 49 b = bb[:4] 50 } 51 n, err := o.get(c, b) 52 if err != nil { 53 return 0, err 54 } 55 if n != o.Len { 56 return 0, errors.New("invalid option length") 57 } 58 if o.Len == 1 { 59 return int(b[0]), nil 60 } 61 return int(NativeEndian.Uint32(b[:4])), nil 62} 63 64// Set writes the option and value to the kernel. 65func (o *Option) Set(c *Conn, b []byte) error { 66 if o.Name < 1 || o.Len < 1 { 67 return errors.New("invalid option") 68 } 69 if len(b) < o.Len { 70 return errors.New("short buffer") 71 } 72 return o.set(c, b) 73} 74 75// SetInt writes the option and value to the kernel. 76// 77// The Len field of Option must be either 1 or 4. 78func (o *Option) SetInt(c *Conn, v int) error { 79 if o.Len != 1 && o.Len != 4 { 80 return errors.New("invalid option") 81 } 82 var b []byte 83 if o.Len == 1 { 84 b = []byte{byte(v)} 85 } else { 86 var bb [4]byte 87 NativeEndian.PutUint32(bb[:o.Len], uint32(v)) 88 b = bb[:4] 89 } 90 return o.set(c, b) 91} 92 93// ControlMessageSpace returns the whole length of control message. 94func ControlMessageSpace(dataLen int) int { 95 return controlMessageSpace(dataLen) 96} 97 98// A ControlMessage represents the head message in a stream of control 99// messages. 100// 101// A control message comprises of a header, data and a few padding 102// fields to conform to the interface to the kernel. 103// 104// See RFC 3542 for further information. 105type ControlMessage []byte 106 107// Data returns the data field of the control message at the head on 108// m. 109func (m ControlMessage) Data(dataLen int) []byte { 110 l := controlHeaderLen() 111 if len(m) < l || len(m) < l+dataLen { 112 return nil 113 } 114 return m[l : l+dataLen] 115} 116 117// Next returns the control message at the next on m. 118// 119// Next works only for standard control messages. 120func (m ControlMessage) Next(dataLen int) ControlMessage { 121 l := ControlMessageSpace(dataLen) 122 if len(m) < l { 123 return nil 124 } 125 return m[l:] 126} 127 128// MarshalHeader marshals the header fields of the control message at 129// the head on m. 130func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error { 131 if len(m) < controlHeaderLen() { 132 return errors.New("short message") 133 } 134 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 135 h.set(controlMessageLen(dataLen), lvl, typ) 136 return nil 137} 138 139// ParseHeader parses and returns the header fields of the control 140// message at the head on m. 141func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) { 142 l := controlHeaderLen() 143 if len(m) < l { 144 return 0, 0, 0, errors.New("short message") 145 } 146 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 147 return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil 148} 149 150// Marshal marshals the control message at the head on m, and returns 151// the next control message. 152func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) { 153 l := len(data) 154 if len(m) < ControlMessageSpace(l) { 155 return nil, errors.New("short message") 156 } 157 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 158 h.set(controlMessageLen(l), lvl, typ) 159 if l > 0 { 160 copy(m.Data(l), data) 161 } 162 return m.Next(l), nil 163} 164 165// Parse parses m as a single or multiple control messages. 166// 167// Parse works for both standard and compatible messages. 168func (m ControlMessage) Parse() ([]ControlMessage, error) { 169 var ms []ControlMessage 170 for len(m) >= controlHeaderLen() { 171 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 172 l := h.len() 173 if l <= 0 { 174 return nil, errors.New("invalid header length") 175 } 176 if uint64(l) < uint64(controlHeaderLen()) { 177 return nil, errors.New("invalid message length") 178 } 179 if uint64(l) > uint64(len(m)) { 180 return nil, errors.New("short buffer") 181 } 182 // On message reception: 183 // 184 // |<- ControlMessageSpace --------------->| 185 // |<- controlMessageLen ---------->| | 186 // |<- controlHeaderLen ->| | | 187 // +---------------+------+---------+------+ 188 // | Header | PadH | Data | PadD | 189 // +---------------+------+---------+------+ 190 // 191 // On compatible message reception: 192 // 193 // | ... |<- controlMessageLen ----------->| 194 // | ... |<- controlHeaderLen ->| | 195 // +-----+---------------+------+----------+ 196 // | ... | Header | PadH | Data | 197 // +-----+---------------+------+----------+ 198 ms = append(ms, ControlMessage(m[:l])) 199 ll := l - controlHeaderLen() 200 if len(m) >= ControlMessageSpace(ll) { 201 m = m[ControlMessageSpace(ll):] 202 } else { 203 m = m[controlMessageLen(ll):] 204 } 205 } 206 return ms, nil 207} 208 209// NewControlMessage returns a new stream of control messages. 210func NewControlMessage(dataLen []int) ControlMessage { 211 var l int 212 for i := range dataLen { 213 l += ControlMessageSpace(dataLen[i]) 214 } 215 return make([]byte, l) 216} 217 218// A Message represents an IO message. 219type Message struct { 220 // When writing, the Buffers field must contain at least one 221 // byte to write. 222 // When reading, the Buffers field will always contain a byte 223 // to read. 224 Buffers [][]byte 225 226 // OOB contains protocol-specific control or miscellaneous 227 // ancillary data known as out-of-band data. 228 OOB []byte 229 230 // Addr specifies a destination address when writing. 231 // It can be nil when the underlying protocol of the raw 232 // connection uses connection-oriented communication. 233 // After a successful read, it may contain the source address 234 // on the received packet. 235 Addr net.Addr 236 237 N int // # of bytes read or written from/to Buffers 238 NN int // # of bytes read or written from/to OOB 239 Flags int // protocol-specific information on the received message 240} 241 242// RecvMsg wraps recvmsg system call. 243// 244// The provided flags is a set of platform-dependent flags, such as 245// syscall.MSG_PEEK. 246func (c *Conn) RecvMsg(m *Message, flags int) error { 247 return c.recvMsg(m, flags) 248} 249 250// SendMsg wraps sendmsg system call. 251// 252// The provided flags is a set of platform-dependent flags, such as 253// syscall.MSG_DONTROUTE. 254func (c *Conn) SendMsg(m *Message, flags int) error { 255 return c.sendMsg(m, flags) 256} 257 258// RecvMsgs wraps recvmmsg system call. 259// 260// It returns the number of processed messages. 261// 262// The provided flags is a set of platform-dependent flags, such as 263// syscall.MSG_PEEK. 264// 265// Only Linux supports this. 266func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) { 267 return c.recvMsgs(ms, flags) 268} 269 270// SendMsgs wraps sendmmsg system call. 271// 272// It returns the number of processed messages. 273// 274// The provided flags is a set of platform-dependent flags, such as 275// syscall.MSG_DONTROUTE. 276// 277// Only Linux supports this. 278func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) { 279 return c.sendMsgs(ms, flags) 280} 281