- if(n->status.sptps)
- return send_sptps_packet(n, origpkt);
-
- /* Make sure we have a valid key */
-
- if(!n->status.validkey) {
- logger(DEBUG_TRAFFIC, LOG_INFO,
- "No valid key known yet for %s (%s), forwarding via TCP",
- n->name, n->hostname);
-
- if(n->last_req_key + 10 <= now.tv_sec) {
- send_req_key(n);
- n->last_req_key = now.tv_sec;
- }
-
- send_tcppacket(n->nexthop->connection, origpkt);
-
- return;
- }
-
- if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) {
- logger(DEBUG_TRAFFIC, LOG_INFO,
- "Packet for %s (%s) larger than minimum MTU, forwarding via %s",
- n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
-
- if(n != n->nexthop)
- send_packet(n->nexthop, origpkt);
- else
- send_tcppacket(n->nexthop->connection, origpkt);
-
- return;
- }
-
- /* Compress the packet */
-
- if(n->outcompression) {
- outpkt = pkt[nextpkt++];
-
- if((outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) {
- logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)",
- n->name, n->hostname);
- return;
- }
-
- inpkt = outpkt;
- }
-
- /* Add sequence number */
-
- inpkt->seqno = htonl(++(n->sent_seqno));
- inpkt->len += sizeof inpkt->seqno;
-
- /* Encrypt the packet */
-
- if(cipher_active(&n->outcipher)) {
- outpkt = pkt[nextpkt++];
- outlen = MAXSIZE;
-
- if(!cipher_encrypt(&n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
- logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname);
- goto end;
- }
-
- outpkt->len = outlen;
- inpkt = outpkt;
- }
-
- /* Add the message authentication code */
-
- if(digest_active(&n->outdigest)) {
- digest_create(&n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len);
- inpkt->len += digest_length(&n->outdigest);
- }
-
- /* Send the packet */
-
- const sockaddr_t *sa;
- int sock;
-
- /* Overloaded use of priority field: -1 means local broadcast */
-
- if(origpriority == -1 && n->prevedge)
- choose_broadcast_address(n, &sa, &sock);
- else
- choose_udp_address(n, &sa, &sock);
-
-#if defined(SOL_IP) && defined(IP_TOS)
- if(priorityinheritance && origpriority != priority
- && listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
- priority = origpriority;
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
- if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
- }
-#endif
-
- if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
- if(sockmsgsize(sockerrno)) {
- if(n->maxmtu >= origlen)
- n->maxmtu = origlen - 1;
- if(n->mtu >= origlen)
- n->mtu = origlen - 1;
- } else
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
- }
-
-end:
- origpkt->len = origlen;