...

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