func destroyTunnel(dst net.IP) (net.IP, error) { // Determine the src and dst ips for the tunnel key := dst.String() tunnel := getTunnel(dst.String()) if tunnel == nil { s := fmt.Sprintf("Failed to find tunnel to dst %s", dst) glog.Errorf(s) return nil, fmt.Errorf(s) } src := opts.src srcNet := netlink.NewIPNet(tunnel.Src) dstNet := netlink.NewIPNet(tunnel.Dst) glog.Infof("Destroying Tunnel: %v, %v", tunnel.Src, tunnel.Dst) for _, state := range getStates(tunnel.Reqid, src, dst, 0, 0, nil, nil) { // crate xfrm state rules err := netlink.XfrmStateDel(&state) if err != nil { glog.Errorf("Failed to delete state %v: %v", state, err) } } for _, policy := range getPolicies(tunnel.Reqid, src, dst, srcNet, dstNet) { // create xfrm policy rules err := netlink.XfrmPolicyDel(&policy) if err != nil { glog.Errorf("Failed to delete policy %v: %v", policy, err) } } index, err := getLinkIndex(src) if err != nil { glog.Errorf("Failed to get link for address: %v", err) } else { // del source route to tunnel ips device route := &netlink.Route{ Scope: netlink.SCOPE_LINK, Src: tunnel.Src, Dst: dstNet, LinkIndex: index, } err = netlink.RouteDel(route) if err != nil { glog.Errorf("Failed to delete route %v: %v", route, err) } } // del IP address to loopback device lo, err := netlink.LinkByName("lo") if err != nil { glog.Errorf("Failed to get loopback device: %v", err) } else { err = netlink.AddrDel(lo, &netlink.Addr{IPNet: srcNet}) if err != nil { glog.Errorf("Failed to delete %v from loopback: %v", tunnel.Src, err) } } if tunnel.SrcPort != 0 { deleteEncapListener(getListener(key)) releasePort(tunnel.SrcPort) } unreserveIP(tunnel.Src) unreserveIP(tunnel.Dst) removeTunnel(key) glog.Infof("Finished destroying tunnel: %v, %v", tunnel.Src, tunnel.Dst) return opts.external, nil }
func (o *Overlay) cleanup() error { changed := false defer func() { if !changed { return } time.Sleep(2 * time.Second) if err := o.loadConns(); err != nil { logrus.Errorf("Failed to reload connections: %v", err) } if err := o.configure(); err != nil { logrus.Errorf("Failed to reconfigure: %v", err) } }() o.Lock() defer o.Unlock() previouslyUnknown := o.unknownSpis o.unknownSpis = map[string]int{} client, err := getClient() if err != nil { return err } defer client.Close() conns, err := client.ListAllVpnConnInfo() if err != nil { return err } knownSpis := map[string]bool{} badConns := map[string]bool{} for _, conn := range conns { if conn.Local_host != "127.0.0.1" && conn.Local_host != o.db.LocalIpAddress() { badConns[conn.IkeSaName] = true if conn.ChildSaName != "" { logrus.Infof("Terminating connection: %s %s != %s", conn.IkeSaName, conn.Local_host, o.db.LocalIpAddress()) err := client.Terminate(&goStrongswanVici.TerminateRequest{ Ike: conn.IkeSaName, }) if err != nil { logrus.Infof("Failed to termination connection %s: %v", conn.ChildSaName, err) } } } children := []goStrongswanVici.Child_sas{conn.Child_sas} for _, child := range conn.IkeSa.Child_sas { children = append(children, child) } for _, child := range children { for _, i := range []string{child.Spi_in, child.Spi_out} { if i != "" { if badConns[conn.IkeSaName] { previouslyUnknown[i] = 4 } else { knownSpis[i] = true } } } } } if len(badConns) > 0 { changed = true logrus.Infof("Bad connections %v", badConns) for badConn, _ := range badConns { logrus.Infof("Deleting %s", badConn) err := client.UnloadConn(&goStrongswanVici.UnloadConnRequest{ Name: badConn, }) if err != nil { logrus.Infof("Failed to delete %s: %v", badConn, err) } } } stateList, err := netlink.XfrmStateList(netlink.FAMILY_V4) if err != nil { return err } for _, state := range stateList { spi := fmt.Sprintf("%x", state.Spi) if !knownSpis[spi] { if previouslyUnknown[spi] > 3 { logrus.Infof("Deleting unknown SPI %s: %#v", spi, state) netlink.XfrmStateDel(&state) } else { o.unknownSpis[spi] = previouslyUnknown[spi] + 1 } } } if len(o.unknownSpis) > 0 { logrus.Infof("Unknown SPIs: %#v, Conns: %#v", o.unknownSpis, conns) } return nil }