예제 #1
0
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
}
예제 #2
0
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
}