-static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
- vpn_packet_t pkt1, pkt2;
- vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
- int nextpkt = 0;
- vpn_packet_t *outpkt = pkt[0];
- size_t outlen;
-
- if(n->status.sptps) {
- sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len);
- return;
- }
-
- if(!cipher_active(&n->incipher)) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
- n->name, n->hostname);
- return;
- }
-
- /* Check packet length */
-
- if(inpkt->len < sizeof inpkt->seqno + digest_length(&n->indigest)) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)",
- n->name, n->hostname);
- return;
- }
-
- /* Check the message authentication code */
-
- if(digest_active(&n->indigest)) {
- inpkt->len -= n->indigest.maclength;
- if(!digest_verify(&n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname);
- return;
- }
- }
- /* Decrypt the packet */
-
- if(cipher_active(&n->incipher)) {
- outpkt = pkt[nextpkt++];
- outlen = MAXSIZE;
-
- if(!cipher_decrypt(&n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname);
- return;
- }
-
- outpkt->len = outlen;
- inpkt = outpkt;
- }
-
- /* Check the sequence number */
-
- inpkt->len -= sizeof inpkt->seqno;
- inpkt->seqno = ntohl(inpkt->seqno);
-
- if(replaywin) {
- if(inpkt->seqno != n->received_seqno + 1) {
- if(inpkt->seqno >= n->received_seqno + replaywin * 8) {
- if(n->farfuture++ < replaywin >> 2) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
- n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
- return;
- }
- logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)",
- inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
- memset(n->late, 0, replaywin);
- } else if (inpkt->seqno <= n->received_seqno) {
- if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
- n->name, n->hostname, inpkt->seqno, n->received_seqno);
- return;
- }
- } else {
- for(int i = n->received_seqno + 1; i < inpkt->seqno; i++)
- n->late[(i / 8) % replaywin] |= 1 << i % 8;
- }