Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/iprawsock_posix.go

Documentation: net

     1  // Copyright 2010 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  //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
     6  // +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows
     7  
     8  package net
     9  
    10  import (
    11  	"context"
    12  	"syscall"
    13  )
    14  
    15  func sockaddrToIP(sa syscall.Sockaddr) Addr {
    16  	switch sa := sa.(type) {
    17  	case *syscall.SockaddrInet4:
    18  		return &IPAddr{IP: sa.Addr[0:]}
    19  	case *syscall.SockaddrInet6:
    20  		return &IPAddr{IP: sa.Addr[0:], Zone: zoneCache.name(int(sa.ZoneId))}
    21  	}
    22  	return nil
    23  }
    24  
    25  func (a *IPAddr) family() int {
    26  	if a == nil || len(a.IP) <= IPv4len {
    27  		return syscall.AF_INET
    28  	}
    29  	if a.IP.To4() != nil {
    30  		return syscall.AF_INET
    31  	}
    32  	return syscall.AF_INET6
    33  }
    34  
    35  func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
    36  	if a == nil {
    37  		return nil, nil
    38  	}
    39  	return ipToSockaddr(family, a.IP, 0, a.Zone)
    40  }
    41  
    42  func (a *IPAddr) toLocal(net string) sockaddr {
    43  	return &IPAddr{loopbackIP(net), a.Zone}
    44  }
    45  
    46  func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
    47  	// TODO(cw,rsc): consider using readv if we know the family
    48  	// type to avoid the header trim/copy
    49  	var addr *IPAddr
    50  	n, sa, err := c.fd.readFrom(b)
    51  	switch sa := sa.(type) {
    52  	case *syscall.SockaddrInet4:
    53  		addr = &IPAddr{IP: sa.Addr[0:]}
    54  		n = stripIPv4Header(n, b)
    55  	case *syscall.SockaddrInet6:
    56  		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneCache.name(int(sa.ZoneId))}
    57  	}
    58  	return n, addr, err
    59  }
    60  
    61  func stripIPv4Header(n int, b []byte) int {
    62  	if len(b) < 20 {
    63  		return n
    64  	}
    65  	l := int(b[0]&0x0f) << 2
    66  	if 20 > l || l > len(b) {
    67  		return n
    68  	}
    69  	if b[0]>>4 != 4 {
    70  		return n
    71  	}
    72  	copy(b, b[l:])
    73  	return n - l
    74  }
    75  
    76  func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
    77  	var sa syscall.Sockaddr
    78  	n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
    79  	switch sa := sa.(type) {
    80  	case *syscall.SockaddrInet4:
    81  		addr = &IPAddr{IP: sa.Addr[0:]}
    82  	case *syscall.SockaddrInet6:
    83  		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneCache.name(int(sa.ZoneId))}
    84  	}
    85  	return
    86  }
    87  
    88  func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
    89  	if c.fd.isConnected {
    90  		return 0, ErrWriteToConnected
    91  	}
    92  	if addr == nil {
    93  		return 0, errMissingAddress
    94  	}
    95  	sa, err := addr.sockaddr(c.fd.family)
    96  	if err != nil {
    97  		return 0, err
    98  	}
    99  	return c.fd.writeTo(b, sa)
   100  }
   101  
   102  func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
   103  	if c.fd.isConnected {
   104  		return 0, 0, ErrWriteToConnected
   105  	}
   106  	if addr == nil {
   107  		return 0, 0, errMissingAddress
   108  	}
   109  	sa, err := addr.sockaddr(c.fd.family)
   110  	if err != nil {
   111  		return 0, 0, err
   112  	}
   113  	return c.fd.writeMsg(b, oob, sa)
   114  }
   115  
   116  func (sd *sysDialer) dialIP(ctx context.Context, laddr, raddr *IPAddr) (*IPConn, error) {
   117  	network, proto, err := parseNetwork(ctx, sd.network, true)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	switch network {
   122  	case "ip", "ip4", "ip6":
   123  	default:
   124  		return nil, UnknownNetworkError(sd.network)
   125  	}
   126  	fd, err := internetSocket(ctx, network, laddr, raddr, syscall.SOCK_RAW, proto, "dial", sd.Dialer.Control)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return newIPConn(fd), nil
   131  }
   132  
   133  func (sl *sysListener) listenIP(ctx context.Context, laddr *IPAddr) (*IPConn, error) {
   134  	network, proto, err := parseNetwork(ctx, sl.network, true)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	switch network {
   139  	case "ip", "ip4", "ip6":
   140  	default:
   141  		return nil, UnknownNetworkError(sl.network)
   142  	}
   143  	fd, err := internetSocket(ctx, network, laddr, nil, syscall.SOCK_RAW, proto, "listen", sl.ListenConfig.Control)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	return newIPConn(fd), nil
   148  }
   149  

View as plain text