The Assimilation Project  based on Assimilation version 1.1.7.1474836767
nanoprobe.c
Go to the documentation of this file.
1 
25 #include <projectcommon.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <frameset.h>
29 #include <framesettypes.h>
30 #include <frametypes.h>
31 #include <compressframe.h>
32 #include <cryptframe.h>
33 #include <cryptcurve25519.h>
34 #include <intframe.h>
35 #include <cstringframe.h>
36 #include <addrframe.h>
37 #include <ipportframe.h>
38 #include <seqnoframe.h>
39 #include <packetdecoder.h>
40 #include <netgsource.h>
41 #include <reliableudp.h>
42 #include <authlistener.h>
43 #include <nvpairframe.h>
44 #include <hblistener.h>
45 #include <hbsender.h>
46 #include <configcontext.h>
47 #include <pcap_min.h>
48 #include <jsondiscovery.h>
49 #include <switchdiscovery.h>
50 #include <arpdiscovery.h>
51 #include <fsprotocol.h>
52 #include <resourcecmd.h>
53 #include <resourcequeue.h>
54 #include <misc.h>
55 #include <nanoprobe.h>
56 
57 
63 void (*nanoprobe_warntime_agent)(HbListener*, guint64 howlate) = NULL;
64 void (*nanoprobe_comealive_agent)(HbListener*, guint64 howlate) = NULL;
65 WINEXPORT NanoHbStats nano_hbstats = {0U, 0U, 0U, 0U, 0U};
66 gboolean nano_connected = FALSE;
68 WINEXPORT GMainLoop* mainloop = NULL;
69 
78 FSTATIC void nanoobey_change_debug(gint plusminus, AuthListener*, FrameSet*, NetAddr*);
84 FSTATIC void _nano_send_rscexitstatus(ConfigContext* request, gpointer user_data
85 , enum HowDied reason, int rc, int signal, gboolean core_dumped
86 , const char * stringresult);
89 FSTATIC void nano_schedule_discovery(const char *name, guint32 interval,const char* json
90  , ConfigContext*, NetGSource* transport, NetAddr* fromaddr);
91 FSTATIC void nano_stop_discovery(const char * discoveryname, NetGSource*, NetAddr*);
92 FSTATIC gboolean nano_startupidle(gpointer gcruft);
93 FSTATIC gboolean nano_reqconfig(gpointer gcruft);
96 FSTATIC void _real_warntime_agent(HbListener* who, guint64 howlate);
97 FSTATIC void _real_comealive_agent(HbListener* who, guint64 howlate);
100 FSTATIC gboolean _nano_final_shutdown(gpointer unused);
101 FSTATIC gboolean shutdown_when_outdone(gpointer unused);
103 FSTATIC gboolean _nanoprobe_is_cma_frameset(const FrameSet * fs, NetAddr*);
104 FSTATIC void _nanoprobe_associate_cma_addrs(const char *key_id, ConfigContext *cfg);
105 FSTATIC void _nano_initial_discovery(AuthListener*parent, NetAddr* fromaddr);
106 
107 HbListener* (*nanoprobe_hblistener_new)(NetAddr*, ConfigContext*) = _real_hblistener_new;
108 
110 gboolean nano_shutting_down = FALSE;
111 static gboolean nano_config_complete = FALSE;
112 GRand* nano_random = NULL;
113 const char * procname = "nanoprobe";
114 static AuthListener* obeycollective = NULL;
115 
116 static NetAddr* nanofailreportaddr = NULL;
117 static NetGSource* nanotransport = NULL;
118 static guint idle_shutdown_gsource = 0;
119 static ResourceQueue* RscQ = NULL;
120 static gboolean is_encryption_enabled = FALSE;
121 
123 
128 {
129  return hblistener_new(addr, context, 0);
130 }
131 
133 void
134 nanoprobe_report_upstream(guint16 reporttype
135 , NetAddr* who
136 , const char * systemnm
137 , guint64 howlate)
138 {
140  FrameSet* fs;
141 
142  if (nano_shutting_down || NULL == nanofailreportaddr) {
143  DEBUGMSG("%s.%d: Ignoring request to send fstype=%d message upstream [%s]."
144  , __FUNCTION__, __LINE__, reporttype
145  , (nano_shutting_down ? "shutting down" : "not connected to CMA"));
146  return;
147  }
148 
149  fs = frameset_new(reporttype);
150  // Construct and send a frameset reporting this event...
151  if (howlate > 0) {
153  lateframe->setint(lateframe, howlate);
154  frameset_append_frame(fs, &lateframe->baseclass);
155  UNREF2(lateframe);
156  }
157  // Add the address - if any...
158  if (who != NULL) {
160  frameset_append_frame(fs, &peeraddr->baseclass);
161  UNREF2(peeraddr);
162  }
163  // Add the system name - if any...
164  if (systemnm != NULL) {
166  usf->baseclass.setvalue(&usf->baseclass, g_strdup(systemnm), strlen(systemnm)+1
168  frameset_append_frame(fs, &usf->baseclass);
169  UNREF2(usf);
170  }
171  DEBUGMSG3("%s - sending frameset of type %d", __FUNCTION__, reporttype);
172  DUMP3("nanoprobe_report_upstream", &nanofailreportaddr->baseclass, NULL);
173  nanotransport->_netio->sendareliablefs(nanotransport->_netio, nanofailreportaddr, DEFAULT_FSP_QID, fs);
174  UNREF(fs);
175 }
176 
177 
179 FSTATIC void
181 {
182  static gint64 last_martian_time = 0; // microseconds
183  static guint recent_martian_count = 0;
184  gint64 now = g_get_monotonic_time(); // microseconds
185  const gint64 uS = 1000000;
186 
188 
189  // If it's been more than MARTIAN_TIMEOUT seconds since the last
190  // martian, then reset the count of recent martians
191  if (now > (last_martian_time + (MARTIAN_TIMEOUT*uS))) {
192  recent_martian_count = 0;
193  }
194 
195  last_martian_time = now;
196  ++recent_martian_count;
197 
198  // This means if we only get one martian then none, we say nothing
199  // This can happen as a result of timing - and it's OK.
200  // But if we get more than one, we complain then and once every 10 afterwards
201  if ((recent_martian_count % 10) == 2) {
202  char * addrstring;
203 
205  addrstring = who->baseclass.toString(who);
206  g_warning("System at address %s is sending unexpected heartbeats.", addrstring);
207  g_free(addrstring);
208 
210  }
211 }
214 FSTATIC void
216 {
220  }else{
221  char * addrstring;
222 
223  addrstring = who->listenaddr->baseclass.toString(who->listenaddr);
224  g_warning("Peer at address %s is dead (has timed out: %ld seconds).", addrstring
225  , (long)(who->get_deadtime(who)/1000000L));
226  g_free(addrstring);
227 
229  }
230 }
231 
234 FSTATIC void
236 {
240  }
241 }
242 
243 
246 FSTATIC void
247 _real_warntime_agent(HbListener* who, guint64 howlate)
248 {
251  nanoprobe_warntime_agent(who, howlate);
252  }else{
253  char * addrstring;
254  guint64 mslate = howlate / 1000;
255  addrstring = who->listenaddr->baseclass.toString(who->listenaddr);
256  g_warning("Heartbeat from peer at address %s was "FMT_64BIT"d ms late.", addrstring, mslate);
257  g_free(addrstring);
259  }
260 }
263 FSTATIC void
264 _real_comealive_agent(HbListener* who, guint64 howlate)
265 {
268  nanoprobe_comealive_agent(who, howlate);
269  }else{
270  char * addrstring;
271  double secsdead = ((double)((howlate+5000) / 10000))/100.0; // Round to nearest .01
272  addrstring = who->listenaddr->baseclass.toString(who->listenaddr);
273  g_warning("Peer at address %s came alive after being dead for %g seconds (deadtime=%ld secs)."
274  , addrstring, secsdead, (long)(who->get_deadtime(who)/1000000));
275  g_free(addrstring);
277  }
278 }
279 FSTATIC void
280 nanoobey_connshut(AuthListener* ignoreauth, FrameSet* ignorefs, NetAddr* fromaddr)
281 {
282  (void)ignoreauth;
283  (void)ignorefs;
284  DUMP1("Received a CONNSHUT packet from ", &fromaddr->baseclass, "")
285 }
286 
298 void
300  , FrameSet* fs
301  , NetAddr* fromaddr)
302 {
303 
304  GSList* slframe;
305  guint addrcount = 0;
307  guint16 sendinterval;
308  gint64 intvalue;
309 
310  if (nano_shutting_down) {
311  return;
312  }
313 
314  g_return_if_fail(fs != NULL);
315  (void)fromaddr;
316 
317  intvalue = config->getint(config, CONFIGNAME_INTERVAL);
318  sendinterval = (intvalue > 0 ? intvalue : CONFIG_DEFAULT_HBTIME);
319 
320  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
321  Frame* frame = CASTTOCLASS(Frame, slframe->data);
322  int frametype = frame->type;
323  switch(frametype) {
324  IntFrame* iframe;
325  IpPortFrame* aframe;
326  HbSender* hb;
327 
329  iframe = CASTTOCLASS(IntFrame, frame);
330  sendinterval = (guint16) iframe->getint(iframe);
331  break;
332  case FRAMETYPE_RSCJSON:{
333  CstringFrame* csf = CASTTOCLASS(CstringFrame, frame);
334  ConfigContext* cfg;
335  const char * json;
336  json = csf->baseclass.value;
337  DEBUGMSG3("%s.%d: Got RSCJSON frame: %s", __FUNCTION__
338  , __LINE__, json);
339  cfg = configcontext_new_JSON_string(json);
340  g_return_if_fail(cfg != NULL);
341  intvalue = cfg->getint(cfg, CONFIGNAME_INTERVAL);
342  sendinterval = (intvalue > 0 ? intvalue : sendinterval);
343  UNREF(cfg);
344  break;
345  }
346  case FRAMETYPE_IPPORT:
347  if (0 == sendinterval) {
348  g_warning("Send interval is zero in %s", __FUNCTION__);
349  continue;
350  }
351  aframe = CASTTOCLASS(IpPortFrame, frame);
352  addrcount++;
353  hb = hbsender_new(aframe->getnetaddr(aframe)
354  , parent->baseclass.transport, sendinterval, 0);
355  (void)hb;
356  break;
357  }
358  }
359 }
371 void
373  , FrameSet* fs
374  , NetAddr* fromaddr)
375 {
376 
377  GSList* slframe;
379  guint addrcount = 0;
380 
381  guint64 deadtime;
382  guint64 warntime;
383  gint64 intvalue;
384 
385  (void)fromaddr;
386 
387  if (nano_shutting_down) {
388  return;
389  }
390 
391  g_return_if_fail(fs != NULL);
392  intvalue = config->getint(config, CONFIGNAME_TIMEOUT);
393  deadtime = (intvalue > 0 ? intvalue : CONFIG_DEFAULT_DEADTIME);
394  intvalue = config->getint(config, CONFIGNAME_WARNTIME);
395  warntime = (intvalue > 0 ? intvalue : CONFIG_DEFAULT_WARNTIME);
396 
397  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
398  Frame* frame = CASTTOCLASS(Frame, slframe->data);
399  int frametype = frame->type;
400  switch(frametype) {
401  IntFrame* iframe;
402 
404  iframe = CASTTOCLASS(IntFrame, frame);
405  deadtime = iframe->getint(iframe);
406  break;
407 
409  iframe = CASTTOCLASS(IntFrame, frame);
410  intvalue = iframe->getint(iframe);
411  warntime = (intvalue > 0 ? (guint64)intvalue : warntime);
412  break;
413 
414  case FRAMETYPE_RSCJSON: {
415  CstringFrame* csf = CASTTOCLASS(CstringFrame, frame);
416  ConfigContext* cfg;
417  const char * json;
418  json = csf->baseclass.value;
419  DEBUGMSG3("%s.%d: Got RSCJSON frame: %s", __FUNCTION__
420  , __LINE__, json);
421  cfg = configcontext_new_JSON_string(json);
422  g_return_if_fail(cfg != NULL);
423  intvalue = cfg->getint(cfg, CONFIGNAME_TIMEOUT);
424  deadtime = (intvalue > 0 ? (guint64)intvalue : deadtime);
425  intvalue = cfg->getint(cfg, CONFIGNAME_WARNTIME);
426  warntime = (intvalue > 0 ? (guint64)intvalue : warntime);
427  UNREF(cfg);
428  }
429  break;
430 
431  case FRAMETYPE_IPPORT: {
432  HbListener* hblisten;
433  IpPortFrame* aframe;
435  aframe = CASTTOCLASS(IpPortFrame, frame);
436  addrcount++;
437  hblisten = hblistener_new(aframe->getnetaddr(aframe), config, 0);
438  hblisten->baseclass.associate(&hblisten->baseclass, transport);
439  if (deadtime > 0) {
440  // Otherwise we get the default deadtime
441  hblisten->set_deadtime(hblisten, deadtime);
442  }
443  if (warntime > 0) {
444  // Otherwise we get the default warntime
445  hblisten->set_warntime(hblisten, warntime);
446  }
447  hblisten->set_deadtime_callback(hblisten, _real_deadtime_agent);
448  hblisten->set_heartbeat_callback(hblisten, _real_heartbeat_agent);
449  hblisten->set_warntime_callback(hblisten, _real_warntime_agent);
450  hblisten->set_comealive_callback(hblisten, _real_comealive_agent);
451  // Intercept incoming heartbeat packets
452  transport->addListener(transport, FRAMESETTYPE_HEARTBEAT
453  , &hblisten->baseclass);
454  // Unref this heartbeat listener, and forget our reference.
455  UNREF2(hblisten);
456  /*
457  * That still leaves two references to 'hblisten':
458  * - in the transport dispatch table
459  * - in the global heartbeat listener table
460  * And one reference to the previous 'hblisten' object:
461  * - in the global heartbeat listener table
462  * Also note that we become the 'proxy' for all incoming heartbeats
463  * but we dispatch them to the right HbListener object.
464  * Since we've become the proxy for all incoming heartbeats, if
465  * we displace and free the old proxy, this all still works nicely,
466  * because the transport object gets rid of its old reference to the
467  * old 'proxy' object.
468  */
469  }
470  break;
471  }
472  }
473 }
474 
484 void
486  , FrameSet* fs
487  , NetAddr* fromaddr)
488 {
489  g_return_if_fail(fs != NULL && fs->fstype == FRAMESETTYPE_SENDEXPECTHB);
490 
491  if (nano_shutting_down) {
492  return;
493  }
494  // This will cause us to ACK the packet twice -- not a problem...
495  nanoobey_sendhb (parent, fs, fromaddr);
496  nanoobey_expecthb(parent, fs, fromaddr);
497 }
505 void
507  , FrameSet* fs
508  , NetAddr* fromaddr)
509 {
510  GSList* slframe;
511  (void)parent;
512  (void)fromaddr;
513 
514  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
515  Frame* frame = CASTTOCLASS(Frame, slframe->data);
516  switch(frame->type) {
517  case FRAMETYPE_IPPORT: {
518  // This is _so_ much simpler than the code to send them ;-)
519  IpPortFrame* aframe = CASTTOCLASS(IpPortFrame, frame);
520  hbsender_stopsend(aframe->getnetaddr(aframe));
521  break;
522  }
523  }//endswitch
524  }//endfor
525 }
526 
534 void
536  , FrameSet* fs
537  , NetAddr* fromaddr)
538 {
539  GSList* slframe;
540  (void)parent;
541  (void)fromaddr;
542 
543  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
544  Frame* frame = CASTTOCLASS(Frame, slframe->data);
545  switch(frame->type) {
546  case FRAMETYPE_IPPORT: {
547  // This is _so_ much simpler than the code to listen for heartbeats...
548  IpPortFrame* aframe = CASTTOCLASS(IpPortFrame, frame);
549  NetAddr* destaddr = aframe->getnetaddr(aframe);
551  hblistener_unlisten(destaddr);
552  transport->closeconn(transport, DEFAULT_FSP_QID, destaddr);
553  break;
554  }
555  }//endswitch
556  }//endfor
557 }
558 
564 void
566  , FrameSet* fs
567  , NetAddr* fromaddr)
568 {
569  nanoobey_stopexpecthb(parent, fs, fromaddr);
570  nanoobey_stopsendhb (parent, fs, fromaddr);
571 }
572 
573 /*
574  * Act on (obey) a <b>FRAMESETTYPE_SETCONFIG</b> @ref FrameSet.
575  * This frameset is sent during the initial configuration phase.
576  * Nowadays we only want one frame type:
577  * <b>FRAMETYPE_CONFIGJSON</b> - A JSON ConfigContext with everything in it.
578  */
579 void
581  , FrameSet* fs
582  , NetAddr* fromaddr)
583 {
584  GSList* slframe;
585  ConfigContext* newconfig = NULL;
587 
588  (void)fromaddr;
589  DUMP2("nanoobey_setconfig config is from: ", &fromaddr->baseclass, NULL);
590 
591 
592  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
593  Frame* frame = CASTTOCLASS(Frame, slframe->data);
594  switch (frame->type) {
595  case FRAMETYPE_CONFIGJSON: { // Configuration JSON string (parameters)
596  CstringFrame* strf = CASTTOCLASS(CstringFrame, frame);
597  const char * jsonstring;
598  int cprs_thresh;
599  g_return_if_fail(strf != NULL);
600  jsonstring = strf->baseclass.value;
601  DEBUGMSG3("%s.%d: Got CONFIGJSON frame: %s", __FUNCTION__, __LINE__
602  , jsonstring);
603  newconfig = configcontext_new_JSON_string(jsonstring);
604  // This is a good place to check for a compression threshold
605  // And possibly other parameters
606  if (newconfig) {
607  cprs_thresh =
608  newconfig->getint(newconfig, CONFIGNAME_CPRS_THRESH);
609  if (cprs_thresh > 0) {
610  Frame* f;
611  f = config->getframe(config, CONFIGNAME_COMPRESS);
612  if (f) {
615  cf->compression_threshold = cprs_thresh;
616  }
617  }
618  }
619  goto endloop;
620  }
621  }
622  }
623 endloop:
624  if (NULL == newconfig) {
625  g_warning("%s.%d: SETCONFIG message without valid JSON configuration"
626  , __FUNCTION__, __LINE__);
627  return;
628  }
629 
630  if (config) {
631  GSList* keylist = newconfig->keys(newconfig);
632  GSList* thiskey;
633  GSList* nextkey;
634 
635  // Merge the new configuration into the old configuration data...
636  for (thiskey = keylist; thiskey; thiskey=nextkey) {
637  const char * key = thiskey->data;
638  enum ConfigValType valtype = newconfig->gettype(newconfig, key);
639 
640  nextkey=thiskey->next;
641 
642  switch(valtype) {
643  case CFG_NETADDR:
644  // We want to keep any CMAINIT value from the command line...
645  // The CMA may not give us the 'right' value for this
646  if (strcmp(key, CONFIGNAME_CMAINIT) != 0) {
647  config->setaddr(config, key, newconfig->getaddr(newconfig, key));
648  }
649  break;
650 
651  case CFG_CFGCTX:
652  config->setconfig(config, key, newconfig->getconfig(newconfig, key));
653  break;
654 
655  case CFG_STRING:
656  config->setstring(config, key, newconfig->getstring(newconfig, key));
657  break;
658 
659  case CFG_BOOL:
660  config->setbool(config, key, newconfig->getbool(newconfig, key));
661  break;
662 
663  case CFG_INT64:
664  config->setint(config, key, newconfig->getint(newconfig, key));
665  break;
666 
667  case CFG_FLOAT:
668  config->setdouble(config, key, newconfig->getdouble(newconfig, key));
669  break;
670  default:
671  break;
672  }
673  g_slist_free1(thiskey);
674  }
676  if (DEBUG >= 2) {
677  g_info("%s.%d: Validating the config we processed...", __FUNCTION__, __LINE__);
678  if (_nano_initconfig_OK(config)) {
679  DEBUGMSG("%s.%d: config we read is good", __FUNCTION__, __LINE__);
680  }else{
681  DEBUGMSG("%s.%d: config we read is BAD", __FUNCTION__, __LINE__);
682  }
683  }
684  }
685  UNREF(newconfig);
686 
687  DUMP3("nanoobey_setconfig: cfg is", &config->baseclass, NULL);
688 
689  if (config && config->getaddr(config, CONFIGNAME_CMAFAIL) != NULL) {
690  if (nanofailreportaddr == NULL) {
691  nanofailreportaddr = config->getaddr(config, CONFIGNAME_CMAFAIL);
692  }else if (config->getaddr(config, CONFIGNAME_CMAFAIL) != nanofailreportaddr) {
693  UNREF(nanofailreportaddr);
694  nanofailreportaddr = config->getaddr(config, CONFIGNAME_CMAFAIL);
695  }
696  DUMP3("nanoobey_setconfig: nanofailreportaddr", &nanofailreportaddr->baseclass, NULL);
697  {
698  // Alias localhost to the CMA nanofailreportaddr (at least for now...)
701 
702  NetAddr* localhost = netaddr_string_new("127.0.0.1");
703  NetIO* io = parent->baseclass.transport->_netio;
704  io->addalias(io, localhost, nanofailreportaddr);
705  UNREF(localhost);
706  }
707  REF(nanofailreportaddr);
708  }
709  if (!nano_connected) {
710  g_message("Connected to CMA. Happiness :-D");
711  // Do this before we get any more work from the CMA
712  _nano_initial_discovery(parent, fromaddr);
713  nano_connected = TRUE;
714  }
715 }//nanoobey_setconfig
727 void
729  , FrameSet* fs
730  , NetAddr* fromaddr)
731 {
732  (void)parent;
733  (void)fs;
734  (void)fromaddr;
735  DUMP2("Received FRAMESETTYPE_ACKSTARTUP from ", &fromaddr->baseclass, NULL);
736  g_info("%s.%d: Configuration from CMA is complete.", __FUNCTION__, __LINE__);
737  nano_config_complete = TRUE;
738 }
739 
746 FSTATIC void
748  , NetAddr* fromaddr) {
749  unsigned j;
750  static struct {
751  const char * name;
752  const char * json;
753  } initdiscovery [] = {
754  { "os", "{\"type\": \"os\", \"parameters\":{}}"},
755  };
756  for (j=0; j < DIMOF(initdiscovery); ++j) {
757  nano_schedule_discovery(initdiscovery[j].name, 0, initdiscovery[j].json
758  , parent->baseclass.config
759  , parent->baseclass.transport
760  , fromaddr);
761  }
762 }
763 
768 FSTATIC void
769 nanoobey_change_debug(gint plusminus
770  , AuthListener* parent
771  , FrameSet* fs
772  , NetAddr* fromaddr)
773 {
774 
775  GSList* slframe;
776  guint changecount = 0;
777 
778  (void)parent;
779  (void)fromaddr;
780 
781  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
782  Frame* frame = CASTTOCLASS(Frame, slframe->data);
783  int frametype = frame->type;
784  switch (frametype) {
785  case FRAMETYPE_CSTRINGVAL: { // String value to set 'paramname' to
786  ++changecount;
787  if (plusminus < 0) {
788  proj_class_decr_debug((char*)frame->value);
789  }else{
790  proj_class_incr_debug((char*)frame->value);
791  }
792  }
793  break;
794  }
795  }
796  if (changecount == 0) {
797  if (plusminus < 0) {
798  proj_class_decr_debug(NULL);
799  }else{
800  proj_class_incr_debug(NULL);
801  }
802  }
803 }
808 FSTATIC void
810  , FrameSet* fs
811  , NetAddr* fromaddr)
812 {
813  nanoobey_change_debug(+1, parent, fs, fromaddr);
814 }
819 FSTATIC void
821  , FrameSet* fs
822  , NetAddr* fromaddr)
823 {
824  nanoobey_change_debug(-1, parent, fs, fromaddr);
825 }
826 
834 FSTATIC void
836  , FrameSet* fs
837  , NetAddr* fromaddr)
838 {
839 
840  GSList* slframe;
841  guint interval = 0;
842  const char * discoveryname = NULL;
843 
844  (void)parent;
845  (void)fromaddr;
846 
847  if (nano_shutting_down) {
848  return;
849  }
850 
851  DEBUGMSG3("%s - got frameset", __FUNCTION__);
852  // Loop over the frames, looking for those we know what to do with ;-)
853  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
854  Frame* frame = CASTTOCLASS(Frame, slframe->data);
855  int frametype = frame->type;
856 
857  switch (frametype) {
858  case FRAMETYPE_DISCNAME: { // Discovery instance name
859  CstringFrame* strf = CASTTOCLASS(CstringFrame, frame);
860  g_return_if_fail(strf != NULL);
861  g_return_if_fail(discoveryname == NULL);
862  discoveryname = strf->baseclass.value;
863  DEBUGMSG3("%s - got DISCOVERYNAME %s", __FUNCTION__, discoveryname);
864  }
865  break;
866 
867  case FRAMETYPE_DISCINTERVAL: { // Discovery interval
868  IntFrame* intf = CASTTOCLASS(IntFrame, frame);
869  interval = (guint)intf->getint(intf);
870  DEBUGMSG3("%s - got DISCOVERYINTERVAL %d", __FUNCTION__, interval);
871  }
872  break;
873 
874  case FRAMETYPE_DISCJSON: { // Discovery JSON string (parameters)
875  CstringFrame* strf = CASTTOCLASS(CstringFrame, frame);
876  const char * jsonstring;
877  g_return_if_fail(strf != NULL);
878  jsonstring = strf->baseclass.value;
879  g_return_if_fail(discoveryname != NULL);
880  DEBUGMSG3("Got DISCJSON frame: %s %d %s" , discoveryname, interval, jsonstring);
881  nano_schedule_discovery(discoveryname, interval, jsonstring
882  , parent->baseclass.config
883  , parent->baseclass.transport
884  , fromaddr);
885  }
886  interval = 0;
887  discoveryname = NULL;
888  break;
889 
890  }
891  }
892 }
893 
895 FSTATIC void
896 _nano_send_rscexitstatus(ConfigContext* request, gpointer user_data
897 , enum HowDied reason, int rc, int signal, gboolean core_dumped
898 , const char * stringresult)
899 {
901  ConfigContext* response = configcontext_new(0);
904  char* rsp_json;
905 
906  struct {
907  const char* framename;
908  int framevalue;
909  } pktframes[] = {
910  {REQREASONENUMNAMEFIELD, reason},
911  {REQRCNAMEFIELD, rc},
912  {REQSIGNALNAMEFIELD, signal},
913  };
914  unsigned j;
915 
916  for (j=0; j < DIMOF(pktframes); ++j) {
917  response->setint(response, pktframes[j].framename, pktframes[j].framevalue);
918  }
919  response->setbool(response, REQCOREDUMPNAMEFIELD, core_dumped);
920  if (stringresult) {
921  response->setstring(response, REQSTRINGRETNAMEFIELD, stringresult);
922  }
923  // Copy the request ID over from the original request
924  response->setint(response, REQIDENTIFIERNAMEFIELD
925  , request->getint(request, REQIDENTIFIERNAMEFIELD));
926  // Copy the resource name (instance) over from the original request
927  response->setstring(response, CONFIGNAME_INSTANCE
928  , request->getstring(request, CONFIGNAME_INSTANCE));
929  // Package it up as a JSON string to send to the CMA
930  rsp_json = response->baseclass.toString(&response->baseclass);
931  UNREF(response);
932  DEBUGMSG1("Reporting resource state change: %s", rsp_json);
933  sf->baseclass.setvalue(&sf->baseclass, rsp_json, strlen(rsp_json)+1, g_free);
935  UNREF2(sf);
936  transport->_netio->sendareliablefs(transport->_netio, nanofailreportaddr, DEFAULT_FSP_QID, fs);
937  UNREF(fs);
938 }
939 FSTATIC void
941 {
942  GSList* slframe;
943 
944  (void)parent;
945  (void)fromaddr;
946  if (nano_shutting_down) {
947  return;
948  }
949  if (NULL == RscQ) {
950  RscQ = resourcequeue_new(0);
951  }
952  // Loop over the frames, looking for those we know what to do with ;-)
953  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
954  Frame* frame = CASTTOCLASS(Frame, slframe->data);
955  CstringFrame* csframe;
956  ConfigContext* cfg;
957  if (frame->type != FRAMETYPE_RSCJSON) {
958  continue;
959  }
960  csframe = CASTTOCLASS(CstringFrame, frame);
962  if (NULL == cfg) {
963  g_warning("%s.%d: Received malformed JSON string [%*s]"
964  , __FUNCTION__, __LINE__
965  , csframe->baseclass.length-1
966  , (char*)csframe->baseclass.value);
967  continue;
968  }
969  RscQ->Qcmd(RscQ, cfg, _nano_send_rscexitstatus, nanotransport);
970  UNREF(cfg);
971  }
972 }
973 
974 FSTATIC void
976 {
977  GSList* slframe;
978 
979  (void)parent;
980  (void)fromaddr;
981  if (NULL == RscQ) {
982  RscQ = resourcequeue_new(0);
983  }
984 
985  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
986  Frame* frame = CASTTOCLASS(Frame, slframe->data);
987  CstringFrame* csframe;
988  ConfigContext* cfg;
989  if (frame->type != FRAMETYPE_RSCJSON) {
990  continue;
991  }
992  csframe = CASTTOCLASS(CstringFrame, frame);
994  if (NULL == cfg) {
995  g_warning("%s.%d: Received malformed JSON string [%*s]"
996  , __FUNCTION__, __LINE__
997  , csframe->baseclass.length-1
998  , (char*)csframe->baseclass.value);
999  continue;
1000  }
1001  RscQ->cancel(RscQ, cfg);
1002  UNREF(cfg);
1003  }
1004 }
1005 
1010 FSTATIC void
1012  , FrameSet* fs
1013  , NetAddr* fromaddr)
1014 {
1015 
1016  GSList* slframe;
1017 
1018  (void)parent;
1019  (void)fromaddr;
1020 
1021 
1022  // Loop over the frames, looking for the one we know what to do with ;-)
1023  for (slframe = fs->framelist; slframe != NULL; slframe = g_slist_next(slframe)) {
1024  Frame* frame = CASTTOCLASS(Frame, slframe->data);
1025  int frametype = frame->type;
1026 
1027  switch (frametype) {
1028  case FRAMETYPE_DISCNAME: { // Discovery instance name
1029  CstringFrame* strf = CASTTOCLASS(CstringFrame, frame);
1030  const char * discoveryname;
1031  g_return_if_fail(strf != NULL);
1032  discoveryname = strf->baseclass.value;
1033  g_return_if_fail(discoveryname == NULL);
1034  discovery_unregister(discoveryname);
1035  }
1036  break;
1037 
1038  }
1039  }
1040 }
1041 
1045 FSTATIC void
1046 nano_schedule_discovery(const char *instance,
1047  guint32 interval,
1048  const char* json,
1051  NetAddr* fromaddr)
1052 {
1053  ConfigContext* jsonroot;
1054  const char* disctype;
1055 
1056  (void)fromaddr;
1057 
1058  DEBUGMSG3("%s(%s,%d,%s)", __FUNCTION__, instance, interval, json);
1059  jsonroot = configcontext_new_JSON_string(json);
1060  if (NULL == jsonroot) {
1061  g_warning("%s.%d: Invalid JSON discovery sent for instance %s: JSON string = \"%s\""
1062  , __FUNCTION__, __LINE__, instance, json);
1063  return;
1064  }
1065  disctype = jsonroot->getstring(jsonroot, CONFIGNAME_TYPE);
1066  g_return_if_fail(disctype != NULL);
1067 
1068  if (strcmp(disctype, "#SWITCH") == 0) {
1069  SwitchDiscovery* discovery;
1070  DEBUGMSG3("%s.%d: jsonroot = %s", __FUNCTION__, __LINE__
1071  , jsonroot->baseclass.toString(&jsonroot->baseclass));
1072  discovery = switchdiscovery_new(jsonroot, G_PRIORITY_LOW, g_main_context_default()
1073  , transport, config, 0);
1074  if (discovery) {
1075  UNREF2(discovery);
1076  }else{
1077  g_warning("%s.%d: Cannot start switch discovery: %s."
1078  , __FUNCTION__, __LINE__, json);
1079  }
1080  }else if (strcmp(disctype, "#ARP") == 0){
1081  ArpDiscovery* discovery;
1082  DEBUGMSG3("%s.%d: jsonroot = %s", __FUNCTION__, __LINE__
1083  , jsonroot->baseclass.toString(&jsonroot->baseclass));
1084  discovery = arpdiscovery_new(jsonroot, G_PRIORITY_LOW, g_main_context_default()
1085  , transport, config, 0);
1086  if (discovery) {
1087  UNREF2(discovery);
1088  }else{
1089  g_warning("%s.%d: Cannot start ARP discovery: %s."
1090  , __FUNCTION__, __LINE__, json);
1091  }
1092  }else{
1093  JsonDiscovery* discovery;
1094  discovery = jsondiscovery_new(disctype, instance, interval, jsonroot
1095  , transport, config, 0);
1096  if (discovery) {
1097  UNREF2(discovery);
1098  }else{
1099  g_warning("%s.%d: Cannot execute discovery script %s."
1100  , __FUNCTION__, __LINE__, disctype);
1101  }
1102  }
1103 
1104  UNREF(jsonroot);
1105 }
1106 
1109  const char * initdiscover;
1112 };
1113 
1120 gboolean
1121 nano_startupidle(gpointer gcruft)
1122 {
1123  static enum istate {INIT=3, WAIT=5, DONE=7} state = INIT;
1124  struct startup_cruft* cruft = gcruft;
1125  const char * cfgname = cruft->initdiscover;
1126 
1127  if (state == DONE || nano_shutting_down) {
1128  return FALSE;
1129  }
1130  if (state == INIT) {
1131  const char * jsontext = "{\"parameters\":{}}";
1132  ConfigContext* jsondata = configcontext_new_JSON_string(jsontext);
1134  ( cruft->initdiscover
1135  , cruft->initdiscover
1136  , cruft->discover_interval
1137  , jsondata
1138  , cruft->iosource, obeycollective->baseclass.config, 0);
1139  if (jd) {
1140  UNREF2(jd);
1141  }else{
1142  g_critical("%s.%d: Cannot execute initial startup discovery script %s. Exiting."
1143  , __FUNCTION__, __LINE__, cruft->initdiscover);
1144  exit(1);
1145  }
1146  UNREF(jsondata);
1147  state = WAIT;
1148  return TRUE;
1149  }
1150  if (obeycollective->baseclass.config->getstring(obeycollective->baseclass.config, cfgname)) {
1151  state = DONE;
1152  // Call it once, and arrange for it to repeat until we hear back.
1153  g_timeout_add_seconds(5, nano_reqconfig, gcruft);
1154  nano_reqconfig(gcruft);
1155  return FALSE;
1156  }
1157  return TRUE;
1158 }
1159 
1160 // Check to see if the parameters we really need are present in our config
1161 FSTATIC gboolean
1163 {
1164  if (config->getaddr(config, CONFIGNAME_CMAFAIL) != NULL
1165  && config->getaddr(config, CONFIGNAME_CMADISCOVER) != NULL) {
1166  DEBUGMSG2("%s.%d: FOUND '%s and '%s' in config.", __FUNCTION__, __LINE__
1168  return TRUE;
1169  }
1170  if (nano_config_complete || DEBUG >= 2) {
1171  DUMP("_nano_initconfig_OK: Could not find both of " CONFIGNAME_CMAFAIL
1172  " and " CONFIGNAME_CMADISCOVER " in " , &config->baseclass, "");
1173  }
1174  return FALSE;
1175 }
1176 
1179 gboolean
1180 nano_reqconfig(gpointer gcruft)
1181 {
1182  struct startup_cruft* cruft = gcruft;
1183  FrameSet* fs;
1184  CstringFrame* csf;
1185  CstringFrame* usf;
1186  IpPortFrame* ippf;
1187  const char * cfgname = cruft->initdiscover;
1188  ConfigContext* context = obeycollective->baseclass.config;
1189  NetAddr* cmainit = context->getaddr(context, CONFIGNAME_CMAINIT);
1190  const char * jsontext;
1191  char * sysname = NULL;
1192  NetAddr* boundaddr;
1193  IntFrame* timeframe;
1194  static guint64 starttime = 0L;
1195 
1196  if (nano_shutting_down) {
1197  return FALSE;
1198  }
1199 
1200  // We <i>have</i> to know our initial request address - or all is lost.
1201  // NOTE THAT THIS ADDRESS MIGHT BE MULTICAST AND MIGHT BE USED ONLY ONCE
1202  g_return_val_if_fail(cmainit != NULL, FALSE);
1203 
1204  // We will keep sending STARTUP framesets until these conditions are fulfilled:
1205  // 1) We received sufficient configuration data from the CMA
1206  // 2) We received a FRAMESETTYPE_ACKSTARTUP FrameSet
1207  if (DEBUG >= 3) {
1208  g_debug("%s.%d: _nano_initconfig_OK(context) => %s, nano_config_complete = %s"
1209  , __FUNCTION__, __LINE__
1210  , (_nano_initconfig_OK(context) ? "True" : "False")
1211  , (nano_config_complete ? "True" : "False"));
1212  }
1213  if (_nano_initconfig_OK(context) && nano_config_complete) {
1214  // We're good
1215  return FALSE;
1216  }
1218 
1219  // Put in the system name
1221  sysname = proj_get_sysname();
1222  usf->baseclass.setvalue(&usf->baseclass, g_strdup(sysname), strlen(sysname)+1
1224  frameset_append_frame(fs, &usf->baseclass);
1225  UNREF2(usf);
1226 
1227  // Put in our listening address - useful if we're NATted
1228  boundaddr = cruft->iosource->_netio->boundaddr(cruft->iosource->_netio);
1229  ippf = ipportframe_netaddr_new(FRAMETYPE_IPPORT, boundaddr);
1230  UNREF(boundaddr);
1231  frameset_append_frame(fs, &ippf->baseclass);
1232  UNREF2(ippf);
1233 
1234  // Put in our startup time - helps the CMA eliminate dups (w/o protocol)
1235  // If it gets busy, we might send it another request before it finishes the first
1236  // one. If it's busy that's the worst time to give it unnecessary work.
1237  if (starttime == 0) {
1238  starttime = g_get_real_time();
1239  }
1240  timeframe = intframe_new(FRAMETYPE_WALLCLOCK, sizeof(starttime));
1241  timeframe->setint(timeframe, starttime);
1242  frameset_append_frame(fs, &timeframe->baseclass);
1243  UNREF2(timeframe);
1244 
1245  // Put in the JSON configuration text
1246  jsontext = context->getstring(context, cfgname);
1248  csf->baseclass.setvalue(&csf->baseclass, g_strdup(jsontext), strlen(jsontext)+1
1250 
1251  frameset_append_frame(fs, &csf->baseclass);
1252  UNREF2(csf);
1253 
1254  if (is_encryption_enabled) {
1255  const char * keyid;
1256  CryptFramePublicKey* ourpubkey;
1258  ourpubkey = cryptframe_public_key_by_id(keyid);
1259  if (NULL != ourpubkey) {
1261  Frame* keyframe = frame_new(ourpubkey->frame_type, 0);
1262 
1263  keyidfr->baseclass.setvalue(&keyidfr->baseclass
1264  , g_strdup(keyid), strlen(keyid)+1
1266  frameset_append_frame(fs, &keyidfr->baseclass);
1267  UNREF2(keyidfr);
1268 
1269  keyframe->setvalue(keyframe
1270  , ourpubkey->public_key
1271  , ourpubkey->key_size
1272  , NULL);
1273  frameset_append_frame(fs, keyframe);
1274  UNREF(keyframe);
1275  }
1276  }
1277 
1278 
1279  // We've constructed the frameset - now send it - unreliably...
1280  // That's because the reply is typically from a different address
1281  // which would confuse the blazes out of the reliable comm code.
1282  cruft->iosource->sendaframeset(cruft->iosource, cmainit, fs);
1283  DEBUGMSG("%s.%d: Sent initial STARTUP frameset for %s."
1284  , __FUNCTION__, __LINE__, sysname);
1285  g_free(sysname); sysname = NULL;
1286  UNREF(fs);
1287  return TRUE;
1288 }
1289 
1290 static PacketDecoder* decoder = NULL;
1291 
1292 
1297  // This is the complete set of commands that nanoprobes know how to obey - so far...
1313  {0, NULL},
1314 };
1315 
1320 {
1321  static FrameTypeToFrame decodeframes[] = FRAMETYPEMAP;
1322  // Set up our packet decoder
1323  decoder = packetdecoder_new(0, decodeframes, DIMOF(decodeframes));
1324  return decoder;
1325 }
1326 
1327 
1354 WINEXPORT void
1355 nano_start_full(const char *initdiscoverpath
1356  , guint discover_interval
1357  , NetGSource* io
1358  , ConfigContext* config
1359  , gboolean(*authfunc)(const FrameSet*, NetAddr*))
1362 {
1363  static struct startup_cruft cruftiness;
1364  struct startup_cruft initcrufty = {
1365  initdiscoverpath,
1367  io,
1368  };
1369 
1370  BINDDEBUG(nanoprobe_main);
1371  nano_shutting_down = FALSE;
1372  if (NULL == nano_random) {
1373  nano_random = g_rand_new();
1374  }
1375  if (NULL == authfunc) {
1376  authfunc = _nanoprobe_is_cma_frameset;
1377  }
1379  cruftiness = initcrufty;
1380  g_source_ref(CASTTOCLASS(GSource, io));
1381  nanotransport = io;
1382 
1383  obeycollective = authlistener_new(0, collective_obeylist, config, TRUE, authfunc);
1384  obeycollective->baseclass.associate(&obeycollective->baseclass, io);
1386  // Initiate the startup process
1387  g_idle_add(nano_startupidle, &cruftiness);
1388 }
1389 
1391 WINEXPORT void
1392 nano_shutdown(gboolean report)
1393 {
1394  if (report) {
1395  NetIOstats* ts = &nanotransport->_netio->stats;
1396  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of heartbeats:", nano_hbstats.heartbeat_count);
1397  g_info("%-35s %8d", "Count of deadtimes:", nano_hbstats.dead_count);
1398  g_info("%-35s %8d", "Count of warntimes:", nano_hbstats.warntime_count);
1399  g_info("%-35s %8d", "Count of comealives:", nano_hbstats.comealive_count);
1400  g_info("%-35s %8d", "Count of martians:", nano_hbstats.martian_count);
1401  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of recvfrom calls:", ts->recvcalls);
1402  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of pkts read:", ts->pktsread);
1403  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of framesets read:", ts->fsreads);
1404  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of sendto calls:", ts->sendcalls);
1405  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of pkts written:", ts->pktswritten);
1406  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of framesets written:", ts->fswritten);
1407  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of reliable framesets sent:", ts->reliablesends);
1408  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of reliable framesets recvd:", ts->reliablereads);
1409  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of ACKs sent:", ts->ackssent);
1410  g_info("%-35s %8"G_GINT64_MODIFIER"d", "Count of ACKs recvd:", ts->acksrecvd);
1411  }
1414 
1415 
1416  if (nanofailreportaddr) {
1417  UNREF(nanofailreportaddr);
1418  }
1419  if (nanotransport) {
1420  g_source_destroy(CASTTOCLASS(GSource, nanotransport));
1421  g_source_unref(CASTTOCLASS(GSource, nanotransport));
1422  nanotransport = NULL;
1423  }
1424  // Free packet decoder
1425  if (decoder) {
1426  UNREF(decoder);
1427  }
1428  obeycollective->baseclass.dissociate(&obeycollective->baseclass);
1429  UNREF2(obeycollective);
1431 }
1432 
1434 WINEXPORT gboolean
1436 {
1437 
1438  if (nano_connected) {
1439  FsProtocol* proto = CASTTOCLASS(ReliableUDP, nanotransport->_netio)->_protocol;
1440  char * sysname;
1441  DEBUGMSG("Sending HBSHUTDOWN to CMA");
1442  sysname = proj_get_sysname();
1444  g_free(sysname); sysname = NULL;
1445  // Initiate connection shutdown.
1446  // This process will wait for all our output to be ACKed.
1447  // It also has an ACK timer, so it won't wait forever...
1448  proto->closeall(proto);
1449  idle_shutdown_gsource = g_timeout_add_full(G_PRIORITY_LOW, 100 // .1 Secs
1450  , shutdown_when_outdone, NULL, NULL);
1451  nano_shutting_down = TRUE;
1452  // Unregister all discovery modules. Keep us from starting any new ones...
1454  // Let's not start any more resource operations either...
1455  if (RscQ) {
1456  RscQ->cancelall(RscQ);
1457  UNREF(RscQ);
1458  }
1459  // @TODO We need to ignore additional requests during shutdown as well...
1460  }else{
1461  nano_shutting_down = TRUE;
1462  g_warning("%s: Never connected to CMA - cannot send shutdown message.", procname);
1463  ++errcount; // Trigger non-zero exit code...
1464  _nano_final_shutdown(NULL);
1465  return TRUE;
1466  }
1467  return FALSE;
1468 }
1469 
1471 FSTATIC gboolean
1472 shutdown_when_outdone(gpointer unused)
1473 {
1474  ReliableUDP* t = CASTTOCLASS(ReliableUDP, nanotransport->_netio);
1476  static gint64 giveuptime = 0;
1477  (void)unused;
1478  if (giveuptime == 0) {
1479  giveuptime = g_get_monotonic_time() + ((gint64)(FSPROTO_ACKTIMEOUTINT+1)*(gint64)1000000L);
1480  }
1481  if (g_get_monotonic_time() > giveuptime) {
1482  g_critical("Immediate shutdown. Connections still active after %d seconds."
1483  , (int)FSPROTO_ACKTIMEOUTINT);
1484  g_main_quit(mainloop);
1485  return FALSE;
1486  }
1487  // Wait for all our connections to be shut down
1488  if (proto->activeconncount(proto) == 0){
1489  g_info("%s.%d: Shutting down - all connections closed."
1490  , __FUNCTION__, __LINE__);
1491  g_main_quit(mainloop);
1492  return FALSE;
1493  }
1494  return TRUE;
1495 }
1496 // Final Shutdown -- a contingency timer to make sure we eventually shut down
1497 FSTATIC gboolean
1498 _nano_final_shutdown(gpointer unused)
1499 {
1500  (void)unused;
1501  g_info("%s.%d: Initiating final shutdown", __FUNCTION__, __LINE__);
1502  if (nano_connected && nanotransport->_netio->outputpending(nanotransport->_netio)){
1503  g_warning("Shutting down with unACKed output.");
1504  DUMP("Transport info", &nanotransport->_netio->baseclass, NULL);
1505  }
1506  if (idle_shutdown_gsource) {
1507  g_source_remove(idle_shutdown_gsource);
1508  idle_shutdown_gsource = 0;
1509  }
1510  if (nano_random) {
1511  g_rand_free(nano_random);
1512  nano_random = NULL;
1513  }
1514  g_main_quit(mainloop);
1515  return FALSE;
1516 }
1517 
1518 // Initialize our encryption setup...
1519 WINEXPORT void
1521 {
1522  GList* key_id_list;
1523  GList* thiselem;
1524  char * sysname = proj_get_sysname();
1525  int sysname_len = strlen(sysname);
1526  // Read in and cache all our key pairs
1528 
1529  key_id_list = cryptframe_get_key_ids();
1530  // We're looking for our own signing key, and all the CMA's signing keys
1531  for (thiselem = key_id_list; NULL != thiselem; thiselem=g_list_next(thiselem)) {
1532  const char * key_id = (char*)thiselem->data;
1533  // Format of our key ids: "system-name@@our-key-hash-value"
1534  if (strncmp(key_id, sysname, sysname_len) == 0 && key_id[sysname_len] == '@') {
1535  if (NULL != cryptframe_public_key_by_id(key_id)) {
1537  }
1538  }else if (strncmp(key_id, CMA_KEY_PREFIX, sizeof(CMA_KEY_PREFIX)-1) == 0) {
1540  }
1541  }
1543  g_warning("%s.%d: Encryption not enabled (no CMA public key available)."
1544  , __FUNCTION__, __LINE__);
1545  }else{
1546  // Generate a key pair if we don't already have one
1547  if (cryptframe_get_signing_key() == NULL) {
1548  char * key_id = cryptcurve25519_gen_persistent_keypair(NULL);
1549  if (NULL != key_id) {
1550  g_info("%s.%d: Generated public key pair [%s]"
1551  , __FUNCTION__, __LINE__, key_id);
1553  g_free(key_id);
1554  }else{
1555  g_warning("%s.%d: Encryption not enabled"
1556  ": cannot generate public key pair.", __FUNCTION__, __LINE__);
1557  }
1558  }
1559  if (cryptframe_get_signing_key() == NULL) {
1560  g_warning("%s.%d: Encryption not enabled"
1561  ": cannot get signing key.", __FUNCTION__, __LINE__);
1562  }else{
1564  is_encryption_enabled = TRUE;
1565  }
1566  }
1567  g_list_free(key_id_list); key_id_list = NULL;
1568  g_free(sysname); sysname = NULL;
1569 }
1570 
1574 WINEXPORT void
1576 {
1577  GSList* keys = cfg->keys(cfg);
1578  GSList* thiskey;
1579  static const char cmaprefix[] = "cma";
1580 
1581  for (thiskey = keys; NULL != thiskey; thiskey=g_slist_next(thiskey)) {
1582  const char * keyname = (const char *)thiskey->data;
1583 
1584  // Is this entry a NetAddr whose name starts with "cma"?
1585  if ( cfg->gettype(cfg, keyname) == CFG_NETADDR
1586  && strncmp(keyname, cmaprefix, sizeof(cmaprefix)-1) == 0) {
1587  NetAddr* destaddr = cfg->getaddr(cfg, keyname);
1588 
1589  cryptframe_set_dest_key_id(destaddr, key_id);
1590  }
1591  }
1592  g_slist_free(keys); keys=NULL;
1593 }
1594 
1595 #define SECOND 1000000
1596 #define COMPLAINT_INTERVAL (60*SECOND)
1597 
1599 FSTATIC gboolean
1601 {
1602  const char* identity;
1603  gboolean retval;
1604 
1605  if (!is_encryption_enabled) {
1606  static gint64 last_complaint = 0L;
1607  gint64 now = g_get_monotonic_time();
1608  if (now >= (last_complaint+COMPLAINT_INTERVAL)) {
1609  g_warning("%s.%d: Encryption is NOT enabled. Encryption REQUIRED for production."
1610  , __FUNCTION__, __LINE__);
1611  g_info("See Assimilation documentation for how to distribute the CMA's public key.");
1612  last_complaint = now;
1613  }
1614  // Without encryption, we have to accept every frameset as authenticated...
1615  return TRUE;
1616  }
1617  identity = frameset_sender_identity(fs);
1618  retval = (identity ? strcmp(identity, CMA_IDENTITY_NAME) == 0 : FALSE);
1619  if (retval) {
1621  }
1622  return retval;
1623 }
WINEXPORT gboolean cryptframe_set_dest_key_id(NetAddr *destaddr, const char *key_id)
Set the encryption key to use when sending to destaddr Set destkey to NULL to stop encrypting to that...
Definition: cryptframe.c:470
FSTATIC void _nano_send_rscexitstatus(ConfigContext *request, gpointer user_data, enum HowDied reason, int rc, int signal, gboolean core_dumped, const char *stringresult)
Callback that gets called when a resource operation sends back status.
Definition: nanoprobe.c:896
guint64 recvcalls
How many recvfrom calls have we done?
Definition: netio.h:42
ConfigContext * configcontext_new_JSON_string(const char *jsontext)
Construct a ConfigContext object from the given JSON string.
Listener baseclass
Definition: authlistener.h:42
#define FRAMESETTYPE_HBDEAD
System named in packet appears to be dead.
Definition: framesettypes.h:39
#define CONFIGNAME_CMADISCOVER
Address of where to send discovery reports.
#define CONFIGNAME_INTERVAL
How long to wait between events.
Frame baseclass
Definition: ipportframe.h:41
#define FRAMESETTYPE_STOPRSCOP
Stop a (possibly-repeating) JSON resource action.
Definition: framesettypes.h:61
FSTATIC gboolean _nanoprobe_is_cma_frameset(const FrameSet *fs, NetAddr *)
Return TRUE if this FrameSet came.
Definition: nanoprobe.c:1600
WINEXPORT GList * cryptframe_get_key_ids(void)
Return a GList of strings of all known key ids.
Definition: cryptframe.c:397
#define CONFIG_DEFAULT_WARNTIME
Default warning time.
This is the base HbSender class. object - which sends heartbeats to particular listeners.
Definition: hbsender.h:39
guint32 length
Frame Length.
Definition: frame.h:46
FSTATIC void nanoobey_dorscoperation(AuthListener *, FrameSet *, NetAddr *)
Definition: nanoprobe.c:940
NetAddr *(* boundaddr)(const NetIO *self)
[in] Object to return bound address/port of
Definition: netio.h:79
int frame_type
FrameType of this type of public key (we never send private keys - no symmetry here) ...
Definition: cryptframe.h:38
gboolean(* getbool)(const ConfigContext *, const char *name)
Get boolean value.
Definition: configcontext.h:77
Frame *(* getframe)(const ConfigContext *, const char *)
Get Frame value.
Definition: configcontext.h:90
FSTATIC void _real_warntime_agent(HbListener *who, guint64 howlate)
Standard nanoprobe &#39;warntime elapsed&#39; agent - called when a heartbeat arrives after &#39;warntime&#39; but be...
Definition: nanoprobe.c:247
FSTATIC gboolean nano_startupidle(gpointer gcruft)
Nanoprobe bootstrap routine.
Definition: nanoprobe.c:1121
void(* set_deadtime)(HbListener *, guint64)
Set deadtime.
Definition: hblistener.h:47
#define DEBUGMSG1(...)
Definition: proj_classes.h:89
FSTATIC void nanoobey_startdiscover(AuthListener *, FrameSet *, NetAddr *)
Act on (obey) a FrameSet class telling us to perform a possibly repeating discovery action...
Definition: nanoprobe.c:835
int discover_interval
Definition: nanoprobe.c:1110
gboolean(* Qcmd)(ResourceQueue *self, ConfigContext *request, ResourceCmdCallback callback, gpointer user_data)
Definition: resourcequeue.h:55
#define FRAMESETTYPE_HBMARTIAN
System named in packet appears gave unexpected heartbeat.
Definition: framesettypes.h:43
#define FRAMESETTYPE_HBSHUTDOWN
System originating packet has shut down.
Definition: framesettypes.h:40
Defines miscellaneous interfaces.
Stuff we need only for passing parameters through our glib infrastructures - to start up nanoprobes...
Definition: nanoprobe.c:1108
#define FRAMETYPE_ELAPSEDTIME
FRAMETYPE_ELAPSEDTIME Frame (frametype 23) Frame subclass - IntFrame class.
Definition: frametypes.h:356
void(* setaddr)(ConfigContext *, const char *, NetAddr *)
Set NetAddr value.
Definition: configcontext.h:93
guint64 ackssent
How many ACKs have we sent?
Definition: netio.h:50
GRand * nano_random
Definition: nanoprobe.c:112
NetAddr * destaddr
Definition: nanomain.c:75
void discovery_unregister_all(void)
Unregister all discovery methods in preparation for shutting down - to make valgrind happy :-D...
Definition: discovery.c:202
void(* set_warntime_callback)(HbListener *, void(*)(HbListener *who, guint64 howlate))
Definition: hblistener.h:52
WINEXPORT char * cryptcurve25519_gen_persistent_keypair(const char *giveitaname)
Create a persistent keypair and write it to disk Returns a MALLOCed string with the key id for the ke...
char * proj_get_sysname(void)
Return a malloced string of the system name.
This is an IntFrame class TLV (type, length, value) frame - representing an integer of some specified...
Definition: intframe.h:39
gboolean outputpending(NetIO *self)
< return TRUE if this object has output pending
void(* sendaframeset)(NetGSource *, const NetAddr *, FrameSet *)
Send a single frameset.
Definition: netgsource.h:53
Structure associating FrameSet class types with actions to perform when they&#39;re received.
Definition: authlistener.h:51
NetIO * _netio
netio this object is based on
Definition: netgsource.h:50
#define FRAMESETTYPE_STOPSENDHB
Stop sending Heartbeats to these addresses.
Definition: framesettypes.h:52
PacketDecoder * nano_packet_decoder(void)
Return our nanoprobe packet decoder map.
Definition: nanoprobe.c:1319
gboolean(* cancel)(ResourceQueue *self, ConfigContext *request)
Definition: resourcequeue.h:59
#define CONFIGNAME_TYPE
Type of resource or discovery.
#define FRAMESETTYPE_HEARTBEAT
A heartbeat packet.
Definition: framesettypes.h:32
NetIOudp is a NetIOudp class subclass specialized to provide reliable UDP connections.
Definition: reliableudp.h:43
FSTATIC void nanoobey_cancelrscoperation(AuthListener *, FrameSet *, NetAddr *)
Definition: nanoprobe.c:975
guint64(* getint)(IntFrame *self)
get value of integer in this IntFrame
Definition: intframe.h:42
#define DEBUGMSG(...)
Definition: proj_classes.h:87
WINEXPORT GMainLoop * mainloop
Definition: nanoprobe.c:68
#define FRAMETYPE_JSDISCOVER
FRAMETYPE_JSDISCOVER Frame (frametype 19) Frame subclass - CstringFrame class.
Definition: frametypes.h:308
HbSender * hbsender_new(NetAddr *sendaddr, NetGSource *outmethod, guint interval, gsize objsize)
Construct a new HbSender - setting up timeout data structures for it.
Definition: hbsender.c:127
Implements minimal client-oriented Frame and Frameset capabilities.
#define FRAMETYPE_HBWARNTIME
FRAMETYPE_HBWARNTIME Frame (frametype 16) Frame subclass - IntFrame class.
Definition: frametypes.h:283
ObeyFrameSetTypeMap collective_obeylist[]
The set of Collective Management Authority FrameTypes we know about, and what to do when we get them...
Definition: nanoprobe.c:1296
WINEXPORT IpPortFrame * ipportframe_netaddr_new(guint16 frame_type, NetAddr *addr)
Construct and initialize an IpPortFrame class from a IP NetAddr class.
Definition: ipportframe.c:234
void(* setconfig)(ConfigContext *, const char *, ConfigContext *)
Set ConfigContext value.
Definition: configcontext.h:96
const char * procname
process name
Definition: nanoprobe.c:113
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
FSTATIC gboolean _nano_final_shutdown(gpointer unused)
Definition: nanoprobe.c:1498
void(* setint)(ConfigContext *, const char *name, gint value)
Set integer value.
Definition: configcontext.h:75
IntFrame * intframe_new(guint16 frametype, int intbytes)
Construct new IntFrame object.
Definition: intframe.c:179
FSTATIC void nano_stop_discovery(const char *discoveryname, NetGSource *, NetAddr *)
WINEXPORT gboolean cryptframe_associate_identity(const char *identity, const char *key_id)
Associate the given key id with the given identity Note that it is OK to associate multiple key ids w...
Definition: cryptframe.c:293
void(* dissociate)(Listener *self)
Dissociate us from our source.
Definition: listener.h:51
#define FRAMESETTYPE_STOPEXPECTHB
Stop expecting (listening for) Heartbeats from these addresses.
Definition: framesettypes.h:53
NetAddr * listenaddr
What address are we listening for?
Definition: hblistener.h:62
guint64 reliablesends
How many reliable FrameSets have we sent?
Definition: netio.h:48
void(* addalias)(NetIO *, NetAddr *, NetAddr *)
Add an alias to our received address alias table.
Definition: netio.h:88
Describes interfaces to C-String Frame (Cstringframe) C-Class It holds conventional zero-terminated b...
void(* nanoprobe_deadtime_agent)(HbListener *)
Definition: nanoprobe.c:61
AssimObj baseclass
Definition: netaddr.h:44
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
WINEXPORT void nanoprobe_initialize_keys(void)
Definition: nanoprobe.c:1520
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
FSTATIC void hblistener_set_martian_callback(void(*callback)(NetAddr *who))
Call to set a callback to be called when an unrecognized node sends us a heartbeat.
Definition: hblistener.c:410
void(* set_comealive_callback)(HbListener *, void(*)(HbListener *who, guint64 howlate))
Definition: hblistener.h:53
void(* set_deadtime_callback)(HbListener *, void(*)(HbListener *who))
Definition: hblistener.h:51
#define FRAMESETTYPE_STOPSENDEXPECTHB
Stop sending Heartbeats to these addresses, and stop expecting them as well.
Definition: framesettypes.h:54
WINEXPORT const char * frameset_sender_identity(const FrameSet *self)
Return the identity of this Frameset&#39;s CryptFrame sender – NULL if None or Unknown.
Definition: frameset.c:451
class defining object discovered by invoking commands that return JSON as their output.
WINEXPORT gint64 g_get_real_time(void)
HAVE_G_GET_MONOTONIC_TIME.
Simple libpcap interface definitions.
ArpDiscovery * arpdiscovery_new(ConfigContext *arpconfig, gint priority, GMainContext *mcontext, NetGSource *iosrc, ConfigContext *config, gsize objsize)
ArpDiscovery constructor - good for listening to ARP packets via pcap.
Definition: arpdiscovery.c:286
FSTATIC void hblistener_shutdown(void)
Shuts down all our hblisteners...
Definition: hblistener.c:222
FSTATIC void nanoobey_connshut(AuthListener *, FrameSet *, NetAddr *)
Definition: nanoprobe.c:280
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
#define DEBUGMSG3(...)
Definition: proj_classes.h:91
#define FRAMETYPE_HOSTNAME
FRAMETYPE_HOSTNAME Frame (frametype 9) Frame subclass - CstringFrame class.
Definition: frametypes.h:192
gpointer public_key
Pointer to the (malloced) public key;.
Definition: cryptframe.h:40
gpointer value
Frame Value (pointer)
Definition: frame.h:47
FSTATIC void nanoobey_stopdiscover(AuthListener *, FrameSet *, NetAddr *)
Act on (obey) a FrameSet class telling us to stop a repeating discovery action.
Definition: nanoprobe.c:1011
void(* setdouble)(ConfigContext *, const char *name, double value)
Definition: configcontext.h:81
SwitchDiscovery C-class - for discovering switch and port configuration via LLDP, CDP and similar pro...
guint32 compression_threshold
Definition: compressframe.h:43
io
Definition: hello.py:115
#define FRAMETYPE_HBINTERVAL
FRAMETYPE_HBINTERVAL Frame (frametype 14) Frame subclass - IntFrame class.
Definition: frametypes.h:257
#define CONFIG_DEFAULT_HBTIME
Default heartbeat interval.
#define FRAMETYPE_CONFIGJSON
FRAMETYPE_CONFIGJSON Frame (frametype 20) Frame subclass - CstringFrame class.
Definition: frametypes.h:319
void(* setvalue)(Frame *self, gpointer value, guint32 length, GDestroyNotify valfinal)
member function for setting value
Definition: frame.h:52
int signal
Definition: childprocess.c:238
#define FRAMETYPEMAP
Definition: frametypes.h:446
guint64 heartbeat_count
Definition: nanoprobe.h:33
CryptFramePublicKey * preferred_cma_key_id
Definition: nanoprobe.c:109
guint16 fstype
Type of frameset.
Definition: frameset.h:52
PacketDecoder * packetdecoder_new(guint objsize, const FrameTypeToFrame *framemap, gint mapsize)
Initialize our frame type map.
Definition: packetdecoder.c:77
FSTATIC gboolean _nano_initconfig_OK(ConfigContext *config)
Definition: nanoprobe.c:1162
FSTATIC gboolean nano_reqconfig(gpointer gcruft)
Function to request our initial configuration data This is typically called from a g_main_loop timeou...
Definition: nanoprobe.c:1180
FSTATIC void nanoobey_decrdebug(AuthListener *, FrameSet *, NetAddr *)
Act on (obey) a FrameSet class telling us to decrement debug levels either on a specific set of class...
Definition: nanoprobe.c:820
void proj_class_decr_debug(const char *Cclass)
Decrement debug level for this class and all its subclasses by one.
Definition: proj_classes.c:148
gboolean nano_shutting_down
Definition: nanoprobe.c:110
void hbsender_stopallsenders(void)
Stop sending heartbeats to anyone...
Definition: hbsender.c:201
#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
FSTATIC void nano_schedule_discovery(const char *name, guint32 interval, const char *json, ConfigContext *, NetGSource *transport, NetAddr *fromaddr)
Schedule a discovery instance, potentially repetitively.
Definition: nanoprobe.c:1046
Implements the IntFrame class - integers in a frame.
WINEXPORT void cryptframe_shutdown(void)
Shut down our key caches and so on... (destroy our maps)
Definition: cryptframe.c:159
FSTATIC void nanoobey_ackstartup(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FRAMESETTYPE_ACKSTARTUP FrameSet class.
Definition: nanoprobe.c:728
Class for discovering Link-Level (switch) information (using CDP or LLDP or some future analogous pro...
AssimObj baseclass
Definition: configcontext.h:72
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
#define __FUNCTION__
void closeconn(NetIO *self, guint16 qid, const NetAddr *destaddr)
< Flush packets in queues to this address
#define CONFIGNAME_WARNTIME
How long w/o heartbeats before whining?
AssimObj baseclass
Definition: netio.h:59
#define FRAMESETTYPE_EXPECTHB
Expect (listen for) Heartbeats from these addresses.
Definition: framesettypes.h:50
#define DEBUG
Definition: proj_classes.h:85
Defines Heartbeat Sender interfaces.
void(* set_heartbeat_callback)(HbListener *, void(*)(HbListener *who))
Definition: hblistener.h:50
#define REQCOREDUMPNAMEFIELD
Definition: resourcecmd.h:79
void(* addListener)(NetGSource *, guint16, Listener *)
Register a new listener.
Definition: netgsource.h:55
This is our CompressFrame class object - used for representing a compression method.
Definition: compressframe.h:41
void(* nanoprobe_heartbeat_agent)(HbListener *)
Definition: nanoprobe.c:62
#define FRAMESETTYPE_SENDHB
Send Heartbeats to these addresses.
Definition: framesettypes.h:49
SwitchDiscovery * switchdiscovery_new(ConfigContext *swconfig, gint priority, GMainContext *mcontext, NetGSource *iosrc, ConfigContext *config, gsize objsize)
SwitchDiscovery constructor.
void(* setint)(IntFrame *self, guint64 value)
set the integer to the given value
Definition: intframe.h:43
#define FRAMETYPE_DISCJSON
FRAMETYPE_DISCJSON Frame (frametype 26) Frame subclass - CstringFrame class.
Definition: frametypes.h:394
Describes interfaces to CryptFrame (encryption) C-Class It represents the abstract base class for Fra...
#define CONFIGNAME_TIMEOUT
How before declaring a serious problem...
#define DUMP1(prefix, obj, suffix)
Definition: proj_classes.h:95
void(* set_warntime)(HbListener *, guint64)
Set warntime.
Definition: hblistener.h:49
Implements the Reliable UDP network I/O transport (ReliableUDP) class.
#define DUMP3(prefix, obj, suffix)
Definition: proj_classes.h:97
#define REQSIGNALNAMEFIELD
Definition: resourcecmd.h:78
gint64(* getint)(const ConfigContext *, const char *name)
Get integer value.
Definition: configcontext.h:74
WINEXPORT int errcount
error count
Definition: nanoprobe.c:67
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:125
FSTATIC gboolean shutdown_when_outdone(gpointer unused)
Shut down everything when output is all ACKed - this is idle loop code.
Definition: nanoprobe.c:1472
#define FRAMETYPE_IPPORT
FRAMETYPE_IPPORT Frame (frametype 13) Frame subclass - IpPortFrame class.
Definition: frametypes.h:244
Header file defining all known FrameSet types THIS FILE MECHANICALLY GENERATED by "/home/alanr/assim/...
#define FRAMESETTYPE_DODISCOVER
Perform (repeating) JSON discovery action.
Definition: framesettypes.h:58
guint64(* get_deadtime)(HbListener *)
Retrieve deadtime.
Definition: hblistener.h:46
This is the AuthListener class. object - which (authorizes and) obeys packets from the Authority...
Definition: authlistener.h:41
JsonDiscovery * jsondiscovery_new(const char *discoverytype, const char *instancename, gint intervalsecs, ConfigContext *jsoninst, NetGSource *iosource, ConfigContext *context, gsize objsize)
JsonDiscovery constructor.
FSTATIC CryptFramePublicKey * cryptframe_public_key_by_id(const char *key_id)
Return the non-const public key with the given id.
Definition: cryptframe.c:270
#define FRAMETYPE_RSCJSON
FRAMETYPE_RSCJSON Frame (frametype 27) Frame subclass - CstringFrame class.
Definition: frametypes.h:406
Describes interfaces to C-String Frame (Compressframe) C-Class It holds conventional zero-terminated ...
#define CMA_IDENTITY_NAME
Definition: nanoprobe.h:42
FSTATIC void nanoobey_sendexpecthb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FRAMESETTYPE_SENDEXPECTHB FrameSet class.
Definition: nanoprobe.c:485
#define FMT_64BIT
Format designator for a 64 bit integer.
Definition: projectcommon.h:32
FSTATIC void nanoobey_change_debug(gint plusminus, AuthListener *, FrameSet *, NetAddr *)
Act on (obey) a FrameSet class telling us to increment or decrement debug levels either on a specific...
Definition: nanoprobe.c:769
#define REF(obj)
Definition: assimobj.h:39
const char * initdiscover
Definition: nanoprobe.c:1109
#define REQREASONENUMNAMEFIELD
Definition: resourcecmd.h:76
FsProtocol * _protocol
Queuing, ordering, retransmission and ACKing discipline.
Definition: reliableudp.h:45
#define FRAMETYPE_WALLCLOCK
FRAMETYPE_WALLCLOCK Frame (frametype 7) Frame subclass - IntFrame class.
Definition: frametypes.h:167
Data structure defining the mapping between frametype integers and corresponding demarshalling module...
Definition: packetdecoder.h:37
FSTATIC void nanoobey_stopsendexpecthb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FrameSet class telling us to stop sending and expecting heartbeats.
Definition: nanoprobe.c:565
#define FRAMESETTYPE_INCRDEBUG
Increment debug for some or all classes.
Definition: framesettypes.h:56
NetIOstats stats
Net I/O stats.
Definition: netio.h:60
WINEXPORT gint64 g_get_monotonic_time(void)
Local replacement for g_get_monotonic_time() - for old releases of glib.
guint64 reliablereads
How many reliable FrameSets have we read?
Definition: netio.h:49
include file defining functions to be called by a main to instantiate a nanoprobe.
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
#define CONFIG_DEFAULT_DEADTIME
Default "deadtime".
WINEXPORT CryptFramePrivateKey * cryptframe_get_signing_key(void)
Return the default signing key.
Definition: cryptframe.c:441
#define FRAMETYPE_CSTRINGVAL
FRAMETYPE_CSTRINGVAL Frame (frametype 21) Frame subclass - CstringFrame class.
Definition: frametypes.h:330
FSTATIC void nanoobey_stopexpecthb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FrameSet class telling us to stop expecting heartbeats.
Definition: nanoprobe.c:535
FSTATIC void _real_comealive_agent(HbListener *who, guint64 howlate)
Standard nanoprobe &#39;returned-from-the-dead&#39; agent - called when a heartbeats arrive after &#39;deadtime&#39;...
Definition: nanoprobe.c:264
This is the base HbListener class. object - which listens for heartbeats from a particular sender...
Definition: hblistener.h:44
#define CMA_KEY_PREFIX
Definition: nanoprobe.h:41
This is our CstringFrame class object - used for holding C-style NULL terminated strings.
Definition: cstringframe.h:36
Listener baseclass
Definition: hblistener.h:45
Project common header file.
#define DIMOF(a)
Definition: lldp_min.c:30
WINEXPORT const char * frameset_sender_key_id(const FrameSet *self)
Return the key_id of this Frameset&#39;s CryptFrame sender – NULL if None.
Definition: frameset.c:434
Header file defining the data layouts for our Frames.
FSTATIC void _nanoprobe_associate_cma_addrs(const char *key_id, ConfigContext *cfg)
Associate the given encryption key for all CMA addresses in the config we&#39;re given.
Definition: nanoprobe.c:1575
#define FRAMESETTYPE_ACKSTARTUP
Acknowledge full response to STARTUP packet.
Definition: framesettypes.h:62
JsonDiscovery abstract C-class - it supports discovering "things" through running commands outputting...
Definition: jsondiscovery.h:37
NetGSource * transport
Definition: listener.h:44
#define FRAMESETTYPE_HBBACKALIVE
System named in packet sent heartbeat after being marked dead.
Definition: framesettypes.h:42
FSTATIC void nanoobey_stopsendhb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FrameSet class telling us to stop sending heartbeats.
Definition: nanoprobe.c:506
ConfigContext *(* getconfig)(const ConfigContext *, const char *name)
Get ConfigContext value.
Definition: configcontext.h:95
#define FRAMETYPE_DISCNAME
FRAMETYPE_DISCNAME Frame (frametype 24) Frame subclass - CstringFrame class.
Definition: frametypes.h:368
WINEXPORT gboolean nano_initiate_shutdown(void)
Initiate shutdown - return TRUE if we have shut down immediately...
Definition: nanoprobe.c:1435
void(* associate)(Listener *self, NetGSource *source)
NetGSource class to associate with
Definition: listener.h:49
Implements Configuration Context class.
WINEXPORT NanoHbStats nano_hbstats
Definition: nanoprobe.c:65
guint64 acksrecvd
How many ACKs have we received?
Definition: netio.h:51
NetGSource * iosource
Definition: nanoprobe.c:1111
void(* nanoprobe_comealive_agent)(HbListener *, guint64 howlate)
Definition: nanoprobe.c:64
#define CONFIGNAME_COMPRESS
Frame to use for compressing/decompressing.
HbListener * hblistener_new(NetAddr *listenaddr, ConfigContext *cfg, gsize objsize)
Construct a new HbListener - setting up GSource and timeout data structures for it.
Definition: hblistener.c:264
FSTATIC void discovery_unregister(const char *instance)
Definition: discovery.c:192
#define FRAMETYPE_DISCINTERVAL
FRAMETYPE_DISCINTERVAL Frame (frametype 25) Frame subclass - IntFrame class.
Definition: frametypes.h:381
void proj_class_incr_debug(const char *Cclass)
Increment debug level for this class and all its subclasses by one.
Definition: proj_classes.c:140
ConfigContext * config
Definition: listener.h:43
Class for discovering address resolution (IP to MAC address information) using the ARP protocol...
ConfigValType
Definition: configcontext.h:44
gboolean sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
[out] source address of return result
guint64 sendcalls
How many sendto calls have we done?
Definition: netio.h:45
WINEXPORT void cryptframe_set_encryption_method(CryptFrame *(*method)(const char *sender_key_id, const char *receiver_key_id, gboolean forsending))
Definition: cryptframe.c:518
void hbsender_stopsend(NetAddr *sendaddr)
Stop sending heartbeats to a particular address.
Definition: hbsender.c:165
#define FRAMESETTYPE_SETCONFIG
Initial configuration packet.
Definition: framesettypes.h:55
void(* closeall)(FsProtocol *)
Close all our connections.
Definition: fsprotocol.h:129
FSTATIC HbListener * _real_hblistener_new(NetAddr *, ConfigContext *)
Default HbListener constructor.
Definition: nanoprobe.c:127
FSTATIC void frame_default_valuefinalize(gpointer value)
Finalize a Frame.
Definition: frame.c:57
FSTATIC void nanoobey_incrdebug(AuthListener *, FrameSet *, NetAddr *)
Act on (obey) a FrameSet class telling us to increment debug levels either on a specific set of class...
Definition: nanoprobe.c:809
#define FRAMESETTYPE_DECRDEBUG
Increment debug for some or all classes.
Definition: framesettypes.h:57
FSTATIC void nanoobey_expecthb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FrameSet class telling us to expect heartbeats.
Definition: nanoprobe.c:372
guint16 type
Frame Type (see Individual TLV &#39;Frame&#39; data types and layouts (by TLV type) - frameformats.h )
Definition: frame.h:45
#define FRAMESETTYPE_HBLATE
System named in packet sent a late heartbeat.
Definition: framesettypes.h:41
guint64 fswritten
How many FrameSet class were successfully written?
Definition: netio.h:47
gboolean nano_connected
Definition: nanoprobe.c:66
GSList * framelist
List of frames in this FrameSet.
Definition: frameset.h:48
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
#define FRAMETYPE_HBDEADTIME
FRAMETYPE_HBDEADTIME Frame (frametype 15) Frame subclass - IntFrame class.
Definition: frametypes.h:270
void nanoprobe_report_upstream(guint16 reporttype, NetAddr *who, const char *systemnm, guint64 howlate)
Construct a frameset reporting something - and send it upstream.
Definition: nanoprobe.c:134
Describes interfaces to Address Frame (AddrFrame) C-Class.
double(* getdouble)(const ConfigContext *, const char *name)
Get double value.
Definition: configcontext.h:80
Frame baseclass
base Frame class object
Definition: intframe.h:40
Describes interfaces to Address Frame (IpPortFrame) C-Class.
ResourceQueue * resourcequeue_new(guint structsize)
Construct a new ResourceQueue system (you probably only need one)
Definition: resourcequeue.c:80
HowDied
Definition: childprocess.h:35
#define REQIDENTIFIERNAMEFIELD
Definition: resourcecmd.h:75
AuthListener * authlistener_new(gsize objsize, ObeyFrameSetTypeMap *map, ConfigContext *config, gboolean autoack, gboolean(*authenticator)(const FrameSet *fs, NetAddr *))
Construct a new Listener - setting up GSource and timeout data structures for it. ...
Definition: authlistener.c:133
#define DUMP(prefix, obj, suffix)
Definition: proj_classes.h:94
#define FRAMESETTYPE_STOPDISCOVER
Stop a repeating JSON discovery action.
Definition: framesettypes.h:59
FSTATIC void _real_deadtime_agent(HbListener *who)
Standard nanoprobe &#39;deadtime elapsed&#39; agent.
Definition: nanoprobe.c:215
#define g_info(...)
Definition: projectcommon.h:66
#define DEFAULT_FSP_QID
Default Queue ID.
Definition: fsprotocol.h:134
#define CONFIGNAME_INSTANCE
Instance name for discovery.
guint dead_count
Definition: nanoprobe.h:34
NetAddr *(* getnetaddr)(IpPortFrame *f)
Definition: ipportframe.h:45
enum ConfigValType(* gettype)(const ConfigContext *, const char *)
Return type.
Definition: configcontext.h:99
void(* setstring)(ConfigContext *, const char *name, const char *value)
Definition: configcontext.h:87
guint64 pktsread
How many packets have been successfully read?
Definition: netio.h:43
#define CONFIGNAME_CPRS_THRESH
Threshold for compressing (integer)
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
guint comealive_count
Definition: nanoprobe.h:36
void(* nanoprobe_warntime_agent)(HbListener *, guint64 howlate)
Definition: nanoprobe.c:63
Implements the resource queue class.
#define FRAMESETTYPE_SENDEXPECTHB
Send Heartbeats to these addresses, and expect them as well.
Definition: framesettypes.h:51
WINEXPORT void nano_shutdown(gboolean report)
Shut down the things started up by nano_start_full() - mainly free storage to make valgrind happy...
Definition: nanoprobe.c:1392
#define FRAMETYPE_RSCJSONREPLY
FRAMETYPE_RSCJSONREPLY Frame (frametype 28) Frame subclass - CstringFrame class.
Definition: frametypes.h:418
WINEXPORT void nano_start_full(const char *initdiscoverpath, guint discover_interval, NetGSource *io, ConfigContext *config, gboolean(*authfunc)(const FrameSet *, NetAddr *))
Here is how the startup process works:
Definition: nanoprobe.c:1355
Implements NetIO GSource object.
WINEXPORT void cryptframe_set_signing_key_id(const char *key_id)
Set the default signing key.
Definition: cryptframe.c:416
#define FRAMESETTYPE_STARTUP
Nanoprobe originating packet is starting up.
Definition: framesettypes.h:35
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC void hblistener_unlisten(NetAddr *unlistenaddr)
Stop expecting (listening for) heartbeats from a particular address.
Definition: hblistener.c:358
#define CONFIGNAME_CMAFAIL
Address of where to send failure reports.
#define CONFIGNAME_CMAINIT
Initial startup contact address for the CMA.
#define DUMP2(prefix, obj, suffix)
Definition: proj_classes.h:96
GSList *(* keys)(const ConfigContext *)
Return list of keys.
Implements the resource command abstract class.
Implements the SeqnoFrame class.
WINEXPORT GHashTable * cryptframe_key_ids_for(const char *identity)
Return a GHashTable of strings of all the key ids associated with the given identity.
Definition: cryptframe.c:380
ArpDiscovery C-class - for discovering IP/MAC address resolution via the ARP protocol captured using ...
Definition: arpdiscovery.h:36
void(* cancelall)(ResourceQueue *self)
Definition: resourcequeue.h:61
#define DEBUGMSG2(...)
Definition: proj_classes.h:90
Defines Listener interfaces for packets coming from the Collective Authority.
ConfigContext * configcontext_new(gsize objsize)
Construct a new ConfigContext object - with no values defaulted.
guint martian_count
Definition: nanoprobe.h:37
WINEXPORT const char * cryptframe_get_signing_key_id(void)
Return the key_id of the default signing key.
Definition: cryptframe.c:434
#define MARTIAN_TIMEOUT
Definition: nanoprobe.h:70
void(* setbool)(ConfigContext *, const char *name, gboolean)
Set bool value.
Definition: configcontext.h:78
WINEXPORT void cryptcurve25519_cache_all_keypairs(void)
We read in and cache all the key pairs (or public keys) that we find in CRYPTKEYDIR.
NetAddr * netaddr_string_new(const char *addrstr)
Create a NetAddr from an ipv4, ipv6 or MAC address string.
Definition: netaddr.c:976
FSTATIC void nanoobey_setconfig(AuthListener *, FrameSet *fs, NetAddr *)
Definition: nanoprobe.c:580
FSTATIC void _nano_initial_discovery(AuthListener *parent, NetAddr *fromaddr)
Perform any self-initiated one-shot discovery actions to make sure these run first.
Definition: nanoprobe.c:747
#define FSPROTO_ACKTIMEOUTINT
ACK timeout interval (2 minutes)
Definition: fsprotocol.h:137
#define FRAMETYPE_KEYID
FRAMETYPE_KEYID Frame (frametype 29) Frame subclass - CstringFrame class.
Definition: frametypes.h:430
This file defines a few functions and interfaces for unmarshalling packet data into FrameSets...
Describes interfaces to name/value pair Frame (NVpairFrame) C-Class It holds conventional zero-termin...
#define UNREF2(obj)
Definition: assimobj.h:36
WINEXPORT CryptFrame * cryptcurve25519_new_generic(const char *sender_key_id, const char *receiver_key_id, gboolean forsending)
Generic "new" function to use with cryptframe_set_encryption_method()
#define CASTTOCLASS(Cclass, obj)
Safely cast &#39;obj&#39; to C-class &#39;class&#39; - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
guint64 fsreads
How many FrameSet class were successfully read?
Definition: netio.h:44
This is a basic NetIO class abstract class for doing network I/O.
Definition: netio.h:58
#define COMPLAINT_INTERVAL
Definition: nanoprobe.c:1596
#define FRAMESETTYPE_RSCOPREPLY
Packet contains return result from a resource operation.
Definition: framesettypes.h:46
int key_size
sizeof(public_key)
Definition: cryptframe.h:37
#define REQSTRINGRETNAMEFIELD
Definition: resourcecmd.h:80
Implements the FsProtocol object.
#define REQRCNAMEFIELD
Definition: resourcecmd.h:77
#define FRAMESETTYPE_DORSCOP
Do a (possibly-repeating) JSON resource action.
Definition: framesettypes.h:60
int(* activeconncount)(FsProtocol *)
How many active connections do we have?
Definition: fsprotocol.h:130
The NetGSource class objects integrate NetIO class objects into the g_main_loop paradigm.
Definition: netgsource.h:43
guint warntime_count
Definition: nanoprobe.h:35
FSTATIC void _real_martian_agent(NetAddr *who)
Standard nanoprobe &#39;martian heartbeat received&#39; agent.
Definition: nanoprobe.c:180
ReliableUDP * transport
Definition: pinger.c:72
FSTATIC void _real_heartbeat_agent(HbListener *who)
Standard nanoprobe &#39;hearbeat received&#39; agent.
Definition: nanoprobe.c:235
WINEXPORT CstringFrame * cstringframe_new(guint16 frame_type, gsize framesize)
Construct a new CstringFrame - allowing for "derived" frame types...
Definition: cstringframe.c:101
#define FRAMESETTYPE_CONNSHUT
Shutting down this connection (can also come from CMA)
Definition: framesettypes.h:37
Describes interfaces to CryptFrame (encryption) C-Class It represents a FrameSet using libsodium (cur...
This is an FsProtocol class object - implementing a reliable user-level FrameSet class delivery syste...
Definition: fsprotocol.h:107
FSTATIC void nanoobey_sendhb(AuthListener *, FrameSet *fs, NetAddr *)
Act on (obey) a FrameSet class telling us to send heartbeats.
Definition: nanoprobe.c:299
Defines Heartbeat Listener interfaces.
guint64 pktswritten
How many packets have been successfully written?
Definition: netio.h:46