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