golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/internal/socket/socket.go (about)

     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.
     7  package socket // import "golang.org/x/net/internal/socket"
     8  
     9  import (
    10  	"errors"
    11  	"net"
    12  	"runtime"
    13  	"unsafe"
    14  )
    15  
    16  var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
    17  
    18  // An Option represents a sticky socket option.
    19  type 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.
    27  func (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.
    40  func (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.
    65  func (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.
    78  func (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.
    94  func 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.
   105  type ControlMessage []byte
   106  
   107  // Data returns the data field of the control message at the head on
   108  // m.
   109  func (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.
   120  func (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.
   130  func (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.
   141  func (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.
   152  func (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.
   168  func (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.
   210  func 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.
   219  type 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.
   246  func (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.
   254  func (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.
   266  func (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.
   278  func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
   279  	return c.sendMsgs(ms, flags)
   280  }