Beispiel #1
0
func (u *NetLinkProbe) handleIntfIsVeth(intf *graph.Node, link netlink.Link) {
	if link.Type() != "veth" {
		return
	}

	if index, ok := intf.Metadata()["PeerIfIndex"]; ok {
		peerResolver := func() error {
			// re get the interface from the graph since the interface could have been deleted
			if u.Graph.GetNode(intf.ID) == nil {
				return errors.New("Node not found")
			}

			// got more than 1 peer, unable to find the right one, wait for the other to discover
			peer := u.Graph.LookupFirstNode(graph.Metadata{"IfIndex": index.(int64), "Type": "veth"})
			if peer != nil && !u.Graph.AreLinked(peer, intf) {
				u.Graph.Link(peer, intf, graph.Metadata{"RelationType": "layer2", "Type": "veth"})
				return nil
			}
			return errors.New("Nodes not linked")
		}

		if index.(int64) > intf.Metadata()["IfIndex"].(int64) {
			if err := peerResolver(); err != nil {
				retryFnc := func() error {
					if u.isRunning() == false {
						return nil
					}
					u.Graph.Lock()
					defer u.Graph.Unlock()
					return peerResolver()
				}
				go common.Retry(retryFnc, 10, 200*time.Millisecond)
			}
		}
	}
}
Beispiel #2
0
func (p *GoPacketProbesHandler) RegisterProbe(n *graph.Node, capture *api.Capture, ft *flow.Table) error {
	name, ok := n.Metadata()["Name"]
	if !ok || name == "" {
		return fmt.Errorf("No name for node %v", n)
	}

	id := string(n.ID)
	ifName := name.(string)

	if _, ok := p.probes[id]; ok {
		return fmt.Errorf("Already registered %s", ifName)
	}

	nodes := p.graph.LookupShortestPath(n, graph.Metadata{"Type": "host"}, graph.Metadata{"RelationType": "ownership"})
	if len(nodes) == 0 {
		return fmt.Errorf("Failed to determine probePath for %s", ifName)
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	origns, err := netns.Get()
	if err != nil {
		return fmt.Errorf("Error while getting current ns: %s", err.Error())
	}
	defer origns.Close()

	for _, node := range nodes {
		if node.Metadata()["Type"] == "netns" {
			name := node.Metadata()["Name"].(string)
			path := node.Metadata()["Path"].(string)
			logging.GetLogger().Debugf("Switching to namespace %s (path: %s)", name, path)

			newns, err := netns.GetFromPath(path)
			if err != nil {
				return fmt.Errorf("Error while opening ns %s (path: %s): %s", name, path, err.Error())
			}
			defer newns.Close()

			if err := netns.Set(newns); err != nil {
				return fmt.Errorf("Error while switching from root ns to %s (path: %s): %s", name, path, err.Error())
			}
			defer netns.Set(origns)
		}
	}

	probe := &GoPacketProbe{
		NodeUUID:  id,
		state:     common.StoppedState,
		flowTable: ft,
	}

	switch capture.Type {
	case "pcap":
		handle, err := pcap.OpenLive(ifName, snaplen, true, time.Second)
		if err != nil {
			return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error())
		}

		if err := handle.SetBPFFilter(capture.BPFFilter); err != nil {
			return fmt.Errorf("BPF Filter failed: %s", err)
		}

		probe.handle = handle
		probe.packetSource = gopacket.NewPacketSource(handle, getGoPacketFirstLayerType(n))

		logging.GetLogger().Infof("PCAP Capture type %s started on %s", capture.Type, n.Metadata()["Name"])
	default:
		var handle *AFPacketHandle
		fnc := func() error {
			handle, err = NewAFPacketHandle(ifName, snaplen)
			if err != nil {
				return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error())
			}
			return nil
		}

		if err = common.Retry(fnc, 2, 100*time.Millisecond); err != nil {
			return err
		}

		probe.handle = handle
		probe.packetSource = gopacket.NewPacketSource(handle, getGoPacketFirstLayerType(n))

		logging.GetLogger().Infof("AfPacket Capture started on %s", n.Metadata()["Name"])
	}

	p.probesLock.Lock()
	p.probes[id] = probe
	p.probesLock.Unlock()
	p.wg.Add(1)

	go func() {
		defer p.wg.Done()

		probe.start()
	}()

	return nil
}
Beispiel #3
0
func (p *GoPacketProbe) run(g *graph.Graph, n *graph.Node, capture *api.Capture) error {
	atomic.StoreInt64(&p.state, common.RunningState)

	g.RLock()
	ifName := n.Metadata()["Name"].(string)
	firstLayerType := getGoPacketFirstLayerType(n)

	nscontext, err := topology.NewNetNSContextByNode(g, n)
	g.RUnlock()

	defer nscontext.Close()

	if err != nil {
		return err
	}

	switch capture.Type {
	case "pcap":
		handle, err := pcap.OpenLive(ifName, snaplen, true, time.Second)
		if err != nil {
			return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error())
		}

		if err := handle.SetBPFFilter(capture.BPFFilter); err != nil {
			return fmt.Errorf("BPF Filter failed: %s", err)
		}

		p.handle = handle
		p.packetSource = gopacket.NewPacketSource(handle, handle.LinkType())

		logging.GetLogger().Infof("PCAP Capture started on %s with First layer: %s", ifName, firstLayerType)
	default:
		var handle *AFPacketHandle
		fnc := func() error {
			handle, err = NewAFPacketHandle(ifName, snaplen)
			if err != nil {
				return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error())
			}
			return nil
		}

		if err = common.Retry(fnc, 2, 100*time.Millisecond); err != nil {
			return err
		}

		p.handle = handle
		p.packetSource = gopacket.NewPacketSource(handle, firstLayerType)

		logging.GetLogger().Infof("AfPacket Capture started on %s with First layer: %s", ifName, firstLayerType)
	}

	// leave the namespace, stay lock in the current thread
	nscontext.Quit()

	packetsChan := p.flowTable.Start()
	defer p.flowTable.Stop()

	p.feedFlowTable(packetsChan)

	return nil
}
Beispiel #4
0
func (u *NetNSProbe) Register(path string, extraMetadata graph.Metadata) *graph.Node {
	// When a new network namespace has been seen by inotify, the path to
	// the namespace may still be a regular file, not a bind mount to the
	// file in /proc/<pid>/tasks/<tid>/ns/net yet, so we wait a bit for the
	// bind mount to be set up
	var newns *NetNs
	err := common.Retry(func() error {
		var stats syscall.Stat_t
		fd, err := syscall.Open(path, syscall.O_RDONLY, 0)
		if err != nil {
			return err
		}

		err = syscall.Fstat(fd, &stats)
		syscall.Close(fd)
		if err != nil {
			return err
		}

		if stats.Dev != u.rootNsDev {
			return fmt.Errorf("%s does not seem to be a valid namespace", path)
		}

		newns = &NetNs{path: path, dev: stats.Dev, ino: stats.Ino}
		return nil
	}, 10, time.Millisecond*20)

	if err != nil {
		logging.GetLogger().Errorf("Could not register namespace: %s", err.Error())
		return nil
	}

	_, ok := u.pathToNetNS[path]
	if !ok {
		u.pathToNetNS[path] = newns
	}

	u.Lock()
	defer u.Unlock()

	nsString := newns.String()
	probe, ok := u.nsnlProbes[nsString]
	if ok {
		probe.useCount++
		logging.GetLogger().Debugf("Increasing counter for namespace %s to %d", nsString, probe.useCount)
		return probe.Root
	}

	u.Graph.Lock()
	defer u.Graph.Unlock()

	logging.GetLogger().Debugf("Network Namespace added: %s", nsString)
	metadata := graph.Metadata{"Name": getNetNSName(path), "Type": "netns", "Path": path}
	if extraMetadata != nil {
		for k, v := range extraMetadata {
			metadata[k] = v
		}
	}
	n := u.Graph.NewNode(graph.GenID(), metadata)
	u.Graph.Link(u.Root, n, graph.Metadata{"RelationType": "ownership"})

	nu := NewNetNsNetLinkTopoUpdater(u.Graph, n)
	nu.Start(newns)

	u.nsnlProbes[nsString] = nu

	return n
}