/*
route.c -- routing
Copyright (C) 2000-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2018 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "protocol.h"
#include "route.h"
#include "subnet.h"
-#include "utils.h"
rmode_t routing_mode = RMODE_ROUTER;
fmode_t forwarding_mode = FMODE_INTERNAL;
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
-volatile int dummy;
static timeout_t age_subnets_timeout;
/* RFC 1071 */
-static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
- uint16_t *p = data;
+static uint16_t inet_checksum(void *vdata, size_t len, uint16_t prevsum) {
+ uint8_t *data = vdata;
+ uint16_t word;
uint32_t checksum = prevsum ^ 0xFFFF;
while(len >= 2) {
- checksum += *p++;
+ memcpy(&word, data, sizeof(word));
+ checksum += word;
+ data += 2;
len -= 2;
}
if(len) {
- checksum += *(uint8_t *)p;
+ checksum += *data;
}
while(checksum >> 16) {
checksum = (checksum & 0xFFFF) + (checksum >> 16);
}
- // Work around a compiler optimization bug.
- if(checksum) {
- dummy = 1;
- }
-
- return ~checksum;
+ return (uint16_t) ~checksum;
}
static bool ratelimit(int frequency) {
addr.sin_family = AF_INET;
socklen_t addrlen = sizeof(addr);
- if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
+ if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && (size_t)addrlen <= sizeof(addr)) {
ip_dst = addr.sin_addr;
}
}
ip.ip_src = ip_dst;
ip.ip_dst = ip_src;
- ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
+ ip.ip_sum = inet_checksum(&ip, ip_size, 0xFFFF);
/* Fill in ICMP header */
icmp.icmp_code = code;
icmp.icmp_cksum = 0;
- icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
+ icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, 0xFFFF);
icmp.icmp_cksum = inet_checksum(DATA(packet) + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
/* Copy structs on stack back to packet */
addr.sin6_family = AF_INET6;
socklen_t addrlen = sizeof(addr);
- if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
+ if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && (size_t)addrlen <= sizeof(addr)) {
pseudo.ip6_src = addr.sin6_addr;
}
}
/* Generate checksum */
- checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
+ checksum = inet_checksum(&pseudo, sizeof(pseudo), 0xFFFF);
checksum = inet_checksum(&icmp6, icmp6_size, checksum);
checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
}
/* Find TCP header */
- int start = ether_size;
+ size_t start = ether_size;
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
if(type == ETH_P_8021Q) {
(void)data;
bool left = false;
- for splay_each(subnet_t, s, myself->subnet_tree) {
+ for splay_each(subnet_t, s, &myself->subnet_tree) {
if(s->expires && s->expires < now.tv_sec) {
if(debug_level >= DEBUG_TRAFFIC) {
char netstr[MAXNETSTR];
}
}
- for list_each(connection_t, c, connection_list)
+ for list_each(connection_t, c, &connection_list)
if(c->edge) {
send_del_subnet(c, s);
}
/* And tell all other tinc daemons it's our MAC */
- for list_each(connection_t, c, connection_list)
+ for list_each(connection_t, c, &connection_list)
if(c->edge) {
send_add_subnet(c, subnet);
}
static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) {
struct ip ip;
vpn_packet_t fragment;
- int maxlen, todo;
+ size_t maxlen, todo;
uint8_t *offset;
uint16_t ip_off, origf;
todo = ntohs(ip.ip_len) - ip_size;
if(ether_size + ip_size + todo != packet->len) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%d)", packet->len, (int)(ether_size + ip_size + todo));
+ logger(DEBUG_TRAFFIC, LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%zu)", packet->len, ether_size + ip_size + todo);
return;
}
ip_off &= IP_OFFMASK;
while(todo) {
- int len = todo > maxlen ? maxlen : todo;
+ size_t len = todo > maxlen ? maxlen : todo;
memcpy(DATA(&fragment) + ether_size + ip_size, offset, len);
todo -= len;
offset += len;
ip.ip_len = htons(ip_size + len);
ip.ip_off = htons(ip_off | origf | (todo ? IP_MF : 0));
ip.ip_sum = 0;
- ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
+ ip.ip_sum = inet_checksum(&ip, ip_size, 0xFFFF);
memcpy(DATA(&fragment), DATA(packet), ether_size);
memcpy(DATA(&fragment) + ether_size, &ip, ip_size);
fragment.len = ether_size + ip_size + len;
/* Generate checksum */
- checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
+ checksum = inet_checksum(&pseudo, sizeof(pseudo), 0xFFFF);
checksum = inet_checksum(&ns, ns_size, checksum);
if(has_opt) {
/* Generate checksum */
- checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
+ checksum = inet_checksum(&pseudo, sizeof(pseudo), 0xFFFF);
checksum = inet_checksum(&ns, ns_size, checksum);
if(has_opt) {
static void send_pcap(vpn_packet_t *packet) {
pcap = false;
- for list_each(connection_t, c, connection_list) {
+ for list_each(connection_t, c, &connection_list) {
if(!c->status.pcap) {
continue;
}
}
if(send_request(c, "%d %d %d", CONTROL, REQ_PCAP, len)) {
- send_meta(c, (char *)DATA(packet), len);
+ send_meta(c, DATA(packet), len);
}
}
}