/** * add received packet to receive queue */ boolean Layer3::receive( void* payload ) { packet_t* packet = (packet_t*) payload; #ifdef DEBUG_NETWORK_ENABLE Serial.print(millis()); Serial.println(F(": L3::rcv")); printPacketInformation(packet); #endif //is this a beacon? if(packet->data.type == PACKET_BEACON) { return handleBeacon(packet); } //update the neighbour - this is no beacon. neighbourMgr.updateNeighbour(packet->data.source, packet->data.source, 0); //do we have to route the packet? - no broadcast routing. if(packet->data.destination != localAddress && packet->data.destination != CONFIG_L3_ADDRESS_BROADCAST) { return routePacket(packet); } //is this an ack? (it is for us!) if(packet->data.destination == localAddress && packet->data.type == PACKET_ACK) { return handleAck(packet); } //nope, store it here. boolean success = receiveQueuePush(packet); //is this a numbered packet? - send ACK if required. if(packet->data.type == PACKET_NUMBERED && packet->data.source != localAddress) { success &= sendAck(packet); } if(!success) { return false; } return true; }
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); }
static void handleBeacon(struct Message* msg, struct ETHInterface* context) { if (!context->beaconState) { // accepting beacons disabled. Log_debug(context->logger, "Dropping beacon because beaconing is disabled"); return; } struct sockaddr_ll addr; Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll)); Message_pop(msg, addr.sll_addr, 8); if (msg->length < Headers_Beacon_SIZE) { // Oversize messages are ok because beacons may contain more information in the future. Log_debug(context->logger, "Dropping wrong size beacon, expected [%d] got [%d]", Headers_Beacon_SIZE, msg->length); return; } struct Headers_Beacon* beacon = (struct Headers_Beacon*) msg->bytes; uint32_t theirVersion = Endian_bigEndianToHost32(beacon->version_be); if (!Version_isCompatible(theirVersion, Version_CURRENT_PROTOCOL)) { #ifdef Log_DEBUG uint8_t mac[18]; AddrTools_printMac(mac, addr.sll_addr); Log_debug(context->logger, "Dropped beacon from [%s] which was version [%d] " "our version is [%d] making them incompatable", mac, theirVersion, Version_CURRENT_PROTOCOL); #endif return; } #ifdef Log_DEBUG uint8_t mac[18]; AddrTools_printMac(mac, addr.sll_addr); Log_debug(context->logger, "Got beacon from [%s]", mac); #endif String passStr = { .bytes = (char*) beacon->password, .len = Headers_Beacon_PASSWORD_LEN }; struct Interface* iface = MultiInterface_ifaceForKey(context->multiIface, addr.sll_addr); int ret = InterfaceController_registerPeer(context->ic, beacon->publicKey, &passStr, false, true, iface); if (ret != 0) { uint8_t mac[18]; AddrTools_printMac(mac, addr.sll_addr); Log_info(context->logger, "Got beacon from [%s] and registerPeer returned [%d]", mac, ret); } } static void sendBeacon(void* vcontext) { struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext); if (context->beaconState != ETHInterface_beacon_ACCEPTING_AND_SENDING) { // beaconing disabled return; } struct { struct sockaddr_ll addr; struct Headers_Beacon beacon; } content; Bits_memcpyConst(&content.addr, &context->addrBase, sizeof(struct sockaddr_ll)); Bits_memset(content.addr.sll_addr, 0xff, 6); InterfaceController_populateBeacon(context->ic, &content.beacon); struct Message m = { .bytes=(uint8_t*)content.addr.sll_addr, .padding=0, .length=sizeof(struct Headers_Beacon) + 8 }; int ret; if ((ret = sendMessage(&m, &context->generic)) != 0) { Log_info(context->logger, "Got error [%d] sending beacon [%s]", ret, strerror(errno)); } } static void handleEvent(void* vcontext) { struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext); struct Message message = { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE }; struct sockaddr_ll addr; uint32_t addrLen = sizeof(struct sockaddr_ll); // Knock it out of alignment by 2 bytes so that it will be // aligned when the idAndPadding is shifted off. Message_shift(&message, 2); int rc = recvfrom(context->socket, message.bytes, message.length, 0, (struct sockaddr*) &addr, &addrLen); if (rc < 0) { Log_debug(context->logger, "Failed to receive eth frame"); return; } //Assert_true(addrLen == SOCKADDR_LL_LEN); // Pop the first 2 bytes of the message containing the node id and amount of padding. uint16_t idAndPadding_be; Message_pop(&message, &idAndPadding_be, 2); const uint16_t idAndPadding = Endian_bigEndianToHost16(idAndPadding_be); message.length = rc - 2 - ((idAndPadding & 7) * 8); const uint16_t id = idAndPadding >> 3; Message_push(&message, &id, 2); Message_push(&message, addr.sll_addr, 6); if (addr.sll_pkttype == PACKET_BROADCAST) { handleBeacon(&message, context); return; } /* Cut down on the noise uint8_t buff[sizeof(addr) * 2 + 1] = {0}; Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr)); Log_debug(context->logger, "Got ethernet frame from [%s]", buff); */ context->generic.receiveMessage(&message, &context->generic); } int ETHInterface_beginConnection(const char* macAddress, uint8_t cryptoKey[32], String* password, struct ETHInterface* ethIf) { Identity_check(ethIf); struct sockaddr_ll addr; Bits_memcpyConst(&addr, ðIf->addrBase, sizeof(struct sockaddr_ll)); if (AddrTools_parseMac(addr.sll_addr, (const uint8_t*)macAddress)) { return ETHInterface_beginConnection_BAD_MAC; } struct Interface* iface = MultiInterface_ifaceForKey(ethIf->multiIface, &addr); int ret = InterfaceController_registerPeer(ethIf->ic, cryptoKey, password, false, false, iface); if (ret) { Allocator_free(iface->allocator); switch(ret) { case InterfaceController_registerPeer_BAD_KEY: return ETHInterface_beginConnection_BAD_KEY; case InterfaceController_registerPeer_OUT_OF_SPACE: return ETHInterface_beginConnection_OUT_OF_SPACE; default: return ETHInterface_beginConnection_UNKNOWN_ERROR; } } return 0; } int ETHInterface_beacon(struct ETHInterface* ethIf, int* state) { Identity_check(ethIf); if (state) { ethIf->beaconState = *state; // Send out a beacon right away so we don't have to wait. if (ethIf->beaconState == ETHInterface_beacon_ACCEPTING_AND_SENDING) { sendBeacon(ethIf); } } return ethIf->beaconState; } struct ETHInterface* ETHInterface_new(struct EventBase* base, const char* bindDevice, struct Allocator* allocator, struct Except* exHandler, struct Log* logger, struct InterfaceController* ic) { struct ETHInterface* context = Allocator_clone(allocator, (&(struct ETHInterface) { .generic = { .sendMessage = sendMessage, .allocator = allocator }, .logger = logger, .ic = ic, .id = getpid() }));