big svn cleanup
[anytun.git] / src / openvpn / mroute.c
blob0a7bcf638c43e182e52f9db25224371a8920e2f1
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.
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
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.
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.
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
25 #ifdef WIN32
26 #include "config-win32.h"
27 #else
28 #include "config.h"
29 #endif
31 #include "syshead.h"
33 #if P2MP_SERVER
35 #include "mroute.h"
36 #include "proto.h"
37 #include "error.h"
38 #include "socket.h"
40 #include "memdbg.h"
42 void
43 mroute_addr_init (struct mroute_addr *addr)
45 CLEAR (*addr);
49 * Ethernet multicast addresses.
52 static inline bool
53 is_mac_mcast_addr (const uint8_t *mac)
55 return (bool) mac[0] & 1;
58 static inline bool
59 is_mac_mcast_maddr (const struct mroute_addr *addr)
61 return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr);
65 * Don't learn certain addresses.
67 bool
68 mroute_learnable_address (const struct mroute_addr *addr)
70 int i;
71 bool not_all_zeros = false;
72 bool not_all_ones = false;
74 for (i = 0; i < addr->len; ++i)
76 int b = addr->addr[i];
77 if (b != 0x00)
78 not_all_zeros = true;
79 if (b != 0xFF)
80 not_all_ones = true;
82 return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
86 * Given a raw packet in buf, return the src and dest
87 * addresses of the packet.
89 unsigned int
90 mroute_extract_addr_from_packet (struct mroute_addr *src,
91 struct mroute_addr *dest,
92 struct buffer *buf,
93 int tunnel_type)
95 unsigned int ret = 0;
96 verify_align_4 (buf);
97 if (tunnel_type == DEV_TYPE_TUN)
99 if (BLEN (buf) >= 1)
101 switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
103 case 4:
104 if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
106 const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
107 if (src)
109 src->type = MR_ADDR_IPV4;
110 src->netbits = 0;
111 src->len = 4;
112 memcpy (src->addr, &ip->saddr, 4);
114 if (dest)
116 dest->type = MR_ADDR_IPV4;
117 dest->netbits = 0;
118 dest->len = 4;
119 memcpy (dest->addr, &ip->daddr, 4);
121 /* mcast address? */
122 if ((ip->daddr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK))
123 ret |= MROUTE_EXTRACT_MCAST;
125 /* IGMP message? */
126 if (ip->protocol == OPENVPN_IPPROTO_IGMP)
127 ret |= MROUTE_EXTRACT_IGMP;
129 ret |= MROUTE_EXTRACT_SUCCEEDED;
131 break;
132 case 6:
134 msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet");
135 break;
140 else if (tunnel_type == DEV_TYPE_TAP)
142 if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
144 const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
145 if (src)
147 src->type = MR_ADDR_ETHER;
148 src->netbits = 0;
149 src->len = 6;
150 memcpy (src->addr, eth->source, 6);
152 if (dest)
154 dest->type = MR_ADDR_ETHER;
155 dest->netbits = 0;
156 dest->len = 6;
157 memcpy (dest->addr, eth->dest, 6);
159 /* ethernet broadcast/multicast packet? */
160 if (is_mac_mcast_addr (eth->dest))
161 ret |= MROUTE_EXTRACT_BCAST;
164 ret |= MROUTE_EXTRACT_SUCCEEDED;
167 return ret;
171 * Translate a struct sockaddr_in (saddr)
172 * to a struct mroute_addr (addr).
174 bool
175 mroute_extract_sockaddr_in (struct mroute_addr *addr, const struct sockaddr_in *saddr, bool use_port)
177 if (saddr->sin_family == AF_INET)
179 if (use_port)
181 addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
182 addr->netbits = 0;
183 addr->len = 6;
184 memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
185 memcpy (addr->addr + 4, &saddr->sin_port, 2);
187 else
189 addr->type = MR_ADDR_IPV4;
190 addr->netbits = 0;
191 addr->len = 4;
192 memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
194 return true;
196 return false;
200 * Zero off the host bits in an address, leaving
201 * only the network bits, using the netbits member of
202 * struct mroute_addr as the controlling parameter.
204 void
205 mroute_addr_mask_host_bits (struct mroute_addr *ma)
207 in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
208 ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
209 addr &= netbits_to_netmask (ma->netbits);
210 *(in_addr_t*)ma->addr = htonl (addr);
214 * The mroute_addr hash function takes into account the
215 * address type, number of bits in the network address,
216 * and the actual address.
218 uint32_t
219 mroute_addr_hash_function (const void *key, uint32_t iv)
221 return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key),
222 mroute_addr_hash_len ((const struct mroute_addr *) key),
223 iv);
226 bool
227 mroute_addr_compare_function (const void *key1, const void *key2)
229 return mroute_addr_equal ((const struct mroute_addr *) key1,
230 (const struct mroute_addr *) key2);
233 const char *
234 mroute_addr_print (const struct mroute_addr *ma,
235 struct gc_arena *gc)
237 struct buffer out = alloc_buf_gc (64, gc);
238 if (ma)
240 struct mroute_addr maddr = *ma;
242 switch (maddr.type & MR_ADDR_MASK)
244 case MR_ADDR_ETHER:
245 buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc));
246 break;
247 case MR_ADDR_IPV4:
249 struct buffer buf;
250 in_addr_t addr;
251 int port;
252 bool status;
253 buf_set_read (&buf, maddr.addr, maddr.len);
254 addr = buf_read_u32 (&buf, &status);
255 if (status)
257 buf_printf (&out, "%s", print_in_addr_t (addr, IA_EMPTY_IF_UNDEF, gc));
258 if (maddr.type & MR_WITH_NETBITS)
259 buf_printf (&out, "/%d", maddr.netbits);
261 if (maddr.type & MR_WITH_PORT)
263 port = buf_read_u16 (&buf);
264 if (port >= 0)
265 buf_printf (&out, ":%d", port);
268 break;
269 case MR_ADDR_IPV6:
270 buf_printf (&out, "IPV6");
271 break;
272 default:
273 buf_printf (&out, "UNKNOWN");
274 break;
276 return BSTR (&out);
278 else
279 return "[NULL]";
283 * mroute_helper's main job is keeping track of
284 * currently used CIDR netlengths, so we don't
285 * have to cycle through all 33.
288 struct mroute_helper *
289 mroute_helper_init (int ageable_ttl_secs)
291 struct mroute_helper *mh;
292 ALLOC_OBJ_CLEAR (mh, struct mroute_helper);
293 /*mutex_init (&mh->mutex);*/
294 mh->ageable_ttl_secs = ageable_ttl_secs;
295 return mh;
298 static void
299 mroute_helper_regenerate (struct mroute_helper *mh)
301 int i, j = 0;
302 for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
304 if (mh->net_len_refcount[i] > 0)
305 mh->net_len[j++] = (uint8_t) i;
307 mh->n_net_len = j;
309 #ifdef ENABLE_DEBUG
310 if (check_debug_level (D_MULTI_DEBUG))
312 struct gc_arena gc = gc_new ();
313 struct buffer out = alloc_buf_gc (256, &gc);
314 buf_printf (&out, "MROUTE CIDR netlen:");
315 for (i = 0; i < mh->n_net_len; ++i)
317 buf_printf (&out, " /%d", mh->net_len[i]);
319 dmsg (D_MULTI_DEBUG, "%s", BSTR (&out));
320 gc_free (&gc);
322 #endif
325 void
326 mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir)
328 if (ir->netbits >= 0)
330 ASSERT (ir->netbits < MR_HELPER_NET_LEN);
331 mroute_helper_lock (mh);
332 ++mh->cache_generation;
333 ++mh->net_len_refcount[ir->netbits];
334 if (mh->net_len_refcount[ir->netbits] == 1)
335 mroute_helper_regenerate (mh);
336 mroute_helper_unlock (mh);
340 void
341 mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
343 if (ir->netbits >= 0)
345 ASSERT (ir->netbits < MR_HELPER_NET_LEN);
346 mroute_helper_lock (mh);
347 ++mh->cache_generation;
348 --mh->net_len_refcount[ir->netbits];
349 ASSERT (mh->net_len_refcount[ir->netbits] >= 0);
350 if (!mh->net_len_refcount[ir->netbits])
351 mroute_helper_regenerate (mh);
352 mroute_helper_unlock (mh);
356 void
357 mroute_helper_free (struct mroute_helper *mh)
359 /*mutex_destroy (&mh->mutex);*/
360 free (mh);
363 #else
364 static void dummy(void) {}
365 #endif /* P2MP_SERVER */