The Assimilation Project  based on Assimilation version 1.1.2.1454953989
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);
35 FSTATIC void _dumphex(const char * id, gconstpointer idstart, gssize len);
41 
43 
45 FSTATIC void
47 {
49  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts sent:"
50  , self->baseclass.reportcount);
51  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts received:"
52  , self->baseclass.discovercount);
53  if (self->source) {
54  g_source_unref(self->source);
55  g_source_destroy(self->source);
56  self->source = NULL;
57  }
58  if (self->switchid) {
59  g_free(self->switchid);
60  self->switchid = NULL;
61  }
62  if (self->portid) {
63  g_free(self->portid);
64  self->portid = NULL;
65  }
66 
67  // Call base object finalization routine (which we saved away)
68  self->finalize(&self->baseclass.baseclass);
69 }
70 
72 FSTATIC gboolean
74 {
75  (void)self;
76  return FALSE;
77 }
78 
79 
86 FSTATIC gboolean
88  pcap_t* capstruct,
89  gconstpointer pkt,
90  gconstpointer pend,
91  const struct pcap_pkthdr* pkthdr,
92  const char * capturedev,
93  gpointer selfptr
94  )
95 {
97  Discovery* dself = &(self->baseclass);
98  NetGSource* transport = dself->_iosource;
99  NetAddr* dest = dself->_config->getaddr(dself->_config, CONFIGNAME_CMADISCOVER);
100  FrameSet* fs;
101 
102  (void)gsource; (void)capstruct;
103  DEBUGMSG2("Got an incoming LLDP/CDP packet - dest is %p", dest);
105  ++ self->baseclass.discovercount;
106  if (!dest || !_switchdiscovery_cache_info(self, pkt, pend)) {
107  DEBUGMSG5("NOT Sending out LLDP/CDP packet - (already cached)");
108  return TRUE;
109  }
110  ++ self->baseclass.reportcount;
111  DEBUGMSG2("Sending out LLDP/CDP packet - hurray!");
112  fs = construct_pcap_frameset(FRAMESETTYPE_SWDISCOVER, pkt, pend, pkthdr, capturedev,
113  self->baseclass.instancename(&self->baseclass));
114  transport->_netio->sendareliablefs(transport->_netio, dest, DEFAULT_FSP_QID, fs);
115  UNREF(fs);
116  return TRUE;
117 }
118 
119 #define DEFAULT_PROTOS (ENABLE_LLDP|ENABLE_CDP)
120 
121 FSTATIC guint
123 {
124  guint protoval = 0;
125  GSList* protoarray;
126  static struct protomap {
127  const char * protoname;
128  guint protobit;
129  }map[] = {
130  {"lldp", ENABLE_LLDP},
131  {"cdp", ENABLE_CDP},
132  };
133  DUMP2("_switchdiscovery_setprotocols: ", &cfg->baseclass, "");
134  for (protoarray = cfg->getarray(cfg, CONFIGNAME_SWPROTOS); protoarray
135  ; protoarray=protoarray->next) {
136  ConfigValue* elem;
137  gsize j;
138 
139  elem = CASTTOCLASS(ConfigValue, protoarray->data);
140  if (elem->valtype != CFG_STRING) {
141  continue;
142  }
143  for (j=0; j < DIMOF(map); ++j) {
144  if (strcmp(map[j].protoname, elem->u.strvalue) == 0) {
145  DEBUGMSG2("%s.%d: protoname = %s", __FUNCTION__, __LINE__
146  , elem->u.strvalue);
147  protoval |= map[j].protobit;
148  continue;
149  }
150  }
151 
152  }
153  if (0 == protoval) {
154  DEBUGMSG2("%s.%d: returning DEFAULT_PROTOS (0x%04x)", __FUNCTION__, __LINE__
155  , DEFAULT_PROTOS);
156  return DEFAULT_PROTOS;
157  }
158  DEBUGMSG2("%s.%d: returning 0x%04x", __FUNCTION__, __LINE__, protoval);
159  return protoval;
160 
161 }
162 
167 , gint priority
168 , GMainContext* mcontext
169 , NetGSource* iosrc
171 , gsize objsize)
172 {
173  const char * instance;
174  const char * dev;
175  guint listenmask;
176  Discovery * dret;
177  SwitchDiscovery* ret;
179  g_return_val_if_fail(swconfig != NULL, NULL);
180  dev = swconfig->getstring(swconfig, CONFIGNAME_DEVNAME);
181  g_return_val_if_fail(dev != NULL, NULL);
182  instance = swconfig->getstring(swconfig, CONFIGNAME_INSTANCE);
183  g_return_val_if_fail(instance != NULL, NULL);
184  if (objsize < sizeof(SwitchDiscovery)) {
185  objsize = sizeof(SwitchDiscovery);
186  }
187  //fprintf(stderr, "%s:%d: instance = %s, dev=%s", __FUNCTION__, __LINE__, instance, dev);
188  dret = discovery_new(instance, iosrc, config, objsize);
189  g_return_val_if_fail(dret != NULL, NULL);
190  proj_class_register_subclassed(dret, "SwitchDiscovery");
191  ret = CASTTOCLASS(SwitchDiscovery, dret);
192  ret->finalize = dret->baseclass._finalize;
195 
196  listenmask = _switchdiscovery_setprotocols(swconfig);
197  DEBUGMSG("%s.%d: dev=%s, listenmask = 0x%04x", __FUNCTION__, __LINE__, dev, listenmask);
198  ret->source = g_source_pcap_new(dev, listenmask, _switchdiscovery_dispatch, NULL, priority, FALSE, mcontext, 0, ret);
199 
200  if (objsize == sizeof(SwitchDiscovery)) {
201  // Subclass constructors need to register themselves, but we'll register
202  // ourselves.
203  DUMP3("Registering switch discovery", &dret->baseclass, dret->instancename(dret));
204  discovery_register(dret);
205  }
206  ret->switchid = NULL; ret->switchidlen = -1;
207  ret->portid = NULL; ret->portidlen = -1;
208  return ret;
209 }
210 
212 FSTATIC void
213 _dumphex(const char * id, gconstpointer idstart, gssize len)
214 {
215  gssize j;
216  fprintf(stderr, "HEX[%d]: %s:", (int)(len), id);
217  for (j=0; j < len; ++j) {
218  fprintf(stderr, " %02x", ((const guint8*)idstart)[j]);
219  }
220  fprintf(stderr, "\n");
221 }
222 
223 typedef struct _SwitchDiscoveryType SwitchDiscoveryType;
224 static struct _SwitchDiscoveryType {
225  const char * discoverytype;
226  gboolean (*isthistype)(gconstpointer tlv_vp, gconstpointer pktend);
227  gconstpointer (*get_switch_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
228  gconstpointer (*get_port_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
229 } discovery_types[] = {
232 };
233 
236 FSTATIC gboolean
238  gconstpointer pkt,
239  gconstpointer pktend)
240 {
241  gsize j;
243 
244  for (j=0; j < DIMOF(discovery_types); ++j) {
245  gconstpointer curswitchid;
246  gssize curswitchidlen = -1;
247  gconstpointer curportid;
248  gssize curportidlen = -1;
249 
250  if (!discovery_types[j].isthistype(pkt, pktend)) {
251  continue;
252  }
253  curswitchid = discovery_types[j].get_switch_id(pkt, &curswitchidlen, pktend);
254  curportid = discovery_types[j].get_port_id(pkt, &curportidlen, pktend);
255  g_return_val_if_fail(curswitchid != NULL, FALSE);
256  g_return_val_if_fail(curportid != NULL, FALSE);
257  if (DEBUG > 3) {
258  _dumphex("switch id", curswitchid, curswitchidlen);
259  _dumphex("port id", curportid, curportidlen);
260  }
261  if (DEBUG >= 3 && NULL != self->switchid) {
262  _dumphex("previous switch id", self->switchid, self->switchidlen);
263  }
264  if (DEBUG >= 3 && NULL != self->portid) {
265  _dumphex("previous port id", self->portid, self->portidlen);
266  }
267 
268  if (self->switchid == NULL || self->portid == NULL
269  || curportidlen != self->portidlen || curswitchidlen != self->switchidlen
270  || memcmp(curswitchid, self->switchid, curswitchidlen) != 0
271  || memcmp(curportid, self->portid, curportidlen) != 0) {
272 
273  if (self->switchid != NULL) {
274  FREE(self->switchid); self->switchid = NULL;
275  }
276  if (self->portid != NULL) {
277  FREE(self->portid); self->portid = NULL;
278  }
279  self->switchid = g_memdup(curswitchid, curswitchidlen);
280  self->portid = g_memdup(curportid, curportidlen);
281  self->switchidlen = curswitchidlen;
282  self->portidlen = curportidlen;
283  DEBUGMSG2("Caching current %s switch info...", discovery_types[j].discoverytype);
284  return TRUE;
285  }
286  break;
287  }
288  return FALSE;
289 }
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:262
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:44
#define CONFIGNAME_SWPROTOS
List of switch protocols as an array of strings.
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
gboolean(* discover)(Discovery *self)
Perform the discovery.
Definition: discovery.h:51
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:94
#define ENABLE_LLDP
Enable LLDP protocol.
Definition: pcap_min.h:42
NetIO * _netio
netio this object is based on
Definition: netgsource.h:50
GSList *(* getarray)(const ConfigContext *, const char *name)
Get array value.
Definition: configcontext.h:84
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
#define DEBUGMSG5(...)
Definition: proj_classes.h:93
struct _SwitchDiscoveryType SwitchDiscoveryType
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
struct _SwitchDiscovery SwitchDiscovery
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:314
#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.
void(* finalize)(AssimObj *self)
GSource for the pcap data.
#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
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
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
#define DUMP3(prefix, obj, suffix)
Definition: proj_classes.h:97
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:293
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:245
gssize switchidlen
Current switch identification information.
char *(* instancename)(const Discovery *self)
Which object is this?
Definition: discovery.h:49
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...
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
FrameSet * construct_pcap_frameset(guint16 framesettype, gconstpointer pkt, gconstpointer pktend, const struct pcap_pkthdr *pkthdr, const char *interfacep, const char *instancename)
Construct a PCAP capture FrameSet from a PCAP packet.
Definition: pcap_GSource.c:240
#define DEFAULT_FSP_QID
Default Queue ID.
Definition: fsprotocol.h:134
#define CONFIGNAME_INSTANCE
Instance name for discovery.
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
NetAddr *(* getaddr)(const ConfigContext *, const char *name)
Get NetAddr value.
Definition: configcontext.h:92
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
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
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:72
FSTATIC void _dumphex(const char *id, gconstpointer idstart, gssize len)
Dump stuff out in hex with a label...