// writeThenReadPayload transmits IPv4 datagram payloads to the // loopback address or interface and captures the loopback'd datagram // payloads. func writeThenReadPayload(t *testing.T, i int, c *ipv4.PacketConn, wb []byte, dst net.Addr) []byte { rb := make([]byte, 1500) c.SetTOS(i + 1) var ip net.IP switch v := dst.(type) { case *net.UDPAddr: ip = v.IP case *net.IPAddr: ip = v.IP } if ip.IsMulticast() { c.SetMulticastTTL(i + 1) } else { c.SetTTL(i + 1) } c.SetDeadline(time.Now().Add(100 * time.Millisecond)) if _, err := c.WriteTo(wb, nil, dst); err != nil { t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) } n, cm, _, err := c.ReadFrom(rb) if err != nil { t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) } t.Logf("rcvd cmsg: %v", cm) return rb[:n] }
// NewIPHAConn creates a new IPHAConn. func NewIPHAConn(laddr, raddr net.IP) (HAConn, error) { sendConn, err := IPConn(laddr, raddr) if err != nil { return nil, err } // For IPv6 unicast and multicast, and for IPv4 unicast, we can use the same IPConn for both // sending and receiving. For IPv4 multicast, we need a separate listener for receiving. recvConn := sendConn if raddr.IsMulticast() { if raddr.To4() != nil { log.Infof("Using IPv4 multicast") if recvConn, err = ListenMulticastIPv4(raddr, laddr); err != nil { return nil, err } } else { log.Infof("Using IPv6 multicast") if err = JoinMulticastIPv6(recvConn, raddr, laddr); err != nil { return nil, err } } } return &IPHAConn{ sendConn: sendConn, recvConn: recvConn, laddr: laddr, raddr: raddr, }, nil }
func validateRemoteAddr(ip net.IP) bool { if ip == nil { return false } if ip.IsInterfaceLocalMulticast() { return false } if ip.IsLinkLocalMulticast() { return false } if ip.IsLinkLocalUnicast() { return false } if ip.IsLoopback() { return false } if ip.IsMulticast() { return false } if ip.IsUnspecified() { return false } if isBroadcasty(ip) { return false } return true }
// runPayloadTransponder transmits IPv4 datagram payloads to the // loopback address or interface and captures the loopback'd datagram // payloads. func runPayloadTransponder(t *testing.T, c *ipv4.PacketConn, wb []byte, dst net.Addr) { cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface rb := make([]byte, 1500) for i, toggle := range []bool{true, false, true} { if err := c.SetControlMessage(cf, toggle); err != nil { t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err) } c.SetTOS(i + 1) var ip net.IP switch v := dst.(type) { case *net.UDPAddr: ip = v.IP case *net.IPAddr: ip = v.IP } if ip.IsMulticast() { c.SetMulticastTTL(i + 1) } else { c.SetTTL(i + 1) } c.SetDeadline(time.Now().Add(100 * time.Millisecond)) if _, err := c.Write(wb, nil, dst); err != nil { t.Fatalf("ipv4.PacketConn.Write failed: %v", err) } _, cm, _, err := c.Read(rb) if err != nil { t.Fatalf("ipv4.PacketConn.Read failed: %v", err) } t.Logf("rcvd cmsg: %v", cm) } }
func InterfaceIPs() ([]*net.IPAddr, error) { var ( addrs []*net.IPAddr ) ifaces, err := net.Interfaces() if err != nil { return nil, err } for _, iface := range ifaces { iaddrs, err := iface.Addrs() if err != nil { return nil, err } for _, iaddr := range iaddrs { var ( ip net.IP zone string ) switch x := iaddr.(type) { case *net.IPAddr: ip = x.IP zone = x.Zone case *net.IPNet: ip = x.IP zone = "" } if ip.IsMulticast() || ip.IsUnspecified() || ip.IsInterfaceLocalMulticast() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() { continue } if ipv4 := ip.To4(); ipv4 != nil { ip = ipv4 } addrs = append(addrs, &net.IPAddr{ IP: ip, Zone: zone, }) } } return addrs, nil }
//validNodeIP verifies that the provided ip is not a loopback or multicast address //and checks whether the ip is in the configured network limits range. func (s *Server) validNodeIP(i net.IP) bool { switch { case i.IsLoopback(): return false case i.IsMulticast(): return false } inRange := false for _, n := range s.netlimits { if n.Contains(i) { inRange = true } } return inRange }
// GetMyIP uses hueristics and guessing to find a usable IP for the current host by iterating over interfaces and // addresses assigned to those interfaces until one is found that is "up", not a loopback, nor a broadcast. if no // address can be found then return an empty string func GetMyIP() (string, error) { ifaces, err := net.Interfaces() if err != nil { return "", err } for _, iface := range ifaces { if iface.Flags&net.FlagUp == 0 { continue // down } if iface.Flags&(net.FlagLoopback) != 0 { continue // broadcast or loopback } addrs, err := iface.Addrs() if err != nil { return "", err } var ip net.IP for _, addr := range addrs { switch v := addr.(type) { case *net.IPNet: ip = v.IP case *net.IPAddr: ip = v.IP } if ip == nil || ip.IsLoopback() || ip.IsMulticast() { continue } if ip.To4() == nil { continue // not v4 } return ip.String(), nil } } return "", nil }
// IPConn creates a net.IPConn using the given local and remote addresses using IP protocol // 112 (VRRP). func IPConn(localAddr, remoteAddr net.IP) (*net.IPConn, error) { c, err := net.ListenIP("ip:112", &net.IPAddr{IP: localAddr}) if err != nil { return nil, err } f, err := c.File() if err != nil { return nil, err } defer f.Close() ip4 := localAddr.To4() switch { case ip4 != nil && !remoteAddr.IsMulticast(): // IPv4 unicast // TTL = 255 per VRRP spec if err := setsockopt(f, syscall.IPPROTO_IP, syscall.IP_TTL, 255); err != nil { return nil, err } case ip4 != nil && remoteAddr.IsMulticast(): // IPv4 multicast // TTL = 255 per VRRP spec if err := setsockopt(f, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, 255); err != nil { return nil, err } // We don't want to receive our own messages. if err := setsockopt(f, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, 0); err != nil { return nil, err } case ip4 == nil && !remoteAddr.IsMulticast(): // IPv6 unicast // HOPLIMIT = 255 per VRRP spec if err := setsockopt(f, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 255); err != nil { return nil, err } case ip4 == nil && remoteAddr.IsMulticast(): // IPv6 multicast // HOPLIMIT = 255 per VRRP spec if err := setsockopt(f, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, 255); err != nil { return nil, err } // We don't want to receive our own messages. if err := setsockopt(f, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, 0); err != nil { return nil, err } } if ip4 == nil { // IPv6 unicast and multicast // Request that the ancillary data for received packets include the hop limit and the // destination address. // TODO(angusc): syscall.IPV6_RECVHOPLIMIT and syscall.IPV6_RECVPKTINFO are prefered but they // don't work on lucid. if err := setsockopt(f, syscall.IPPROTO_IPV6, syscall.IPV6_2292HOPLIMIT, 1); err != nil { return nil, err } if err := setsockopt(f, syscall.IPPROTO_IPV6, syscall.IPV6_2292PKTINFO, 1); err != nil { return nil, err } } log.Infof("ha.IPConn: laddr=%v, raddr=%v", localAddr, remoteAddr) return c, nil }