Home | History | Annotate | Download | only in net
      1 // Copyright 2009 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
      6 
      7 package net
      8 
      9 import (
     10 	"context"
     11 	"internal/poll"
     12 	"os"
     13 	"syscall"
     14 )
     15 
     16 // A sockaddr represents a TCP, UDP, IP or Unix network endpoint
     17 // address that can be converted into a syscall.Sockaddr.
     18 type sockaddr interface {
     19 	Addr
     20 
     21 	// family returns the platform-dependent address family
     22 	// identifier.
     23 	family() int
     24 
     25 	// isWildcard reports whether the address is a wildcard
     26 	// address.
     27 	isWildcard() bool
     28 
     29 	// sockaddr returns the address converted into a syscall
     30 	// sockaddr type that implements syscall.Sockaddr
     31 	// interface. It returns a nil interface when the address is
     32 	// nil.
     33 	sockaddr(family int) (syscall.Sockaddr, error)
     34 
     35 	// toLocal maps the zero address to a local system address (127.0.0.1 or ::1)
     36 	toLocal(net string) sockaddr
     37 }
     38 
     39 // socket returns a network file descriptor that is ready for
     40 // asynchronous I/O using the network poller.
     41 func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr) (fd *netFD, err error) {
     42 	s, err := sysSocket(family, sotype, proto)
     43 	if err != nil {
     44 		return nil, err
     45 	}
     46 	if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
     47 		poll.CloseFunc(s)
     48 		return nil, err
     49 	}
     50 	if fd, err = newFD(s, family, sotype, net); err != nil {
     51 		poll.CloseFunc(s)
     52 		return nil, err
     53 	}
     54 
     55 	// This function makes a network file descriptor for the
     56 	// following applications:
     57 	//
     58 	// - An endpoint holder that opens a passive stream
     59 	//   connection, known as a stream listener
     60 	//
     61 	// - An endpoint holder that opens a destination-unspecific
     62 	//   datagram connection, known as a datagram listener
     63 	//
     64 	// - An endpoint holder that opens an active stream or a
     65 	//   destination-specific datagram connection, known as a
     66 	//   dialer
     67 	//
     68 	// - An endpoint holder that opens the other connection, such
     69 	//   as talking to the protocol stack inside the kernel
     70 	//
     71 	// For stream and datagram listeners, they will only require
     72 	// named sockets, so we can assume that it's just a request
     73 	// from stream or datagram listeners when laddr is not nil but
     74 	// raddr is nil. Otherwise we assume it's just for dialers or
     75 	// the other connection holders.
     76 
     77 	if laddr != nil && raddr == nil {
     78 		switch sotype {
     79 		case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
     80 			if err := fd.listenStream(laddr, listenerBacklog); err != nil {
     81 				fd.Close()
     82 				return nil, err
     83 			}
     84 			return fd, nil
     85 		case syscall.SOCK_DGRAM:
     86 			if err := fd.listenDatagram(laddr); err != nil {
     87 				fd.Close()
     88 				return nil, err
     89 			}
     90 			return fd, nil
     91 		}
     92 	}
     93 	if err := fd.dial(ctx, laddr, raddr); err != nil {
     94 		fd.Close()
     95 		return nil, err
     96 	}
     97 	return fd, nil
     98 }
     99 
    100 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
    101 	switch fd.family {
    102 	case syscall.AF_INET, syscall.AF_INET6:
    103 		switch fd.sotype {
    104 		case syscall.SOCK_STREAM:
    105 			return sockaddrToTCP
    106 		case syscall.SOCK_DGRAM:
    107 			return sockaddrToUDP
    108 		case syscall.SOCK_RAW:
    109 			return sockaddrToIP
    110 		}
    111 	case syscall.AF_UNIX:
    112 		switch fd.sotype {
    113 		case syscall.SOCK_STREAM:
    114 			return sockaddrToUnix
    115 		case syscall.SOCK_DGRAM:
    116 			return sockaddrToUnixgram
    117 		case syscall.SOCK_SEQPACKET:
    118 			return sockaddrToUnixpacket
    119 		}
    120 	}
    121 	return func(syscall.Sockaddr) Addr { return nil }
    122 }
    123 
    124 func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr) error {
    125 	var err error
    126 	var lsa syscall.Sockaddr
    127 	if laddr != nil {
    128 		if lsa, err = laddr.sockaddr(fd.family); err != nil {
    129 			return err
    130 		} else if lsa != nil {
    131 			if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
    132 				return os.NewSyscallError("bind", err)
    133 			}
    134 		}
    135 	}
    136 	var rsa syscall.Sockaddr  // remote address from the user
    137 	var crsa syscall.Sockaddr // remote address we actually connected to
    138 	if raddr != nil {
    139 		if rsa, err = raddr.sockaddr(fd.family); err != nil {
    140 			return err
    141 		}
    142 		if crsa, err = fd.connect(ctx, lsa, rsa); err != nil {
    143 			return err
    144 		}
    145 		fd.isConnected = true
    146 	} else {
    147 		if err := fd.init(); err != nil {
    148 			return err
    149 		}
    150 	}
    151 	// Record the local and remote addresses from the actual socket.
    152 	// Get the local address by calling Getsockname.
    153 	// For the remote address, use
    154 	// 1) the one returned by the connect method, if any; or
    155 	// 2) the one from Getpeername, if it succeeds; or
    156 	// 3) the one passed to us as the raddr parameter.
    157 	lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
    158 	if crsa != nil {
    159 		fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
    160 	} else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
    161 		fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
    162 	} else {
    163 		fd.setAddr(fd.addrFunc()(lsa), raddr)
    164 	}
    165 	return nil
    166 }
    167 
    168 func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
    169 	if err := setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
    170 		return err
    171 	}
    172 	if lsa, err := laddr.sockaddr(fd.family); err != nil {
    173 		return err
    174 	} else if lsa != nil {
    175 		if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
    176 			return os.NewSyscallError("bind", err)
    177 		}
    178 	}
    179 	if err := listenFunc(fd.pfd.Sysfd, backlog); err != nil {
    180 		return os.NewSyscallError("listen", err)
    181 	}
    182 	if err := fd.init(); err != nil {
    183 		return err
    184 	}
    185 	lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
    186 	fd.setAddr(fd.addrFunc()(lsa), nil)
    187 	return nil
    188 }
    189 
    190 func (fd *netFD) listenDatagram(laddr sockaddr) error {
    191 	switch addr := laddr.(type) {
    192 	case *UDPAddr:
    193 		// We provide a socket that listens to a wildcard
    194 		// address with reusable UDP port when the given laddr
    195 		// is an appropriate UDP multicast address prefix.
    196 		// This makes it possible for a single UDP listener to
    197 		// join multiple different group addresses, for
    198 		// multiple UDP listeners that listen on the same UDP
    199 		// port to join the same group address.
    200 		if addr.IP != nil && addr.IP.IsMulticast() {
    201 			if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
    202 				return err
    203 			}
    204 			addr := *addr
    205 			switch fd.family {
    206 			case syscall.AF_INET:
    207 				addr.IP = IPv4zero
    208 			case syscall.AF_INET6:
    209 				addr.IP = IPv6unspecified
    210 			}
    211 			laddr = &addr
    212 		}
    213 	}
    214 	if lsa, err := laddr.sockaddr(fd.family); err != nil {
    215 		return err
    216 	} else if lsa != nil {
    217 		if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
    218 			return os.NewSyscallError("bind", err)
    219 		}
    220 	}
    221 	if err := fd.init(); err != nil {
    222 		return err
    223 	}
    224 	lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
    225 	fd.setAddr(fd.addrFunc()(lsa), nil)
    226 	return nil
    227 }
    228