Commit 82fa5337 authored by Daniele Lacamera's avatar Daniele Lacamera

Finished up basic ipv6 support inclusion from private branch

parent d5f620e9
RTOS:
IPV4:
IPV6:
DEVLOOP:
CRC:
ETH: IPV4
......
......@@ -36,7 +36,6 @@ SLAACV4?=1
#IPv6 related
IPV6?=1
ICMP6?=1
CFLAGS=-Iinclude -Imodules -Wall -Wdeclaration-after-statement -W -Wextra -Wshadow -Wcast-qual -Wwrite-strings -Wmissing-field-initializers $(EXTRA_CFLAGS)
# extra flags recommanded by TIOBE TICS framework to score an A on compiler warnings
......@@ -193,9 +192,6 @@ endif
ifneq ($(IPV6),0)
include rules/ipv6.mk
endif
ifneq ($(ICMP6),0)
include rules/icmp6.mk
endif
all: mod core lib
......@@ -219,7 +215,7 @@ test: posix $(TEST_ELF) $(TEST_OBJ)
@mkdir -p $(PREFIX)/test/
@rm test/*.o
@mv test/*.elf $(PREFIX)/test
@cp $(PREFIX)/$(TEST_ELF) $(PREFIX)/$(TEST6_ELF)
@install $(PREFIX)/$(TEST_ELF) $(PREFIX)/$(TEST6_ELF)
tst: test
......
......@@ -36,11 +36,6 @@ static int pico_null_poll(struct pico_device *dev, int loop_score)
/* Public interface: create/destroy. */
void pico_null_destroy(struct pico_device *dev)
{
struct pico_device_null *null = (struct pico_device_null *) dev;
pico_free(null);
}
struct pico_device *pico_null_create(char *name)
{
......@@ -50,8 +45,6 @@ struct pico_device *pico_null_create(char *name)
return NULL;
if( 0 != pico_device_init((struct pico_device *)null, name, NULL)) {
dbg ("Tun init failed.\n");
pico_null_destroy((struct pico_device *)null);
return NULL;
}
......@@ -59,7 +52,6 @@ struct pico_device *pico_null_create(char *name)
null->statistics_frames_out = 0;
null->dev.send = pico_null_send;
null->dev.poll = pico_null_poll;
null->dev.destroy = pico_null_destroy;
dbg("Device %s created.\n", null->dev.name);
return (struct pico_device *)null;
}
......
......@@ -47,7 +47,6 @@ void pico_pcap_destroy(struct pico_device *dev)
{
struct pico_device_pcap *pcap = (struct pico_device_pcap *) dev;
pcap_close(pcap->conn);
pico_free(pcap);
}
#define PICO_PCAP_MODE_LIVE 0
......
......@@ -57,7 +57,6 @@ void pico_tun_destroy(struct pico_device *dev)
{
struct pico_device_tun *tun = (struct pico_device_tun *) dev;
close(tun->fd);
pico_free(tun);
}
......
......@@ -57,7 +57,6 @@ void pico_vde_destroy(struct pico_device *dev)
{
struct pico_device_vde *vde = (struct pico_device_vde *) dev;
vde_close(vde->conn);
pico_free(vde);
}
......
......@@ -515,6 +515,7 @@ static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_prefix *pre,
asuffix = (struct pico_dns_answer_suffix *)psuffix;
if (!asuffix)
break;
if (pico_dns_client_check_asuffix(asuffix, q) < 0) {
psuffix += (sizeof(struct pico_dns_answer_suffix) + short_be(asuffix->rdlength));
continue;
......
......@@ -18,8 +18,8 @@
#define PICO_ICMP6_OPT_SRC_LINK_LAYER_ADDR 1
#define PICO_ICMP6_OPT_TGT_LINK_LAYER_ADDR 2
#define icmp6_dbg(...) do {} while(0)
/* #define icmp6_dbg dbg */
#define icmp6_dbg(...) do {} while(0)
/* #define icmp6_dbg dbg */
static struct pico_queue icmp6_in;
static struct pico_queue icmp6_out;
......@@ -52,7 +52,7 @@ static int pico_icmp6_process_in(struct pico_protocol *self, struct pico_frame *
IGNORE_PARAMETER(self);
icmp6_dbg("Process IN\n");
icmp6_dbg("Process IN, type = %d\n", hdr->type);
switch (hdr->type)
{
......@@ -89,6 +89,7 @@ static int pico_icmp6_process_in(struct pico_protocol *self, struct pico_frame *
break;
case PICO_ICMP6_ROUTER_SOL:
icmp6_dbg("ICMP6: received ROUTER SOL\n");
pico_nd_router_sol_recv(f);
break;
......@@ -97,6 +98,7 @@ static int pico_icmp6_process_in(struct pico_protocol *self, struct pico_frame *
break;
case PICO_ICMP6_NEIGH_SOL:
icmp6_dbg("ICMP6: received NEIGH SOL\n");
pico_nd_neigh_sol_recv(f);
break;
......
......@@ -1619,4 +1619,19 @@ void pico_ipv4_unreachable(struct pico_frame *f, int err)
#endif
}
int pico_ipv4_cleanup_links(struct pico_device *dev)
{
struct pico_tree_node *index = NULL, *_tmp = NULL;
struct pico_ipv4_link *link = NULL;
pico_tree_foreach_safe(index, &Tree_dev_link, _tmp)
{
link = index->keyValue;
if (dev == link->dev)
pico_ipv4_link_del(dev, link->address);
}
return 0;
}
#endif
......@@ -100,5 +100,6 @@ void pico_ipv4_unreachable(struct pico_frame *f, int err);
int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter);
int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter);
struct pico_ipv4_link *pico_ipv4_get_default_mcastlink(void);
int pico_ipv4_cleanup_links(struct pico_device *dev);
#endif /* _INCLUDE_PICO_IPV4 */
......@@ -40,7 +40,7 @@
#define PICO_IPV6_MAX_RTR_SOLICITATION_DELAY 1000
#define ipv6_dbg(...) do {} while(0)
/* #define ipv6_dbg dbg */
/* #define ipv6_dbg dbg */
/* queues */
static struct pico_queue ipv6_in;
......@@ -312,24 +312,29 @@ int pico_ipv6_is_global(const uint8_t addr[PICO_SIZE_IP6])
int pico_ipv6_is_localhost(const uint8_t addr[PICO_SIZE_IP6])
{
const uint8_t localhost[PICO_SIZE_IP6] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
if (memcmp(addr, localhost, PICO_SIZE_IP6)== 0)
const uint8_t localhost[PICO_SIZE_IP6] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
if (memcmp(addr, localhost, PICO_SIZE_IP6) == 0)
return 1;
return 0;
}
int pico_ipv6_is_unicast(const uint8_t addr[PICO_SIZE_IP6])
int pico_ipv6_is_unicast(struct pico_ip6 *a)
{
if (pico_ipv6_is_global(addr))
if (pico_ipv6_is_global(a->addr))
return 1;
else if (pico_ipv6_is_uniquelocal(addr))
else if (pico_ipv6_is_uniquelocal(a->addr))
return 1;
else if (pico_ipv6_is_sitelocal(addr))
else if (pico_ipv6_is_sitelocal(a->addr))
return 1;
else if (pico_ipv6_is_linklocal(addr))
else if (pico_ipv6_is_linklocal(a->addr))
return 1;
else if (pico_ipv6_is_localhost(addr))
else if (pico_ipv6_is_localhost(a->addr))
return 1;
else if(pico_ipv6_link_get(a))
return 1;
else
return 0;
......@@ -628,7 +633,7 @@ int pico_ipv6_process_in(struct pico_protocol *self, struct pico_frame *f)
/* XXX: IPV6 filter implementation */
if (0) {
} else if (pico_ipv6_is_unicast(hdr->dst.addr)) {
} else if (pico_ipv6_is_unicast(&hdr->dst)) {
pico_transport_receive(f, f->proto);
} else if (pico_ipv6_is_multicast(hdr->dst.addr)) {
/* XXX perform multicast filtering: solicited-node multicast address MUST BE allowed! */
......@@ -822,6 +827,8 @@ int pico_ipv6_route_add(struct pico_ip6 address, struct pico_ip6 netmask, struct
return -1;
}
ipv6_dbg("Adding IPV6 static route\n");
new->dest = address;
new->netmask = netmask;
new->gateway = gateway;
......
......@@ -75,7 +75,7 @@ struct __attribute__((packed)) pico_ipv6_exthdr {
int pico_string_to_ipv6(const char *ipstr, uint8_t *ip);
int pico_ipv6_to_string(char *ipbuf, const uint8_t ip[PICO_SIZE_IP6]);
int pico_ipv6_is_unicast(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_is_unicast(struct pico_ip6 *a);
int pico_ipv6_is_multicast(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_is_global(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_is_uniquelocal(const uint8_t addr[PICO_SIZE_IP6]);
......
......@@ -141,8 +141,8 @@ static struct pico_neighbor *pico_nd_add_neighbor(struct pico_ip6 *host, struct
n->failure_count = 0;
n->state_timestamp = PICO_TIME_MS();
n->rate_timestamp = 0;
n->neighbor = *neighbor;
n->host = *host;
memcpy(&n->neighbor, neighbor, sizeof(struct pico_ip6));
memcpy(&n->host, host, sizeof(struct pico_ip6));
n->dev = dev;
n->pending.max_frames = PICO_ND_MAX_FRAMES_QUEUED;
pico_tree_insert(&NDNeighbors, n);
......@@ -523,6 +523,11 @@ static int pico_nd_send_solicitation(struct pico_neighbor *n, struct pico_frame
dev = n->dev;
}
if (!dev) {
dbg("ND: No device set!\n");
return -1;
}
/* RFC4861 $7.2.1
* while awaiting a response, the sender SHOULD retransmit neighbor
* solicitation messages approximately every RetransTimer milliseconds,
......@@ -565,6 +570,7 @@ int pico_nd_neigh_sol_recv(struct pico_frame *f)
#ifdef PICO_SUPPORT_CRC
if (pico_icmp6_checksum(f) != 0)
goto out;
#endif
if (f->transport_len < PICO_ICMP6HDR_NEIGH_SOL_SIZE)
......@@ -611,7 +617,7 @@ int pico_nd_neigh_sol_recv(struct pico_frame *f)
if (!link)
goto out;
if (pico_ipv6_is_unicast(icmp6_hdr->msg.info.neigh_adv.target.addr))
if (pico_ipv6_is_unicast(&icmp6_hdr->msg.info.neigh_adv.target))
if(link->dev != f->dev)
goto out;
......@@ -713,15 +719,20 @@ int pico_nd_neigh_adv_recv(struct pico_frame *f)
neighbor->state_timestamp = PICO_TIME_MS();
/* is a response to a solicitation? */
if (IS_SOLICITED(icmp6_hdr))
if (IS_SOLICITED(icmp6_hdr)) {
neighbor->state = PICO_ND_STATE_REACHABLE;
else
pico_timer_add(1, &pico_nd_pending, neighbor);
}
else {
neighbor->state = PICO_ND_STATE_STALE;
}
if (IS_ROUTER(icmp6_hdr))
neighbor->isrouter = 1;
else
neighbor->isrouter = 0;
}
else { /* any other state than INCOMPLETE */
if (!IS_OVERRIDE(icmp6_hdr) && opt && !in_cache) {
......
......@@ -89,7 +89,7 @@ static void pico_slaacv4_send_announce_timer(pico_time __attribute__((unused)) n
{
struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg;
struct pico_ip4 netmask = {
.addr = 0x0000FFFF
.addr = long_be(0xFFFF0000)
};
if (tmp->announce_nb < ANNOUNCE_NB)
......
......@@ -122,6 +122,7 @@ int pico_socket_tcp_deliver(struct pico_sockport *sp, struct pico_frame *f)
found = s;
}
}
#endif
} /* FOREACH */
if (found != NULL) {
......
......@@ -62,6 +62,7 @@ static int pico_socket_udp_deliver_ipv4(struct pico_socket *s, struct pico_frame
s->wakeup(PICO_SOCK_EV_RD, s);
}
}
pico_frame_discard(f);
return 0;
}
......@@ -86,6 +87,7 @@ int pico_socket_udp_deliver(struct pico_sockport *sp, struct pico_frame *f)
pico_frame_discard(f);
if (s)
return 0;
pico_err = PICO_ERR_ENXIO;
#endif
return -1;
......
......@@ -384,6 +384,9 @@ static int release_all_until(struct pico_tcp_queue *q, uint32_t seq, pico_time *
return ret;
}
/* API calls */
/* API calls */
uint16_t pico_tcp_checksum_ipv4(struct pico_frame *f)
......@@ -412,6 +415,53 @@ uint16_t pico_tcp_checksum_ipv4(struct pico_frame *f)
return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv4_pseudo_hdr), tcp_hdr, f->transport_len);
}
#ifdef PICO_SUPPORT_IPV6
uint16_t pico_tcp_checksum_ipv6(struct pico_frame *f)
{
struct pico_ipv6_hdr *ipv6_hdr = (struct pico_ipv6_hdr *)f->net_hdr;
struct pico_tcp_hdr *tcp_hdr = (struct pico_tcp_hdr *)f->transport_hdr;
struct pico_ipv6_pseudo_hdr pseudo;
struct pico_socket *s = f->sock;
/* XXX If the IPv6 packet contains a Routing header, the Destination
* Address used in the pseudo-header is that of the final destination */
if (s) {
/* Case of outgoing frame */
pseudo.src = s->local_addr.ip6;
pseudo.dst = s->remote_addr.ip6;
} else {
/* Case of incomming frame */
pseudo.src = ipv6_hdr->src;
pseudo.dst = ipv6_hdr->dst;
}
pseudo.zero[0] = 0;
pseudo.zero[1] = 0;
pseudo.zero[2] = 0;
pseudo.len = long_be(f->transport_len);
pseudo.nxthdr = PICO_PROTO_TCP;
return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv6_pseudo_hdr), tcp_hdr, f->transport_len);
}
#endif
static uint16_t pico_tcp_checksum(void *_s, struct pico_frame *f)
{
struct pico_socket *s = (struct pico_socket *)_s;
(void)f;
#ifdef PICO_SUPPORT_IPV4
if (s->net->proto_number == PICO_PROTO_IPV4)
return pico_tcp_checksum_ipv4(f);
#endif
#ifdef PICO_SUPPORT_IPV6
else if (s->net->proto_number == PICO_PROTO_IPV6)
return pico_tcp_checksum_ipv6(f);
#endif
return 0xffff;
}
static void tcp_send_fin(struct pico_socket_tcp *t);
static int pico_tcp_process_out(struct pico_protocol *self, struct pico_frame *f)
{
......@@ -684,7 +734,7 @@ inline static void tcp_add_header(struct pico_socket_tcp *t, struct pico_frame *
hdr->flags |= PICO_TCP_PSH | PICO_TCP_ACK;
hdr->ack = long_be(t->rcv_nxt);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(t, f));
}
static void tcp_rcv_sack(struct pico_socket_tcp *t, uint8_t *opt, int len)
......@@ -825,7 +875,7 @@ static int tcp_send(struct pico_socket_tcp *ts, struct pico_frame *f)
f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
hdr->rwnd = short_be(ts->wnd);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(ts, f));
/* TCP: ENQUEUE to PROTO ( Transmit ) */
cpy = pico_frame_copy(f);
......@@ -992,7 +1042,7 @@ int pico_tcp_initconn(struct pico_socket *s)
hdr->trans.dport = ts->sock.remote_port;
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(syn));
hdr->crc = short_be(pico_tcp_checksum(s, syn));
/* TCP: ENQUEUE to PROTO ( SYN ) */
tcp_dbg("Sending SYN... (ports: %d - %d) size: %d\n", short_be(ts->sock.local_port), short_be(ts->sock.remote_port), syn->buffer_len);
......@@ -1061,7 +1111,7 @@ static void tcp_send_empty(struct pico_socket_tcp *t, uint16_t flags, int is_kee
f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
hdr->rwnd = short_be(t->wnd);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(t, f));
/* TCP: ENQUEUE to PROTO */
pico_enqueue(&tcp_out, f);
......@@ -1125,7 +1175,7 @@ static int tcp_send_rst(struct pico_socket *s, struct pico_frame *fr)
f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
hdr->rwnd = short_be(t->wnd);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(s, f));
/* TCP: ENQUEUE to PROTO */
pico_enqueue(&tcp_out, f);
......@@ -1160,9 +1210,13 @@ int pico_tcp_reply_rst(struct pico_frame *fr)
f = fr->sock->net->alloc(fr->sock->net, size);
/* fill in IP data from original frame */
/* TODO if IPv4 */
((struct pico_ipv4_hdr *)(f->net_hdr))->dst.addr = ((struct pico_ipv4_hdr *)(fr->net_hdr))->src.addr;
((struct pico_ipv4_hdr *)(f->net_hdr))->src.addr = ((struct pico_ipv4_hdr *)(fr->net_hdr))->dst.addr;
if (IS_IPV4(f)) {
((struct pico_ipv4_hdr *)(f->net_hdr))->dst.addr = ((struct pico_ipv4_hdr *)(fr->net_hdr))->src.addr;
((struct pico_ipv4_hdr *)(f->net_hdr))->src.addr = ((struct pico_ipv4_hdr *)(fr->net_hdr))->dst.addr;
} else {
((struct pico_ipv6_hdr *)(f->net_hdr))->dst = ((struct pico_ipv6_hdr *)(fr->net_hdr))->src;
((struct pico_ipv6_hdr *)(f->net_hdr))->src = ((struct pico_ipv6_hdr *)(fr->net_hdr))->dst;
}
/* fill in TCP data from original frame */
((struct pico_tcp_hdr *)(f->transport_hdr))->trans.dport = ((struct pico_tcp_hdr *)(fr->transport_hdr))->trans.sport;
......@@ -1184,9 +1238,15 @@ int pico_tcp_reply_rst(struct pico_frame *fr)
if(!(hdr1->flags & PICO_TCP_ACK))
hdr->ack = long_be(long_be(((struct pico_tcp_hdr *)(fr->transport_hdr))->seq) + fr->payload_len);
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
/* enqueue for transmission */
pico_ipv4_frame_push(f, &(((struct pico_ipv4_hdr *)(f->net_hdr))->dst), PICO_PROTO_TCP);
hdr->crc = short_be(pico_tcp_checksum(fr->sock, f));
if (IS_IPV4(f)) {
pico_ipv4_frame_push(f, &(((struct pico_ipv4_hdr *)(f->net_hdr))->dst), PICO_PROTO_TCP);
#ifdef PICO_SUPPORT_IPV6
} else {
pico_ipv6_frame_push(f, &(((struct pico_ipv6_hdr *)(f->net_hdr))->dst), PICO_PROTO_TCP);
#endif
}
return 0;
}
......@@ -1237,7 +1297,7 @@ static int tcp_nosync_rst(struct pico_socket *s, struct pico_frame *fr)
f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
hdr->rwnd = short_be(t->wnd);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(s, f));
/* TCP: ENQUEUE to PROTO */
pico_enqueue(&tcp_out, f);
......@@ -1275,7 +1335,7 @@ static void tcp_send_fin(struct pico_socket_tcp *t)
f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
hdr->rwnd = short_be(t->wnd);
hdr->crc = 0;
hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
hdr->crc = short_be(pico_tcp_checksum(t, f));
/* tcp_dbg("SENDING FIN...\n"); */
/* TCP: ENQUEUE to PROTO ( Pure ACK ) */
pico_enqueue(&tcp_out, f);
......@@ -1787,7 +1847,7 @@ static int tcp_ack(struct pico_socket *s, struct pico_frame *f)
if (t->x_mode < PICO_TCP_RECOVER) {
t->x_mode++;
tcp_dbg("Mode: DUPACK %d, due to PURE ACK %0x, len = %d\n", t->x_mode, SEQN(f), f->payload_len);
tcp_dbg("ACK: %x - QUEUE: %x\n", ACKN(f), SEQN(first_segment(&t->tcpq_out)));
/* tcp_dbg("ACK: %x - QUEUE: %x\n", ACKN(f), SEQN(first_segment(&t->tcpq_out))); */
if (t->x_mode == PICO_TCP_RECOVER) { /* Switching mode */
t->snd_retry = SEQN((struct pico_frame *)first_segment(&t->tcpq_out));
if (t->ssthresh > t->cwnd)
......@@ -1799,7 +1859,7 @@ static int tcp_ack(struct pico_socket *s, struct pico_frame *f)
t->ssthresh = 2;
}
} else if (t->x_mode == PICO_TCP_RECOVER) {
tcp_dbg("TCP RECOVER> DUPACK! snd_una: %08x, snd_nxt: %08x, acked now: %08x\n", SEQN(first_segment(&t->tcpq_out)), t->snd_nxt, ACKN(f));
/* tcp_dbg("TCP RECOVER> DUPACK! snd_una: %08x, snd_nxt: %08x, acked now: %08x\n", SEQN(first_segment(&t->tcpq_out)), t->snd_nxt, ACKN(f)); */
if (t->in_flight <= t->cwnd) {
struct pico_frame *nxt = peek_segment(&t->tcpq_out, t->snd_retry);
if (!nxt)
......
OPTIONS+=-DPICO_SUPPORT_ICMP6
MOD_OBJ+=modules/pico_icmp6.o
ifneq ($(PING),0)
OPTIONS+=-DPICO_SUPPORT_PING
endif
OPTIONS+=-DPICO_SUPPORT_IPV6
MOD_OBJ+=modules/pico_ipv6.o modules/pico_ipv6_nd.o
OPTIONS+=-DPICO_SUPPORT_IPV6 -DPICO_SUPPORT_ICMP6
MOD_OBJ+=modules/pico_ipv6.o modules/pico_ipv6_nd.o modules/pico_icmp6.o
......@@ -14,6 +14,7 @@
#include "pico_protocol.h"
#include "pico_tree.h"
#include "pico_ipv6.h"
#include "pico_ipv4.h"
#include "pico_icmp6.h"
struct pico_devices_rr_info {
......@@ -79,6 +80,7 @@ int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
pico_free(dev->eth);
return -1;
}
#endif
}
......@@ -101,13 +103,14 @@ int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
linklocal.addr[15] = (uint8_t)(len >> 24);
pico_rand_feed(dev->hash);
} while (pico_ipv6_link_get(&linklocal));
if (pico_ipv6_link_add(dev, linklocal, netmask6)) {
pico_free(dev->q_in);
pico_free(dev->q_out);
return -1;
}
}
#endif
}
......@@ -121,6 +124,7 @@ int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
dev->hostvars.retranstime = PICO_ND_RETRANS_TIMER;
pico_icmp6_router_solicitation(dev, &linklocal);
}
dev->hostvars.hoplimit = PICO_IPV6_DEFAULT_HOP;
#endif
......@@ -147,6 +151,15 @@ void pico_device_destroy(struct pico_device *dev)
if (dev->eth)
pico_free(dev->eth);
#ifdef PICO_SUPPORT_IPV4
pico_ipv4_cleanup_links(dev);
#endif
#ifdef PICO_SUPPORT_IPV6
pico_ipv6_cleanup_links(dev);
#endif
pico_tree_delete(&Device_tree, dev);
pico_tree_delete(&Device_tree, dev);
Devices_rr_info.node_in = NULL;
Devices_rr_info.node_out = NULL;
......
......@@ -227,6 +227,7 @@ static int pico_port_in_use_with_this_ipv4_address(struct pico_sockport *sp, str
}
}
}
return 0;
}
......@@ -270,6 +271,7 @@ static int pico_port_in_use_with_this_ipv6_address(struct pico_sockport *sp, str
}
}
}
return 0;
}
......@@ -278,7 +280,7 @@ static int pico_port_in_use_ipv6(struct pico_sockport *sp, void *addr)
struct pico_ip6 ip;
/* IPv6 */
if (addr)
memcpy(&ip.addr,((struct pico_ip6 *)addr)->addr, sizeof(struct pico_ip6));
memcpy(&ip.addr, ((struct pico_ip6 *)addr)->addr, sizeof(struct pico_ip6));
else
memcpy(&ip.addr, PICO_IP6_ANY, sizeof(struct pico_ip6));
......@@ -290,6 +292,7 @@ static int pico_port_in_use_ipv6(struct pico_sockport *sp, void *addr)
return 1;
}
}
return pico_port_in_use_with_this_ipv6_address(sp, ip);
}
#endif
......@@ -302,15 +305,18 @@ static int pico_generic_port_in_use(uint16_t proto, uint16_t port, struct pico_s
if (pico_port_in_use_by_nat(proto, port)) {
return 1;
}
if (pico_port_in_use_ipv4(sp, addr)) {
return 1;
}
#endif
#ifdef PICO_SUPPORT_IPV6
if (pico_port_in_use_ipv6(sp, addr)) {
return 1;
}
#endif
return 0;
......@@ -319,7 +325,7 @@ static int pico_generic_port_in_use(uint16_t proto, uint16_t port, struct pico_s
int pico_is_port_free(uint16_t proto, uint16_t port, void *addr, void *net)
{
struct pico_sockport *sp;
(void) net;
(void) net;
sp = pico_get_sockport(proto, port);
if (pico_generic_port_in_use(proto, port, sp, addr))
......
......@@ -348,9 +348,11 @@ static struct pico_ipv4_link *setop_multicast_link_search(void *value, int bysou
mreq_src = (struct pico_ip_mreq_source *) value;
if (!mreq_src)
return NULL;
mcast_link = pico_socket_setoption_validate_s_mreq(mreq_src);
if (!mcast_link)
return NULL;
if (!mreq_src->mcast_link_addr.addr)
mreq_src->mcast_link_addr.addr = mcast_link->address.addr;
}
......
......@@ -39,6 +39,14 @@ const uint8_t PICO_ETHADDR_MCAST[6] = {
0x01, 0x00, 0x5e, 0x00, 0x00, 0x00
};
#ifdef PICO_SUPPORT_IPV6
# define PICO_SIZE_MCAST6 2
const uint8_t PICO_ETHADDR_MCAST6[6] = {
0x33, 0x33, 0x00, 0x00, 0x00, 0x00
};
#endif
volatile pico_time pico_tick;
volatile pico_err_t pico_err;
......@@ -316,6 +324,9 @@ int32_t pico_ethernet_receive(struct pico_frame *f)
hdr = (struct pico_eth_hdr *) f->datalink_hdr;
if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
(memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
#ifdef PICO_SUPPORT_IPV6
(memcmp(hdr->daddr, PICO_ETHADDR_MCAST6, PICO_SIZE_MCAST6) != 0) &&
#endif
(memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0))
{
pico_frame_discard(f);
......@@ -347,20 +358,25 @@ static int destination_is_bcast(struct pico_frame *f)
static int destination_is_mcast(struct pico_frame *f)
{
int ret = 0;
if (!f)
return 0;
if (IS_IPV6(f))
return 0;
#ifdef PICO_SUPPORT_IPV6
if (IS_IPV6(f)) {
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *) f->net_hdr;
ret = pico_ipv6_is_multicast(hdr->dst.addr);
}
#endif
#ifdef PICO_SUPPORT_IPV4
else {
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
return pico_ipv4_is_multicast(hdr->dst.addr);
ret = pico_ipv4_is_multicast(hdr->dst.addr);
}
#else
return 0;
#endif
return ret;
}
static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
......@@ -376,13 +392,39 @@ static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint
}
#ifdef PICO_SUPPORT_IPV6
static struct pico_eth *pico_ethernet_mcast6_translate(struct pico_frame *f, uint8_t *pico_mcast6_mac)
{
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr;
/* first 2 octets are 0x33, last four are the last four of dst */
pico_mcast6_mac[5] = hdr->dst.addr[PICO_SIZE_IP6 - 1];
pico_mcast6_mac[4] = hdr->dst.addr[PICO_SIZE_IP6 - 2];
pico_mcast6_mac[3] = hdr->dst.addr[PICO_SIZE_IP6 - 3];
pico_mcast6_mac[2] = hdr->dst.addr[PICO_SIZE_IP6 - 4];
return (struct pico_eth *)pico_mcast6_mac;
}
#endif
int32_t pico_ethernet_send_ipv6(struct pico_frame *f)
struct pico_eth *pico_ethernet_ipv6_dst(struct pico_frame *f)
{
struct pico_eth *dstmac = NULL;
#ifdef PICO_SUPPORT_IPV6
if (destination_is_mcast(f)) {
uint8_t pico_mcast6_mac[