func discoverTunnels() { glog.Infof("Discovering existing tunnels") lo, err := netlink.LinkByName("lo") if err != nil { glog.Errorf("Failed to get loopback device: %v", err) return } addrs, err := netlink.AddrList(lo, netlink.FAMILY_ALL) if err != nil { glog.Errorf("Failed to get addrs: %v", err) return } routes, err := netlink.RouteList(nil, netlink.FAMILY_ALL) if err != nil { glog.Errorf("Failed to get routes: %v", err) return } policies, err := netlink.XfrmPolicyList(netlink.FAMILY_ALL) if err != nil { glog.Errorf("Failed to get xfrm policies: %v", err) return } states, err := netlink.XfrmStateList(netlink.FAMILY_ALL) if err != nil { glog.Errorf("Failed to get xfrm states: %v", err) return } for _, addr := range addrs { if opts.cidr.Contains(addr.IP) { tunnel := client.Tunnel{} tunnel.Src = addr.IP err := reserveIP(tunnel.Src) if err != nil { glog.Warningf("Duplicate tunnel ip detected: %v", tunnel.Src) } tunnel.Dst = nil glog.Infof("Potential tunnel found from %s", tunnel.Src) for _, route := range routes { if route.Src == nil || !route.Src.Equal(tunnel.Src) { continue } tunnel.Dst = route.Dst.IP break } if tunnel.Dst == nil { glog.Warningf("could not find dst for tunnel src %s", tunnel.Src) continue } err = reserveIP(tunnel.Dst) if err != nil { glog.Warningf("Duplicate tunnel ip detected: %v", tunnel.Dst) } var dst net.IP for _, policy := range policies { if !policy.Dst.IP.Equal(tunnel.Dst) { continue } if len(policy.Tmpls) == 0 { glog.Warningf("Tunnel policy has no associated template") continue } dst = policy.Tmpls[0].Dst break } if dst == nil { glog.Warningf("could not find ip for tunnel between %s and %s", tunnel.Src, tunnel.Dst) continue } for _, state := range states { if !state.Dst.Equal(dst) { continue } tunnel.Reqid = state.Reqid if state.Auth == nil { glog.Warningf("Tunnel state has no associated authentication entry") continue } tunnel.AuthKey = state.Auth.Key if state.Crypt == nil { glog.Warningf("Tunnel state has no associated encryption entry") continue } tunnel.EncKey = state.Crypt.Key if state.Encap != nil { tunnel.SrcPort = state.Encap.SrcPort tunnel.SrcPort = state.Encap.DstPort } glog.Infof("Discovered tunnel between %v and %v over %v", tunnel.Src, tunnel.Dst, dst) var socket int if tunnel.SrcPort != 0 { socket, err = createEncapListener(tunnel.Src, tunnel.SrcPort) if err != nil { glog.Warningf("Failed to create udp listener: %v", err) } } addTunnel(dst.String(), &tunnel, socket) break } } } glog.Infof("Finished discovering existing tunnels") }