// ============================================================================================================================================== // double Orbit::TimeToNode(Orbit *tgt, double *trl_of_node) { if (Defined()) { double hpa=TrlOfNode(tgt); double hpd=limit(hpa+PI); // Avoid oscilation when the ship is at the node. if (fabs(hpa-trl)<1e-6) hpa=hpd; if (fabs(hpd-trl)<1e-6) hpd=hpa; double tn; double a=TimeTo(hpa); double d=TimeTo(hpd); if (ecc>1.0) { if (a>0 && d>0) tn=MIN(a,d); else tn=MAX(a,d); } else tn=MIN(a,d); if (trl_of_node) { if (tn==a) *trl_of_node=hpa; else if (tn==d) *trl_of_node=hpd; else *trl_of_node=0; } return(tn); } return 0; }
void RumorMill__addNode(struct RumorMill* mill, struct Address* addr, const char* file, int line) { struct RumorMill_pvt* rm = Identity_check((struct RumorMill_pvt*) mill); Address_getPrefix(addr); for (int i = 0; i < rm->pub.count; i++) { if (rm->pub.addresses[i].path == addr->path && !Bits_memcmp(rm->pub.addresses[i].key, addr->key, 32)) { return; } } if (!Bits_memcmp(addr->key, rm->selfAddr->key, 32)) { return; } struct Address* replace; if (rm->pub.count < rm->capacity) { replace = &rm->pub.addresses[rm->pub.count++]; } else { replace = getWorst(rm); } Bits_memcpyConst(replace, addr, sizeof(struct Address)); if (Defined(Log_DEBUG)) { uint8_t addrStr[60]; Address_print(addrStr, addr); Log_debug(rm->log, "[%s] addNode(%s) count[%d] from [%s:%d]", rm->pub.name, addrStr, rm->pub.count, file, line); } }
struct CryptoAuth* CryptoAuth_new(struct Allocator* allocator, const uint8_t* privateKey, struct EventBase* eventBase, struct Log* logger, struct Random* rand) { struct CryptoAuth_pvt* ca = Allocator_calloc(allocator, sizeof(struct CryptoAuth_pvt), 1); Identity_set(ca); ca->allocator = allocator; ca->eventBase = eventBase; ca->logger = logger; ca->pub.resetAfterInactivitySeconds = CryptoAuth_DEFAULT_RESET_AFTER_INACTIVITY_SECONDS; ca->rand = rand; if (privateKey != NULL) { Bits_memcpyConst(ca->privateKey, privateKey, 32); } else { Random_bytes(rand, ca->privateKey, 32); } crypto_scalarmult_curve25519_base(ca->pub.publicKey, ca->privateKey); if (Defined(Log_KEYS)) { uint8_t publicKeyHex[65]; printHexKey(publicKeyHex, ca->pub.publicKey); uint8_t privateKeyHex[65]; printHexKey(privateKeyHex, ca->privateKey); Log_keys(logger, "Initialized CryptoAuth:\n myPrivateKey=%s\n myPublicKey=%s\n", privateKeyHex, publicKeyHex); } return &ca->pub; }
/* * Send a ping packet to one of the endpoints. */ static void sendPing(struct Peer* ep) { struct InterfaceController_pvt* ic = Identity_check(ep->ici->ic); ep->pingCount++; struct SwitchPinger_Ping* ping = SwitchPinger_newPing(ep->addr.path, String_CONST(""), ic->timeoutMilliseconds, onPingResponse, ep->alloc, ic->switchPinger); if (Defined(Log_DEBUG)) { uint8_t key[56]; Base32_encode(key, 56, ep->caSession->herPublicKey, 32); if (!ping) { Log_debug(ic->logger, "Failed to ping [%s.k], out of ping slots", key); } else { Log_debug(ic->logger, "SwitchPing [%s.k]", key); } } if (ping) { ping->onResponseContext = ep; } }
bool Preprocessor::HandleSection(size_t line_no, Tokenizer & tok){ if (tok.next_token().get_type() != Tokenizer::Type::String){ throw Exception::Error("Section name must be a quoted string; got `" + tok.get_string() + "`."); } size_t file_number = push_file(filenames, filedata.name()); std::string version; std::string prefix; if (Defined(currentSection, "__INTERNAL VERSION", version) && defines.size() == 1){ prefix += "#version " + version + "\n"; } if (currentSection == ""){ prefix += "#line 1 " + std::to_string(file_number) + "\n"; } sections[currentSection].data = prefix + currentData; currentData = ""; currentData += "#line " + std::to_string(line_no) + " " + std::to_string(file_number) + "\n"; std::string section = tok; section.pop_back(); section.erase(section.begin(), section.begin() + 1); currentSection = section; if (currentSection == "__END"){ return true; } return true; }
// This is directly called from SwitchCore, message is not encrypted. static Iface_DEFUN sendFromSwitch(struct Message* msg, struct Iface* switchIf) { struct Peer* ep = Identity_check((struct Peer*) switchIf); ep->bytesOut += msg->length; int msgs = PeerLink_send(msg, ep->peerLink); for (int i = 0; i < msgs; i++) { msg = PeerLink_poll(ep->peerLink); Assert_true(!CryptoAuth_encrypt(ep->caSession, msg)); Assert_true(!(((uintptr_t)msg->bytes) % 4) && "alignment fault"); // push the lladdr... Message_push(msg, ep->lladdr, ep->lladdr->addrLen, NULL); // very noisy if (Defined(Log_DEBUG) && false) { char* printedAddr = Hex_print(&ep->lladdr[1], ep->lladdr->addrLen - Sockaddr_OVERHEAD, msg->alloc); Log_debug(ep->ici->ic->logger, "Outgoing message to [%s]", printedAddr); } Iface_send(&ep->ici->pub.addrIf, msg); } return NULL; }
static void sendBeacon(struct InterfaceController_Iface_pvt* ici, struct Allocator* tempAlloc) { if (ici->beaconState < InterfaceController_beaconState_newState_SEND) { Log_debug(ici->ic->logger, "sendBeacon(%s) -> beaconing disabled", ici->name->bytes); return; } Log_debug(ici->ic->logger, "sendBeacon(%s)", ici->name->bytes); struct Message* msg = Message_new(0, 128, tempAlloc); Message_push(msg, &ici->ic->beacon, Headers_Beacon_SIZE, NULL); if (Defined(Log_DEBUG)) { char* content = Hex_print(msg->bytes, msg->length, tempAlloc); Log_debug(ici->ic->logger, "SEND BEACON CONTENT[%s]", content); } struct Sockaddr sa = { .addrLen = Sockaddr_OVERHEAD, .flags = Sockaddr_flags_BCAST }; Message_push(msg, &sa, Sockaddr_OVERHEAD, NULL); Iface_send(&ici->pub.addrIf, msg); }
static void check(struct Allocator_pvt* alloc) { if (!Defined(Allocator_PARANOIA)) { return; } uint64_t totalAllocated = alloc->rootAlloc->maxSpace - alloc->rootAlloc->spaceAvailable; uint64_t accounted = bytesAllocated(Identity_check((struct Allocator_pvt*)alloc->rootAlloc)); Assert_true(totalAllocated == accounted); }
// ============================================================================================================================================== // void Orbit::SetTime(double t) { if (Defined()) { timeto=0; time=oapiGetSimMJD()+(t/86400); } }
static void sendMsg(struct MsgCore_pvt* mcp, Dict* msgDict, struct Address* addr, struct Allocator* allocator) { struct Allocator* alloc = Allocator_child(allocator); // Send the encoding scheme definition Dict_putString(msgDict, CJDHTConstants_ENC_SCHEME, mcp->schemeDefinition, allocator); // And tell the asker which interface the message came from int encIdx = EncodingScheme_getFormNum(mcp->scheme, addr->path); Assert_true(encIdx != EncodingScheme_getFormNum_INVALID); Dict_putInt(msgDict, CJDHTConstants_ENC_INDEX, encIdx, allocator); // send the protocol version Dict_putInt(msgDict, CJDHTConstants_PROTOCOL, Version_CURRENT_PROTOCOL, allocator); if (!Defined(SUBNODE)) { String* q = Dict_getStringC(msgDict, "q"); String* sq = Dict_getStringC(msgDict, "sq"); if (q || sq) { Log_debug(mcp->log, "Send query [%s] to [%s]", ((q) ? q->bytes : sq->bytes), Address_toString(addr, alloc)->bytes); String* txid = Dict_getStringC(msgDict, "txid"); Assert_true(txid); String* newTxid = String_newBinary(NULL, txid->len + 1, alloc); Bits_memcpy(&newTxid->bytes[1], txid->bytes, txid->len); newTxid->bytes[0] = '1'; Dict_putStringC(msgDict, "txid", newTxid, alloc); } } struct Message* msg = Message_new(0, 2048, alloc); BencMessageWriter_write(msgDict, msg, NULL); //Log_debug(mcp->log, "Sending msg [%s]", Escape_getEscaped(msg->bytes, msg->length, alloc)); // Sanity check (make sure the addr was actually calculated) Assert_true(addr->ip6.bytes[0] == 0xfc); struct DataHeader data; Bits_memset(&data, 0, sizeof(struct DataHeader)); DataHeader_setVersion(&data, DataHeader_CURRENT_VERSION); DataHeader_setContentType(&data, ContentType_CJDHT); Message_push(msg, &data, sizeof(struct DataHeader), NULL); struct RouteHeader route; Bits_memset(&route, 0, sizeof(struct RouteHeader)); Bits_memcpy(route.ip6, addr->ip6.bytes, 16); route.version_be = Endian_hostToBigEndian32(addr->protocolVersion); route.sh.label_be = Endian_hostToBigEndian64(addr->path); Bits_memcpy(route.publicKey, addr->key, 32); Message_push(msg, &route, sizeof(struct RouteHeader), NULL); Iface_send(&mcp->pub.interRouterIf, msg); }
// ============================================================================================================================================== // double Orbit::GetTime() { if (Defined()) { if (timeto>0) return timeto; timeto=(time-oapiGetSimMJD())*86400; if (timeto<0) timeto=0; return timeto; } else return 0; }
// ============================================================================================================================================== // double Orbit::TimeToPeriapsis() { if (Defined()) { // For ellipse if (ecc<1.0) return( (PI2-mna) / mnm ); // For hyperbola return( (-mna) / mnm ); } return 0; }
static void onPingResponse(struct SwitchPinger_Response* resp, void* onResponseContext) { if (SwitchPinger_Result_OK != resp->res) { return; } struct Peer* ep = Identity_check((struct Peer*) onResponseContext); struct InterfaceController_pvt* ic = Identity_check(ep->ici->ic); ep->addr.protocolVersion = resp->version; if (Defined(Log_DEBUG)) { String* addr = Address_toString(&ep->addr, resp->ping->pingAlloc); if (!Version_isCompatible(Version_CURRENT_PROTOCOL, resp->version)) { Log_debug(ic->logger, "got switch pong from node [%s] with incompatible version", addr->bytes); } else if (ep->addr.path != resp->label) { uint8_t sl[20]; AddrTools_printPath(sl, resp->label); Log_debug(ic->logger, "got switch pong from node [%s] mismatch label [%s]", addr->bytes, sl); } else { Log_debug(ic->logger, "got switch pong from node [%s]", addr->bytes); } } if (!Version_isCompatible(Version_CURRENT_PROTOCOL, resp->version)) { return; } if (ep->state == InterfaceController_PeerState_ESTABLISHED) { sendPeer(0xffffffff, PFChan_Core_PEER, ep); } ep->timeOfLastPing = Time_currentTimeMilliseconds(ic->eventBase); if (Defined(Log_DEBUG)) { String* addr = Address_toString(&ep->addr, resp->ping->pingAlloc); Log_debug(ic->logger, "Received [%s] from lazy endpoint [%s]", SwitchPinger_resultString(resp->res)->bytes, addr->bytes); } }
// ============================================================================================================================================== // Hyberbolic use only // ReCalculate orbit position (mna,tra,trl,rad,vel) // void Orbit::SetTimeToPeriapsis(double t) { if (Defined()) { mna = -t * MeanMotion(); tra = mna2tra(mna,ecc); trl = limit(tra+lpe); vv = Tangent(trl); rv = Position(trl); rad = length(rv); vel = length(vv); } }
static void supernodes(List* supernodes, struct Allocator* tempAlloc, struct Context* ctx) { if (!supernodes) { return; } String* s; for (int i = 0; (s = List_getString(supernodes, i)) != NULL; i++) { Log_debug(ctx->logger, "Loading supernode connection to [%s]", s->bytes); Dict reqDict = Dict_CONST(String_CONST("key"), String_OBJ(s), NULL); if (!Defined(SUBNODE)) { Log_debug(ctx->logger, "Skipping because SUBNODE is not enabled"); continue; } rpcCall0(String_CONST("SupernodeHunter_addSnode"), &reqDict, ctx, tempAlloc, NULL, true); } }
// ============================================================================================================================================== // void Orbit::DrawPlaneIntersection(HDC hDC,Orbit *t,double cx,double cy,double zoom,int color,bool box) { if (!Defined()) return; double x,y,x2,y2,hpa,s,hpd; double w=cx*2; double h=cy*2; if (t==NULL) return; HPEN pen=CreatePen(PS_DOT,1,color); HPEN spen=CreatePen(PS_SOLID,1,color); HBRUSH brush=CreateSolidBrush(color); HBRUSH brushb=CreateSolidBrush(0); hpa=TrlOfNode(t); hpd=limit(hpa+PI); if (hpa!=-1 && hpd!=-1) { s=3.0; if (length(displacement)>0) Point(displacement,cx,cy,zoom,&cx,&cy); Point(cx,cy,hpd,&x,&y,zoom); Point(cx,cy,hpa,&x2,&y2,zoom); SelectObject(hDC,pen); DrawLine(hDC,x,y,x2,y2,w,h,false); SelectObject(hDC,spen); SelectObject(hDC,brushb); if (box) DrawRectangle(hDC,x-s,y-s,x+s,y+s,w,h); SelectObject(hDC,brush); if (box) DrawRectangle(hDC,x2-s,y2-s,x2+s,y2+s,w,h); } SelectObject(hDC,GetStockObject(NULL_BRUSH)); SelectObject(hDC,GetStockObject(WHITE_PEN)); DeleteObject(pen); DeleteObject(spen); DeleteObject(brush); DeleteObject(brushb); }
/** * Encrypt and authenticate. * Shifts the message by 16 bytes. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. */ static inline void encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { Assert_true(msg->padding >= 32); uint8_t* startAt = msg->bytes - 32; // This function trashes 16 bytes of the padding so we will put it back uint8_t paddingSpace[16]; Bits_memcpyConst(paddingSpace, startAt, 16); Bits_memset(startAt, 0, 32); if (!Defined(NSA_APPROVED)) { crypto_box_curve25519xsalsa20poly1305_afternm( startAt, startAt, msg->length + 32, nonce, secret); } Bits_memcpyConst(startAt, paddingSpace, 16); Message_shift(msg, 16, NULL); }
void Configurator_config(Dict* config, struct Sockaddr* sockAddr, String* adminPassword, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc) { struct Allocator* tempAlloc = Allocator_child(alloc); struct UDPAddrIface* udp = UDPAddrIface_new(eventBase, NULL, alloc, NULL, logger); struct AdminClient* client = AdminClient_new(&udp->generic, sockAddr, adminPassword, eventBase, logger, tempAlloc); struct Context ctx = { .logger = logger, .alloc = tempAlloc, .client = client, .base = eventBase, }; waitUntilPong(&ctx); List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords")); if (authedPasswords) { authorizedPasswords(authedPasswords, &ctx); } Dict* ifaces = Dict_getDict(config, String_CONST("interfaces")); udpInterface(ifaces, &ctx); if (Defined(HAS_ETH_INTERFACE)) { ethInterface(ifaces, &ctx); } Dict* routerConf = Dict_getDict(config, String_CONST("router")); routerConfig(routerConf, tempAlloc, &ctx); List* secList = Dict_getList(config, String_CONST("security")); security(tempAlloc, secList, logger, &ctx); Log_debug(logger, "Cjdns started in the background"); Allocator_free(tempAlloc); }
// ============================================================================================================================================== // Longitudes are on source plane // [Private] void Orbit::IntersectionAll(Orbit *tgt, double *lpa, double *lpd) { if (!Defined()) return; double start,end; start = tgt->lpe; end = PI; double e=tgt->ecc; if (e>1.0) end = tgt->MaxTra(); if (lpa && lpd) { *lpa=IntersectionInterpolate(tgt,start,end,false); *lpd=IntersectionInterpolate(tgt,start,end,true); } }
static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external) { struct TAPWrapper_pvt* tw = Identity_containerOf(external, struct TAPWrapper_pvt, external); if (msg->length < Ethernet_SIZE-2) { Log_debug(tw->log, "runt"); return 0; } // wacky 14 byte headers, back off into outer-space to create the padding... Message_shift(msg, 2, NULL); struct Ethernet eth; Message_pop(msg, ð, sizeof(struct Ethernet), NULL); // Not for us and not multicast... if (Bits_memcmp(eth.destAddr, TAPWrapper_LOCAL_MAC, Ethernet_ADDRLEN) && !(eth.destAddr[0] & 0x01)) { if (Defined(Log_DEBUG)) { uint8_t printedMac[18]; AddrTools_printMac(printedMac, eth.destAddr); Log_debug(tw->log, "Packet destine for unknown ethernet MAC [%s]", printedMac); } //return 0; } if (Bits_memcmp(eth.srcAddr, tw->pub.peerAddress, Ethernet_ADDRLEN)) { if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) { Bits_memcpy(tw->pub.peerAddress, eth.srcAddr, Ethernet_ADDRLEN); } else { #ifdef Log_DEBUG uint8_t printedMac[18]; AddrTools_printMac(printedMac, eth.srcAddr); Log_debug(tw->log, "DROP Packet with unexpected source MAC [%s]", printedMac); #endif return 0; } } TUNMessageType_push(msg, eth.ethertype, NULL); return Iface_next(&tw->pub.internal, msg); }
// ============================================================================================================================================== // double Orbit::TrlOfNode(VECTOR3 tgt_norv) { if (Defined()) { VECTOR3 z; z.x=0; z.z=0; z.y=1.0; VECTOR3 vlan,vect; if (length(crossp(z,norv))==0) vlan=majv, vect=minv; else { vlan = unit(crossp(z,norv)); vect = unit(crossp(norv,vlan)); } VECTOR3 lv = crossp(norv, tgt_norv); double xf=dotp(lv,vect); double xl=dotp(lv,vlan); return limit(atan2(xf,xl)+lan); } return 0; }
// connect an allocator to a new parent. static void connect(struct Allocator_pvt* parent, struct Allocator_pvt* child, const char* file, int line) { Assert_ifParanoid(child->parent == NULL); Assert_ifParanoid(child->lastSibling == NULL); Assert_ifParanoid(child->nextSibling == NULL); Assert_true(parent != child); if (Defined(PARANOIA)) { for (struct Allocator_pvt* c = parent->firstChild; c; c = c->nextSibling) { Assert_true(child != c); } } child->nextSibling = parent->firstChild; if (parent->firstChild) { parent->firstChild->lastSibling = child; } parent->firstChild = child; child->parent = parent; }
/** * Get a shared secret. * * @param outputSecret an array to place the shared secret in. * @param myPrivateKey * @param herPublicKey * @param logger * @param passwordHash a 32 byte value known to both ends, this must be provably pseudorandom * the first 32 bytes of a sha256 output from hashing a password is ok, * whatever she happens to send me in the Auth field is NOT ok. * If this field is null, the secret will be generated without the password. */ static inline void getSharedSecret(uint8_t outputSecret[32], uint8_t myPrivateKey[32], uint8_t herPublicKey[32], uint8_t passwordHash[32], struct Log* logger) { if (passwordHash == NULL) { crypto_box_curve25519xsalsa20poly1305_beforenm(outputSecret, herPublicKey, myPrivateKey); } else { union { struct { uint8_t key[32]; uint8_t passwd[32]; } components; uint8_t bytes[64]; } buff; crypto_scalarmult_curve25519(buff.components.key, myPrivateKey, herPublicKey); Bits_memcpyConst(buff.components.passwd, passwordHash, 32); crypto_hash_sha256(outputSecret, buff.bytes, 64); } if (Defined(Log_KEYS)) { uint8_t myPublicKeyHex[65]; printHexPubKey(myPublicKeyHex, myPrivateKey); uint8_t herPublicKeyHex[65]; printHexKey(herPublicKeyHex, herPublicKey); uint8_t passwordHashHex[65]; printHexKey(passwordHashHex, passwordHash); uint8_t outputSecretHex[65] = "NULL"; printHexKey(outputSecretHex, outputSecret); Log_keys(logger, "Generated a shared secret:\n" " myPublicKey=%s\n" " herPublicKey=%s\n" " passwordHash=%s\n" " outputSecret=%s\n", myPublicKeyHex, herPublicKeyHex, passwordHashHex, outputSecretHex); } }
static Iface_DEFUN handleIncomingFromWire(struct Message* msg, struct Iface* addrIf) { struct InterfaceController_Iface_pvt* ici = Identity_containerOf(addrIf, struct InterfaceController_Iface_pvt, pub.addrIf); struct Sockaddr* lladdr = (struct Sockaddr*) msg->bytes; if (msg->length < Sockaddr_OVERHEAD || msg->length < lladdr->addrLen) { Log_debug(ici->ic->logger, "DROP runt"); return NULL; } Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment fault"); Assert_true(!((uintptr_t)lladdr->addrLen % 4) && "alignment fault"); // noisy if (Defined(Log_DEBUG) && false) { char* printedAddr = Hex_print(&lladdr[1], lladdr->addrLen - Sockaddr_OVERHEAD, msg->alloc); Log_debug(ici->ic->logger, "Incoming message from [%s]", printedAddr); } if (lladdr->flags & Sockaddr_flags_BCAST) { return handleBeacon(msg, ici); } int epIndex = Map_EndpointsBySockaddr_indexForKey(&lladdr, &ici->peerMap); if (epIndex == -1) { return handleUnexpectedIncoming(msg, ici); } struct Peer* ep = Identity_check((struct Peer*) ici->peerMap.values[epIndex]); Message_shift(msg, -lladdr->addrLen, NULL); CryptoAuth_resetIfTimeout(ep->caSession); if (CryptoAuth_decrypt(ep->caSession, msg)) { return NULL; } PeerLink_recv(msg, ep->peerLink); return receivedPostCryptoAuth(msg, ep, ici->ic); }
// ============================================================================================================================================== // void Orbit::Make2DimensionalWithEcliptic() { if (Defined()) { VECTOR3 zero=_V(1,0,0); VECTOR3 normal=_V(0,-1,0); VECTOR3 ANv = create_vector(normal,zero,lan); double an = tra2gamma(tra,ecc); // Compute new major axis VECTOR3 newmaj = create_vector(normal,ANv,agp); // Compute new position vector VECTOR3 newpos = create_vector(normal,newmaj,tra); // Compute new velocity vector VECTOR3 newvel = create_vector(normal,newpos,an); // Setup lengths newpos=set_length(newpos,rad); newvel=set_length(newvel,vel); Elements(newpos,newvel,myy,false); } }
/** * Decrypt and authenticate. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. * @return 0 if decryption is succeddful, otherwise -1. */ static inline Gcc_USE_RET int decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { if (msg->length < 16) { return -1; } Assert_true(msg->padding >= 16); uint8_t* startAt = msg->bytes - 16; uint8_t paddingSpace[16]; Bits_memcpyConst(paddingSpace, startAt, 16); Bits_memset(startAt, 0, 16); if (!Defined(NSA_APPROVED)) { if (crypto_box_curve25519xsalsa20poly1305_open_afternm( startAt, startAt, msg->length + 16, nonce, secret) != 0) { return -1; } } Bits_memcpyConst(startAt, paddingSpace, 16); Message_shift(msg, -16, NULL); return 0; }
/** * Expects [ struct LLAddress ][ beacon ] */ static Iface_DEFUN handleBeacon(struct Message* msg, struct InterfaceController_Iface_pvt* ici) { struct InterfaceController_pvt* ic = ici->ic; if (!ici->beaconState) { // accepting beacons disabled. Log_debug(ic->logger, "[%s] Dropping beacon because beaconing is disabled", ici->name->bytes); return NULL; } if (msg->length < Headers_Beacon_SIZE) { Log_debug(ic->logger, "[%s] Dropping runt beacon", ici->name->bytes); return NULL; } struct Sockaddr* lladdrInmsg = (struct Sockaddr*) msg->bytes; // clear the bcast flag lladdrInmsg->flags = 0; Message_shift(msg, -lladdrInmsg->addrLen, NULL); struct Headers_Beacon beacon; Message_pop(msg, &beacon, Headers_Beacon_SIZE, NULL); if (Defined(Log_DEBUG)) { char* content = Hex_print(&beacon, Headers_Beacon_SIZE, msg->alloc); Log_debug(ici->ic->logger, "RECV BEACON CONTENT[%s]", content); } struct Address addr; Bits_memset(&addr, 0, sizeof(struct Address)); Bits_memcpy(addr.key, beacon.publicKey, 32); addr.protocolVersion = Endian_bigEndianToHost32(beacon.version_be); Address_getPrefix(&addr); String* printedAddr = NULL; if (Defined(Log_DEBUG)) { printedAddr = Address_toString(&addr, msg->alloc); } if (addr.ip6.bytes[0] != 0xfc || !Bits_memcmp(ic->ca->publicKey, addr.key, 32)) { Log_debug(ic->logger, "handleBeacon invalid key [%s]", printedAddr->bytes); return NULL; } if (!Version_isCompatible(addr.protocolVersion, Version_CURRENT_PROTOCOL)) { if (Defined(Log_DEBUG)) { Log_debug(ic->logger, "[%s] DROP beacon from [%s] which was version [%d] " "our version is [%d] making them incompatable", ici->name->bytes, printedAddr->bytes, addr.protocolVersion, Version_CURRENT_PROTOCOL); } return NULL; } String* beaconPass = String_newBinary(beacon.password, Headers_Beacon_PASSWORD_LEN, msg->alloc); int epIndex = Map_EndpointsBySockaddr_indexForKey(&lladdrInmsg, &ici->peerMap); if (epIndex > -1) { // The password might have changed! struct Peer* ep = ici->peerMap.values[epIndex]; CryptoAuth_setAuth(beaconPass, NULL, ep->caSession); return NULL; } struct Allocator* epAlloc = Allocator_child(ici->alloc); struct Peer* ep = Allocator_calloc(epAlloc, sizeof(struct Peer), 1); struct Sockaddr* lladdr = Sockaddr_clone(lladdrInmsg, epAlloc); ep->alloc = epAlloc; ep->ici = ici; ep->lladdr = lladdr; int setIndex = Map_EndpointsBySockaddr_put(&lladdr, &ep, &ici->peerMap); ep->handle = ici->peerMap.handles[setIndex]; ep->isIncomingConnection = true; Bits_memcpy(&ep->addr, &addr, sizeof(struct Address)); Identity_set(ep); Allocator_onFree(epAlloc, closeInterface, ep); ep->peerLink = PeerLink_new(ic->eventBase, epAlloc); ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, beacon.publicKey, false, "outer"); CryptoAuth_setAuth(beaconPass, NULL, ep->caSession); ep->switchIf.send = sendFromSwitch; if (SwitchCore_addInterface(ic->switchCore, &ep->switchIf, epAlloc, &ep->addr.path)) { Log_debug(ic->logger, "handleBeacon() SwitchCore out of space"); Allocator_free(epAlloc); return NULL; } // We want the node to immedietly be pinged but we don't want it to appear unresponsive because // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node". ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1; Log_info(ic->logger, "Added peer [%s] from beacon", Address_toString(&ep->addr, msg->alloc)->bytes); // This should be safe because this is an outgoing request and we're sure the node will not // be relocated by moveEndpointIfNeeded() sendPeer(0xffffffff, PFChan_Core_PEER, ep); return NULL; }
static void iciPing(struct InterfaceController_Iface_pvt* ici, struct InterfaceController_pvt* ic) { if (!ici->peerMap.count) { return; } uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); // scan for endpoints have not sent anything recently. uint32_t startAt = Random_uint32(ic->rand) % ici->peerMap.count; for (uint32_t i = startAt, count = 0; count < ici->peerMap.count;) { i = (i + 1) % ici->peerMap.count; count++; struct Peer* ep = ici->peerMap.values[i]; if (now < ep->timeOfLastMessage + ic->pingAfterMilliseconds) { if (now < ep->timeOfLastPing + ic->pingAfterMilliseconds) { // Possibly an out-of-date node which is mangling packets, don't ping too often // because it causes the RumorMill to be filled with this node over and over. continue; } } uint8_t keyIfDebug[56]; if (Defined(Log_DEBUG)) { Base32_encode(keyIfDebug, 56, ep->caSession->herPublicKey, 32); } if (ep->isIncomingConnection && now > ep->timeOfLastMessage + ic->forgetAfterMilliseconds) { Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] " "seconds, dropping connection", keyIfDebug, ic->forgetAfterMilliseconds / 1024); sendPeer(0xffffffff, PFChan_Core_PEER_GONE, ep); Allocator_free(ep->alloc); continue; } bool unresponsive = (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds); if (unresponsive) { // our link to the peer is broken... // Lets skip 87% of pings when they're really down. if (ep->pingCount % 8) { ep->pingCount++; continue; } sendPeer(0xffffffff, PFChan_Core_PEER_GONE, ep); ep->state = InterfaceController_PeerState_UNRESPONSIVE; SwitchCore_setInterfaceState(&ep->switchIf, SwitchCore_setInterfaceState_ifaceState_DOWN); } Log_debug(ic->logger, "Pinging %s peer [%s.k] lag [%u]", (unresponsive ? "unresponsive" : "lazy"), keyIfDebug, (uint32_t)((now - ep->timeOfLastMessage) / 1024)); sendPing(ep); // we only ping one node return; } }
int InterfaceController_bootstrapPeer(struct InterfaceController* ifc, int interfaceNumber, uint8_t* herPublicKey, const struct Sockaddr* lladdrParm, String* password, String* login, String* user, struct Allocator* alloc) { struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc); Assert_true(herPublicKey); Assert_true(password); struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber); if (!ici) { return InterfaceController_bootstrapPeer_BAD_IFNUM; } Log_debug(ic->logger, "bootstrapPeer total [%u]", ici->peerMap.count); uint8_t ip6[16]; AddressCalc_addressForPublicKey(ip6, herPublicKey); if (!AddressCalc_validAddress(ip6) || !Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) { return InterfaceController_bootstrapPeer_BAD_KEY; } struct Allocator* epAlloc = Allocator_child(ici->alloc); struct Sockaddr* lladdr = Sockaddr_clone(lladdrParm, epAlloc); // TODO(cjd): eps are created in 3 places, there should be a factory function. struct Peer* ep = Allocator_calloc(epAlloc, sizeof(struct Peer), 1); int index = Map_EndpointsBySockaddr_put(&lladdr, &ep, &ici->peerMap); Assert_true(index >= 0); ep->alloc = epAlloc; ep->handle = ici->peerMap.handles[index]; ep->lladdr = lladdr; ep->ici = ici; ep->isIncomingConnection = false; Bits_memcpy(ep->addr.key, herPublicKey, 32); Address_getPrefix(&ep->addr); Identity_set(ep); Allocator_onFree(epAlloc, closeInterface, ep); Allocator_onFree(alloc, freeAlloc, epAlloc); ep->peerLink = PeerLink_new(ic->eventBase, epAlloc); ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, herPublicKey, false, "outer"); CryptoAuth_setAuth(password, login, ep->caSession); if (user) { ep->caSession->displayName = String_clone(user, epAlloc); } ep->switchIf.send = sendFromSwitch; if (SwitchCore_addInterface(ic->switchCore, &ep->switchIf, epAlloc, &ep->addr.path)) { Log_debug(ic->logger, "bootstrapPeer() SwitchCore out of space"); Allocator_free(epAlloc); return InterfaceController_bootstrapPeer_OUT_OF_SPACE; } // We want the node to immedietly be pinged but we don't want it to appear unresponsive because // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node". ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1; if (Defined(Log_INFO)) { struct Allocator* tempAlloc = Allocator_child(alloc); String* addrStr = Address_toString(&ep->addr, tempAlloc); Log_info(ic->logger, "Adding peer [%s] from bootstrapPeer()", addrStr->bytes); Allocator_free(tempAlloc); } // We can't just add the node directly to the routing table because we do not know // the version. We'll send it a switch ping and when it responds, we will know it's // key (if we don't already) and version number. sendPing(ep); return 0; }
bool Preprocessor::HandleInclude(size_t line_no, Tokenizer & tok){ bool issection = false; if (tok.next_token() == "section"){ issection = true; tok.next_token(); } if (tok.get_type() != Tokenizer::Type::String){ throw Exception::Error("Include name must be quoted string; got `" + tok.get_string() + "`."); } MappedFile mfile; std::string section = ""; if (issection){ section = tok.get_string(); trim_ends(section); mfile = filedata; } else{ std::string file = tok; trim_ends(file); size_t pos = file.find_first_of("?"); if (pos != std::string::npos){ section = file.substr(pos + 1); file.erase(file.begin() + pos, file.end()); } else{ if (tok.next_token()){ if (tok == "section"){ if (tok.next_token().get_type() == Tokenizer::Type::String){ section = tok.get_string(); trim_ends(section); } else{ throw Exception::Error("String expected after `section`; got `" + tok.get_string() + "`."); } } else{ throw Exception::Error("Unknown include specifier `" + tok.get_string() + "`. Did you mean to use `section`?"); } } } mfile = MappedFile(file, include_paths); } size_t file_number;// = push_file(filenames, mfile.name()); std::string test_name = "___ONCE_INCLUDE " + section + "?" + mfile.name(); if (Defined(section, test_name)){ currentData.push_back('\n'); return true; } //currentData += "#line 1 " + std::to_string(file_number) + "\n"; defines.push_back(§ions[currentSection].defines); Preprocessor p = Preprocessor(mfile, include_paths, defines, filenames, section); auto newSections = p.Preprocess(); auto& back = *defines.back(); defines.pop_back(); for (auto & def : back){ Define(def.first, def.second); } file_number = push_file(filenames, filedata.name()); currentData += newSections.at(section).data; currentData.push_back('\n'); currentData += "#line " + std::to_string(line_no) + " " + std::to_string(file_number) + "\n"; return true; }