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
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@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
37 mroute_addr_init (struct mroute_addr
*addr
)
43 * Ethernet multicast addresses.
47 is_mac_mcast_addr (const uint8_t *mac
)
49 return (bool) mac
[0] & 1;
53 is_mac_mcast_maddr (const struct mroute_addr
*addr
)
55 return (addr
->type
& MR_ADDR_MASK
) == MR_ADDR_ETHER
&& is_mac_mcast_addr (addr
->addr
);
59 * Don't learn certain addresses.
62 mroute_learnable_address (const struct mroute_addr
*addr
)
65 bool not_all_zeros
= false;
66 bool not_all_ones
= false;
68 for (i
= 0; i
< addr
->len
; ++i
)
70 int b
= addr
->addr
[i
];
76 return not_all_zeros
&& not_all_ones
&& !is_mac_mcast_maddr (addr
);
80 mroute_get_in_addr_t (struct mroute_addr
*ma
, const in_addr_t src
, unsigned int mask
)
84 ma
->type
= MR_ADDR_IPV4
| mask
;
87 *(in_addr_t
*)ma
->addr
= src
;
92 mroute_is_mcast (const in_addr_t addr
)
94 return ((addr
& htonl(IP_MCAST_SUBNET_MASK
)) == htonl(IP_MCAST_NETWORK
));
100 mroute_extract_addr_arp (struct mroute_addr
*src
,
101 struct mroute_addr
*dest
,
102 const struct buffer
*buf
)
104 unsigned int ret
= 0;
105 if (BLEN (buf
) >= (int) sizeof (struct openvpn_arp
))
107 const struct openvpn_arp
*arp
= (const struct openvpn_arp
*) BPTR (buf
);
108 if (arp
->mac_addr_type
== htons(0x0001)
109 && arp
->proto_addr_type
== htons(0x0800)
110 && arp
->mac_addr_size
== 0x06
111 && arp
->proto_addr_size
== 0x04)
113 mroute_get_in_addr_t (src
, arp
->ip_src
, MR_ARP
);
114 mroute_get_in_addr_t (dest
, arp
->ip_dest
, MR_ARP
);
116 /* multicast packet? */
117 if (mroute_is_mcast (arp
->ip_dest
))
118 ret
|= MROUTE_EXTRACT_MCAST
;
120 ret
|= MROUTE_EXTRACT_SUCCEEDED
;
129 mroute_extract_addr_ipv4 (struct mroute_addr
*src
,
130 struct mroute_addr
*dest
,
131 const struct buffer
*buf
)
133 unsigned int ret
= 0;
136 switch (OPENVPN_IPH_GET_VER (*BPTR(buf
)))
139 if (BLEN (buf
) >= (int) sizeof (struct openvpn_iphdr
))
141 const struct openvpn_iphdr
*ip
= (const struct openvpn_iphdr
*) BPTR (buf
);
143 mroute_get_in_addr_t (src
, ip
->saddr
, 0);
144 mroute_get_in_addr_t (dest
, ip
->daddr
, 0);
146 /* multicast packet? */
147 if (mroute_is_mcast (ip
->daddr
))
148 ret
|= MROUTE_EXTRACT_MCAST
;
151 if (ip
->protocol
== OPENVPN_IPPROTO_IGMP
)
152 ret
|= MROUTE_EXTRACT_IGMP
;
154 ret
|= MROUTE_EXTRACT_SUCCEEDED
;
159 msg (M_WARN
, "Need IPv6 code in mroute_extract_addr_from_packet");
168 mroute_extract_addr_ether (struct mroute_addr
*src
,
169 struct mroute_addr
*dest
,
170 struct mroute_addr
*esrc
,
171 struct mroute_addr
*edest
,
172 const struct buffer
*buf
)
174 unsigned int ret
= 0;
175 if (BLEN (buf
) >= (int) sizeof (struct openvpn_ethhdr
))
177 const struct openvpn_ethhdr
*eth
= (const struct openvpn_ethhdr
*) BPTR (buf
);
180 src
->type
= MR_ADDR_ETHER
;
183 memcpy (src
->addr
, eth
->source
, 6);
187 dest
->type
= MR_ADDR_ETHER
;
190 memcpy (dest
->addr
, eth
->dest
, 6);
192 /* ethernet broadcast/multicast packet? */
193 if (is_mac_mcast_addr (eth
->dest
))
194 ret
|= MROUTE_EXTRACT_BCAST
;
197 ret
|= MROUTE_EXTRACT_SUCCEEDED
;
202 struct buffer b
= *buf
;
203 if (buf_advance (&b
, sizeof (struct openvpn_ethhdr
)))
205 switch (ntohs (eth
->proto
))
207 case OPENVPN_ETH_P_IPV4
:
208 ret
|= (mroute_extract_addr_ipv4 (esrc
, edest
, &b
) << MROUTE_SEC_SHIFT
);
210 case OPENVPN_ETH_P_ARP
:
211 ret
|= (mroute_extract_addr_arp (esrc
, edest
, &b
) << MROUTE_SEC_SHIFT
);
222 * Translate a struct openvpn_sockaddr (osaddr)
223 * to a struct mroute_addr (addr).
225 bool mroute_extract_openvpn_sockaddr (struct mroute_addr
*addr
,
226 const struct openvpn_sockaddr
*osaddr
,
229 if (osaddr
->sa
.sin_family
== AF_INET
)
233 addr
->type
= MR_ADDR_IPV4
| MR_WITH_PORT
;
236 memcpy (addr
->addr
, &osaddr
->sa
.sin_addr
.s_addr
, 4);
237 memcpy (addr
->addr
+ 4, &osaddr
->sa
.sin_port
, 2);
241 addr
->type
= MR_ADDR_IPV4
;
244 memcpy (addr
->addr
, &osaddr
->sa
.sin_addr
.s_addr
, 4);
252 * Zero off the host bits in an address, leaving
253 * only the network bits, using the netbits member of
254 * struct mroute_addr as the controlling parameter.
257 mroute_addr_mask_host_bits (struct mroute_addr
*ma
)
259 in_addr_t addr
= ntohl(*(in_addr_t
*)ma
->addr
);
260 ASSERT ((ma
->type
& MR_ADDR_MASK
) == MR_ADDR_IPV4
);
261 addr
&= netbits_to_netmask (ma
->netbits
);
262 *(in_addr_t
*)ma
->addr
= htonl (addr
);
266 * The mroute_addr hash function takes into account the
267 * address type, number of bits in the network address,
268 * and the actual address.
271 mroute_addr_hash_function (const void *key
, uint32_t iv
)
273 return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr
*) key
),
274 mroute_addr_hash_len ((const struct mroute_addr
*) key
),
279 mroute_addr_compare_function (const void *key1
, const void *key2
)
281 return mroute_addr_equal ((const struct mroute_addr
*) key1
,
282 (const struct mroute_addr
*) key2
);
286 mroute_addr_print (const struct mroute_addr
*ma
,
289 return mroute_addr_print_ex (ma
, MAPF_IA_EMPTY_IF_UNDEF
, gc
);
293 mroute_addr_print_ex (const struct mroute_addr
*ma
,
294 const unsigned int flags
,
297 struct buffer out
= alloc_buf_gc (64, gc
);
300 struct mroute_addr maddr
= *ma
;
302 switch (maddr
.type
& MR_ADDR_MASK
)
305 buf_printf (&out
, "%s", format_hex_ex (ma
->addr
, 6, 0, 1, ":", gc
));
313 buf_set_read (&buf
, maddr
.addr
, maddr
.len
);
314 addr
= buf_read_u32 (&buf
, &status
);
317 if ((flags
& MAPF_SHOW_ARP
) && (maddr
.type
& MR_ARP
))
318 buf_printf (&out
, "ARP/");
319 buf_printf (&out
, "%s", print_in_addr_t (addr
, (flags
& MAPF_IA_EMPTY_IF_UNDEF
) ? IA_EMPTY_IF_UNDEF
: 0, gc
));
320 if (maddr
.type
& MR_WITH_NETBITS
)
322 if (flags
& MAPF_SUBNET
)
324 const in_addr_t netmask
= netbits_to_netmask (maddr
.netbits
);
325 buf_printf (&out
, "/%s", print_in_addr_t (netmask
, 0, gc
));
328 buf_printf (&out
, "/%d", maddr
.netbits
);
331 if (maddr
.type
& MR_WITH_PORT
)
333 port
= buf_read_u16 (&buf
);
335 buf_printf (&out
, ":%d", port
);
340 buf_printf (&out
, "IPV6");
343 buf_printf (&out
, "UNKNOWN");
353 * mroute_helper's main job is keeping track of
354 * currently used CIDR netlengths, so we don't
355 * have to cycle through all 33.
358 struct mroute_helper
*
359 mroute_helper_init (int ageable_ttl_secs
)
361 struct mroute_helper
*mh
;
362 ALLOC_OBJ_CLEAR (mh
, struct mroute_helper
);
363 /*mutex_init (&mh->mutex);*/
364 mh
->ageable_ttl_secs
= ageable_ttl_secs
;
369 mroute_helper_regenerate (struct mroute_helper
*mh
)
372 for (i
= MR_HELPER_NET_LEN
- 1; i
>= 0; --i
)
374 if (mh
->net_len_refcount
[i
] > 0)
375 mh
->net_len
[j
++] = (uint8_t) i
;
380 if (check_debug_level (D_MULTI_DEBUG
))
382 struct gc_arena gc
= gc_new ();
383 struct buffer out
= alloc_buf_gc (256, &gc
);
384 buf_printf (&out
, "MROUTE CIDR netlen:");
385 for (i
= 0; i
< mh
->n_net_len
; ++i
)
387 buf_printf (&out
, " /%d", mh
->net_len
[i
]);
389 dmsg (D_MULTI_DEBUG
, "%s", BSTR (&out
));
396 mroute_helper_add_iroute (struct mroute_helper
*mh
, const struct iroute
*ir
)
398 if (ir
->netbits
>= 0)
400 ASSERT (ir
->netbits
< MR_HELPER_NET_LEN
);
401 mroute_helper_lock (mh
);
402 ++mh
->cache_generation
;
403 ++mh
->net_len_refcount
[ir
->netbits
];
404 if (mh
->net_len_refcount
[ir
->netbits
] == 1)
405 mroute_helper_regenerate (mh
);
406 mroute_helper_unlock (mh
);
411 mroute_helper_del_iroute (struct mroute_helper
*mh
, const struct iroute
*ir
)
413 if (ir
->netbits
>= 0)
415 ASSERT (ir
->netbits
< MR_HELPER_NET_LEN
);
416 mroute_helper_lock (mh
);
417 ++mh
->cache_generation
;
418 --mh
->net_len_refcount
[ir
->netbits
];
419 ASSERT (mh
->net_len_refcount
[ir
->netbits
] >= 0);
420 if (!mh
->net_len_refcount
[ir
->netbits
])
421 mroute_helper_regenerate (mh
);
422 mroute_helper_unlock (mh
);
427 mroute_helper_free (struct mroute_helper
*mh
)
429 /*mutex_destroy (&mh->mutex);*/
434 static void dummy(void) {}
435 #endif /* P2MP_SERVER */