1/* 2 * OpenVPN -- An application to securely tunnel IP networks 3 * over a single TCP/UDP port, with support for SSL/TLS-based 4 * session authentication and key exchange, 5 * packet encryption, packet authentication, and 6 * packet compression. 7 * 8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 12 * as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program (see the file COPYING included with this 21 * distribution); if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#elif defined(_MSC_VER) 28#include "config-msvc.h" 29#endif 30 31#include "syshead.h" 32 33#if P2MP_SERVER 34 35#include "mroute.h" 36#include "proto.h" 37#include "error.h" 38#include "socket.h" 39 40#include "memdbg.h" 41 42void 43mroute_addr_init (struct mroute_addr *addr) 44{ 45 CLEAR (*addr); 46} 47 48/* 49 * Ethernet multicast addresses. 50 */ 51 52static inline bool 53is_mac_mcast_addr (const uint8_t *mac) 54{ 55 return (bool) (mac[0] & 1); 56} 57 58static inline bool 59is_mac_mcast_maddr (const struct mroute_addr *addr) 60{ 61 return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr); 62} 63 64/* 65 * Don't learn certain addresses. 66 */ 67bool 68mroute_learnable_address (const struct mroute_addr *addr) 69{ 70 int i; 71 bool not_all_zeros = false; 72 bool not_all_ones = false; 73 74 for (i = 0; i < addr->len; ++i) 75 { 76 int b = addr->addr[i]; 77 if (b != 0x00) 78 not_all_zeros = true; 79 if (b != 0xFF) 80 not_all_ones = true; 81 } 82 return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr); 83} 84 85static inline void 86mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask) 87{ 88 if (ma) 89 { 90 ma->type = MR_ADDR_IPV4 | mask; 91 ma->netbits = 0; 92 ma->len = 4; 93 *(in_addr_t*)ma->addr = src; 94 } 95} 96 97static inline void 98mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask) 99{ 100 if (ma) 101 { 102 ma->type = MR_ADDR_IPV6 | mask; 103 ma->netbits = 0; 104 ma->len = 16; 105 *(struct in6_addr *)ma->addr = src; 106 } 107} 108 109static inline bool 110mroute_is_mcast (const in_addr_t addr) 111{ 112 return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK)); 113} 114 115/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies 116 * the address as being a multicast address" 117 */ 118static inline bool 119mroute_is_mcast_ipv6 (const struct in6_addr addr) 120{ 121 return (addr.s6_addr[0] == 0xff); 122} 123 124#ifdef ENABLE_PF 125 126static unsigned int 127mroute_extract_addr_arp (struct mroute_addr *src, 128 struct mroute_addr *dest, 129 const struct buffer *buf) 130{ 131 unsigned int ret = 0; 132 if (BLEN (buf) >= (int) sizeof (struct openvpn_arp)) 133 { 134 const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf); 135 if (arp->mac_addr_type == htons(0x0001) 136 && arp->proto_addr_type == htons(0x0800) 137 && arp->mac_addr_size == 0x06 138 && arp->proto_addr_size == 0x04) 139 { 140 mroute_get_in_addr_t (src, arp->ip_src, MR_ARP); 141 mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP); 142 143 /* multicast packet? */ 144 if (mroute_is_mcast (arp->ip_dest)) 145 ret |= MROUTE_EXTRACT_MCAST; 146 147 ret |= MROUTE_EXTRACT_SUCCEEDED; 148 } 149 } 150 return ret; 151} 152 153#endif 154 155unsigned int 156mroute_extract_addr_ipv4 (struct mroute_addr *src, 157 struct mroute_addr *dest, 158 const struct buffer *buf) 159{ 160 unsigned int ret = 0; 161 if (BLEN (buf) >= 1) 162 { 163 switch (OPENVPN_IPH_GET_VER (*BPTR(buf))) 164 { 165 case 4: 166 if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr)) 167 { 168 const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf); 169 170 mroute_get_in_addr_t (src, ip->saddr, 0); 171 mroute_get_in_addr_t (dest, ip->daddr, 0); 172 173 /* multicast packet? */ 174 if (mroute_is_mcast (ip->daddr)) 175 ret |= MROUTE_EXTRACT_MCAST; 176 177 /* IGMP message? */ 178 if (ip->protocol == OPENVPN_IPPROTO_IGMP) 179 ret |= MROUTE_EXTRACT_IGMP; 180 181 ret |= MROUTE_EXTRACT_SUCCEEDED; 182 } 183 break; 184 case 6: 185 if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr)) 186 { 187 const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf); 188#if 0 /* very basic debug */ 189 struct gc_arena gc = gc_new (); 190 msg( M_INFO, "IPv6 packet! src=%s, dst=%s", 191 print_in6_addr( ipv6->saddr, 0, &gc ), 192 print_in6_addr( ipv6->daddr, 0, &gc )); 193 gc_free (&gc); 194#endif 195 196 mroute_get_in6_addr (src, ipv6->saddr, 0); 197 mroute_get_in6_addr (dest, ipv6->daddr, 0); 198 199 if (mroute_is_mcast_ipv6 (ipv6->daddr)) 200 ret |= MROUTE_EXTRACT_MCAST; 201 202 ret |= MROUTE_EXTRACT_SUCCEEDED; 203 } 204 break; 205 default: 206 msg (M_WARN, "IP packet with unknown IP version=%d seen", 207 OPENVPN_IPH_GET_VER (*BPTR(buf))); 208 } 209 } 210 return ret; 211} 212 213unsigned int 214mroute_extract_addr_ether (struct mroute_addr *src, 215 struct mroute_addr *dest, 216 struct mroute_addr *esrc, 217 struct mroute_addr *edest, 218 const struct buffer *buf) 219{ 220 unsigned int ret = 0; 221 if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr)) 222 { 223 const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf); 224 if (src) 225 { 226 src->type = MR_ADDR_ETHER; 227 src->netbits = 0; 228 src->len = 6; 229 memcpy (src->addr, eth->source, 6); 230 } 231 if (dest) 232 { 233 dest->type = MR_ADDR_ETHER; 234 dest->netbits = 0; 235 dest->len = 6; 236 memcpy (dest->addr, eth->dest, 6); 237 238 /* ethernet broadcast/multicast packet? */ 239 if (is_mac_mcast_addr (eth->dest)) 240 ret |= MROUTE_EXTRACT_BCAST; 241 } 242 243 ret |= MROUTE_EXTRACT_SUCCEEDED; 244 245#ifdef ENABLE_PF 246 if (esrc || edest) 247 { 248 struct buffer b = *buf; 249 if (buf_advance (&b, sizeof (struct openvpn_ethhdr))) 250 { 251 switch (ntohs (eth->proto)) 252 { 253 case OPENVPN_ETH_P_IPV4: 254 ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT); 255 break; 256 case OPENVPN_ETH_P_ARP: 257 ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT); 258 break; 259 } 260 } 261 } 262#endif 263 } 264 return ret; 265} 266 267/* 268 * Translate a struct openvpn_sockaddr (osaddr) 269 * to a struct mroute_addr (addr). 270 */ 271bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr, 272 const struct openvpn_sockaddr *osaddr, 273 bool use_port) 274{ 275 switch (osaddr->addr.sa.sa_family) 276 { 277 case AF_INET: 278 { 279 if (use_port) 280 { 281 addr->type = MR_ADDR_IPV4 | MR_WITH_PORT; 282 addr->netbits = 0; 283 addr->len = 6; 284 memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4); 285 memcpy (addr->addr + 4, &osaddr->addr.in4.sin_port, 2); 286 } 287 else 288 { 289 addr->type = MR_ADDR_IPV4; 290 addr->netbits = 0; 291 addr->len = 4; 292 memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4); 293 } 294 return true; 295 } 296 case AF_INET6: 297 if (use_port) 298 { 299 addr->type = MR_ADDR_IPV6 | MR_WITH_PORT; 300 addr->netbits = 0; 301 addr->len = 18; 302 memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16); 303 memcpy (addr->addr + 16, &osaddr->addr.in6.sin6_port, 2); 304 } 305 else 306 { 307 addr->type = MR_ADDR_IPV6; 308 addr->netbits = 0; 309 addr->len = 16; 310 memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16); 311 } 312 return true; 313 } 314 return false; 315} 316 317/* 318 * Zero off the host bits in an address, leaving 319 * only the network bits, using the netbits member of 320 * struct mroute_addr as the controlling parameter. 321 * 322 * TODO: this is called for route-lookup for every yet-unhashed 323 * destination address, so for lots of active net-iroutes, this 324 * might benefit from some "zeroize 32 bit at a time" improvements 325 */ 326void 327mroute_addr_mask_host_bits (struct mroute_addr *ma) 328{ 329 in_addr_t addr = ntohl(*(in_addr_t*)ma->addr); 330 if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4) 331 { 332 addr &= netbits_to_netmask (ma->netbits); 333 *(in_addr_t*)ma->addr = htonl (addr); 334 } 335 else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6) 336 { 337 int byte = ma->len-1; /* rightmost byte in address */ 338 int bits_to_clear = 128 - ma->netbits; 339 340 while( byte >= 0 && bits_to_clear > 0 ) 341 { 342 if ( bits_to_clear >= 8 ) 343 { ma->addr[byte--] = 0; bits_to_clear -= 8; } 344 else 345 { ma->addr[byte--] &= (IPV4_NETMASK_HOST << bits_to_clear); bits_to_clear = 0; } 346 } 347 ASSERT( bits_to_clear == 0 ); 348 } 349 else 350 ASSERT(0); 351} 352 353/* 354 * The mroute_addr hash function takes into account the 355 * address type, number of bits in the network address, 356 * and the actual address. 357 */ 358uint32_t 359mroute_addr_hash_function (const void *key, uint32_t iv) 360{ 361 return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key), 362 mroute_addr_hash_len ((const struct mroute_addr *) key), 363 iv); 364} 365 366bool 367mroute_addr_compare_function (const void *key1, const void *key2) 368{ 369 return mroute_addr_equal ((const struct mroute_addr *) key1, 370 (const struct mroute_addr *) key2); 371} 372 373const char * 374mroute_addr_print (const struct mroute_addr *ma, 375 struct gc_arena *gc) 376{ 377 return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc); 378} 379 380const char * 381mroute_addr_print_ex (const struct mroute_addr *ma, 382 const unsigned int flags, 383 struct gc_arena *gc) 384{ 385 struct buffer out = alloc_buf_gc (64, gc); 386 if (ma) 387 { 388 struct mroute_addr maddr = *ma; 389 390 switch (maddr.type & MR_ADDR_MASK) 391 { 392 case MR_ADDR_ETHER: 393 buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 394 break; 395 case MR_ADDR_IPV4: 396 { 397 struct buffer buf; 398 in_addr_t addr; 399 int port; 400 bool status; 401 buf_set_read (&buf, maddr.addr, maddr.len); 402 addr = buf_read_u32 (&buf, &status); 403 if (status) 404 { 405 if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP)) 406 buf_printf (&out, "ARP/"); 407 buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc)); 408 if (maddr.type & MR_WITH_NETBITS) 409 { 410 if (flags & MAPF_SUBNET) 411 { 412 const in_addr_t netmask = netbits_to_netmask (maddr.netbits); 413 buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc)); 414 } 415 else 416 buf_printf (&out, "/%d", maddr.netbits); 417 } 418 } 419 if (maddr.type & MR_WITH_PORT) 420 { 421 port = buf_read_u16 (&buf); 422 if (port >= 0) 423 buf_printf (&out, ":%d", port); 424 } 425 } 426 break; 427 case MR_ADDR_IPV6: 428 { 429 buf_printf (&out, "%s", 430 print_in6_addr( *(struct in6_addr*)&maddr.addr, 0, gc)); 431 if (maddr.type & MR_WITH_NETBITS) 432 { 433 buf_printf (&out, "/%d", maddr.netbits); 434 } 435 } 436 break; 437 default: 438 buf_printf (&out, "UNKNOWN"); 439 break; 440 } 441 return BSTR (&out); 442 } 443 else 444 return "[NULL]"; 445 } 446 447/* 448 * mroute_helper's main job is keeping track of 449 * currently used CIDR netlengths, so we don't 450 * have to cycle through all 33. 451 */ 452 453struct mroute_helper * 454mroute_helper_init (int ageable_ttl_secs) 455{ 456 struct mroute_helper *mh; 457 ALLOC_OBJ_CLEAR (mh, struct mroute_helper); 458 mh->ageable_ttl_secs = ageable_ttl_secs; 459 return mh; 460} 461 462static void 463mroute_helper_regenerate (struct mroute_helper *mh) 464{ 465 int i, j = 0; 466 for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i) 467 { 468 if (mh->net_len_refcount[i] > 0) 469 mh->net_len[j++] = (uint8_t) i; 470 } 471 mh->n_net_len = j; 472 473#ifdef ENABLE_DEBUG 474 if (check_debug_level (D_MULTI_DEBUG)) 475 { 476 struct gc_arena gc = gc_new (); 477 struct buffer out = alloc_buf_gc (256, &gc); 478 buf_printf (&out, "MROUTE CIDR netlen:"); 479 for (i = 0; i < mh->n_net_len; ++i) 480 { 481 buf_printf (&out, " /%d", mh->net_len[i]); 482 } 483 dmsg (D_MULTI_DEBUG, "%s", BSTR (&out)); 484 gc_free (&gc); 485 } 486#endif 487} 488 489void 490mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir) 491{ 492 if (ir->netbits >= 0) 493 { 494 ASSERT (ir->netbits < MR_HELPER_NET_LEN); 495 ++mh->cache_generation; 496 ++mh->net_len_refcount[ir->netbits]; 497 if (mh->net_len_refcount[ir->netbits] == 1) 498 mroute_helper_regenerate (mh); 499 } 500} 501 502void 503mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir) 504{ 505 if (ir->netbits >= 0) 506 { 507 ASSERT (ir->netbits < MR_HELPER_NET_LEN); 508 ++mh->cache_generation; 509 --mh->net_len_refcount[ir->netbits]; 510 ASSERT (mh->net_len_refcount[ir->netbits] >= 0); 511 if (!mh->net_len_refcount[ir->netbits]) 512 mroute_helper_regenerate (mh); 513 } 514} 515 516/* this is a bit inelegant, we really should have a helper to that 517 * is only passed the netbits value, and not the whole struct iroute * 518 * - thus one helper could do IPv4 and IPv6. For the sake of "not change 519 * code unrelated to IPv4" this is left for later cleanup, for now. 520 */ 521void 522mroute_helper_add_iroute6 (struct mroute_helper *mh, 523 const struct iroute_ipv6 *ir6) 524{ 525 if (ir6->netbits >= 0) 526 { 527 ASSERT (ir6->netbits < MR_HELPER_NET_LEN); 528 ++mh->cache_generation; 529 ++mh->net_len_refcount[ir6->netbits]; 530 if (mh->net_len_refcount[ir6->netbits] == 1) 531 mroute_helper_regenerate (mh); 532 } 533} 534 535void 536mroute_helper_del_iroute6 (struct mroute_helper *mh, 537 const struct iroute_ipv6 *ir6) 538{ 539 if (ir6->netbits >= 0) 540 { 541 ASSERT (ir6->netbits < MR_HELPER_NET_LEN); 542 ++mh->cache_generation; 543 --mh->net_len_refcount[ir6->netbits]; 544 ASSERT (mh->net_len_refcount[ir6->netbits] >= 0); 545 if (!mh->net_len_refcount[ir6->netbits]) 546 mroute_helper_regenerate (mh); 547 } 548} 549 550void 551mroute_helper_free (struct mroute_helper *mh) 552{ 553 free (mh); 554} 555 556#else 557static void dummy(void) {} 558#endif /* P2MP_SERVER */ 559