Iface_DEFUN TUNTools_genericIP6Echo(struct Message* msg, struct TUNTools* tt) { uint16_t ethertype = TUNMessageType_pop(msg, NULL); if (ethertype != Ethernet_TYPE_IP6) { Log_debug(tt->log, "Spurious packet with ethertype [%04x]\n", Endian_bigEndianToHost16(ethertype)); return 0; } struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes; if (msg->length != Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12) { int type = (msg->length >= Headers_IP6Header_SIZE) ? header->nextHeader : -1; Log_debug(tt->log, "Message of unexpected length [%u] ip6->nextHeader: [%d]\n", msg->length, type); return 0; } uint8_t* address; Sockaddr_getAddress(tt->tunDestAddr, &address); Assert_true(!Bits_memcmp(header->destinationAddr, address, 16)); Sockaddr_getAddress(tt->udpBindTo, &address); Assert_true(!Bits_memcmp(header->sourceAddr, address, 16)); Sockaddr_getAddress(tt->udpBindTo, &address); Bits_memcpy(header->destinationAddr, address, 16); Sockaddr_getAddress(tt->tunDestAddr, &address); Bits_memcpy(header->sourceAddr, address, 16); TUNMessageType_push(msg, ethertype, NULL); return Iface_next(&tt->tunIface, msg); }
static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventIf) { struct UpperDistributor_pvt* ud = Identity_containerOf(eventIf, struct UpperDistributor_pvt, eventIf); Assert_true(Message_pop32(msg, NULL) == PFChan_Pathfinder_SENDMSG); Message_pop32(msg, NULL); return Iface_next(&ud->pub.sessionManagerIf, msg); }
static Iface_DEFUN sendToTunIf(struct Message* msg, struct TUNAdapter_pvt* ud) { if (!&ud->pub.tunIf.connectedIf) { Log_debug(ud->log, "DROP message for tun because no device is defined"); return NULL; } return Iface_next(&ud->pub.tunIf, msg); }
// Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch. static Iface_DEFUN receivedPostCryptoAuth(struct Message* msg, struct Peer* ep, struct InterfaceController_pvt* ic) { ep->bytesIn += msg->length; int caState = CryptoAuth_getState(ep->caSession); if (ep->state < InterfaceController_PeerState_ESTABLISHED) { // EP states track CryptoAuth states... ep->state = caState; SwitchCore_setInterfaceState(&ep->switchIf, SwitchCore_setInterfaceState_ifaceState_UP); Bits_memcpy(ep->addr.key, ep->caSession->herPublicKey, 32); Address_getPrefix(&ep->addr); if (caState == CryptoAuth_ESTABLISHED) { moveEndpointIfNeeded(ep); //sendPeer(0xffffffff, PFChan_Core_PEER, ep);// version is not known at this point. } else { // prevent some kinds of nasty things which could be done with packet replay. // This is checking the message switch header and will drop it unless the label // directs it to *this* router. if (msg->length < 8 || msg->bytes[7] != 1) { Log_info(ic->logger, "DROP message because CA is not established."); return 0; } else { // When a "server" gets a new connection from a "client" the router doesn't // know about that client so if the client sends a packet to the server, the // server will be unable to handle it until the client has sent inter-router // communication to the server. Here we will ping the client so when the // server gets the ping response, it will insert the client into its table // and know its version. // prevent DoS by limiting the number of times this can be called per second // limit it to 7, this will affect innocent packets but it doesn't matter much // since this is mostly just an optimization and for keeping the tests happy. if ((ep->pingCount + 1) % 7) { sendPing(ep); } } } } else if (ep->state == InterfaceController_PeerState_UNRESPONSIVE && caState == CryptoAuth_ESTABLISHED) { ep->state = InterfaceController_PeerState_ESTABLISHED; SwitchCore_setInterfaceState(&ep->switchIf, SwitchCore_setInterfaceState_ifaceState_UP); } else { ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase); } Identity_check(ep); Assert_true(!(msg->capacity % 4)); return Iface_next(&ep->switchIf, msg); }
static Iface_DEFUN incomingFromSessionManagerIf(struct Message* msg, struct Iface* sessionManagerIf) { struct UpperDistributor_pvt* ud = Identity_containerOf(sessionManagerIf, struct UpperDistributor_pvt, pub.sessionManagerIf); Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE); struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes; struct DataHeader* dh = (struct DataHeader*) &hdr[1]; enum ContentType type = DataHeader_getContentType(dh); if (type <= ContentType_IP6_RAW) { return Iface_next(&ud->pub.tunAdapterIf, msg); } if (type == ContentType_CJDHT) { Message_push32(msg, 0xffffffff, NULL); Message_push32(msg, PFChan_Core_MSG, NULL); return Iface_next(&ud->eventIf, msg); } if (type == ContentType_IPTUN) { return Iface_next(&ud->pub.ipTunnelIf, msg); } Log_debug(ud->log, "DROP message with unknown type [%d]", type); return NULL; }
static Iface_DEFUN incomingFromUs(struct Message* message, struct Iface* internalIf) { struct TUNInterface_Illumos_pvt* ctx = Identity_containerOf(internalIf, struct TUNInterface_Illumos_pvt, internalIf); Message_shift(message, -4, NULL); uint16_t ethertype = ((uint16_t*) message->bytes)[-1]; if (ethertype != Ethernet_TYPE_IP6 && ethertype != Ethernet_TYPE_IP4) { Assert_true(!"Unsupported ethertype"); } return Iface_next(&ctx->externalIf, message); }
static Iface_DEFUN sendToPathfinder(struct Message* msg, struct Pathfinder* pf) { if (!pf || pf->state != Pathfinder_state_CONNECTED) { return NULL; } if (pf->bytesSinceLastPing < 8192 && pf->bytesSinceLastPing + msg->length >= 8192) { struct Message* ping = Message_new(0, 512, msg->alloc); Message_push32(ping, pf->bytesSinceLastPing, NULL); Message_push32(ping, PING_MAGIC, NULL); Message_push32(ping, PFChan_Core_PING, NULL); Iface_send(&pf->iface, ping); } pf->bytesSinceLastPing += msg->length; return Iface_next(&pf->iface, msg); }
static Iface_DEFUN handleError(struct Message* msg, struct ControlHandler_pvt* ch, uint64_t label, uint8_t* labelStr) { if (msg->length < handleError_MIN_SIZE) { Log_info(ch->log, "DROP runt error packet from [%s]", labelStr); return NULL; } Message_shift(msg, SwitchHeader_SIZE + 4, NULL); Message_push32(msg, 0xffffffff, NULL); Message_push32(msg, PFChan_Core_SWITCH_ERR, NULL); return Iface_next(&ch->eventIf, msg); }
static Iface_DEFUN incoming(struct Message* msg, struct Iface* iface) { struct FakeNetwork_UDPIface_pvt* fnip = Identity_check((struct FakeNetwork_UDPIface_pvt*) iface); struct FakeNetwork_pvt* fnp = Identity_check(fnip->fnp); // Swap so that the message contains [dest][src][content] struct Sockaddr_storage dest; popSockaddr(msg, &dest); pushSockaddr(msg, fnip->pub.generic.addr); pushSockaddr(msg, &dest.addr); return Iface_next(&fnp->toAsync, msg); }
static Iface_DEFUN sendNode(struct Message* msg, struct Address* addr, uint32_t metric, struct Pathfinder_pvt* pf) { Message_reset(msg); Message_shift(msg, PFChan_Node_SIZE, NULL); nodeForAddress((struct PFChan_Node*) msg->bytes, addr, metric); if (addr->path == UINT64_MAX) { ((struct PFChan_Node*) msg->bytes)->path_be = 0; } Message_push32(msg, PFChan_Pathfinder_NODE, NULL); return Iface_next(&pf->pub.eventIf, msg); }
static Iface_DEFUN incomingFromWire(struct Message* message, struct Iface* externalIf) { struct TUNInterface_Illumos_pvt* ctx = Identity_containerOf(externalIf, struct TUNInterface_Illumos_pvt, externalIf); if (message->length < 4) { return 0; } Message_shift(message, 4, NULL); ((uint16_t*) message->bytes)[0] = 0; ((uint16_t*) message->bytes)[1] = ethertypeForPacketType(message->bytes[4]); return Iface_next(&ctx->internalIf, message); }
/** * Handle an incoming control message from a switch. * * @param context the ducttape context. * @param message the control message, this should be alligned on the beginning of the content, * that is to say, after the end of the switch header. * @param switchHeader the header. * @param switchIf the interface which leads to the switch. * @param isFormV8 true if the control message is in the form specified by protocol version 8+ */ static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf) { struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf); struct RouteHeader routeHdr; Message_pop(msg, &routeHdr, RouteHeader_SIZE, NULL); uint8_t labelStr[20]; uint64_t label = Endian_bigEndianToHost64(routeHdr.sh.label_be); AddrTools_printPath(labelStr, label); // happens in benchmark // Log_debug(ch->log, "ctrl packet from [%s]", labelStr); if (msg->length < 4 + Control_Header_SIZE) { Log_info(ch->log, "DROP runt ctrl packet from [%s]", labelStr); return NULL; } Assert_true(routeHdr.flags & RouteHeader_flags_CTRLMSG); if (Checksum_engine(msg->bytes, msg->length)) { Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr); return NULL; } struct Control* ctrl = (struct Control*) msg->bytes; if (ctrl->header.type_be == Control_ERROR_be) { return handleError(msg, ch, label, labelStr); } else if (ctrl->header.type_be == Control_KEYPING_be || ctrl->header.type_be == Control_PING_be) { return handlePing(msg, ch, label, labelStr, ctrl->header.type_be); } else if (ctrl->header.type_be == Control_KEYPONG_be || ctrl->header.type_be == Control_PONG_be) { Log_debug(ch->log, "got switch pong from [%s]", labelStr); Message_push(msg, &routeHdr, RouteHeader_SIZE, NULL); return Iface_next(&ch->pub.switchPingerIf, msg); } Log_info(ch->log, "DROP control packet of unknown type from [%s], type [%d]", labelStr, Endian_bigEndianToHost16(ctrl->header.type_be)); return NULL; }
/** * Handle an incoming control message from a switch. * * @param context the ducttape context. * @param message the control message, this should be alligned on the beginning of the content, * that is to say, after the end of the switch header. * @param switchHeader the header. * @param switchIf the interface which leads to the switch. * @param isFormV8 true if the control message is in the form specified by protocol version 8+ */ static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf) { struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf); struct SwitchHeader switchHeader; Message_pop(msg, &switchHeader, SwitchHeader_SIZE, NULL); uint8_t labelStr[20]; uint64_t label = Endian_bigEndianToHost64(switchHeader.label_be); AddrTools_printPath(labelStr, label); Log_debug(ch->log, "ctrl packet from [%s]", labelStr); if (msg->length < 4 + Control_Header_SIZE) { Log_info(ch->log, "DROP runt ctrl packet from [%s]", labelStr); return NULL; } Assert_true(Message_pop32(msg, NULL) == 0xffffffff); if (Checksum_engine(msg->bytes, msg->length)) { Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr); return NULL; } struct Control* ctrl = (struct Control*) msg->bytes; if (ctrl->header.type_be == Control_ERROR_be) { return handleError(msg, ch, label, labelStr); } else if (ctrl->header.type_be == Control_KEYPING_be || ctrl->header.type_be == Control_PING_be) { return handlePing(msg, ch, label, labelStr, ctrl->header.type_be); } else if (ctrl->header.type_be == Control_KEYPONG_be || ctrl->header.type_be == Control_PONG_be) { Log_debug(ch->log, "got switch pong from [%s]", labelStr); // Shift back over the header Message_shift(msg, 4 + SwitchHeader_SIZE, NULL); return Iface_next(&ch->pub.switchPingerIf, msg); } Log_info(ch->log, "DROP control packet of unknown type from [%s], type [%d]", labelStr, Endian_bigEndianToHost16(ctrl->header.type_be)); return NULL; }
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); }
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal) { struct TAPWrapper_pvt* tw = Identity_containerOf(internal, struct TAPWrapper_pvt, pub.internal); uint16_t etherType = TUNMessageType_pop(msg, NULL); struct Ethernet eth = { .ethertype = etherType }; Bits_memcpyConst(eth.srcAddr, TAPWrapper_LOCAL_MAC, Ethernet_ADDRLEN); Bits_memcpyConst(eth.destAddr, tw->pub.peerAddress, Ethernet_ADDRLEN); if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) { Log_debug(tw->log, "DROP Packet because peers MAC is not yet known"); return NULL; } Message_push(msg, ð, sizeof(struct Ethernet), NULL); // struct Ethernet contains 2 bytes of padding at the beginning. Message_shift(msg, -2, NULL); return Iface_next(&tw->external, msg); }
static Iface_DEFUN fromAsync(struct Message* msg, struct Iface* fnpFromAsync) { struct FakeNetwork_pvt* fnp = Identity_containerOf(fnpFromAsync, struct FakeNetwork_pvt, fromAsync); struct Sockaddr_storage dest; struct Sockaddr* dp = &dest.addr; popSockaddr(msg, &dest); int idx = Map_OfIfaces_indexForKey(&dp, &fnp->map); if (idx == -1) { char* destAddr = Sockaddr_print(dp, msg->alloc); // hack, the 'dest' becomes the source. popSockaddr(msg, &dest); char* srcAddr = Sockaddr_print(dp, msg->alloc); Log_debug(fnp->log, "Message with unknown dest address [%s] from [%s]", destAddr, srcAddr); return NULL; } struct FakeNetwork_UDPIface_pvt* fnip = Identity_check(fnp->map.values[idx]); return Iface_next(&fnip->pub.generic.iface, msg); }
static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf) { struct Address addr; struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes; Message_shift(msg, -(RouteHeader_SIZE + DataHeader_SIZE), NULL); Bits_memcpy(addr.ip6.bytes, hdr->ip6, 16); Bits_memcpy(addr.key, hdr->publicKey, 32); addr.protocolVersion = Endian_bigEndianToHost32(hdr->version_be); addr.padding = 0; addr.path = Endian_bigEndianToHost64(hdr->sh.label_be); //Log_debug(pf->log, "Incoming DHT"); struct DHTMessage dht = { .address = &addr, .binMessage = msg, .allocator = msg->alloc }; DHTModuleRegistry_handleIncoming(&dht, pf->registry); struct Message* nodeMsg = Message_new(0, 256, msg->alloc); Iface_CALL(sendNode, nodeMsg, &addr, 0xfffffff0u, pf); if (dht.pleaseRespond) { // what a beautiful hack, see incomingFromDHT return Iface_next(&pf->pub.eventIf, msg); } return NULL; } static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventIf) { struct Pathfinder_pvt* pf = Identity_containerOf(eventIf, struct Pathfinder_pvt, pub.eventIf); enum PFChan_Core ev = Message_pop32(msg, NULL); if (Pathfinder_pvt_state_INITIALIZING == pf->state) { Assert_true(ev == PFChan_Core_CONNECT); return connected(pf, msg); } // Let the PF send another 128 path changes again because it's basically a new tick. pf->bestPathChanges = 0; switch (ev) { case PFChan_Core_SWITCH_ERR: return switchErr(msg, pf); case PFChan_Core_SEARCH_REQ: return searchReq(msg, pf); case PFChan_Core_PEER: return peer(msg, pf); case PFChan_Core_PEER_GONE: return peerGone(msg, pf); case PFChan_Core_SESSION: return session(msg, pf); case PFChan_Core_SESSION_ENDED: return sessionEnded(msg, pf); case PFChan_Core_DISCOVERED_PATH: return discoveredPath(msg, pf); case PFChan_Core_MSG: return incomingMsg(msg, pf); case PFChan_Core_PING: return handlePing(msg, pf); case PFChan_Core_PONG: return handlePong(msg, pf); case PFChan_Core_UNSETUP_SESSION: case PFChan_Core_LINK_STATE: case PFChan_Core_CTRL_MSG: return NULL; default:; } Assert_failure("unexpected event [%d]", ev); } static void sendEvent(struct Pathfinder_pvt* pf, enum PFChan_Pathfinder ev, void* data, int size) { struct Allocator* alloc = Allocator_child(pf->alloc); struct Message* msg = Message_new(0, 512+size, alloc); Message_push(msg, data, size, NULL); Message_push32(msg, ev, NULL); Iface_send(&pf->pub.eventIf, msg); Allocator_free(alloc); } static void init(void* vpf) { struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vpf); struct PFChan_Pathfinder_Connect conn = { .superiority_be = Endian_hostToBigEndian32(1), .version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL) }; CString_strncpy(conn.userAgent, "Cjdns internal pathfinder", 64); sendEvent(pf, PFChan_Pathfinder_CONNECT, &conn, PFChan_Pathfinder_Connect_SIZE); } struct Pathfinder* Pathfinder_register(struct Allocator* allocator, struct Log* log, struct EventBase* base, struct Random* rand, struct Admin* admin) { struct Allocator* alloc = Allocator_child(allocator); struct Pathfinder_pvt* pf = Allocator_calloc(alloc, sizeof(struct Pathfinder_pvt), 1); Identity_set(pf); pf->alloc = alloc; pf->log = log; pf->base = base; pf->rand = rand; pf->admin = admin; pf->pub.eventIf.send = incomingFromEventIf; pf->dhtModule.context = pf; pf->dhtModule.handleOutgoing = incomingFromDHT; // This needs to be done asynchronously so the pf can be plumbed to the core Timeout_setTimeout(init, pf, 0, base, alloc); return &pf->pub; }
static Iface_DEFUN handlePing(struct Message* msg, struct Pathfinder_pvt* pf) { Log_debug(pf->log, "Received ping"); Message_push32(msg, PFChan_Pathfinder_PONG, NULL); return Iface_next(&pf->pub.eventIf, msg); }
static Iface_DEFUN aliceToBob(struct Message* msg, struct Iface* aliceIf) { struct SwitchingContext* sc = Identity_containerOf(aliceIf, struct SwitchingContext, aliceIf); return Iface_next(&sc->bobIf, msg); }
static Iface_DEFUN bobToAlice(struct Message* msg, struct Iface* bobIf) { struct SwitchingContext* sc = Identity_containerOf(bobIf, struct SwitchingContext, bobIf); return Iface_next(&sc->aliceIf, msg); }
static Iface_DEFUN incomingFromTunIf(struct Message* msg, struct Iface* tunIf) { struct TUNAdapter_pvt* ud = Identity_containerOf(tunIf, struct TUNAdapter_pvt, pub.tunIf); uint16_t ethertype = TUNMessageType_pop(msg, NULL); int version = Headers_getIpVersion(msg->bytes); if ((ethertype == Ethernet_TYPE_IP4 && version != 4) || (ethertype == Ethernet_TYPE_IP6 && version != 6)) { Log_debug(ud->log, "DROP packet because ip version [%d] " "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype)); return NULL; } if (ethertype == Ethernet_TYPE_IP4) { return Iface_next(&ud->pub.ipTunnelIf, msg); } if (ethertype != Ethernet_TYPE_IP6) { Log_debug(ud->log, "DROP packet unknown ethertype [%u]", Endian_bigEndianToHost16(ethertype)); return NULL; } if (msg->length < Headers_IP6Header_SIZE) { Log_debug(ud->log, "DROP runt"); return NULL; } struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes; if (!AddressCalc_validAddress(header->destinationAddr)) { return Iface_next(&ud->pub.ipTunnelIf, msg); } if (Bits_memcmp(header->sourceAddr, ud->myIp6, 16)) { if (Defined(Log_DEBUG)) { uint8_t expectedSource[40]; AddrTools_printIp(expectedSource, ud->myIp6); uint8_t packetSource[40]; AddrTools_printIp(packetSource, header->sourceAddr); Log_debug(ud->log, "DROP packet from [%s] because all messages must have source address [%s]", packetSource, expectedSource); } return NULL; } if (!Bits_memcmp(header->destinationAddr, ud->myIp6, 16)) { // I'm Gonna Sit Right Down and Write Myself a Letter TUNMessageType_push(msg, ethertype, NULL); return Iface_next(tunIf, msg); } if (!Bits_memcmp(header->destinationAddr, "\xfc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01", 16)) { return Iface_next(&ud->pub.magicIf, msg); } // first move the dest addr to the right place. Bits_memmoveConst(&header->destinationAddr[-DataHeader_SIZE], header->destinationAddr, 16); Message_shift(msg, DataHeader_SIZE + RouteHeader_SIZE - Headers_IP6Header_SIZE, NULL); struct RouteHeader* rh = (struct RouteHeader*) msg->bytes; struct DataHeader* dh = (struct DataHeader*) &rh[1]; Bits_memset(dh, 0, DataHeader_SIZE); DataHeader_setContentType(dh, header->nextHeader); DataHeader_setVersion(dh, DataHeader_CURRENT_VERSION); // Other than the ipv6 addr at the end, everything is zeros right down the line. Bits_memset(rh, 0, RouteHeader_SIZE - 16); return Iface_next(&ud->pub.upperDistributorIf, msg); }
static Iface_DEFUN incomingFromMagicIf(struct Message* msg, struct Iface* magicIf) { struct TUNAdapter_pvt* ud = Identity_containerOf(magicIf, struct TUNAdapter_pvt, pub.magicIf); return Iface_next(&ud->pub.tunIf, msg); }
static Iface_DEFUN handlePing(struct Message* msg, struct ControlHandler_pvt* ch, uint64_t label, uint8_t* labelStr, uint16_t messageType_be) { if (msg->length < handlePing_MIN_SIZE) { Log_info(ch->log, "DROP runt ping"); return NULL; } struct Control* ctrl = (struct Control*) msg->bytes; Message_shift(msg, -Control_Header_SIZE, NULL); // Ping and keyPing share version location struct Control_Ping* ping = (struct Control_Ping*) msg->bytes; uint32_t herVersion = Endian_bigEndianToHost32(ping->version_be); if (!Version_isCompatible(Version_CURRENT_PROTOCOL, herVersion)) { Log_debug(ch->log, "DROP ping from incompatible version [%d]", herVersion); return NULL; } if (messageType_be == Control_KEYPING_be) { Log_debug(ch->log, "got switch keyPing from [%s]", labelStr); if (msg->length < Control_KeyPing_HEADER_SIZE) { // min keyPing size is longer Log_debug(ch->log, "DROP runt keyPing"); return NULL; } if (msg->length > Control_KeyPing_MAX_SIZE) { Log_debug(ch->log, "DROP long keyPing"); return NULL; } if (ping->magic != Control_KeyPing_MAGIC) { Log_debug(ch->log, "DROP keyPing (bad magic)"); return NULL; } struct Control_KeyPing* keyPing = (struct Control_KeyPing*) msg->bytes; keyPing->magic = Control_KeyPong_MAGIC; ctrl->header.type_be = Control_KEYPONG_be; Bits_memcpy(keyPing->key, ch->myPublicKey, 32); } else if (messageType_be == Control_PING_be) { // Happens in benchmark. //Log_debug(ch->log, "got switch ping from [%s]", labelStr); if (ping->magic != Control_Ping_MAGIC) { Log_debug(ch->log, "DROP ping (bad magic)"); return NULL; } ping->magic = Control_Pong_MAGIC; ctrl->header.type_be = Control_PONG_be; } else { Assert_failure("2+2=5"); } ping->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL); Message_shift(msg, Control_Header_SIZE, NULL); ctrl->header.checksum_be = 0; ctrl->header.checksum_be = Checksum_engine(msg->bytes, msg->length); Message_shift(msg, RouteHeader_SIZE, NULL); struct RouteHeader* routeHeader = (struct RouteHeader*) msg->bytes; Bits_memset(routeHeader, 0, RouteHeader_SIZE); SwitchHeader_setVersion(&routeHeader->sh, SwitchHeader_CURRENT_VERSION); routeHeader->sh.label_be = Endian_hostToBigEndian64(label); routeHeader->flags |= RouteHeader_flags_CTRLMSG; return Iface_next(&ch->pub.coreIf, msg); }
static Iface_DEFUN incomingFromIpTunnelIf(struct Message* msg, struct Iface* ipTunnelIf) { struct UpperDistributor_pvt* ud = Identity_containerOf(ipTunnelIf, struct UpperDistributor_pvt, pub.ipTunnelIf); return Iface_next(&ud->pub.sessionManagerIf, msg); }
// Forward from switch pinger directly to core. static Iface_DEFUN incomingFromSwitchPinger(struct Message* msg, struct Iface* switchPingerIf) { struct ControlHandler_pvt* ch = Identity_containerOf(switchPingerIf, struct ControlHandler_pvt, pub.switchPingerIf); return Iface_next(&ch->pub.coreIf, msg); }