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 FSTATIC void
44 {
46  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts sent:"
47  , self->baseclass.reportcount);
48  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of LLDP/CDP pkts received:"
49  , self->baseclass.discovercount);
50  if (self->source) {
51  g_source_unref(self->source);
52  g_source_destroy(self->source);
53  self->source = NULL;
54  }
55  if (self->switchid) {
56  g_free(self->switchid);
57  self->switchid = NULL;
58  }
59  if (self->portid) {
60  g_free(self->portid);
61  self->portid = NULL;
62  }
63 
64  // Call base object finalization routine (which we saved away)
65  self->finalize(&self->baseclass.baseclass);
66 }
67 
69 FSTATIC gboolean
71 {
72  (void)self;
73  return FALSE;
74 }
75 
76 
83 FSTATIC gboolean
85  pcap_t* capstruct,
86  gconstpointer pkt,
87  gconstpointer pend,
88  const struct pcap_pkthdr* pkthdr,
89  const char * capturedev,
90  gpointer selfptr
91  )
92 {
94  Discovery* dself = &(self->baseclass);
95  NetGSource* transport = dself->_iosource;
96  NetAddr* dest = dself->_config->getaddr(dself->_config, CONFIGNAME_CMADISCOVER);
97  FrameSet* fs;
98 
99  (void)gsource; (void)capstruct;
100  //g_debug("Got an incoming LLDP/CDP packet - dest is %p", dest);
102  ++ self->baseclass.discovercount;
103  if (!dest || !_switchdiscovery_cache_info(self, pkt, pend)) {
104  return TRUE;
105  }
106  ++ self->baseclass.reportcount;
107  //g_debug("Sending out LLDP/CDP packet - hurray!");
108  fs = construct_pcap_frameset(FRAMESETTYPE_SWDISCOVER, pkt, pend, pkthdr, capturedev);
109  transport->_netio->sendareliablefs(transport->_netio, dest, DEFAULT_FSP_QID, fs);
110  UNREF(fs);
111  return TRUE;
112 }
113 
114 #define DEFAULT_PROTOS (ENABLE_LLDP|ENABLE_CDP)
115 
116 FSTATIC guint
118 {
119  guint protoval = 0;
120  GSList* protoarray;
121  static struct protomap {
122  const char * protoname;
123  guint protobit;
124  }map[] = {
125  {"lldp", ENABLE_LLDP},
126  {"cdp", ENABLE_CDP},
127  };
128  for (protoarray = cfg->getarray(cfg, CONFIGNAME_SWPROTOS); protoarray
129  ; protoarray=protoarray->next) {
130  ConfigValue* elem;
131  gsize j;
132 
133  elem = CASTTOCLASS(ConfigValue, protoarray->data);
134  if (elem->valtype != CFG_STRING) {
135  continue;
136  }
137  for (j=0; j < DIMOF(map); ++j) {
138  if (strcmp(map[j].protoname, elem->u.strvalue) == 0) {
139  protoval |= map[j].protobit;
140  continue;
141  }
142  }
143 
144  }
145  if (0 == protoval) {
146  return DEFAULT_PROTOS;
147  }
148  return protoval;
149 
150 }
151 
156 , gint priority
157 , GMainContext* mcontext
158 , NetGSource* iosrc
160 , gsize objsize)
161 {
162  const char * instance;
163  const char * dev;
164  guint listenmask;
165  Discovery * dret;
166  SwitchDiscovery* ret;
167  g_return_val_if_fail(swconfig != NULL, NULL);
168  dev = swconfig->getstring(swconfig, CONFIGNAME_DEVNAME);
169  g_return_val_if_fail(dev != NULL, NULL);
170  instance = swconfig->getstring(swconfig, CONFIGNAME_INSTANCE);
171  g_return_val_if_fail(instance != NULL, NULL);
172  listenmask = _switchdiscovery_setprotocols(swconfig);
173  dret = discovery_new(instance, iosrc, config
174  , objsize < sizeof(SwitchDiscovery) ? sizeof(SwitchDiscovery) : objsize);
175  g_return_val_if_fail(dret != NULL, NULL);
176  proj_class_register_subclassed(dret, "SwitchDiscovery");
177 
178 
179  ret = CASTTOCLASS(SwitchDiscovery, dret);
180 
181  ret->finalize = dret->baseclass._finalize;
184  ret->source = g_source_pcap_new(dev, listenmask, _switchdiscovery_dispatch, NULL, priority, FALSE, mcontext, 0, ret);
185 
186  if (objsize == sizeof(SwitchDiscovery)) {
187  // Subclass constructors need to register themselves, but we'll register
188  // ourselves.
189  discovery_register(dret);
190  }
191  ret->switchid = NULL; ret->switchidlen = -1;
192  ret->portid = NULL; ret->portidlen = -1;
193  return ret;
194 }
195 
196 typedef struct _SwitchDiscoveryType SwitchDiscoveryType;
197 static struct _SwitchDiscoveryType {
198  const char * discoverytype;
199  gboolean (*isthistype)(gconstpointer tlv_vp, gconstpointer pktend);
200  gconstpointer (*get_switch_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
201  gconstpointer (*get_port_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
202 } discovery_types[] = {
205 };
206 
209 FSTATIC gboolean
211  gconstpointer pkt,
212  gconstpointer pktend)
213 {
214  gsize j;
216 
217  for (j=0; j < DIMOF(discovery_types); ++j) {
218  gconstpointer curswitchid;
219  gssize curswitchidlen = -1;
220  gconstpointer curportid;
221  gssize curportidlen = -1;
222 
223  if (!discovery_types[j].isthistype(pkt, pktend)) {
224  continue;
225  }
226  curswitchid = discovery_types[j].get_switch_id(pkt, &curswitchidlen, pktend);
227  curportid = discovery_types[j].get_port_id(pkt, &curportidlen, pktend);
228  g_return_val_if_fail(curswitchid != NULL, FALSE);
229  g_return_val_if_fail(curportid != NULL, FALSE);
230 
231  if (self->switchid == NULL || self->portid == NULL
232  || curportidlen != self->portidlen || curswitchidlen != self->switchidlen
233  || memcmp(curswitchid, self->switchid, curswitchidlen) != 0
234  || memcmp(curportid, self->portid, curportidlen) != 0) {
235 
236  if (self->switchid != NULL) {
237  FREE(self->switchid); self->switchid = NULL;
238  }
239  if (self->portid != NULL) {
240  FREE(self->portid); self->portid = NULL;
241  }
242  self->switchid = g_memdup(curswitchid, curswitchidlen);
243  self->portid = g_memdup(curportid, curportidlen);
244  self->switchidlen = curswitchidlen;
245  self->portidlen = curportidlen;
246  return TRUE;
247  }
248  break;
249  }
250  return FALSE;
251 }
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
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:282
#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
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...
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
#define CONFIGNAME_DEVNAME
Name of NIC for discovery.
FSTATIC void _switchdiscovery_finalize(AssimObj *self)
finalize a SwitchDiscovery object
#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:261
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:45
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.
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:67