The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
switchdiscovery.c
Go to the documentation of this file.
1 
24 #include <projectcommon.h>
25 #include <memory.h>
26 #include <switchdiscovery.h>
27 #include <lldp.h>
28 #include <cdp.h>
29 #include <fsprotocol.h>
32 FSTATIC gboolean _switchdiscovery_cache_info(SwitchDiscovery* self, gconstpointer pkt, gconstpointer pend);
33 FSTATIC gboolean _switchdiscovery_dispatch(GSource_pcap_t* gsource, pcap_t*, gconstpointer, gconstpointer, const struct pcap_pkthdr* pkthdr, const char * capturedev, gpointer selfptr);
40 
42 
44 FSTATIC void
46 {
48  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts sent:"
49  , self->baseclass.reportcount);
50  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts received:"
51  , self->baseclass.discovercount);
52  if (self->source) {
53  g_source_unref(self->source);
54  g_source_destroy(self->source);
55  self->source = NULL;
56  }
57  if (self->switchid) {
58  g_free(self->switchid);
59  self->switchid = NULL;
60  }
61  if (self->portid) {
62  g_free(self->portid);
63  self->portid = NULL;
64  }
65 
66  // Call base object finalization routine (which we saved away)
67  self->finalize(&self->baseclass.baseclass);
68 }
69 
71 FSTATIC gboolean
73 {
74  (void)self;
75  return FALSE;
76 }
77 
78 
85 FSTATIC gboolean
87  pcap_t* capstruct,
88  gconstpointer pkt,
89  gconstpointer pend,
90  const struct pcap_pkthdr* pkthdr,
91  const char * capturedev,
92  gpointer selfptr
93  )
94 {
96  Discovery* dself = &(self->baseclass);
97  NetGSource* transport = dself->_iosource;
98  NetAddr* dest = dself->_config->getaddr(dself->_config, CONFIGNAME_CMADISCOVER);
99  FrameSet* fs;
100 
101  (void)gsource; (void)capstruct;
102  DEBUGMSG2("Got an incoming LLDP/CDP packet - dest is %p", dest);
104  ++ self->baseclass.discovercount;
105  if (!dest || !_switchdiscovery_cache_info(self, pkt, pend)) {
106  return TRUE;
107  }
108  ++ self->baseclass.reportcount;
109  DEBUGMSG2("Sending out LLDP/CDP packet - hurray!");
110  fs = construct_pcap_frameset(FRAMESETTYPE_SWDISCOVER, pkt, pend, pkthdr, capturedev);
111  transport->_netio->sendareliablefs(transport->_netio, dest, DEFAULT_FSP_QID, fs);
112  UNREF(fs);
113  return TRUE;
114 }
115 
116 #define DEFAULT_PROTOS (ENABLE_LLDP|ENABLE_CDP)
117 
118 FSTATIC guint
120 {
121  guint protoval = 0;
122  GSList* protoarray;
123  static struct protomap {
124  const char * protoname;
125  guint protobit;
126  }map[] = {
127  {"lldp", ENABLE_LLDP},
128  {"cdp", ENABLE_CDP},
129  };
130  DUMP2("_switchdiscovery_setprotocols: ", &cfg->baseclass, "");
131  for (protoarray = cfg->getarray(cfg, CONFIGNAME_SWPROTOS); protoarray
132  ; protoarray=protoarray->next) {
133  ConfigValue* elem;
134  gsize j;
135 
136  elem = CASTTOCLASS(ConfigValue, protoarray->data);
137  if (elem->valtype != CFG_STRING) {
138  continue;
139  }
140  for (j=0; j < DIMOF(map); ++j) {
141  if (strcmp(map[j].protoname, elem->u.strvalue) == 0) {
142  DEBUGMSG("%s.%d: protoname = %s", __FUNCTION__, __LINE__
143  , elem->u.strvalue);
144  protoval |= map[j].protobit;
145  continue;
146  }
147  }
148 
149  }
150  if (0 == protoval) {
151  DEBUGMSG("%s.%d: returning DEFAULT_PROTOS (0x%04x)", __FUNCTION__, __LINE__
152  , DEFAULT_PROTOS);
153  return DEFAULT_PROTOS;
154  }
155  DEBUGMSG("%s.%d: returning 0x%04x", __FUNCTION__, __LINE__, protoval);
156  return protoval;
157 
158 }
159 
164 , gint priority
165 , GMainContext* mcontext
166 , NetGSource* iosrc
168 , gsize objsize)
169 {
170  const char * instance;
171  const char * dev;
172  guint listenmask;
173  Discovery * dret;
174  SwitchDiscovery* ret;
176  DEBUG = (DEBUG < 2 ? 2 : DEBUG); // DEFAULT DEBUG ON FOR A WHILE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
177  g_return_val_if_fail(swconfig != NULL, NULL);
178  dev = swconfig->getstring(swconfig, CONFIGNAME_DEVNAME);
179  g_return_val_if_fail(dev != NULL, NULL);
180  instance = swconfig->getstring(swconfig, CONFIGNAME_INSTANCE);
181  g_return_val_if_fail(instance != NULL, NULL);
182  dret = discovery_new(instance, iosrc, config
183  , objsize < sizeof(SwitchDiscovery) ? sizeof(SwitchDiscovery) : objsize);
184  g_return_val_if_fail(dret != NULL, NULL);
185  proj_class_register_subclassed(dret, "SwitchDiscovery");
186  ret = CASTTOCLASS(SwitchDiscovery, dret);
187  ret->finalize = dret->baseclass._finalize;
190 
191  listenmask = _switchdiscovery_setprotocols(swconfig);
192  DEBUGMSG("%s.%d: dev=%s, listenmask = 0x%04x", __FUNCTION__, __LINE__, dev, listenmask);
193  ret->source = g_source_pcap_new(dev, listenmask, _switchdiscovery_dispatch, NULL, priority, FALSE, mcontext, 0, ret);
194 
195  if (objsize == sizeof(SwitchDiscovery)) {
196  // Subclass constructors need to register themselves, but we'll register
197  // ourselves.
198  discovery_register(dret);
199  }
200  ret->switchid = NULL; ret->switchidlen = -1;
201  ret->portid = NULL; ret->portidlen = -1;
202  return ret;
203 }
204 
205 typedef struct _SwitchDiscoveryType SwitchDiscoveryType;
206 static struct _SwitchDiscoveryType {
207  const char * discoverytype;
208  gboolean (*isthistype)(gconstpointer tlv_vp, gconstpointer pktend);
209  gconstpointer (*get_switch_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
210  gconstpointer (*get_port_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
211 } discovery_types[] = {
214 };
215 
218 FSTATIC gboolean
220  gconstpointer pkt,
221  gconstpointer pktend)
222 {
223  gsize j;
225 
226  for (j=0; j < DIMOF(discovery_types); ++j) {
227  gconstpointer curswitchid;
228  gssize curswitchidlen = -1;
229  gconstpointer curportid;
230  gssize curportidlen = -1;
231 
232  if (!discovery_types[j].isthistype(pkt, pktend)) {
233  continue;
234  }
235  curswitchid = discovery_types[j].get_switch_id(pkt, &curswitchidlen, pktend);
236  curportid = discovery_types[j].get_port_id(pkt, &curportidlen, pktend);
237  g_return_val_if_fail(curswitchid != NULL, FALSE);
238  g_return_val_if_fail(curportid != NULL, FALSE);
239 
240  if (self->switchid == NULL || self->portid == NULL
241  || curportidlen != self->portidlen || curswitchidlen != self->switchidlen
242  || memcmp(curswitchid, self->switchid, curswitchidlen) != 0
243  || memcmp(curportid, self->portid, curportidlen) != 0) {
244 
245  if (self->switchid != NULL) {
246  FREE(self->switchid); self->switchid = NULL;
247  }
248  if (self->portid != NULL) {
249  FREE(self->portid); self->portid = NULL;
250  }
251  self->switchid = g_memdup(curswitchid, curswitchidlen);
252  self->portid = g_memdup(curportid, curportidlen);
253  self->switchidlen = curswitchidlen;
254  self->portidlen = curportidlen;
255  return TRUE;
256  }
257  break;
258  }
259  return FALSE;
260 }
const void * get_lldp_port_id(gconstpointer tlv_vp, gssize *idlength, gconstpointer pktend)
Return a pointer to the port id Value entry, and its length.
Definition: lldp_min.c:241
gpointer switchid
Saved parent class destructor.
#define CONFIGNAME_CMADISCOVER
Address of where to send discovery reports.
#define ENABLE_CDP
Enable CDP protocol.
Definition: pcap_min.h:42
#define CONFIGNAME_SWPROTOS
List of switch protocols as an array of strings.
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
enum ConfigValType valtype
Definition: configcontext.h:59
void discovery_register(Discovery *self)
Function for registering a discovery object with the discovery infrastructure.
Definition: discovery.c:174
WINEXPORT gboolean is_valid_cdp_packet(const void *packet, const void *pktend)
Check to see if this is a valid CDP packet.
Definition: cdp_min.c:93
#define ENABLE_LLDP
Enable LLDP protocol.
Definition: pcap_min.h:40
NetIO * _netio
netio this object is based on
Definition: netgsource.h:50
FSTATIC gboolean _switchdiscovery_cache_info(SwitchDiscovery *self, gconstpointer pkt, gconstpointer pend)
char * strvalue
Definition: configcontext.h:64
#define DEBUGMSG(...)
Definition: proj_classes.h:87
GSource * g_source_pcap_new(const char *dev, unsigned listenmask, gboolean(*dispatch)(GSource_pcap_t *gsource, pcap_t *capstruct, gconstpointer pkt, gconstpointer pend, const struct pcap_pkthdr *pkthdr, const char *capturedev, gpointer userdata), GDestroyNotify notify, gint priority, gboolean can_recurse, GMainContext *context, gsize objectsize, gpointer userdata)
Construct new GSource from a newly constructed pcap capture object.
Definition: pcap_GSource.c:86
void(* finalize)(AssimObj *self)
GSource for the pcap data.
struct _SwitchDiscoveryType SwitchDiscoveryType
WINEXPORT const void * get_cdp_port_id(gconstpointer packet, gssize *idlength, gconstpointer pktend)
get the port ID associated with this CDP packet
Definition: cdp_min.c:297
#define FSTATIC
Definition: projectcommon.h:31
GSource * source
Base class object.
SwitchDiscovery C-class - for discovering switch and port configuration via LLDP, CDP and similar pro...
Discovery * discovery_new(const char *instname, NetGSource *iosource, ConfigContext *context, gsize objsize)
Discovery constructor.
Definition: discovery.c:143
FSTATIC gboolean _switchdiscovery_discover(Discovery *self)
Discover member function for timed discovery – not applicable – return FALSE.
#define DEFAULT_PROTOS
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
NetAddr *(* getaddr)(const ConfigContext *, const char *name)
Get NetAddr value.
Definition: configcontext.h:92
FrameSet * construct_pcap_frameset(guint16 framesettype, gconstpointer pkt, gconstpointer pktend, const struct pcap_pkthdr *pkthdr, const char *interfacep)
Construct a PCAP capture FrameSet from a PCAP packet.
Definition: pcap_GSource.c:237
union _ConfigValue::@2 u
Class for discovering Link-Level (switch) information (using CDP or LLDP or some future analogous pro...
AssimObj baseclass
Definition: configcontext.h:72
#define __FUNCTION__
#define DEBUG
Definition: proj_classes.h:85
GSList *(* getarray)(const ConfigContext *, const char *name)
Get array value.
Definition: configcontext.h:84
gpointer portid
Length of 'switchid'.
SwitchDiscovery * switchdiscovery_new(ConfigContext *swconfig, gint priority, GMainContext *mcontext, NetGSource *iosrc, ConfigContext *config, gsize objsize)
SwitchDiscovery constructor.
NetGSource * _iosource
How to send packets.
Definition: discovery.h:61
gpointer proj_class_register_subclassed(gpointer object, const char *static_subclassname)
Log the creation of a subclassed object from a superclassed object.
Definition: proj_classes.c:192
FSTATIC void _switchdiscovery_finalize(AssimObj *self)
finalize a SwitchDiscovery object
#define CONFIGNAME_DEVNAME
Name of NIC for discovery.
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
WINEXPORT const void * get_cdp_chassis_id(gconstpointer packet, gssize *idlength, gconstpointer pktend)
Get the chassis ID associated with this CDP packet.
Definition: cdp_min.c:276
Provides basic Link Layer Discovery Protocol (LLDP) definitions and accessor functions for LLPD packe...
Project common header file.
#define DIMOF(a)
Definition: lldp_min.c:30
const void * get_lldp_chassis_id(gconstpointer tlv_vp, gssize *idlength, gconstpointer pktend)
Return a pointer to the chassis id Value entry, and its length.
Definition: lldp_min.c:224
gssize switchidlen
Current switch identification information.
g_main_loop GSource object for creating events from libpcap (pcap_t) objects We manage this with our ...
Definition: pcap_GSource.h:38
Discovery class abstract C-class - it supports discovering "things" through subclasses for different ...
Definition: discovery.h:47
gboolean sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
[out] source address of return result
gssize portidlen
Current port id information.
#define FRAMESETTYPE_SWDISCOVER
Packet encapsulates switch discovery packet.
Definition: framesettypes.h:44
FSTATIC guint _switchdiscovery_setprotocols(ConfigContext *cfg)
Header file for various basic CDP (Cisco Discovery Protocol definitions and accessor functions...
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
#define g_info(...)
Definition: projectcommon.h:66
#define DEFAULT_FSP_QID
Default Queue ID.
Definition: fsprotocol.h:127
#define CONFIGNAME_INSTANCE
Instance name for discovery.
gboolean(* discover)(Discovery *self)
Perform the discovery.
Definition: discovery.h:51
gboolean is_valid_lldp_packet(const void *tlv_vp, const void *pktend)
Definition: lldp_min.c:116
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
FSTATIC gboolean _switchdiscovery_dispatch(GSource_pcap_t *gsource, pcap_t *, gconstpointer, gconstpointer, const struct pcap_pkthdr *pkthdr, const char *capturedev, gpointer selfptr)
Internal pcap gsource dispatch routine - called when we get a packet.
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
#define DUMP2(prefix, obj, suffix)
Definition: proj_classes.h:96
#define DEBUGMSG2(...)
Definition: proj_classes.h:90
ConfigContext * _config
Configuration Parameters - has address of CMA.
Definition: discovery.h:62
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
Implements the FsProtocol object.
AssimObj baseclass
Base object class.
Definition: discovery.h:48
The NetGSource class objects integrate NetIO class objects into the g_main_loop paradigm.
Definition: netgsource.h:43
ReliableUDP * transport
Definition: pinger.c:70