sys_asmreq.go raw

   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  //go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || windows
   6  
   7  package ipv4
   8  
   9  import (
  10  	"errors"
  11  	"net"
  12  	"unsafe"
  13  
  14  	"golang.org/x/net/internal/socket"
  15  )
  16  
  17  var errNoSuchInterface = errors.New("no such interface")
  18  
  19  func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
  20  	mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
  21  	if err := setIPMreqInterface(&mreq, ifi); err != nil {
  22  		return err
  23  	}
  24  	b := (*[sizeofIPMreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPMreq]
  25  	return so.Set(c, b)
  26  }
  27  
  28  func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
  29  	var b [4]byte
  30  	if _, err := so.Get(c, b[:]); err != nil {
  31  		return nil, err
  32  	}
  33  	ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
  34  	if err != nil {
  35  		return nil, err
  36  	}
  37  	return ifi, nil
  38  }
  39  
  40  func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
  41  	ip, err := netInterfaceToIP4(ifi)
  42  	if err != nil {
  43  		return err
  44  	}
  45  	var b [4]byte
  46  	copy(b[:], ip)
  47  	return so.Set(c, b[:])
  48  }
  49  
  50  func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error {
  51  	if ifi == nil {
  52  		return nil
  53  	}
  54  	ifat, err := ifi.Addrs()
  55  	if err != nil {
  56  		return err
  57  	}
  58  	for _, ifa := range ifat {
  59  		switch ifa := ifa.(type) {
  60  		case *net.IPAddr:
  61  			if ip := ifa.IP.To4(); ip != nil {
  62  				copy(mreq.Interface[:], ip)
  63  				return nil
  64  			}
  65  		case *net.IPNet:
  66  			if ip := ifa.IP.To4(); ip != nil {
  67  				copy(mreq.Interface[:], ip)
  68  				return nil
  69  			}
  70  		}
  71  	}
  72  	return errNoSuchInterface
  73  }
  74  
  75  func netIP4ToInterface(ip net.IP) (*net.Interface, error) {
  76  	ift, err := net.Interfaces()
  77  	if err != nil {
  78  		return nil, err
  79  	}
  80  	for _, ifi := range ift {
  81  		ifat, err := ifi.Addrs()
  82  		if err != nil {
  83  			return nil, err
  84  		}
  85  		for _, ifa := range ifat {
  86  			switch ifa := ifa.(type) {
  87  			case *net.IPAddr:
  88  				if ip.Equal(ifa.IP) {
  89  					return &ifi, nil
  90  				}
  91  			case *net.IPNet:
  92  				if ip.Equal(ifa.IP) {
  93  					return &ifi, nil
  94  				}
  95  			}
  96  		}
  97  	}
  98  	return nil, errNoSuchInterface
  99  }
 100  
 101  func netInterfaceToIP4(ifi *net.Interface) (net.IP, error) {
 102  	if ifi == nil {
 103  		return net.IPv4zero.To4(), nil
 104  	}
 105  	ifat, err := ifi.Addrs()
 106  	if err != nil {
 107  		return nil, err
 108  	}
 109  	for _, ifa := range ifat {
 110  		switch ifa := ifa.(type) {
 111  		case *net.IPAddr:
 112  			if ip := ifa.IP.To4(); ip != nil {
 113  				return ip, nil
 114  			}
 115  		case *net.IPNet:
 116  			if ip := ifa.IP.To4(); ip != nil {
 117  				return ip, nil
 118  			}
 119  		}
 120  	}
 121  	return nil, errNoSuchInterface
 122  }
 123