Let tinc figure out the exact MTU of the link.
This commit is contained in:
parent
e8fbef5de6
commit
6b12bea62f
12 changed files with 193 additions and 78 deletions
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: connection.h,v 1.1.2.38 2003/11/17 15:30:16 guus Exp $
|
||||
$Id: connection.h,v 1.1.2.39 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_CONNECTION_H__
|
||||
|
@ -30,6 +30,7 @@
|
|||
|
||||
#define OPTION_INDIRECT 0x0001
|
||||
#define OPTION_TCPONLY 0x0002
|
||||
#define OPTION_DONTFRAGMENT 0x0004
|
||||
|
||||
typedef struct connection_status_t {
|
||||
int pinged:1; /* sent ping */
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: graph.c,v 1.1.2.30 2003/10/10 16:23:30 guus Exp $
|
||||
$Id: graph.c,v 1.1.2.31 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
/* We need to generate two trees from the graph:
|
||||
|
@ -229,6 +229,12 @@ void sssp_bfs(void)
|
|||
|
||||
e->to->hostname = sockaddr2hostname(&e->to->address);
|
||||
avl_insert_node(node_udp_tree, node);
|
||||
|
||||
if(e->to->options & OPTION_DONTFRAGMENT) {
|
||||
e->to->mtuprobes = 0;
|
||||
if(e->to->status.validkey)
|
||||
send_mtu_probe(e->to);
|
||||
}
|
||||
}
|
||||
|
||||
node = avl_alloc_node();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net.c,v 1.35.4.202 2003/12/12 19:52:24 guus Exp $
|
||||
$Id: net.c,v 1.35.4.203 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -334,7 +334,8 @@ int main_loop(void)
|
|||
while(running) {
|
||||
now = time(NULL);
|
||||
|
||||
tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
|
||||
// tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
maxfd = build_fdset(&fset);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net.h,v 1.9.4.72 2003/10/08 12:09:37 guus Exp $
|
||||
$Id: net.h,v 1.9.4.73 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NET_H__
|
||||
|
@ -150,6 +150,7 @@ extern int main_loop(void);
|
|||
extern void terminate_connection(struct connection_t *, bool);
|
||||
extern void flush_queue(struct node_t *);
|
||||
extern bool read_rsa_public_key(struct connection_t *);
|
||||
extern void send_mtu_probe(struct node_t *);
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
#define closesocket(s) close(s)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net_packet.c,v 1.1.2.44 2003/12/12 19:52:25 guus Exp $
|
||||
$Id: net_packet.c,v 1.1.2.45 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -52,9 +52,58 @@ int keyexpires = 0;
|
|||
EVP_CIPHER_CTX packet_ctx;
|
||||
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
|
||||
|
||||
static void send_udppacket(node_t *, vpn_packet_t *);
|
||||
|
||||
#define MAX_SEQNO 1073741824
|
||||
|
||||
void send_mtu_probe(node_t *n)
|
||||
{
|
||||
vpn_packet_t packet;
|
||||
int len, i;
|
||||
|
||||
cp();
|
||||
|
||||
n->mtuprobes++;
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
if(n->mtuprobes >= 100 || n->probedmtu >= n->mtu) {
|
||||
n->mtu = n->probedmtu;
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, _("Fixing MTU of %s (%s) to %d after %d probes"), n->name, n->hostname, n->mtu, n->mtuprobes);
|
||||
return;
|
||||
}
|
||||
|
||||
len = n->probedmtu + 1 + random() % (n->mtu - n->probedmtu);
|
||||
if(len < 64)
|
||||
len = 64;
|
||||
|
||||
memset(packet.data, 0, 14);
|
||||
RAND_pseudo_bytes(packet.data + 14, len - 14);
|
||||
packet.len = len;
|
||||
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, _("Sending MTU probe length %d to %s (%s)"), len, n->name, n->hostname);
|
||||
|
||||
send_udppacket(n, &packet);
|
||||
}
|
||||
|
||||
n->mtuevent = xmalloc(sizeof(*n->mtuevent));
|
||||
n->mtuevent->handler = (event_handler_t)send_mtu_probe;
|
||||
n->mtuevent->data = n;
|
||||
n->mtuevent->time = now + 1;
|
||||
event_add(n->mtuevent);
|
||||
}
|
||||
|
||||
void mtu_probe_h(node_t *n, vpn_packet_t *packet) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, _("Got MTU probe length %d from %s (%s)"), packet->len, n->name, n->hostname);
|
||||
|
||||
if(!packet->data[0]) {
|
||||
packet->data[0] = 1;
|
||||
send_packet(n, packet);
|
||||
} else {
|
||||
if(n->probedmtu < packet->len)
|
||||
n->probedmtu = packet->len;
|
||||
}
|
||||
}
|
||||
|
||||
static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level)
|
||||
{
|
||||
if(level == 10) {
|
||||
|
@ -203,7 +252,10 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
|
|||
if(n->connection)
|
||||
n->connection->last_ping_time = now;
|
||||
|
||||
receive_packet(n, inpkt);
|
||||
if(!inpkt->data[12] && !inpkt->data[13])
|
||||
mtu_probe_h(n, inpkt);
|
||||
else
|
||||
receive_packet(n, inpkt);
|
||||
}
|
||||
|
||||
void receive_tcppacket(connection_t *c, char *buffer, int len)
|
||||
|
@ -328,6 +380,10 @@ static void send_udppacket(node_t *n, vpn_packet_t *inpkt)
|
|||
|
||||
if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) {
|
||||
logger(LOG_ERR, _("Error sending packet to %s (%s): %s"), n->name, n->hostname, strerror(errno));
|
||||
if(errno == EMSGSIZE) {
|
||||
if(n->mtu >= origlen)
|
||||
n->mtu = origlen - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net_setup.c,v 1.1.2.47 2003/12/07 14:28:39 guus Exp $
|
||||
$Id: net_setup.c,v 1.1.2.48 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -272,21 +272,20 @@ bool setup_myself(void)
|
|||
|
||||
/* Check some options */
|
||||
|
||||
if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice) && choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice) && choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "DontFragment"), &choice) && choice)
|
||||
myself->options |= OPTION_DONTFRAGMENT;
|
||||
|
||||
if(myself->options & OPTION_TCPONLY)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net_socket.c,v 1.1.2.35 2003/12/12 19:52:25 guus Exp $
|
||||
$Id: net_socket.c,v 1.1.2.36 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -49,13 +49,10 @@ int listen_sockets;
|
|||
|
||||
int setup_listen_socket(const sockaddr_t *sa)
|
||||
{
|
||||
int nfd, flags;
|
||||
int nfd;
|
||||
char *addrstr;
|
||||
int option;
|
||||
char *iface;
|
||||
#ifdef SO_BINDTODEVICE
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
cp();
|
||||
|
||||
|
@ -67,13 +64,15 @@ int setup_listen_socket(const sockaddr_t *sa)
|
|||
}
|
||||
|
||||
#ifdef O_NONBLOCK
|
||||
flags = fcntl(nfd, F_GETFL);
|
||||
{
|
||||
int flags = fcntl(nfd, F_GETFL);
|
||||
|
||||
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -94,6 +93,8 @@ int setup_listen_socket(const sockaddr_t *sa)
|
|||
if(get_config_string
|
||||
(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
||||
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
||||
|
||||
|
@ -129,13 +130,9 @@ int setup_listen_socket(const sockaddr_t *sa)
|
|||
|
||||
int setup_vpn_in_socket(const sockaddr_t *sa)
|
||||
{
|
||||
int nfd, flags;
|
||||
int nfd;
|
||||
char *addrstr;
|
||||
int option;
|
||||
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
||||
char *iface;
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
cp();
|
||||
|
||||
|
@ -147,29 +144,51 @@ int setup_vpn_in_socket(const sockaddr_t *sa)
|
|||
}
|
||||
|
||||
#ifdef O_NONBLOCK
|
||||
flags = fcntl(nfd, F_GETFL);
|
||||
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
{
|
||||
int flags = fcntl(nfd, F_GETFL);
|
||||
|
||||
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
option = 1;
|
||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
|
||||
|
||||
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
||||
if(get_config_string
|
||||
(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
||||
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||
{
|
||||
bool choice;
|
||||
|
||||
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("Can't bind to interface %s: %s"), iface,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "DontFragment"), &choice) && choice) {
|
||||
option = IP_PMTUDISC_DO;
|
||||
if(setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option))) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("Can't set MTU discovery mode: %s"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
||||
{
|
||||
char *iface;
|
||||
struct ifreq ifr;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
||||
|
||||
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, _("Can't bind to interface %s: %s"), iface,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: node.c,v 1.1.2.28 2003/08/28 21:05:10 guus Exp $
|
||||
$Id: node.c,v 1.1.2.29 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -80,6 +80,7 @@ node_t *new_node(void)
|
|||
n->edge_tree = new_edge_tree();
|
||||
n->queue = list_alloc((list_action_t) free);
|
||||
EVP_CIPHER_CTX_init(&n->packet_ctx);
|
||||
n->mtu = MTU;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
32
src/node.h
32
src/node.h
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: node.h,v 1.1.2.29 2003/07/30 21:52:41 guus Exp $
|
||||
$Id: node.h,v 1.1.2.30 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NODE_H__
|
||||
|
@ -25,13 +25,14 @@
|
|||
|
||||
#include "avl_tree.h"
|
||||
#include "connection.h"
|
||||
#include "event.h"
|
||||
#include "list.h"
|
||||
#include "subnet.h"
|
||||
|
||||
typedef struct node_status_t {
|
||||
int active:1; /* 1 if active.. */
|
||||
int validkey:1; /* 1 if we currently have a valid key for him */
|
||||
int waitingforkey:1; /* 1 if we already sent out a request */
|
||||
int waitingforkey:1; /* 1 if we already sent out a request */
|
||||
int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
|
||||
int reachable:1; /* 1 if this node is reachable in the graph */
|
||||
int indirect:1; /* 1 if this node is not directly reachable by us */
|
||||
|
@ -39,7 +40,7 @@ typedef struct node_status_t {
|
|||
} node_status_t;
|
||||
|
||||
typedef struct node_t {
|
||||
char *name; /* name of this node */
|
||||
char *name; /* name of this node */
|
||||
long int options; /* options turned on for this node */
|
||||
|
||||
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
||||
|
@ -47,30 +48,35 @@ typedef struct node_t {
|
|||
|
||||
node_status_t status;
|
||||
|
||||
const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
|
||||
char *key; /* Cipher key and iv */
|
||||
const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
|
||||
char *key; /* Cipher key and iv */
|
||||
int keylength; /* Cipher key and iv length */
|
||||
EVP_CIPHER_CTX packet_ctx; /* Cipher context */
|
||||
EVP_CIPHER_CTX packet_ctx; /* Cipher context */
|
||||
|
||||
const EVP_MD *digest; /* Digest type for MAC */
|
||||
const EVP_MD *digest; /* Digest type for MAC */
|
||||
int maclength; /* Length of MAC */
|
||||
|
||||
int compression; /* Compressionlevel, 0 = no compression */
|
||||
|
||||
list_t *queue; /* Queue for packets awaiting to be encrypted */
|
||||
|
||||
struct node_t *nexthop; /* nearest node from us to him */
|
||||
struct node_t *nexthop; /* nearest node from us to him */
|
||||
struct node_t *via; /* next hop for UDP packets */
|
||||
|
||||
avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
|
||||
avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
|
||||
|
||||
avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
|
||||
avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
|
||||
|
||||
struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
|
||||
|
||||
uint32_t sent_seqno; /* Sequence number last sent to this node */
|
||||
uint32_t received_seqno; /* Sequence number last received from this node */
|
||||
unsigned char late[16]; /* Bitfield marking late packets */
|
||||
uint32_t sent_seqno; /* Sequence number last sent to this node */
|
||||
uint32_t received_seqno; /* Sequence number last received from this node */
|
||||
unsigned char late[16]; /* Bitfield marking late packets */
|
||||
|
||||
length_t mtu; /* Maximum size of packets to send to this node */
|
||||
length_t probedmtu; /* Probed MTU */
|
||||
int mtuprobes; /* Number of probes */
|
||||
event_t *mtuevent; /* Probe event */
|
||||
} node_t;
|
||||
|
||||
extern struct node_t *myself;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: protocol_auth.c,v 1.1.4.30 2003/11/17 15:30:18 guus Exp $
|
||||
$Id: protocol_auth.c,v 1.1.4.31 2003/12/20 19:47:52 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -476,6 +476,9 @@ bool send_ack(connection_t *c)
|
|||
if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY)
|
||||
c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
|
||||
|
||||
if((get_config_bool(lookup_config(c->config_tree, "DontFragment"), &choice) && choice) || myself->options & OPTION_DONTFRAGMENT)
|
||||
c->options |= OPTION_DONTFRAGMENT;
|
||||
|
||||
return send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, c->options);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: protocol_key.c,v 1.1.4.24 2003/11/17 15:30:18 guus Exp $
|
||||
$Id: protocol_key.c,v 1.1.4.25 2003/12/20 19:47:53 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -267,6 +267,8 @@ bool ans_key_h(connection_t *c)
|
|||
return false;
|
||||
}
|
||||
|
||||
if(from->options & OPTION_DONTFRAGMENT && !from->mtuprobes)
|
||||
send_mtu_probe(from);
|
||||
|
||||
flush_queue(from);
|
||||
|
||||
|
|
40
src/route.c
40
src/route.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: route.c,v 1.1.2.71 2003/12/13 21:50:26 guus Exp $
|
||||
$Id: route.c,v 1.1.2.72 2003/12/20 19:47:53 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
@ -206,7 +206,7 @@ static __inline__ void route_mac(node_t *source, vpn_packet_t *packet)
|
|||
|
||||
/* RFC 792 */
|
||||
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t code)
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code)
|
||||
{
|
||||
struct ip ip = {0};
|
||||
struct icmp icmp = {0};
|
||||
|
@ -231,6 +231,9 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
|
||||
oldlen = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
||||
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
||||
|
||||
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
||||
oldlen = IP_MSS - ip_size - icmp_size;
|
||||
|
||||
|
@ -256,7 +259,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp.icmp_type = ICMP_DEST_UNREACH;
|
||||
icmp.icmp_type = type;
|
||||
icmp.icmp_code = code;
|
||||
icmp.icmp_cksum = 0;
|
||||
|
||||
|
@ -269,7 +272,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size);
|
||||
|
||||
packet->len = ether_size + ip_size + icmp_size + oldlen;
|
||||
|
||||
|
||||
send_packet(source, packet);
|
||||
}
|
||||
|
||||
|
@ -289,7 +292,7 @@ static __inline__ void route_ipv4_unicast(node_t *source, vpn_packet_t *packet)
|
|||
packet->data[32],
|
||||
packet->data[33]);
|
||||
|
||||
route_ipv4_unreachable(source, packet, ICMP_NET_UNKNOWN);
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -299,7 +302,14 @@ static __inline__ void route_ipv4_unicast(node_t *source, vpn_packet_t *packet)
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
route_ipv4_unreachable(source, packet, ICMP_NET_UNREACH);
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
||||
|
||||
if(subnet->owner->options & OPTION_DONTFRAGMENT && packet->len > subnet->owner->mtu && subnet->owner != myself) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, _("Packet for %s (%s) length %d larger than MTU %d"), subnet->owner->name, subnet->owner->hostname, packet->len, subnet->owner->mtu);
|
||||
packet->len = subnet->owner->mtu;
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||
return;
|
||||
}
|
||||
|
||||
if(priorityinheritance)
|
||||
packet->priority = packet->data[15];
|
||||
|
@ -319,7 +329,7 @@ static __inline__ void route_ipv4(node_t *source, vpn_packet_t *packet)
|
|||
|
||||
/* RFC 2463 */
|
||||
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t code)
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code)
|
||||
{
|
||||
struct ip6_hdr ip6;
|
||||
struct icmp6_hdr icmp6 = {0};
|
||||
|
@ -347,6 +357,9 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
pseudo.ip6_dst = ip6.ip6_src;
|
||||
|
||||
pseudo.length = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP6_PACKET_TOO_BIG)
|
||||
icmp6.icmp6_mtu = htonl(pseudo.length);
|
||||
|
||||
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
||||
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
||||
|
@ -366,7 +379,7 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp6.icmp6_type = ICMP6_DST_UNREACH;
|
||||
icmp6.icmp6_type = type;
|
||||
icmp6.icmp6_code = code;
|
||||
icmp6.icmp6_cksum = 0;
|
||||
|
||||
|
@ -413,7 +426,7 @@ static __inline__ void route_ipv6_unicast(node_t *source, vpn_packet_t *packet)
|
|||
ntohs(*(uint16_t *) &packet->data[50]),
|
||||
ntohs(*(uint16_t *) &packet->data[52]));
|
||||
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH_ADDR);
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -423,8 +436,15 @@ static __inline__ void route_ipv6_unicast(node_t *source, vpn_packet_t *packet)
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH_NOROUTE);
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
||||
|
||||
if(subnet->owner->options & OPTION_DONTFRAGMENT && packet->len > subnet->owner->mtu && subnet->owner != myself) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, _("Packet for %s (%s) length %d larger than MTU %d"), subnet->owner->name, subnet->owner->hostname, packet->len, subnet->owner->mtu);
|
||||
packet->len = subnet->owner->mtu;
|
||||
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
send_packet(subnet->owner, packet);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue