github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/ipv4/packet.go (about)

     1  // Copyright 2012 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 ipv4
     6  
     7  import (
     8  	"net"
     9  	"syscall"
    10  )
    11  
    12  // A packetHandler represents the IPv4 datagram handler.
    13  type packetHandler struct {
    14  	c *net.IPConn
    15  	rawOpt
    16  }
    17  
    18  func (c *packetHandler) ok() bool { return c != nil && c.c != nil }
    19  
    20  // ReadFrom reads an IPv4 datagram from the endpoint c, copying the
    21  // datagram into b.  It returns the received datagram as the IPv4
    22  // header h, the payload p and the control message cm.
    23  func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
    24  	if !c.ok() {
    25  		return nil, nil, nil, syscall.EINVAL
    26  	}
    27  	oob := newControlMessage(&c.rawOpt)
    28  	n, oobn, _, src, err := c.c.ReadMsgIP(b, oob)
    29  	if err != nil {
    30  		return nil, nil, nil, err
    31  	}
    32  	var hs []byte
    33  	if hs, p, err = slicePacket(b[:n]); err != nil {
    34  		return nil, nil, nil, err
    35  	}
    36  	if h, err = ParseHeader(hs); err != nil {
    37  		return nil, nil, nil, err
    38  	}
    39  	if cm, err = parseControlMessage(oob[:oobn]); err != nil {
    40  		return nil, nil, nil, err
    41  	}
    42  	if src != nil && cm != nil {
    43  		cm.Src = src.IP
    44  	}
    45  	return
    46  }
    47  
    48  func slicePacket(b []byte) (h, p []byte, err error) {
    49  	if len(b) < HeaderLen {
    50  		return nil, nil, errHeaderTooShort
    51  	}
    52  	hdrlen := int(b[0]&0x0f) << 2
    53  	return b[:hdrlen], b[hdrlen:], nil
    54  }
    55  
    56  // WriteTo writes an IPv4 datagram through the endpoint c, copying the
    57  // datagram from the IPv4 header h and the payload p.  The control
    58  // message cm allows the datagram path and the outgoing interface to be
    59  // specified.  Currently only Darwin and Linux support this.  The cm
    60  // may be nil if control of the outgoing datagram is not required.
    61  //
    62  // The IPv4 header h must contain appropriate fields that include:
    63  //
    64  //	Version       = ipv4.Version
    65  //	Len           = <must be specified>
    66  //	TOS           = <must be specified>
    67  //	TotalLen      = <must be specified>
    68  //	ID            = platform sets an appropriate value if ID is zero
    69  //	FragOff       = <must be specified>
    70  //	TTL           = <must be specified>
    71  //	Protocol      = <must be specified>
    72  //	Checksum      = platform sets an appropriate value if Checksum is zero
    73  //	Src           = platform sets an appropriate value if Src is nil
    74  //	Dst           = <must be specified>
    75  //	Options       = optional
    76  func (c *packetHandler) WriteTo(h *Header, p []byte, cm *ControlMessage) error {
    77  	if !c.ok() {
    78  		return syscall.EINVAL
    79  	}
    80  	oob := marshalControlMessage(cm)
    81  	wh, err := h.Marshal()
    82  	if err != nil {
    83  		return err
    84  	}
    85  	dst := &net.IPAddr{}
    86  	if cm != nil {
    87  		if ip := cm.Dst.To4(); ip != nil {
    88  			dst.IP = ip
    89  		}
    90  	}
    91  	if dst.IP == nil {
    92  		dst.IP = h.Dst
    93  	}
    94  	wh = append(wh, p...)
    95  	_, _, err = c.c.WriteMsgIP(wh, oob, dst)
    96  	return err
    97  }