/*
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
/* 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);
}
- 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) {
}
static void age_subnets(void *data) {
+ (void)data;
bool left = false;
for splay_each(subnet_t, s, myself->subnet_tree) {
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;
logger(DEBUG_TRAFFIC, LOG_INFO, "Fragmenting packet of %d bytes to %s (%s)", packet->len, dest->name, dest->hostname);
offset = DATA(packet) + ether_size + ip_size;
- maxlen = (dest->mtu - ether_size - ip_size) & ~0x7;
+ maxlen = (MAX(dest->mtu, 590) - ether_size - ip_size) & ~0x7;
ip_off = ntohs(ip.ip_off);
origf = ip_off & ~IP_OFFMASK;
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) {
memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
DATA(packet)[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
- ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
+ ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocol address */
ip6.ip6_src = ns.nd_ns_target;
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) {