X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=371632fa3c57c18ff7c204754a41463555acff65;hb=bb6b97ce3493d49b79f1bd57fdac420c312ef8d6;hp=4df8d9750277fe2cf03e5fe3e2478f4285d0873f;hpb=7a71d48009e03ff1143a6e1084803f456a27c849;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index 4df8d975..371632fa 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -253,7 +253,7 @@ static void receive_packet(node_t *n, vpn_packet_t *packet) { static bool try_mac(node_t *n, const vpn_packet_t *inpkt) { if(n->status.sptps) - return sptps_verify_datagram(&n->sptps, (char *)inpkt->data - 4, inpkt->len); + return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len); if(!digest_active(&n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(&n->indigest)) return false; @@ -269,7 +269,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { size_t outlen; if(n->status.sptps) { - sptps_receive_data(&n->sptps, (char *)inpkt->data - 4, inpkt->len); + sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len); return; } @@ -388,6 +388,51 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) { receive_packet(c->node, &outpkt); } +static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) { + if(!n->status.validkey) { + logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname); + if(!n->status.waitingforkey) + send_req_key(n); + else if(n->last_req_key + 10 < time(NULL)) { + sptps_stop(&n->sptps); + n->status.waitingforkey = false; + send_req_key(n); + } + } + + uint8_t type = 0; + int offset = 0; + + if(!(origpkt->data[12] | origpkt->data[13])) { + sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len); + return; + } + + if(routing_mode == RMODE_ROUTER) + offset = 14; + else + type = PKT_MAC; + + if(origpkt->len < offset) + return; + + vpn_packet_t outpkt; + + if(n->outcompression) { + int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression); + if(len < 0) { + logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname); + } else if(len < origpkt->len - offset) { + outpkt.len = len + offset; + origpkt = &outpkt; + type |= PKT_COMPRESSED; + } + } + + sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset); + return; +} + static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; @@ -406,6 +451,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { return; } + if(n->status.sptps) + return send_sptps_packet(n, origpkt); + /* Make sure we have a valid key */ if(!n->status.validkey) { @@ -438,14 +486,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { return; } - if(n->status.sptps) { - uint8_t type = 0; - if(!(inpkt->data[12] | inpkt->data[13])) - type = PKT_PROBE; - sptps_send_record(&n->sptps, type, (char *)inpkt->data, inpkt->len); - return; - } - /* Compress the packet */ if(n->outcompression) { @@ -550,11 +590,11 @@ end: bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { node_t *to = handle; - if(type >= SPTPS_HANDSHAKE) { + if(type >= SPTPS_HANDSHAKE || ((myself->options | to->options) & OPTION_TCPONLY)) { char buf[len * 4 / 3 + 5]; b64encode(data, buf, len); if(!to->status.validkey) - return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 -1", ANS_KEY, myself->name, to->name, buf); + return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, myself->name, to->name, buf, myself->incompression); else return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_SPTPS, buf); } @@ -589,6 +629,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t if(type == SPTPS_HANDSHAKE) { from->status.validkey = true; + from->status.waitingforkey = false; logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname); return true; } @@ -599,19 +640,61 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t } vpn_packet_t inpkt; - inpkt.len = len; - memcpy(inpkt.data, data, len); if(type == PKT_PROBE) { + inpkt.len = len; + memcpy(inpkt.data, data, len); mtu_probe_h(from, &inpkt, len); return true; - } - if(type != 0) { + + if(type & ~(PKT_COMPRESSED | PKT_MAC)) { logger(DEBUG_ALWAYS, LOG_ERR, "Unexpected SPTPS record type %d len %d from %s (%s)", type, len, from->name, from->hostname); return false; } + /* Check if we have the headers we need */ + if(routing_mode != RMODE_ROUTER && !(type & PKT_MAC)) { + logger(DEBUG_TRAFFIC, LOG_ERR, "Received packet from %s (%s) without MAC header (maybe Mode is not set correctly)", from->name, from->hostname); + return false; + } else if(routing_mode == RMODE_ROUTER && (type & PKT_MAC)) { + logger(DEBUG_TRAFFIC, LOG_WARNING, "Received packet from %s (%s) with MAC header (maybe Mode is not set correctly)", from->name, from->hostname); + } + + int offset = (type & PKT_MAC) ? 0 : 14; + if(type & PKT_COMPRESSED) { + len = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression); + if(len < 0) { + return false; + } else { + inpkt.len = len + offset; + } + if(inpkt.len > MAXSIZE) + abort(); + } else { + memcpy(inpkt.data + offset, data, len); + inpkt.len = len + offset; + } + + /* Generate the Ethernet packet type if necessary */ + if(offset) { + switch(inpkt.data[14] >> 4) { + case 4: + inpkt.data[12] = 0x08; + inpkt.data[13] = 0x00; + break; + case 6: + inpkt.data[12] = 0x86; + inpkt.data[13] = 0xDD; + break; + default: + logger(DEBUG_TRAFFIC, LOG_ERR, + "Unknown IP version %d while reading packet from %s (%s)", + inpkt.data[14] >> 4, from->name, from->hostname); + return false; + } + } + receive_packet(from, &inpkt); return true; } @@ -643,6 +726,11 @@ void send_packet(node_t *n, vpn_packet_t *packet) { n->out_packets++; n->out_bytes += packet->len; + if(n->status.sptps) { + send_sptps_packet(n, packet); + return; + } + via = (packet->priority == -1 || n->via == myself) ? n->nexthop : n->via; if(via != n) @@ -695,7 +783,7 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) { if(from != myself) break; - for(node = node_udp_tree->head; node; node = node->next) { + for(node = node_tree->head; node; node = node->next) { n = node->data; if(n->status.reachable && ((n->via == myself && n->nexthop == n) || n->via == n)) @@ -719,7 +807,7 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { for(node = edge_weight_tree->head; node; node = node->next) { e = node->data; - if(e->to == myself) + if(!e->to->status.reachable || e->to == myself) continue; if(sockaddrcmp_noport(from, &e->address)) { @@ -745,7 +833,7 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { void handle_incoming_vpn_data(int sock, short events, void *data) { vpn_packet_t pkt; char *hostname; - sockaddr_t from; + sockaddr_t from = {{0}}; socklen_t fromlen = sizeof from; node_t *n; int len;