Guest User

lldp.go

a guest
Oct 24th, 2022
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 5.01 KB | Source Code | 0 0
  1. package main
  2.  
  3. import "github.com/RackHD/inservice/plugins/lldp/neighbors"
  4. import "github.com/RackHD/inservice/plugins/lldp/grpc/lldp"
  5. import "google.golang.org/grpc"
  6. import "time"
  7. import "net"
  8. import "fmt"
  9. import "log"
  10. import "sync"
  11. import (
  12.         "github.com/google/gopacket"
  13.     "github.com/google/gopacket/pcap"
  14.     "golang.org/x/net/context"
  15. )
  16.  
  17.  
  18. // LLDPPlugin implements the Plugin interface.
  19. type LLDPPlugin struct {
  20.     address     string
  21.     port        int
  22.     interfaces  []string
  23.     promiscuous bool
  24.     timeout     time.Duration
  25.     start       chan bool
  26.     stop        chan bool
  27.     packets     chan neighbors.Packet
  28.     wg          *sync.WaitGroup
  29.     Neighbors   neighbors.Neighbors
  30. }
  31.  
  32. // NewLLDPPlugin initializes a new LLDPPlugin struct.
  33. func NewLLDPPlugin(address string, port int, interfaces []string) (*LLDPPlugin, error) {
  34.     if ip := net.ParseIP(address); ip == nil {
  35.         return nil, fmt.Errorf("IP Address Not Valid")
  36.     }
  37.     if 0 >= port || port >= 65535 {
  38.         return nil, fmt.Errorf("Invalid Port Selection")
  39.     }
  40.     ifaces := []net.Interface{}
  41.     for _, iface := range interfaces {
  42.         netDev, err := net.InterfaceByName(iface)
  43.         if err != nil {
  44.             log.Println("No interface named: ", iface)
  45.             continue
  46.         }
  47.         ifaces = append(ifaces, *netDev)
  48.     }
  49.     if len(ifaces) < 1 {
  50.         return nil, fmt.Errorf("No valid interfaces selected")
  51.     }
  52.     start := make(chan bool)
  53.     wg := &sync.WaitGroup{}
  54.     n, err := neighbors.NewNeighbors()
  55.     if err != nil {
  56.         log.Println("Error initializing neighbors")
  57.     }
  58.     n.NetDevList = ifaces //hitting some linter error where this cant be an argument
  59.     return &LLDPPlugin{
  60.         address:     address,
  61.         port:        port,
  62.         interfaces:  interfaces,
  63.         promiscuous: true,
  64.         timeout:     30 * time.Second,
  65.         start:       start,
  66.         stop:        nil,
  67.         wg:          wg,
  68.         Neighbors:   *n,
  69.     }, nil
  70. }
  71.  
  72. // Start handles plugin startup. This creates goroutines to handle the packet capture
  73. // and serve the gRPC API or REST API
  74. func (p *LLDPPlugin) Start() error {
  75.     log.Println("LLDP Plugin Started.")
  76.     p.stop = make(chan bool)
  77.     p.wg.Add(1)
  78.     go p.Capture()
  79.     p.wg.Add(1)
  80.     go p.Serve()
  81.     time.Sleep(10 * time.Second)
  82.     p.start <- true
  83.     return nil
  84. }
  85.  
  86. // Stop closes a channel that should stop all capture
  87. func (p *LLDPPlugin) Stop(ctx context.Context) error {
  88.     log.Println("LLDP Plugin Stopped.")
  89.     close(p.stop)
  90.     p.wg.Wait()
  91.     return nil
  92. }
  93.  
  94. // Status is a dummy function for now until a better status mechanism is identified
  95. func (p *LLDPPlugin) Status(ctx context.Context) error {
  96.     log.Println("LLDP Plugin Stopped.")
  97.     return nil
  98. }
  99.  
  100. // Serve creates the gRPC and REST endpoints for external model access
  101. func (p *LLDPPlugin) Serve() {
  102.     listenAddr := fmt.Sprintf("%s:%d", p.address, p.port)
  103.     listen, err := net.Listen("tcp", listenAddr)
  104.     if err != nil {
  105.         log.Fatalf("Failed to Listen: %v", err)
  106.     }
  107.  
  108.     server := grpc.NewServer()
  109.     lldp.RegisterLldpServer(server, &p.Neighbors)
  110.  
  111.     server.Serve(listen)
  112. }
  113.  
  114. // Capture opens an LLDP hook for each interface and processes packets.
  115. func (p *LLDPPlugin) Capture() {
  116.     log.Println("Started Capture")
  117.     p.packets = make(chan neighbors.Packet, 1000)
  118.     defer close(p.packets)
  119.     for {
  120.         select {
  121.         case <-p.start:
  122.             // create all interfaces
  123.             for _, iface := range p.Neighbors.NetDevList {
  124.                 p.wg.Add(1)
  125.                 go p.openInterface(iface)
  126.             }
  127.             // process captured packets
  128.             p.wg.Add(1)
  129.             go func(p *LLDPPlugin) {
  130.                 for {
  131.                     select {
  132.                     case <-p.stop:
  133.                         log.Println("Stopping aggregator")
  134.                         p.wg.Done()
  135.                         return
  136.                     case recPacket := <-p.packets:
  137.                         p.wg.Add(1)
  138.                         fmt.Println(recPacket)
  139.                         go p.Neighbors.ProcessPacket(p.wg, recPacket)
  140.                     }
  141.                 }
  142.             }(p)
  143.         case <-p.stop:
  144.             p.wg.Done()
  145.             log.Println("Waited for all processes to stop")
  146.             return
  147.         }
  148.     }
  149. }
  150.  
  151. // openInterface creates a handle for each interface in the configuration and pushes
  152. // packet to the global processing channel
  153. func (p *LLDPPlugin) openInterface(iface net.Interface) error {
  154.     log.Println("Opened interface: ", iface.Name)
  155.     handle, err := pcap.OpenLive(iface.Name, 65536, p.promiscuous, p.timeout)
  156.     if err != nil {
  157.         return err
  158.     }
  159.     defer handle.Close()
  160.     err = handle.SetBPFFilter("ether proto 0x88cc")
  161.     if err != nil {
  162.         return err
  163.     }
  164.     src := gopacket.NewPacketSource(handle, handle.LinkType())
  165.     in := src.Packets()
  166.     for {
  167.         var packet gopacket.Packet
  168.         select {
  169.         case <-p.stop:
  170.             log.Println("Exiting: ", iface.Name)
  171.             handle.Close()
  172.             p.wg.Done()
  173.             return nil
  174.         case packet = <-in:
  175.             p.packets <- neighbors.Packet{Iface: iface, Packet: packet}
  176.         }
  177.     }
  178. }
  179.  
  180. func main() {
  181.     address := "127.0.0.1"
  182.     port := 9999
  183.     interfaces := []string{"en0"}
  184.  
  185.     myPlugin, _ := NewLLDPPlugin(address, port, interfaces);
  186.  
  187.     //myPlugin.wg.Add(1)
  188.     //myPlugin.Capture()
  189.     //what := context.Context
  190.     myPlugin.Start()
  191.  
  192.     time.Sleep(2 * time.Second)
  193.  
  194.  
  195.   fmt.Println("SysName: %s", myPlugin.Neighbors.SysName, "lol")
  196.  
  197.     myPlugin.stop <- true
  198.     myPlugin.wg.Wait()
  199.  
  200.     time.Sleep(2 * time.Second)
  201.  
  202.     fmt.Println("SysName: %s", myPlugin.Neighbors.SysName, "lol")
  203.  
  204. }
  205.  
Advertisement
Add Comment
Please, Sign In to add comment