Porting PicoTCP WIP

This commit is contained in:
2025-10-29 14:29:06 +01:00
parent 6722f42e68
commit 815c2239fe
464 changed files with 235009 additions and 24 deletions

View File

@ -0,0 +1,259 @@
/*********************************************************************
PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
This module handles the equalities between the IGMP and the MLD protocol
Authors: Roel Postelmans
*********************************************************************/
#include "pico_stack.h"
#include "pico_ipv6.h"
#include "pico_mld.h"
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_addressing.h"
#include "pico_frame.h"
#include "pico_tree.h"
#include "pico_device.h"
#include "pico_socket.h"
#include "pico_icmp6.h"
#include "pico_dns_client.h"
#include "pico_mld.h"
#include "pico_igmp.h"
#include "pico_constants.h"
#include "pico_mcast.h"
#if (((defined(PICO_SUPPORT_MLD) && defined(PICO_SUPPORT_IPV6)) || defined(PICO_SUPPORT_IGMP)) && defined(PICO_SUPPORT_MCAST))
#ifdef DEBUG_MCAST
#define multicast_dbg dbg
#else
#define multicast_dbg(...) do {} while(0)
#endif
#define MCAST_EVENT_DELETE_GROUP (0x0)
#define MCAST_EVENT_CREATE_GROUP (0x1)
#define MCAST_EVENT_UPDATE_GROUP (0x2)
#define MCAST_EVENT_QUERY_RECV (0x3)
#define MCAST_EVENT_REPORT_RECV (0x4)
#define MCAST_EVENT_TIMER_EXPIRED (0x5)
#define MCAST_MODE_IS_INCLUDE (1)
#define MCAST_MODE_IS_EXCLUDE (2)
#define MCAST_CHANGE_TO_INCLUDE_MODE (3)
#define MCAST_CHANGE_TO_EXCLUDE_MODE (4)
#define MCAST_MODE_IS_INCLUDE (1)
#define MCAST_MODE_IS_EXCLUDE (2)
#define MCAST_CHANGE_TO_INCLUDE_MODE (3)
#define MCAST_CHANGE_TO_EXCLUDE_MODE (4)
#define MCAST_ALLOW_NEW_SOURCES (5)
#define MCAST_BLOCK_OLD_SOURCES (6)
typedef int (*mcast_callback)(struct mcast_filter_parameters *);
static void pico_mcast_src_filtering_cleanup(struct mcast_filter_parameters*mcast )
{
struct pico_tree_node *index = NULL, *_tmp = NULL;
/* cleanup filters */
pico_tree_foreach_safe(index, mcast->allow, _tmp)
{
pico_tree_delete(mcast->allow, index->keyValue);
}
pico_tree_foreach_safe(index, mcast->block, _tmp)
{
pico_tree_delete(mcast->block, index->keyValue);
}
}
static int pico_mcast_src_filtering_inc_inc(struct mcast_filter_parameters*mcast )
{
struct pico_tree_node *index = NULL;
union pico_address *source;
/* all ADD_SOURCE_MEMBERSHIP had an equivalent DROP_SOURCE_MEMBERSHIP */
if (mcast->p->event == MCAST_EVENT_DELETE_GROUP) {
/* TO_IN (B) */
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
mcast->filter = mcast->allow;
if (mcast->p->MCASTFilter) {
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
} /* else { allow stays empty } */
return 0;
}
/* ALLOW (B-A) */
/* if event is CREATE A will be empty, thus only ALLOW (B-A) has sense */
if (mcast->p->event == MCAST_EVENT_CREATE_GROUP) /* first ADD_SOURCE_MEMBERSHIP */
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
else
mcast->record_type = MCAST_ALLOW_NEW_SOURCES;
mcast->filter = mcast->allow;
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
{
source = pico_tree_findKey(mcast->allow, index->keyValue);
if (source) {
pico_tree_delete(mcast->allow, source);
mcast->sources--;
}
}
if (!pico_tree_empty(mcast->allow)) /* record type is ALLOW */
return 0;
/* BLOCK (A-B) */
mcast->record_type = MCAST_BLOCK_OLD_SOURCES;
mcast->filter = mcast->block;
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
{
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
source = pico_tree_findKey(mcast->block, index->keyValue);
if (source) {
pico_tree_delete(mcast->block, source);
mcast->sources--;
}
}
if (!pico_tree_empty(mcast->block)) /* record type is BLOCK */
return 0;
/* ALLOW (B-A) and BLOCK (A-B) are empty: do not send report */
(mcast->p)->f = NULL;
return MCAST_NO_REPORT;
}
static int pico_mcast_src_filtering_inc_excl(struct mcast_filter_parameters*mcast )
{
struct pico_tree_node *index = NULL;
mcast->record_type = MCAST_CHANGE_TO_EXCLUDE_MODE;
mcast->filter = mcast->block;
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
return 0;
}
static int pico_mcast_src_filtering_excl_inc(struct mcast_filter_parameters*mcast )
{
struct pico_tree_node *index = NULL;
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
mcast->filter = mcast->allow;
if (mcast->p->MCASTFilter) {
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
} /* else { allow stays empty } */
return 0;
}
static int pico_mcast_src_filtering_excl_excl(struct mcast_filter_parameters*mcast )
{
struct pico_tree_node *index = NULL;
struct pico_ip6 *source = NULL;
mcast->record_type = MCAST_BLOCK_OLD_SOURCES;
mcast->filter = mcast->block;
pico_tree_foreach(index, mcast->p->MCASTFilter)
{
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
{
source = pico_tree_findKey(mcast->block, index->keyValue); /* B */
if (source) {
pico_tree_delete(mcast->block, source);
mcast->sources--;
}
}
if (!pico_tree_empty(mcast->block)) /* record type is BLOCK */
return 0;
/* ALLOW (A-B) */
mcast->record_type = MCAST_ALLOW_NEW_SOURCES;
mcast->filter = mcast->allow;
pico_tree_foreach(index, &mcast->g->MCASTSources)
{
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
multicast_dbg("MCAST: Failed to insert entry in tree\n");
return -1;
}
mcast->sources++;
}
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
{
source = pico_tree_findKey(mcast->allow, index->keyValue); /* A */
if (source) {
pico_tree_delete(mcast->allow, source);
mcast->sources--;
}
}
if (!pico_tree_empty(mcast->allow)) /* record type is ALLOW */
return 0;
/* BLOCK (B-A) and ALLOW (A-B) are empty: do not send report */
mcast->p->f = NULL;
return MCAST_NO_REPORT;
}
static const mcast_callback mcast_filter_state[2][2] =
{
{ pico_mcast_src_filtering_excl_excl, pico_mcast_src_filtering_excl_inc},
{ pico_mcast_src_filtering_inc_excl, pico_mcast_src_filtering_inc_inc }
};
int8_t pico_mcast_generate_filter(struct mcast_filter_parameters *filter, struct mcast_parameters *p)
{
int ret = -1;
/* "non-existent" state of filter mode INCLUDE and empty source list */
if (p->event == MCAST_EVENT_DELETE_GROUP) {
p->filter_mode = PICO_IP_MULTICAST_INCLUDE;
p->MCASTFilter = NULL;
}
if (p->event == MCAST_EVENT_QUERY_RECV)
return 0;
pico_mcast_src_filtering_cleanup(filter);
if(filter->g->filter_mode <= PICO_IP_MULTICAST_INCLUDE )
{
if(p->filter_mode <= PICO_IP_MULTICAST_INCLUDE)
{
ret = mcast_filter_state[filter->g->filter_mode][p->filter_mode](filter);
}
}
return (int8_t) ret;
}
#endif