github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/ipv4/sys_asmreq.go (about)

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