proxy_rtadvd.c revision f0c792e78a8bf77c28c7814441e514bea7c5362b
/* -*- indent-tabs-mode: nil; -*- */
#include "winutils.h"
#include "proxy.h"
#include "lwip/inet_chksum.h"
#include <string.h>
static void proxy_rtadvd_timer(void *);
static void proxy_rtadvd_send_multicast(struct netif *);
static void proxy_rtadvd_fill_payload(struct netif *, int);
/* ff02::1 - link-local all nodes multicast address */
static ip6_addr_t allnodes_linklocal = {
};
/*
* Unsolicited Router Advertisement payload.
*
* NB: Since ICMP checksum covers pseudo-header with destination
* address (link-local allnodes multicast in this case) this payload
* cannot be used for solicited replies to unicast addresses.
*/
static unsigned int unsolicited_ra_payload_length;
static u8_t unsolicited_ra_payload[
sizeof(struct ra_header)
/* reserves enough space for NETIF_MAX_HWADDR_LEN */
+ sizeof(struct lladdr_option)
/* we only announce one prefix */
+ sizeof(struct prefix_option) * 1
];
static int ndefaults = 0;
static struct raw_pcb *rtadvd_pcb;
void
{
if (ndefaults < 0) {
DPRINTF0(("rtadvd: failed to read IPv6 routing table, aborting\n"));
return;
}
if (rtadvd_pcb == NULL) {
DPRINTF0(("rtadvd: failed to allocate pcb, aborting\n"));
return;
}
/*
* We cannot use raw_bind_ip6() since raw_input() doesn't grok
* multicasts. We are going to use ip6_output_if() directly.
*/
}
static int quick_ras = 2;
static void
proxy_rtadvd_timer(void *arg)
{
int newdefs;
}
if (quick_ras > 0) {
--quick_ras;
}
else {
}
}
/*
* solve this in general, making it configurable, etc.
*
* Cf. RFC 4861:
* 6.1.1. Validation of Router Solicitation Messages
*/
static u8_t
{
struct lladdr_option *lladdr_opt;
void *option;
/* save a pointer to IP6 header and skip to ICMP6 payload */
pbuf_header(p, -ip_current_header_tot_len());
goto drop;
}
ip6_current_dest_addr()) != 0)
{
goto drop;
}
return RAW_RECV_CONTINUE; /* not interested */
}
/* only now that we know it's ICMP6_TYPE_RS we can check IP6 hop limit */
goto drop;
}
/* future, backward-incompatible changes may use different Code values. */
goto drop;
}
/* skip past rs_header, nothing interesting in it */
goto drop;
}
lladdr_opt = NULL;
while (p->len > 0) {
unsigned int optlen;
if (p->len < 8) {
goto drop;
}
if (optlen8 == 0) {
goto drop;
}
goto drop;
}
if (opttype == ND6_OPTION_TYPE_SOURCE_LLADDR) {
goto drop;
}
}
pbuf_header(p, -optlen);
}
if (ip6_addr_isany(ip6_current_src_addr())) {
if (lladdr_opt != NULL) {
goto drop;
}
/* reply with multicast RA */
}
else {
/*
* XXX: Router is supposed to update its Neighbor Cache (6.2.6),
* but it's hidden inside nd6.c.
*/
/* may reply with either unicast or multicast RA */
}
/* we just always reply with multicast RA */
pbuf_free(p); /* NB: this invalidates lladdr_option */
return RAW_RECV_CONSUMED;
drop:
pbuf_free(p);
return RAW_RECV_CONSUMED;
}
static void
{
return;
}
return;
}
&allnodes_linklocal, /* dst */
255, /* hop limit */
0, /* traffic class */
}
}
/*
* XXX: TODO: Only ra_header::router_lifetime (and hence
* ra_header::chksum) need to be changed, so we can precompute it once
* and then only update these two fields.
*/
static void
{
struct pbuf *p;
struct lladdr_option *lladdr_opt;
struct prefix_option *pfx_opt;
unsigned int lladdr_optlen;
LWIP_ASSERT("netif hwaddr too long",
/* type + length + ll addr + round up to 8 octets */
/* actual payload length */
sizeof(struct ra_header)
+ sizeof(struct prefix_option) * 1;
/* Set fields. */
#if 0
/*
* "M" flag. Tell guests to use stateful DHCP6. Disabled here
* since we don't provide stateful server.
*/
#endif
/*
* XXX: TODO: Disable "O" flag for now to match disabled stateless
* server. We don't yet get IPv6 nameserver addresses from
* HostDnsService, so we have nothing to say, don't tell guests to
* come asking.
*/
#if 0
/*
* "O" flag. Tell guests to use DHCP6 for DNS and the like. This
* is served by simple stateless server (RFC 3736).
*
* XXX: "STATEFUL" in the flag name was probably a bug in RFC2461.
* It's present in the text, but not in the router configuration
* variable name. It's dropped in the text in RFC4861.
*/
#endif
if (is_default) {
}
else {
ra_hdr->router_lifetime = 0;
}
/* we need a temp pbuf to calculate the checksum */
if (p == NULL) {
DPRINTF0(("rtadvd: failed to allocate RA pbuf\n"));
return;
}
/* src addr: netif's link-local */
/* dst addr */
pbuf_free(p);
}