static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) { DHT *dht = object; if (packet[0] == NET_PACKET_CRYPTO) { if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; int len = handle_request(dht->c->self_public_key, dht->c->self_secret_key, public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; if (!dht->c->cryptopackethandlers[number].function) return 1; dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, data, len); } else { /* If request is not for us, try routing it. */ int retval = route_packet(dht, packet + 1, packet, length); if ((unsigned int)retval == length) return 0; } } return 1; }
static int friendreq_handlepacket(IP_Port source, uint8_t * packet, uint32_t length) { if (packet[0] == 32) { if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. if (handle_friendrequest_isset == 0) return 1; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; int len = handle_request(public_key, data, packet, length); if (len == -1) return 1; if (request_received(public_key)) return 1; addto_receivedlist(public_key); (*handle_friendrequest)(public_key, data, len); } else { /* if request is not for us, try routing it. */ if(route_packet(packet + 1, packet, length) == length) return 0; } } return 1; }
/*============================================================================= Function listen_iface Purpose: used as a listening thread for an interface. When a packet is received slip decoding is performed as it is paced in the buffer, the packet is then passed to the route_packet routine Parameters: *i (IN) - a pointer to the interface to listen on Returns: nothing =============================================================================*/ void *listen_iface(void *i) { struct interface *iface = (struct interface *)i; int sd, addlen, c, totbytes = 0; char buf[1]; char slipBuf[MAX_PACKET]; struct sockaddr_in sin; struct protoent *ptrp; /* set up the sockaddr */ memset((char *)&sin,0,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(iface->lport); if (((int)(ptrp = getprotobyname("udp"))) == 0) error("getprotobyname"); if ((sd = socket(AF_INET, SOCK_DGRAM,ptrp->p_proto)) < 0) error("socket"); if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) < 0) error("bind"); while(1) { recvfrom(sd,buf,1,0,(struct sockaddr *)&sin,&addlen); c = 0xff & buf[0]; switch (c) { case END: if (totbytes) { route_packet(slipBuf,totbytes); /* handle the packet */ totbytes = 0; /* reset for next packet */ } break; case ESC: recvfrom(sd,buf,1,0,(struct sockaddr *)&sin,&addlen); c = 0xff & buf[0]; switch (c) { case ESC_END: c = END; break; case ESC_ESC: c = ESC; break; } /* falling through here */ default: if (totbytes<MAX_PACKET) slipBuf[totbytes++] = c; } } }
static int cryptopacket_handle(IP_Port source, uint8_t * packet, uint32_t length) { if (packet[0] == 32) { if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; int len = handle_request(public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; if (!cryptopackethandlers[number]) return 1; cryptopackethandlers[number](source, public_key, data, len); } else { /* if request is not for us, try routing it. */ if(route_packet(packet + 1, packet, length) == length) return 0; } } return 1; }
void nl_rx_task() { uint8_t len; // to hold the size of the received packet, always = sizeof(NW_Packet) int8_t rssi; // to hold rssi of received packet uint8_t *local_rx_buf; // pointer to receive buffer of link layer int8_t val; // status variable to hold the return type of function calls int8_t flag; nrk_time_t start, end, elapsed; // needed by nl_rx_task() // to decide when to send own NGB_LIST if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("NL_RX_TASK PID = ")); printf("%d\r\n",nrk_get_pid()); } // initialise the timer nrk_time_get(&start); end.secs = start.secs; end.nano_secs = start.nano_secs; // initialise the link layer val = bmac_init(25); if(val == NRK_ERROR) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by bmac_init()\r\n")); } // give the link layer a rx buffer val = bmac_rx_pkt_set_buffer(rx_buf, RF_BUFFER_SIZE); if(val == NRK_ERROR) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by bmac_rx_pkt_set_buffer()\r\n")); } // start processing forever while(1) { // decide whether it is time to send your own Ngb_List message if(CONNECTED_TO_GATEWAY == TRUE) { nrk_time_get(&end); val = nrk_time_sub(&elapsed, end, start); nrk_time_compact_nanos(&elapsed); if(elapsed.secs >= NGB_LIST_PERIOD) { ntg_pkt.type = SERIAL_NGB_LIST; ntg_pkt.length = SIZE_MSG_NGB_LIST; enter_cr(nl_sem, 34); pack_Msg_NgbList(ntg_pkt.data, &nl); leave_cr(nl_sem, 34); pack_NodeToGatewaySerial_Packet_header(to_gw_buf, &ntg_pkt); memcpy(to_gw_buf + SIZE_NODETOGATEWAYSERIAL_PACKET_HEADER, ntg_pkt.data, MAX_SERIAL_PAYLOAD); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("Sending own NGB_LIST message to gateway\r\n")); } sendToSerial(to_gw_buf, SIZE_NODETOGATEWAYSERIAL_PACKET); // reset the timer start.secs = end.secs; start.nano_secs = end.nano_secs; } // end if } // end if if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("Waiting for next pkt from link layer\r\n")); } flag = 0; // wait for the next packet while(bmac_rx_pkt_ready() == 0) { val = bmac_wait_until_rx_pkt(); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("NL: bmac_wait_until_rx_packet() returned ")); printf("%d\n", val); } } // Get the packet do { local_rx_buf = bmac_rx_pkt_get(&len,&rssi); if(local_rx_buf == NULL) { nrk_kprintf(PSTR("NL: NULL returned by bmac_rx_pkt_get()\r\n")); } } while(local_rx_buf == NULL); // sanity check for debugging if(len != SIZE_NW_PACKET) // this should not happen { /* nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("NL: Wrong length of packet received: ")); printf("%d\r\n", len); } */ if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("NL: nl_rx_task(): Wrong length of packet received: ")); printf("%d\r\n", len); } flag = 1; } nrk_led_set(GREEN_LED); if(DEBUG_NL == 2)// || flag == 1) { int8_t i; nrk_kprintf(PSTR("NL: Contents of received packet are\r\n")); printf("["); for(i = 0; i < len; i++) printf("%d ", local_rx_buf[i]); printf("]\r\n"); } if(flag == 1) { bmac_rx_pkt_release(); // drop the packet and go receive another nrk_led_clr(GREEN_LED); continue; } // unpack the packet header from the received buffer unpack_NW_Packet_header(&pkt_rx, local_rx_buf); // copy the packet payload to the data field of the local packet memcpy(pkt_rx.data, local_rx_buf + SIZE_NW_PACKET_HEADER, MAX_NETWORK_PAYLOAD); // Release the RX buffer quickly so future packets can arrive bmac_rx_pkt_release(); // begin processing this packet if(pkt_type(&pkt_rx) == APPLICATION) // its an application layer packet { // case 1: Destination is NODE_ADDR or BCAST_ADDR if(pkt_rx.dest == NODE_ADDR || pkt_rx.dest == BCAST_ADDR) process_app_pkt(&pkt_rx, rssi); // case 2: I am enroute to the destination else if(pkt_rx.nextHop == NODE_ADDR) { if(pkt_rx.src == NODE_ADDR) // routing table corrupted { nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("Routing table corrupted at ")); printf("%d\r\n", NODE_ADDR); } // end while } // end if else route_packet(&pkt_rx); } // end if // case 3: Routing tables still not made else if(pkt_rx.nextHop == BCAST_ADDR) route_packet(&pkt_rx); else ; // drop all other packets } // end if(type == APPLICATION) else { if(pkt_type(&pkt_rx) == NW_CONTROL) // its a network control packet { // case 1: Destination is NODE_ADDR or BCAST_ADDR if(pkt_rx.dest == NODE_ADDR || pkt_rx.dest == BCAST_ADDR) process_nw_ctrl_pkt(&pkt_rx, rssi); // case 2: I am enroute to a destination else if(pkt_rx.nextHop == NODE_ADDR) { if(pkt_rx.src == NODE_ADDR) // routing table corrupted { nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("Routing table corrupted at ")); printf("%d\r\n", NODE_ADDR); } // end while } // end if else route_packet(&pkt_rx); } // end if // case 3: Routing tables still not made else if(pkt_rx.nextHop == BCAST_ADDR) route_packet(&pkt_rx); else ; // drop all other packets } // end if(type == NW_CONTROL) else // unknown packet type { nrk_kprintf(PSTR("NL: Unknown pkt type received = ")); printf("%d\r\n", pkt_type(&pkt_rx)); } } nrk_led_clr(GREEN_LED); } // end while(1) return; } // end nl_rx_task
void process_nw_ctrl_pkt(NW_Packet *pkt, int8_t rssi) { int8_t ret; // to hold the return value of various function calls int8_t i; if(DEBUG_NL >= 1) nrk_kprintf(PSTR("NL: Entered process_nw_ctrl_pkt()\n")); switch( nw_ctrl_type(pkt -> type) ) { case HELLO: // HELLO msg // unpack the Msg_Hello from the packet payload unpack_Msg_Hello(&mh, pkt -> data); mh.n.rssi = rssi; ret = add_neighbor(mh.n); if(ret == NRK_ERROR) { record_max_ngb_limit_reached(pkt); // record this fact } if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("Received HELLO msg from: ")); printf("%d ", mh.n.addr); nrk_kprintf(PSTR("with RSSI = ")); printf("%d\r\n",mh.n.rssi); } break; case NGB_LIST: // NGB_LIST msg // if the node gets it's own NgbList message back, drop it if(pkt -> src == NODE_ADDR) break; // unpack the Msg_NgbList from the packet payload unpack_Msg_NgbList(&mnlist, pkt -> data); nlist = mnlist.nl; if(DEBUG_NL >= 1) { int8_t i; // loop index printf("NL: Received NGB_LIST msg from %d with count = %d\n", nlist.my_addr, nlist.count); for(i = 0; i < MAX_NGBS; i++) { if(nlist.ngbs[i].addr != BCAST_ADDR) // valid entry printf("%u, ", nlist.ngbs[i].addr); } printf("\r\n"); } //multihop(pkt); // multihop this NGB_LIST message. route_packet(pkt); if(CONNECTED_TO_GATEWAY == TRUE) // this node is connected to the gateway { // construct a packet to be sent to the gateway over the serial connection ntg_pkt.type = SERIAL_NGB_LIST; ntg_pkt.length = SIZE_MSG_NGB_LIST; // pack the message in the data field of the NodeToGatewaySerial_Packet pack_Msg_NgbList(ntg_pkt.data, &mnlist); // pack the NodeToGatewaySerial_Packet header into the serial transmit buffer pack_NodeToGatewaySerial_Packet_header(to_gw_buf, &ntg_pkt); // append the payload into the serial transmit buffer memcpy(to_gw_buf + SIZE_NODETOGATEWAYSERIAL_PACKET_HEADER, ntg_pkt.data, MAX_SERIAL_PAYLOAD); // CHECK //send the packet to gateway if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("Sending packet to gateway\r\n")); } sendToSerial(to_gw_buf, SIZE_NODETOGATEWAYSERIAL_PACKET); //printBuffer(to_gw_buf, SIZE_NODETOGATEWAYSERIAL_PACKET); } break; case ROUTE_CONFIG: unpack_Msg_RoutingTable(&mrt, pkt -> data); enter_cr(nl_sem, 34); DEFAULT_GATEWAY = mrt.dg; // get the value of DEFAULT_GATEWAY in any case leave_cr(nl_sem, 34); if(DEBUG_NL == 0) { nrk_kprintf(PSTR("Received a ROUTE_CONFIG message\r\n")); for(i = 0; i < MAX_NODES; i++) { printf("%d -> %d [%d, %d]\r\n", mrt.node, mrt.rt[i].dest, mrt.rt[i].nextHop, mrt.rt[i].cost); } } if(mrt.node == NODE_ADDR) // this is my routing table { /*enter_cr(nl_sem, 34); initialise_routing_table(); // invalidate all entries for(i = 0; i < MAX_NODES; i++) { rt[i] = mrt.rt[i]; } leave_cr(nl_sem, 34); */ set_RoutingTable(&mrt); } else // some other node's routing table. Route it { route_packet(pkt); } break; default: nrk_kprintf(PSTR("NL: process_nw_ctrl_pkt(): Unsupported network control message received = ")); printf("%u\n", pkt -> type); break; } // end switch return; }
/* up_to_network() IS CALLED FROM THE DATA LINK LAYER (BELOW) TO ACCEPT A PACKET FOR THIS NODE, OR TO RE-ROUTE IT TO THE INTENDED DESTINATION. */ int up_to_network(char *packet, size_t length, int arrived_on_link) { //printf("up to network at hop %d\n", nodeinfo.address); NL_PACKET *p = (NL_PACKET *) packet; if (p->src == nodeinfo.address) { printf("drop a packet at %d, src = %d, des = %d, seqno = %d\n\n", nodeinfo.address, p->src, p->dest, p->seqno); return 0; } //printf("up to network at %d (from %d to %d)\n", nodeinfo.address, p->src, p->dest); ++p->hopcount; /* took 1 hop to get here */ mtu = linkinfo[arrived_on_link].mtu; p->trans_time += ((CnetTime) 8000 * 1000 * mtu / linkinfo[arrived_on_link].bandwidth + linkinfo[arrived_on_link].propagationdelay) * 100 / mtu; /* IS THIS PACKET IS FOR ME? */ if (p->dest == nodeinfo.address) { switch (p->kind) { case NL_DATA: if (p->seqno == NL_packetexpected(p->src)) { //length = p->length; //memcpy(rb[p->src], (char *) p->msg, length); //rb[p->src] = rb[p->src] + length; //packet_length[p->src] += length; RB_save_msg_link(p, arrived_on_link); if (p->pieceEnd) { RB_copy_whole_msg_link(p, arrived_on_link); up_to_application(p, arrived_on_link); return 0; } } break; case NL_ACK: if (p->seqno == NL_ackexpected(p->src)) { ////("ACK come!\n"); inc_NL_ackexpected(p->src); NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_set_has_resent(p->src, 0); CHECK(CNET_enable_application(p->src)); } break; case NL_ERR_ACK: printf("NL_ERR_ACK!\n"); if (p->seqno == NL_ackexpected(p->src)) { if (NL_get_has_resent(p->src) == 0) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); printf("resend it\n"); int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; NL_set_has_resent(p->src, 1); //NL_inc_resent_times(p->src); // for debug flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been resent, dont resent it again\n"); } } else { printf( "this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; case NL_ERR_ACK_RESENT: printf("NL_ERR_ACK_RESENT!\n"); if (p->seqno == NL_ackexpected(p->src)) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "resend a resent packet, src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); //printf("this packet has been resent %d times before this time\n", NL_get_resent_times(p->src)); //for debug //NL_inc_resent_times(p->src); // for debug int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; default: //("it's nothing!====================\n"); break; } } /* THIS PACKET IS FOR SOMEONE ELSE */ else { if (p->hopcount < MAXHOPS) { /* if not too many hops... */ //length = p->length; //memcpy(rb[p->src], (char *) p->msg, length); //rb[p->src] = rb[p->src] + length; if(p->kind != NL_DATA){ route_packet(p, arrived_on_link); } else{ RB_save_msg_link(p, arrived_on_link); printf("finish new rb save msg\n"); if (p->pieceEnd){ RB_copy_whole_msg_link(p, arrived_on_link); printf("finish copy whole msg\n"); printf("p->length after copy = %d\n", p->length); route_packet(p, arrived_on_link); } } } else {/* silently drop */; } } return 0; }
int main(int argc, char **argv) { TYPE_FD_SET actread; char buf[1024]; int addrlen; int arg; int ch; int errflag = 0; int fail = 0; int flisten; int i; int n; struct connection *p; struct sockaddr *addr; while ((ch = getopt(argc, argv, "af:")) != EOF) switch (ch) { case 'a': all = 1; break; case 'f': fail = atoi(optarg); if (fail < 0 || fail > 100) errflag = 1; break; case '?': errflag = 1; break; } if (errflag || optind < argc) { fprintf(stderr, "Usage: %s [-a] [-f failures]\n", *argv); exit(1); } for (n = 0; n < FD_SETSIZE; n++) close(n); chdir("/"); setsid(); signal(SIGPIPE, SIG_IGN); addr = build_sockaddr("*:4713", &addrlen); if (!addr) exit(1); flisten = socket(addr->sa_family, SOCK_STREAM, 0); if (flisten < 0) exit(1); arg = 1; setsockopt(flisten, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg)); if (bind(flisten, addr, addrlen)) exit(1); if (listen(flisten, SOMAXCONN)) exit(1); FD_SET(flisten, &chkread); if (maxfd < flisten) maxfd = flisten; for (;;) { actread = chkread; if (select(maxfd + 1, &actread, 0, 0, 0) <= 0) continue; if (FD_ISSET(flisten, &actread)) create_connection(flisten); for (p = connections; p; p = p->next) if (FD_ISSET(p->fd, &actread)) { n = read(p->fd, buf, sizeof(buf)); if (n <= 0) { close_connection(p); break; } for (i = 0; i < n; i++) if (((p->buf[p->cnt++] = buf[i]) & 0xff) == FR_END) { if (p->cnt > 1 && (fail == 0 || rand() % 100 >= fail)) route_packet(p); p->cnt = 0; } } } }