X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet_packet.c;h=64b0f8e8490adb7d5f0a06c2c99f6fcf39db2e64;hb=f5dc136cfd7a3a195b75f7174722734e25f30fd9;hp=3627f31d317bfcc122269b0a84a9eff6327900d5;hpb=365f60f3f8a8ff85a616d5014d555b470740d395;p=meshlink diff --git a/src/net_packet.c b/src/net_packet.c index 3627f31d..64b0f8e8 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -62,13 +62,21 @@ static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999 static void send_udppacket(node_t *, vpn_packet_t *); unsigned replaywin = 16; +bool localdiscovery = false; #define MAX_SEQNO 1073741824 -// mtuprobes == 1..30: initial discovery, send bursts with 1 second interval -// mtuprobes == 31: sleep pinginterval seconds -// mtuprobes == 32: send 1 burst, sleep pingtimeout second -// mtuprobes == 33: no response from other side, restart PMTU discovery process +/* mtuprobes == 1..30: initial discovery, send bursts with 1 second interval + mtuprobes == 31: sleep pinginterval seconds + mtuprobes == 32: send 1 burst, sleep pingtimeout second + mtuprobes == 33: no response from other side, restart PMTU discovery process + + Probes are sent in batches of three, with random sizes between the lower and + upper boundaries for the MTU thus far discovered. + + In case local discovery is enabled, a fourth packet is added to each batch, + which will be broadcast to the local network. +*/ static void send_mtu_probe_handler(int fd, short events, void *data) { node_t *n = data; @@ -119,7 +127,7 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { timeout = pingtimeout; } - for(i = 0; i < 3; i++) { + for(i = 0; i < 3 + localdiscovery; i++) { if(n->maxmtu <= n->minmtu) len = n->maxmtu; else @@ -131,7 +139,7 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { memset(packet.data, 0, 14); randomize(packet.data + 14, len - 14); packet.len = len; - packet.priority = 0; + packet.priority = i < 3 ? 0 : -1; ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); @@ -381,7 +389,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { static int priority = 0; int origpriority = origpkt->priority; #endif - int sock; if(!n->status.reachable) { ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname); @@ -463,26 +470,51 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { /* Determine which socket we have to use */ - for(sock = 0; sock < listen_sockets; sock++) - if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) - break; - - if(sock >= listen_sockets) - sock = 0; /* If none is available, just use the first and hope for the best. */ + if(n->address.sa.sa_family != listen_socket[n->sock].sa.sa.sa_family) { + for(int sock = 0; sock < listen_sockets; sock++) { + if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) { + n->sock = sock; + break; + } + } + } /* Send the packet */ + struct sockaddr *sa; + socklen_t sl; + int sock; + + /* Overloaded use of priority field: -1 means local broadcast */ + + if(origpriority == -1 && n->prevedge) { + struct sockaddr_in in; + in.sin_family = AF_INET; + in.sin_addr.s_addr = -1; + in.sin_port = n->prevedge->address.in.sin_port; + sa = (struct sockaddr *)∈ + sl = sizeof in; + sock = 0; + } else { + if(origpriority == -1) + origpriority = 0; + + sa = &(n->address.sa); + sl = SALEN(n->address.sa); + sock = n->sock; + } + #if defined(SOL_IP) && defined(IP_TOS) if(priorityinheritance && origpriority != priority - && listen_socket[sock].sa.sa.sa_family == AF_INET) { + && listen_socket[n->sock].sa.sa.sa_family == AF_INET) { priority = origpriority; ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting outgoing packet priority to %d", priority); - if(setsockopt(listen_socket[sock].udp, SOL_IP, IP_TOS, &priority, sizeof priority)) /* SO_PRIORITY doesn't seem to work */ + if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); } #endif - if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(n->maxmtu >= origlen) n->maxmtu = origlen - 1; @@ -507,7 +539,7 @@ void send_packet(node_t *n, vpn_packet_t *packet) { memcpy(packet->data, mymac.x, ETH_ALEN); n->out_packets++; n->out_bytes += packet->len; - write_packet(packet); + devops.write(packet); return; } @@ -570,11 +602,6 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { static time_t last_hard_try = 0; time_t now = time(NULL); - if(last_hard_try == now) - return NULL; - else - last_hard_try = now; - for(node = edge_weight_tree->head; node; node = node->next) { e = node->data; @@ -597,6 +624,7 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { if(hard) last_hard_try = now; + last_hard_try = now; return n; } @@ -636,6 +664,8 @@ void handle_incoming_vpn_data(int sock, short events, void *data) { return; } + n->sock = (intptr_t)data; + receive_udppacket(n, &pkt); } @@ -644,7 +674,7 @@ void handle_device_data(int sock, short events, void *data) { packet.priority = 0; - if(read_packet(&packet)) { + if(devops.read(&packet)) { myself->in_packets++; myself->in_bytes += packet.len; route(myself, &packet);