- Timestamping management added - Errors due to reading uninitialized data in ARP fixed - EthInterface reworked, incoming packet notification and payload readout separated (through which fixing concurrent access problems) - RX and TX offloads added - Capability to add a packet sieve layer without prior registration of specific packet class added (this makes it possible to register arbitrary EtherType connection blocks, for example)
110 lines
3.5 KiB
C
110 lines
3.5 KiB
C
#include "igmp_connblock.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "../packet_parsers/packet_parsers.h"
|
|
#include "../../utils.h"
|
|
#include "../../dynmem.h"
|
|
#include "../../pckt_assembler.h"
|
|
#include "../../eth_interface.h"
|
|
#include "ipv4_connblock.h"
|
|
#include "../packet_parsers/igmp_packet.h"
|
|
|
|
static bool filtIgmp(const PcktSieveFilterCondition * filtCond, const PcktProps * contProps, const PcktProps * ownProps, EthInterface * intf) {
|
|
IPv4Props * ipProps = (IPv4Props *) contProps;
|
|
IgmpProps * icmpProps = (IgmpProps *) ownProps;
|
|
|
|
return ipProps->Protocol == ETH_IGMP_PACKET_CLASS;
|
|
}
|
|
|
|
ConnBlock igmp_new_connblock(struct EthInterface_ *intf) {
|
|
ConnBlock igmpConnB;
|
|
connb_init_defaults(&igmpConnB);
|
|
|
|
ConnBlock ipConnB = ipv4_new_connblock(intf, IPv4_IF_ADDR, NULL); // create new IPv4 connection block
|
|
|
|
PcktSieveFilterCondition filtCond;
|
|
packfiltcond_zero(&filtCond);
|
|
PcktSieveLayerTag tag;
|
|
tag.p = intf; // Ethernet-interface passed in 'tag.p'
|
|
igmpConnB.sieveLayer = packsieve_new_layer(ipConnB.sieveLayer, &filtCond, false, filtIgmp, NULL, tag, ETH_IGMP_PACKET_CLASS);
|
|
ASSERT_NULL(igmpConnB.sieveLayer);
|
|
|
|
igmpConnB.sieve = &intf->sieve;
|
|
igmpConnB.sieveLayer->connBReportFn = igmp_print_report;
|
|
|
|
return igmpConnB;
|
|
}
|
|
|
|
static void igmp_send(ConnBlock * connBlock, ip4_addr ga, int mt) {
|
|
// allocate headers
|
|
PcktHeaderElement * igmpHeader = ALLOC_HEADER_ELEMENT(IgmpProps);
|
|
PcktHeaderElement * ipHeader = ALLOC_HEADER_ELEMENT(IPv4Props);
|
|
PcktHeaderElement * ethHeader = ALLOC_HEADER_ELEMENT(EthernetProps);
|
|
|
|
igmpHeader->next = NULL;
|
|
igmpHeader->prev = ipHeader;
|
|
ipHeader->next = igmpHeader;
|
|
ipHeader->prev = ethHeader;
|
|
ethHeader->next = ipHeader;
|
|
ethHeader->prev = NULL;
|
|
|
|
// prepare headers
|
|
IgmpProps * igmpProps = HEADER_FETCH_PROPS(IgmpProps, igmpHeader);
|
|
IPv4Props * ipProps = HEADER_FETCH_PROPS(IPv4Props, ipHeader);
|
|
EthernetProps * ethProps = HEADER_FETCH_PROPS(EthernetProps, ethHeader);
|
|
|
|
// fetch sieve layers and fill transmit headers
|
|
PcktSieveLayer * layer = connBlock->sieveLayer; // UDP layer
|
|
igmpProps->type = mt;
|
|
igmpProps->maxRespTime = 0;
|
|
igmpProps->checksum = 0;
|
|
igmpProps->groupAddr = ga;
|
|
|
|
// common fields for packet assembly
|
|
igmpProps->headerSize = ETH_IGMP_HEADER_SIZE;
|
|
igmpProps->hdrInsFn = insert_igmp_header;
|
|
|
|
// IP
|
|
layer = layer->parent;
|
|
ipv4_fill_props(ipProps, ETH_IGMP_HEADER_SIZE, ETH_IGMP_PACKET_CLASS, connBlock->sieve->intf->ip, ga);
|
|
|
|
// Ethernet
|
|
ethmc_from_ipmc(ethProps->destAddr, ga);
|
|
memcpy(ethProps->sourceAddr, connBlock->sieve->intf->mac, ETH_HW_ADDR_LEN);
|
|
ethProps->length_type = ETH_IPv4_PACKET_CLASS;
|
|
|
|
// common fields for packet assembly
|
|
ethProps->hdrInsFn = insert_ethernet_header;
|
|
ethProps->headerSize = ETH_ETHERNET_HEADER_SIZE;
|
|
|
|
Pckt cooked;
|
|
cooked.payload = NULL;
|
|
cooked.payloadSize = 0;
|
|
cooked.header = ethHeader;
|
|
|
|
// NOT FILLED FIELDS
|
|
cooked.headerSize = 0;
|
|
cooked.time_s = 0;
|
|
cooked.time_ns = 0;
|
|
|
|
RawPckt raw;
|
|
pckt_assemble(&raw, &cooked, connBlock->sieve->intf);
|
|
|
|
ethinf_transmit(connBlock->sieve->intf, &raw);
|
|
|
|
// free headers
|
|
pckthdr_chain_free(ethHeader);
|
|
}
|
|
|
|
void igmp_report_membership(ConnBlock * connBlock, ip4_addr ga) {
|
|
igmp_send(connBlock, ga, IGMP_MT_MEMBERSHIP_REPORT);
|
|
}
|
|
|
|
void igmp_leave_group(ConnBlock *connBlock, ip4_addr ga) {
|
|
igmp_send(connBlock, ga, IGMP_MT_LEAVE_GROUP);
|
|
}
|
|
|
|
void igmp_print_report(const ConnBlock* connBlock) {
|
|
INFO("IGMP");
|
|
} |