/** * Test program looping and reading LLDP/CDP packets and exercising most of the packet * send/receive mechanism and a good bit of nanoprobe and CMA basic infrastructure. * * It plays both sides of the game - the CMA and the nanoprobe. * * It leaves most of the work of starting up the nanoprobe code to nano_start_full() */ int main(int argc, char **argv) { const guint8 loopback[] = CONST_IPV6_LOOPBACK; //const guint8 mcastaddrstring[] = CONST_ASSIM_DEFAULT_V4_MCAST; //NetAddr* mcastaddr; const guint8 otheradstring[] = {127,0,0,1}; const guint8 otheradstring2[] = {10,10,10,4}; const guint8 anyadstring[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; guint16 testport = TESTPORT; SignFrame* signature = signframe_glib_new(G_CHECKSUM_SHA256, 0); Listener* otherlistener; ConfigContext* config = configcontext_new(0); PacketDecoder* decoder = nano_packet_decoder(); AuthListener* listentonanoprobes; ReliableUDP* rtransport; #if 0 # ifdef HAVE_MCHECK_PEDANTIC g_assert(mcheck_pedantic(NULL) == 0); # else # ifdef HAVE_MCHECK g_assert(mcheck(NULL) == 0); # endif # endif #endif g_setenv("G_MESSAGES_DEBUG", "all", TRUE); #if 0 proj_class_incr_debug(NULL); proj_class_incr_debug(NULL); proj_class_incr_debug(NULL); proj_class_incr_debug(NULL); #endif g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); if (argc > 1) { maxpkts = atol(argv[1]); g_debug("Max packet count is "FMT_64BIT"d", maxpkts); } if (netio_is_dual_ipv4v6_stack()) { g_message("Our OS supports dual ipv4/v6 sockets. Hurray!"); }else{ g_warning("Our OS DOES NOT support dual ipv4/v6 sockets - this may not work!!"); } config->setframe(config, CONFIGNAME_OUTSIG, &signature->baseclass); // Create a network transport object for normal UDP packets rtransport = reliableudp_new(0, config, decoder, 0); rtransport->_protocol->window_size = 8; nettransport = &(rtransport->baseclass.baseclass); g_return_val_if_fail(NULL != nettransport, 2); // Set up the parameters the 'CMA' is going to send to our 'nanoprobe' // in response to their request for configuration data. nanoconfig = configcontext_new(0); nanoconfig->setint(nanoconfig, CONFIGNAME_INTERVAL, 1); nanoconfig->setint(nanoconfig, CONFIGNAME_TIMEOUT, 3); nanoconfig->setint(nanoconfig, CONFIGNAME_CMAPORT, testport); // Construct the NetAddr we'll talk to (i.e., ourselves) and listen from destaddr = netaddr_ipv6_new(loopback, testport); g_return_val_if_fail(NULL != destaddr, 3); config->setaddr(config, CONFIGNAME_CMAINIT, destaddr); nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMAADDR, destaddr); nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMAFAIL, destaddr); nanoconfig->setaddr(nanoconfig, CONFIGNAME_CMADISCOVER, destaddr); // Construct another couple of NetAddrs to talk to and listen from // for good measure... otheraddr = netaddr_ipv4_new(otheradstring, testport); g_return_val_if_fail(NULL != otheraddr, 4); otheraddr2 = netaddr_ipv4_new(otheradstring2, testport); g_return_val_if_fail(NULL != otheraddr2, 4); // Construct another NetAddr to bind to (anything) anyaddr = netaddr_ipv6_new(anyadstring, testport); g_return_val_if_fail(NULL != destaddr, 5); // Bind to ANY address (as noted above) g_return_val_if_fail(nettransport->bindaddr(nettransport, anyaddr, FALSE),16); //g_return_val_if_fail(nettransport->bindaddr(nettransport, destaddr),16); g_message("NOT Joining multicast address."); #if 0 // We can't do this because of encryption and we will likely screw up // others on our network even if that weren't a problem... mcastaddr = netaddr_ipv4_new(mcastaddrstring, testport); g_return_val_if_fail(nettransport->mcastjoin(nettransport, mcastaddr, NULL), 17); UNREF(mcastaddr); g_message("multicast join succeeded."); #endif // Connect up our network transport into the g_main_loop paradigm // so we get dispatched when packets arrive netpkt = netgsource_new(nettransport, NULL, G_PRIORITY_HIGH, FALSE, NULL, 0, NULL); // Set up so that we can observe all unclaimed packets otherlistener = listener_new(config, 0); otherlistener->got_frameset = gotnetpkt; netpkt->addListener(netpkt, 0, otherlistener); otherlistener->associate(otherlistener,netpkt); // Unref the "other" listener - we hold other references to it UNREF(otherlistener); // Pretend to be the CMA... // Listen for packets from our nanoprobes - scattered throughout space... listentonanoprobes = authlistener_new(0, cmalist, config, TRUE, NULL); listentonanoprobes->baseclass.associate(&listentonanoprobes->baseclass, netpkt); nano_start_full("netconfig", 900, netpkt, config, test_cma_authentication); g_timeout_add_seconds(1, timeout_agent, NULL); mainloop = g_main_loop_new(g_main_context_default(), TRUE); /******************************************************************** * Start up the main loop - run our test program... * (the one pretending to be both the nanoprobe and the CMA) ********************************************************************/ g_main_loop_run(mainloop); /******************************************************************** * We exited the main loop. Shut things down. ********************************************************************/ nano_shutdown(TRUE); // Tell it to shutdown and print stats g_message("Count of 'other' pkts received:\t%d", wirepktcount); UNREF(nettransport); // Main loop is over - shut everything down, free everything... g_main_loop_unref(mainloop); mainloop=NULL; // Unlink misc dispatcher - this should NOT be necessary... netpkt->addListener(netpkt, 0, NULL); // Dissociate packet actions from the packet source. listentonanoprobes->baseclass.dissociate(&listentonanoprobes->baseclass); // Unref the AuthListener object UNREF2(listentonanoprobes); g_source_destroy(&netpkt->baseclass); g_source_unref(&netpkt->baseclass); //g_main_context_unref(g_main_context_default()); // Free signature frame UNREF2(signature); // Free misc addresses UNREF(destaddr); UNREF(otheraddr); UNREF(otheraddr2); UNREF(anyaddr); // Free config object UNREF(config); UNREF(nanoconfig); // At this point - nothing should show up - we should have freed everything if (proj_class_live_object_count() > 0) { g_warning("Too many objects (%d) alive at end of test.", proj_class_live_object_count()); proj_class_dump_live_objects(); ++errcount; }else{ g_message("No objects left alive. Awesome!"); } proj_class_finalize_sys(); // Shut down object system to make valgrind happy :-D return(errcount <= 127 ? errcount : 127); }
/// Send JSON that we discovered to the CMA - with some caching going on FSTATIC void _discovery_sendjson(Discovery* self, ///< Our discovery object char * jsonout, ///< malloced JSON output - which we free (!) gsize jsonlen) ///< length of jsonout { FrameSet* fs; CstringFrame* jsf; IntFrame* intf; Frame* fsf; ConfigContext* cfg = self->_config; NetGSource* io = self->_iosource; NetAddr* cma; const char * basename = self->instancename(self); ConfigContext* jsonobject; g_return_if_fail(cfg != NULL && io != NULL); if (NULL == (jsonobject = configcontext_new_JSON_string(jsonout))) { g_warning("%s.%d: JSON Discovery is not legal JSON [%s]" , __FUNCTION__, __LINE__, jsonout); return; } g_free(jsonout); jsonobject->setstring(jsonobject, CONFIGNAME_INSTANCE, basename); jsonout = jsonobject->baseclass.toString(&jsonobject->baseclass); jsonlen = strlen(jsonout); UNREF(jsonobject); DEBUGMSG2("%s.%d: discovering %s: _sentyet == %d" , __FUNCTION__, __LINE__, basename, self->_sentyet); // Primitive caching - don't send what we've already sent. if (self->_sentyet) { const char * oldvalue = cfg->getstring(cfg, basename); if (oldvalue != NULL && strcmp(jsonout, oldvalue) == 0) { DEBUGMSG2("%s.%d: %s sent this value - don't send again." , __FUNCTION__, __LINE__, basename); g_free(jsonout); return; } DEBUGMSG2("%s.%d: %s this value is different from previous value" , __FUNCTION__, __LINE__, basename); } DEBUGMSG2("%s.%d: Sending %"G_GSIZE_FORMAT" bytes of JSON text" , __FUNCTION__, __LINE__, jsonlen); cfg->setstring(cfg, basename, jsonout); cma = cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER); if (cma == NULL) { DEBUGMSG2("%s.%d: %s address is unknown - skipping send" , __FUNCTION__, __LINE__, CONFIGNAME_CMADISCOVER); g_free(jsonout); return; } self->_sentyet = TRUE; fs = frameset_new(FRAMESETTYPE_JSDISCOVERY); intf = intframe_new(FRAMETYPE_WALLCLOCK, 8); intf->setint(intf, self->starttime); frameset_append_frame(fs, &intf->baseclass); UNREF2(intf); jsf = cstringframe_new(FRAMETYPE_JSDISCOVER, 0); fsf = &jsf->baseclass; // base class object of jsf fsf->setvalue(fsf, jsonout, jsonlen+1, frame_default_valuefinalize); // jsonlen is strlen(jsonout) frameset_append_frame(fs, fsf); DEBUGMSG2("%s.%d: Sending a %"G_GSIZE_FORMAT" bytes JSON frameset" , __FUNCTION__, __LINE__, jsonlen); io->_netio->sendareliablefs(io->_netio, cma, DEFAULT_FSP_QID, fs); ++ self->reportcount; UNREF(fsf); UNREF(fs); }
/// Routine to pretend to be the initial CMA void fakecma_startup(AuthListener* auth, FrameSet* ifs, NetAddr* nanoaddr) { FrameSet* pkt; NetGSource* netpkt = auth->baseclass.transport; char * nanostr = nanoaddr->baseclass.toString(nanoaddr); GSList* thisgsf; const char * keyid = NULL; (void)ifs; g_message("CMA received startup message from nanoprobe at address %s/%d." , nanostr, nanoaddr->port(nanoaddr)); g_free(nanostr); nanostr = NULL; check_JSON(ifs); netpkt->_netio->addalias(netpkt->_netio, nanoaddr, destaddr); // Set up our crypto... cryptframe_set_dest_key_id(nanoaddr, cryptframe_get_signing_key_id()); cryptframe_set_dest_key_id(destaddr, cryptframe_get_signing_key_id()); cryptframe_associate_identity(CMA_IDENTITY_NAME, cryptframe_get_signing_key_id()); cryptframe_set_encryption_method(cryptcurve25519_new_generic); for (thisgsf = ifs->framelist; thisgsf; thisgsf=thisgsf->next) { Frame* thisframe = CASTTOCLASS(Frame, thisgsf->data); if (thisframe->type == FRAMETYPE_KEYID) { CstringFrame* csf = CASTTOCLASS(CstringFrame, thisframe); keyid = (const char *)csf->baseclass.value; }else if (keyid && thisframe->type == FRAMETYPE_PUBKEYCURVE25519) { cryptcurve25519_save_public_key(keyid, thisframe->value , thisframe->length); } } // Send the configuration data to our new "client" pkt = create_setconfig(nanoconfig); netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt); UNREF(pkt); // Now tell them to send/expect heartbeats to various places pkt = create_sendexpecthb(auth->baseclass.config, FRAMESETTYPE_SENDEXPECTHB, destaddr, 1); netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt); UNREF(pkt); { const char * monopjson[] = { START, MONITOR, STOP}; unsigned j; // Create a frameset for a few resource operations pkt = frameset_new(FRAMESETTYPE_DORSCOP); for (j=0; j < DIMOF(monopjson); j++) { CstringFrame* csf = cstringframe_new(FRAMETYPE_RSCJSON,0); csf->baseclass.setvalue(&csf->baseclass, g_strdup(monopjson[j]) , strlen(monopjson[j])+1, g_free); frameset_append_frame(pkt, &csf->baseclass); UNREF2(csf); } netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt); UNREF(pkt); } { const char * discoverjson[] = {SWITCHDISCOVER, ARPDISCOVER}; const char * discoverinstnm[] = {SWINSTNM, ARPINSTNM}; unsigned j; // Create a frameset for a few discovery operations pkt = frameset_new(FRAMESETTYPE_DODISCOVER); for (j=0; j < DIMOF(discoverjson); j++) { CstringFrame* csf = cstringframe_new(FRAMETYPE_DISCJSON,0); CstringFrame* inst = cstringframe_new(FRAMETYPE_DISCNAME,0); fprintf(stderr, "Creating discovery frameset: %s: %s\n" , discoverinstnm[j] , discoverjson[j]); inst->baseclass.setvalue(&inst->baseclass, g_strdup(discoverjson[j]) , strlen(discoverjson[j])+1, g_free); frameset_append_frame(pkt, &inst->baseclass); UNREF2(inst); csf->baseclass.setvalue(&csf->baseclass, g_strdup(discoverjson[j]) , strlen(discoverjson[j])+1, g_free); frameset_append_frame(pkt, &csf->baseclass); UNREF2(csf); } netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt); UNREF(pkt); } pkt = frameset_new(FRAMESETTYPE_ACKSTARTUP); netpkt->_netio->sendareliablefs(netpkt->_netio, nanoaddr, DEFAULT_FSP_QID, pkt); UNREF(pkt); g_info("ACKSTARTUP packet queued to send"); }