func (ipad Net) ResolveIPAddr(p string, a string) (*net.IPAddr, error) { var i net.IPAddr i.Zone = "france" i.IP = net.ParseIP("localhost") ptr := &i return ptr, nil }
func sendPing(conn *net.IPConn, addr *net.IPAddr, id, seq int) { bytes, err := (&icmpMessage{ Type: icmpv4EchoRequest, Code: 0, Body: &icmpEcho{ ID: id, Seq: seq, Data: timeToBytes(time.Now()), }, }).Marshal() if err != nil { panic(err) } for { if _, _, err := conn.WriteMsgIP(bytes, nil, addr); err != nil { if neterr, ok := err.(*net.OpError); ok { if neterr.Err == syscall.ENOBUFS { // creating a busy loop? continue } } } fmt.Printf("ICMP: Ping sent: %s, id=%d.\n", addr.String(), id) break } }
func (cloud *OpenStack) ReturnFloatingIP(addr net.IPAddr) error { // grab the address out of the used index := indexOfAddress(cloud.usedIPs, addr) if index == -1 { return errors.New(fmt.Sprintf("'%s' address was not previously allocated", addr.String())) } // mutex cloud.mutex.Lock() // remove from usedIPs cloud.usedIPs = cloud.usedIPs[:index+copy(cloud.usedIPs[index:], cloud.usedIPs[index+1:])] // recreate the availableIPs slice if it was set to nil if cloud.availableIps == nil { cloud.availableIps = make([]net.IPAddr, 0) } // add the address to available cloud.availableIps = append(cloud.availableIps, addr) // mutex cloud.mutex.Unlock() return nil }
// AddIPAddr adds an IP address to Pinger. ip arg should be a net.IPAddr // pointer. func (p *Pinger) AddIPAddr(ip *net.IPAddr) { p.addrs[ip.String()] = ip if isIPv4(ip.IP) { p.hasIPv4 = true } else if isIPv6(ip.IP) { p.hasIPv6 = true } }
func ReverseLookup(ip net.IPAddr) (name string, err error) { names, err := net.LookupAddr(ip.String()) if err == nil && len(names) > 0 { name = names[0] // names seem to have a . at the end. remove it if name[len(name)-1] == '.' { name = name[:len(name)-1] } } return }
// SetIPAddr sets the ip address of the target host. func (p *Pinger) SetIPAddr(ipaddr *net.IPAddr) { var ipv4 bool if isIPv4(ipaddr.IP) { ipv4 = true } else if isIPv6(ipaddr.IP) { ipv4 = false } p.ipaddr = ipaddr p.addr = ipaddr.String() p.ipv4 = ipv4 }
func (state *State) onRecv(addr *net.IPAddr, rtt time.Duration) { s := state.PingSessions[addr.String()] s.Lock() s.TotalRTT += rtt s.PingCount++ if s.PingCount > state.PingChecker.PingLimit { state.Pinger.RemoveIPAddr(addr) } s.Unlock() return }
func ping(host string, ra *net.IPAddr, rtt time.Duration, c chan bool, lock *sync.RWMutex, store map[string]*HostStore) { p := fastping.NewPinger() results := make(map[string]*response) results[ra.String()] = nil p.AddIPAddr(ra) onRecv, onIdle := make(chan *response), make(chan bool) p.AddHandler("receive", func(addr *net.IPAddr, t time.Duration) { onRecv <- &response{addr: addr, rtt: t} }) p.AddHandler("idle", func() { onIdle <- true }) p.MaxRTT = rtt quit, errch := p.RunLoop() wait := make(chan bool) loop: for { select { case <-c: log.Printf("get interrupted %v", ra) quit <- wait case res := <-onRecv: if _, ok := results[res.addr.String()]; ok { results[res.addr.String()] = res } case <-onIdle: for v, r := range results { lock.Lock() if r == nil { store[host].Insert(0) } else { store[host].Insert(r.rtt) } lock.Unlock() results[v] = nil } case err := <-errch: log.Println("%v failed: %v", ra, err) c <- true case <-wait: break loop } } log.Printf("exit %v", ra) }
// Bootstrap message initiator retrieving possible peer addresses from various // seed generators and sending bootstrap requests at a given rate. func (b *Bootstrapper) initiator() { b.log.Info("starting initiator") // Repeat message initiation until termination is requested var errc chan error for errc == nil { // Retrieve a possible seed address from a random algorithm var addr *net.IPAddr select { // Short circuit termination request case errc = <-b.quit: continue default: select { case addr = <-b.scanSink: case addr = <-b.probeSink: case addr = <-b.coreOSSink: case errc = <-b.quit: continue } } // Discard self addresses self := 0 if b.ipnet.IP.String() == addr.IP.String() { self = b.addr.Port } // Send a bootstrap request on all configured ports for _, port := range config.BootPorts { if port == self { continue } host := net.JoinHostPort(addr.String(), strconv.Itoa(port)) addr, err := net.ResolveUDPAddr("udp", host) if err != nil { panic(fmt.Sprintf("failed to resolve remote bootstrapper (%v): %v.", host, err)) } b.sock.WriteToUDP(b.request, addr) } time.Sleep(100 * time.Millisecond) } // Report termination and sync closer b.log.Info("terminating initiator") errc <- nil }
// Tests that the scanning ad-hoc seeder indeed generates IP addresses in the // correct order and range for a specific ipnet configuration. func testScanSeeder(t *testing.T, subnet int, addr *net.IPAddr) { // Create the IP net from the configurations ipnet := &net.IPNet{ IP: addr.IP, Mask: net.CIDRMask(subnet, 32), } // Create the scanning seed generator, address sink and boot it seeder := newScanSeeder(ipnet, log15.New("ipnet", ipnet)) sink, phase := make(chan *net.IPAddr), uint32(0) if err := seeder.Start(sink, &phase); err != nil { t.Fatalf("failed to start seed generator: %v.", err) } // Retrieve twice the possible host count, ensuring they are in range valid := (1 << uint(32-subnet)) - 2 addrs := make(map[string]int) for i := 0; i < 2*valid; i++ { select { case addr := <-sink: if !ipnet.Contains(addr.IP) { t.Fatalf("out of range address generated: %v.", addr) } addrs[addr.String()]++ case <-time.After(time.Second): t.Fatalf("failed to retrieve next address") } } // Verify that enough hosts were returned and the right multiplier if len(addrs) != valid { t.Fatalf("address variation mismatch: have %v, want %v.", len(addrs), valid) } for _, count := range addrs { if count != 2 { t.Fatalf("address generation count mismatch: have %v, want %v.", count, 2) } } // Terminate the generator if err := seeder.Close(); err != nil { t.Fatalf("failed to terminate seed generator: %v.", err) } }
// Tests that the probing ad-hoc seeder indeed generates IP addresses in the // correct range for a specific ipnet configuration. func testProbeSeeder(t *testing.T, subnet int, addr *net.IPAddr) { // Create the IP net from the configurations ipnet := &net.IPNet{ IP: addr.IP, Mask: net.CIDRMask(subnet, 32), } // Create the probing seed generator, address sink and boot it seeder := newProbeSeeder(ipnet, log15.New("ipnet", ipnet)) sink, phase := make(chan *net.IPAddr), uint32(0) if err := seeder.Start(sink, &phase); err != nil { t.Fatalf("failed to start seed generator: %v.", err) } // Retrieve a large batch of random addresses, ensuring they are in range iters := 100000 addrs := make(map[string]int) for i := 0; i < iters; i++ { select { case addr := <-sink: if !ipnet.Contains(addr.IP) { t.Fatalf("out of range address generated: %v.", addr) } addrs[addr.String()]++ case <-time.After(time.Second): t.Fatalf("failed to retrieve next address") } } // Verify that multipliers are within expected range for _, count := range addrs { lo := (iters / ((1 << uint(32-subnet)) - 2)) / 10 * 5 hi := (iters / ((1 << uint(32-subnet)) - 2)) / 10 * 15 if lo > count || count > hi { t.Fatalf("non uniform address count: have %v, want in [%v-%v].", count, lo, hi) } } // Terminate the generator if err := seeder.Close(); err != nil { t.Fatalf("failed to terminate seed generator: %v.", err) } }
func Ping(addr *net.IPAddr, duration time.Duration) *time.Duration { reply := make(chan *time.Duration, 3) pingChan <- PingJob{ Reply: reply, Addr: addr, Deadline: time.Now().Add(duration), } select { case rtt := <-reply: if rtt == nil { fmt.Printf("Ping: %s: got timeout.\n", addr.String()) } else { fmt.Printf("Ping: %s: %s.\n", addr.String(), rtt) } return rtt case <-time.After(duration): fmt.Printf("Ping: %s: no reply.\n", addr.String()) return nil } }
func (l *icmpLoop) sendEchoRequest(addr *net.IPAddr) (*requestContext, error) { var conn *icmp.PacketConn var proto int var typ icmp.Type if l == nil { panic("icmp loop not initialized") } if isIPv4(addr.IP) { conn = l.conn4 proto = protocolICMP typ = ipv4.ICMPTypeEcho } else if isIPv6(addr.IP) { conn = l.conn6 proto = protocolIPv6ICMP typ = ipv6.ICMPTypeEchoRequest } else { return nil, fmt.Errorf("%v is unknown ip address", addr) } id := requestID{ addr: addr.String(), proto: proto, id: rand.Intn(0xffff), seq: rand.Intn(0xffff), } ctx := &requestContext{ l: l, id: id, result: make(chan requestResult, 1), } l.mutex.Lock() l.requests[id] = ctx l.mutex.Unlock() payloadBuf := make([]byte, 0, 8) payload := bytes.NewBuffer(payloadBuf) ts := time.Now() binary.Write(payload, binary.BigEndian, ts.UnixNano()) msg := &icmp.Message{ Type: typ, Body: &icmp.Echo{ ID: id.id, Seq: id.seq, Data: payload.Bytes(), }, } encoded, _ := msg.Marshal(nil) _, err := conn.WriteTo(encoded, addr) if err != nil { return nil, err } ctx.ts = ts return ctx, nil }
func ExamplePacketConn_tracingIPPacketRoute() { // Tracing an IP packet route to www.google.com. const host = "www.google.com" ips, err := net.LookupIP(host) if err != nil { log.Fatal(err) } var dst net.IPAddr for _, ip := range ips { if ip.To4() != nil { dst.IP = ip fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) break } } if dst.IP == nil { log.Fatal("no A record found") } c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolICMP), "0.0.0.0") // ICMP for IPv4 if err != nil { log.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { log.Fatal(err) } wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Data: []byte("HELLO-R-U-THERE"), }, } rb := make([]byte, 1500) for i := 1; i <= 64; i++ { // up to 64 hops wm.Body.(*icmp.Echo).Seq = i wb, err := wm.Marshal(nil) if err != nil { log.Fatal(err) } if err := p.SetTTL(i); err != nil { log.Fatal(err) } // In the real world usually there are several // multiple traffic-engineered paths for each hop. // You may need to probe a few times to each hop. begin := time.Now() if _, err := p.WriteTo(wb, nil, &dst); err != nil { log.Fatal(err) } if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { log.Fatal(err) } n, cm, peer, err := p.ReadFrom(rb) if err != nil { if err, ok := err.(net.Error); ok && err.Timeout() { fmt.Printf("%v\t*\n", i) continue } log.Fatal(err) } rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) if err != nil { log.Fatal(err) } rtt := time.Since(begin) // In the real world you need to determine whether the // received message is yours using ControlMessage.Src, // ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq. switch rm.Type { case ipv4.ICMPTypeTimeExceeded: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) case ipv4.ICMPTypeEchoReply: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) return default: log.Printf("unknown ICMP message: %+v\n", rm) } } }
func (p *Pinger) procRecv(recv *packet, queue map[string]*net.IPAddr) { var ipaddr *net.IPAddr switch adr := recv.addr.(type) { case *net.IPAddr: ipaddr = adr case *net.UDPAddr: ipaddr = &net.IPAddr{IP: adr.IP, Zone: adr.Zone} default: return } addr := ipaddr.String() p.mu.Lock() if _, ok := p.addrs[addr]; !ok { p.mu.Unlock() return } p.mu.Unlock() var bytes []byte var proto int if isIPv4(ipaddr.IP) { if p.network == "ip" { bytes = ipv4Payload(recv.bytes) } else { bytes = recv.bytes } proto = ProtocolICMP } else if isIPv6(ipaddr.IP) { bytes = recv.bytes proto = ProtocolIPv6ICMP } else { return } var m *icmp.Message var err error if m, err = icmp.ParseMessage(proto, bytes); err != nil { return } if m.Type != ipv4.ICMPTypeEchoReply && m.Type != ipv6.ICMPTypeEchoReply { return } var rtt time.Duration switch pkt := m.Body.(type) { case *icmp.Echo: p.mu.Lock() if pkt.ID == p.id && pkt.Seq == p.seq { rtt = time.Since(bytesToTime(pkt.Data[:TimeSliceLength])) } p.mu.Unlock() default: return } if _, ok := queue[addr]; ok { delete(queue, addr) p.mu.Lock() handler := p.OnRecv p.mu.Unlock() if handler != nil { handler(ipaddr, rtt) } } }
// RemoveIPAddr removes an IP address from Pinger. ip arg should be a net.IPAddr // pointer. func (p *Pinger) RemoveIPAddr(ip *net.IPAddr) { p.mu.Lock() delete(p.addrs, ip.String()) p.mu.Unlock() }
func (p *Pingbeat) Addr2Name(addr *net.IPAddr) (string, string) { var name, tag string if _, found := p.ipv4targets[addr.String()]; found { name = p.ipv4targets[addr.String()][0] tag = p.ipv4targets[addr.String()][1] } else if _, found := p.ipv6targets[addr.String()]; found { name = p.ipv6targets[addr.String()][0] tag = p.ipv6targets[addr.String()][1] } else { logp.Err("Error: %s not found in Pingbeat targets!", addr.String()) name = "err" tag = "err" } return name, tag }
// RemoveIPAddr removes an IP address from Pinger. ip arg should be a net.IPAddr // pointer. func (p *Pinger) RemoveIPAddr(ip *net.IPAddr) { delete(p.addrs, ip.String()) }
func updateNamespaceNetworkLinks(name string, sourceAddr *net.IPAddr, ports io.Reader) error { // Enable routing in the namespace output, err := exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.conf.all.route_localnet=1").Output() if err != nil { log.Printf("gear: Failed to enable localnet routing: %v", err) log.Printf("gear: error output: %v", output) return err } // Enable ip forwarding output, err = exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.ip_forward=1").Output() if err != nil { log.Printf("gear: Failed to enable ipv4 forwarding: %v", err) log.Printf("gear: error output: %v", output) return err } // Restore a set of rules to the table cmd := exec.Command("ip", "netns", "exec", name, "iptables-restore") stdin, errp := cmd.StdinPipe() if errp != nil { log.Printf("gear: Could not open pipe to iptables-restore: %v", errp) return errp } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr defer stdin.Close() if err := cmd.Start(); err != nil { log.Printf("gear: Could not start iptables-restore: %v", errp) return err } fmt.Fprintf(stdin, "*nat\n") for { link := containers.NetworkLink{} if _, err := fmt.Fscanf(ports, "%s\t%v\t%v\t%s\n", &link.FromHost, &link.FromPort, &link.ToPort, &link.ToHost); err != nil { if err == io.EOF { break } log.Printf("gear: Could not read from network links file: %v", err) continue } if err := link.Check(); err != nil { log.Printf("gear: Link in file is not valid: %v", err) continue } if link.Complete() { srcIP, err := net.ResolveIPAddr("ip", link.FromHost) if err != nil { log.Printf("gear: Link source host does not resolve %v", err) continue } destIP, err := resolver.ResolveIP(link.ToHost) if err != nil { log.Printf("gear: Link destination host does not resolve %v", err) continue } log.Printf("Mapping %s(%s):%d -> %s:%d", sourceAddr.String(), srcIP.String(), link.FromPort, destIP.String(), link.ToPort) data := OutboundNetworkIptables{sourceAddr.String(), srcIP.IP.String(), link.FromPort, destIP.String(), link.ToPort} if err := OutboundNetworkIptablesTemplate.Execute(stdin, &data); err != nil { log.Printf("gear: Unable to write network link rules: %v", err) return err } } } fmt.Fprintf(stdin, "COMMIT\n") stdin.Close() if err := cmd.Wait(); err != nil { log.Printf("gear: iptables-restore did not successfully complete: %v", err) return err } return nil }
func ServiceRequests() { var sockConfig tls.Config // resolve the bind address bindAddressStr := GetStringOpt("bind address") var bindAddr *net.IPAddr if bindAddressStr != "" { var err error bindAddr, err = net.ResolveIPAddr("ip", bindAddressStr) if err != nil { o.Warn("Ignoring bind address. Couldn't resolve \"%s\": %s", bindAddressStr, err) } else { bindAddr = nil } } // load the x509 certificate and key, then attach it to the tls config. x509CertFilename := GetStringOpt("x509 certificate") x509PrivateKeyFilename := GetStringOpt("x509 private key") serverCert, err := tls.LoadX509KeyPair(x509CertFilename, x509PrivateKeyFilename) o.MightFail(err, "Couldn't load certificates") sockConfig.Certificates = append(sockConfig.Certificates, serverCert) // load the CA certs CACertPool = x509.NewCertPool() caCertNames := GetCACertList() if caCertNames != nil { for _, filename := range caCertNames { fh, err := os.Open(filename) if err != nil { o.Warn("Whilst parsing CA certs, couldn't open %s: %s", filename, err) continue } defer fh.Close() fi, err := fh.Stat() o.MightFail(err, "Couldn't stat CA certificate file: %s", filename) data := make([]byte, fi.Size()) fh.Read(data) CACertPool.AppendCertsFromPEM(data) } } sockConfig.ClientCAs = CACertPool // determine the server hostname. servername := GetStringOpt("server name") if servername != "" { o.Info("Using %s as the server name", servername) sockConfig.ServerName = servername } else { if bindAddr != nil { o.Warn("Probing for FQDN for bind address as none was provided") hostnames, err := net.LookupAddr(bindAddr.String()) o.MightFail(err, "Failed to get full hostname for bind address") sockConfig.ServerName = hostnames[0] } else { o.Warn("Probing for FQDN as no server name was provided") sockConfig.ServerName = o.ProbeHostname() } } // ask the client to authenticate sockConfig.ClientAuth = tls.RequireAndVerifyClientCert if *DontVerifyPeer { sockConfig.ClientAuth = tls.RequestClientCert } /* convert the bindAddress to a string suitable for the Listen call */ var laddr string if bindAddr == nil { laddr = fmt.Sprintf(":%d", o.DefaultMasterPort) } else { laddr = fmt.Sprintf("%s:%d", bindAddr.String(), o.DefaultMasterPort) } o.Info("Binding to %s...", laddr) listener, err := tls.Listen("tcp", laddr, &sockConfig) o.MightFail(err, "Couldn't bind TLS listener") for { o.Info("Waiting for connection...") c, err := listener.Accept() o.MightFail(err, "Couldn't accept TLS connection") o.Info("Connection received from %s", c.RemoteAddr().String()) HandleConnection(c) } }
func (p *Pinger) procRecv(bytes []byte, ra net.Addr, ctx *context) { var ipaddr *net.IPAddr switch adr := ra.(type) { case *net.IPAddr: ipaddr = adr case *net.UDPAddr: ipaddr = &net.IPAddr{IP: adr.IP, Zone: adr.Zone} default: return } addr := ipaddr.String() p.mu.Lock() _, ok := p.addrs[addr] p.mu.Unlock() if !ok { return } var proto int if isIPv4(ipaddr.IP) { if p.network == "ip" { bytes = ipv4Payload(bytes) } proto = ProtocolICMP } else if isIPv6(ipaddr.IP) { proto = ProtocolIPv6ICMP } else { return } var m *icmp.Message var err error if m, err = icmp.ParseMessage(proto, bytes); err != nil { return } if m.Type != ipv4.ICMPTypeEchoReply && m.Type != ipv6.ICMPTypeEchoReply { return } var rtt time.Duration switch pkt := m.Body.(type) { case *icmp.Echo: if pkt.ID == p.id && pkt.Seq == p.seq { rtt = time.Since(bytesToTime(pkt.Data[:TimeSliceLength])) } default: return } if 0 == rtt { return } p.mu.Lock() delete(p.sent, addr) if len(p.sent) == 0 && !p.done { p.done = true close(ctx.done) } p.mu.Unlock() if p.OnRecv != nil { p.OnRecv(ipaddr, rtt) } }
func PingIP(hostname string, raddr *net.IPAddr, pcount int, debug bool) (sent int, received int, etimes []float64) { // Make the IP connection to the destination host ipconn, err := net.DialIP("ip4:icmp", nil, raddr) if err != nil { fmt.Printf("could not connect to %s: %v\n", raddr.IP, err) return } sendid := os.Getpid() & 0xffff sendseq := 1 pingpktlen := 64 //if debug { fmt.Printf("PING %s (%s): %d data bytes\n", hostname, raddr.String(), pingpktlen-8) //} for { var check4reply bool var etime float64 // Generate our ICMP packet sendpkt := makePingRequest(sendid, sendseq, pingpktlen, []byte("Go Ping")) // Start timer start := time.Now() // Send ICMP packet n, err := ipconn.Write(sendpkt) // Err out if we couldn't send the full packet size if err != nil || n != pingpktlen { etime = elapsedTime(start) fmt.Printf("0 bytes from %s: icmp_req=%d time=%.3f ms ERR: Network is down\n", raddr.IP, sendseq, etime) } else { // We will check this flag later to see if we need to wait for a returned packet check4reply = true } // increment our sent counter sent++ // set a 0.5 second timer as our max packet reply wait time var deadline = start.Add(500 * time.Millisecond) ipconn.SetReadDeadline(deadline) // Read response packet (or process timeout if it occurs) resp := make([]byte, 1024) for { if check4reply == false { break } n, _, err := ipconn.ReadFrom(resp) if err != nil { // Could not read response packet etime = elapsedTime(start) if debug { fmt.Printf("%d bytes from %s: icmp_req=%d time=%.3f ms ERR: %s\n", n, raddr.IP, sendseq, etime, err.Error()) } break } else { // Response was okay } if resp[0] != ICMP_ECHO_REPLY { // Skip non-ICMP packets continue } rcvid, rcvseq := parsePingReply(resp) if rcvid != sendid || rcvseq != sendseq { etime = elapsedTime(start) if debug { fmt.Printf("%d bytes from %s: icmp_req=%d time=%.3f ms ERR: Out of sequence (0x%x,0x%x)\n", n, raddr.IP, sendseq, etime, rcvid, rcvseq) } } else { // Packet reply came back okay etime = elapsedTime(start) if debug { fmt.Printf("%d bytes from %s: icmp_req=%d time=%.3f ms\n", n, raddr.IP, sendseq, etime) } received++ etimes = append(etimes, etime) } break } sendseq++ if sendseq > pcount { // We've reached the maximum number of packets to send so return return } else { // Sleep 1 second before moving onto the next packet time.Sleep(1 * time.Second) } } }