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,
34  const struct pcap_pkthdr*, const char *, 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 
113 switchdiscovery_new(const char * instance
114 , const char * dev
115 , guint listenmask
116 , gint priority
117 , GMainContext* mcontext
118 , NetGSource* iosrc
120 , gsize objsize)
121 {
122  Discovery * dret = discovery_new(instance, iosrc, config
123  , objsize < sizeof(SwitchDiscovery) ? sizeof(SwitchDiscovery) : objsize);
124  SwitchDiscovery* ret;
125  g_return_val_if_fail(dret != NULL, NULL);
126  proj_class_register_subclassed(dret, "SwitchDiscovery");
127 
128  ret = CASTTOCLASS(SwitchDiscovery, dret);
129 
130  ret->finalize = dret->baseclass._finalize;
133  ret->source = g_source_pcap_new(dev, listenmask, _switchdiscovery_dispatch, NULL, priority, FALSE, mcontext, 0, ret);
134 
135  if (objsize == sizeof(SwitchDiscovery)) {
136  // Subclass constructors need to register themselves, but we'll register
137  // ourselves.
138  discovery_register(dret);
139  }
140  ret->switchid = NULL; ret->switchidlen = -1;
141  ret->portid = NULL; ret->portidlen = -1;
142  return ret;
143 }
144 
145 typedef struct _SwitchDiscoveryType SwitchDiscoveryType;
146 static struct _SwitchDiscoveryType {
147  const char * discoverytype;
148  gboolean (*isthistype)(gconstpointer tlv_vp, gconstpointer pktend);
149  gconstpointer (*get_switch_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
150  gconstpointer (*get_port_id)(gconstpointer tlv_vp, gssize* idlength, gconstpointer pktend);
151 } discovery_types[] = {
154 };
155 
158 FSTATIC gboolean
160  gconstpointer pkt,
161  gconstpointer pktend)
162 {
163  gsize j;
165 
166  for (j=0; j < DIMOF(discovery_types); ++j) {
167  gconstpointer curswitchid;
168  gssize curswitchidlen = -1;
169  gconstpointer curportid;
170  gssize curportidlen = -1;
171 
172  if (!discovery_types[j].isthistype(pkt, pktend)) {
173  continue;
174  }
175  curswitchid = discovery_types[j].get_switch_id(pkt, &curswitchidlen, pktend);
176  curportid = discovery_types[j].get_port_id(pkt, &curportidlen, pktend);
177  g_return_val_if_fail(curswitchid != NULL, FALSE);
178  g_return_val_if_fail(curportid != NULL, FALSE);
179 
180  if (self->switchid == NULL || self->portid == NULL
181  || curportidlen != self->portidlen || curswitchidlen != self->switchidlen
182  || memcmp(curswitchid, self->switchid, curswitchidlen) != 0
183  || memcmp(curportid, self->portid, curportidlen) != 0) {
184 
185  if (self->switchid != NULL) {
186  FREE(self->switchid); self->switchid = NULL;
187  }
188  if (self->portid != NULL) {
189  FREE(self->portid); self->portid = NULL;
190  }
191  self->switchid = g_memdup(curswitchid, curswitchidlen);
192  self->portid = g_memdup(curportid, curportidlen);
193  self->switchidlen = curswitchidlen;
194  self->portidlen = curportidlen;
195  return TRUE;
196  }
197  break;
198  }
199  return FALSE;
200 }