...

Source file src/net/iprawsock_posix.go

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

View as plain text