#include "icmp_connblock.h" #include #include "../packet_parsers/packet_parsers.h" #include "../../utils.h" #include "../../dynmem.h" #include "../../pckt_assembler.h" #include "../../eth_interface.h" #include "../packet_parsers/icmp_packet.h" #include "ipv4_connblock.h" static bool filtIcmp(const PcktSieveFilterCondition * filtCond, const PcktProps * contProps, const PcktProps * ownProps, EthInterface * intf) { IPv4Props * ipProps = (IPv4Props *) contProps; IcmpProps * icmpProps = (IcmpProps *) ownProps; return ipProps->Protocol == ETH_ICMP_PACKET_CLASS; } static int icmp_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) { IcmpProps * icmpProps = HEADER_FETCH_PROPS(IcmpProps, pckt->header); EthInterface * intf = (EthInterface *) tag.p; // icmp_new_connblock() puts pointer to intf into tag field switch (icmpProps->type) { case ICMP_MT_ECHO_REQUEST: { icmpProps->type = ICMP_MT_ECHO_REPLY; // replace request with reply icmpProps->hdrInsFn = insert_icmp_header; // swap source an destination IP addresses IPv4Props * iPv4Props = HEADER_FETCH_PROPS(IPv4Props, pckt->header->prev); ip4_addr tmpIp = iPv4Props->SourceIPAddr; iPv4Props->SourceIPAddr = iPv4Props->DestIPAddr; iPv4Props->DestIPAddr = tmpIp; iPv4Props->hdrInsFn = insert_ipv4_header; // swap Ethernet fields EthernetAddress tmpEth; EthernetProps * ethProps = HEADER_FETCH_PROPS(EthernetProps, pckt->header->prev->prev); HWACPY(tmpEth, ethProps->sourceAddr); HWACPY(ethProps->sourceAddr, ethProps->destAddr); HWACPY(ethProps->destAddr, tmpEth); ethProps->hdrInsFn = insert_ethernet_header; // payload is the same... // assemble packet RawPckt raw; pckt_assemble(&raw, pckt); // release headers pckthdr_chain_free(pckt->header); ethinf_transmit(intf, &raw); } break; default: break; } return 0; } ConnBlock icmp_new_connblock(EthInterface * intf) { ConnBlock icmpConnB; 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' icmpConnB.sieveLayer = packsieve_new_layer(ipConnB.sieveLayer, &filtCond, false, filtIcmp, icmp_recv_cb, tag, ETH_ICMP_PACKET_CLASS); ASSERT_NULL(icmpConnB.sieveLayer); icmpConnB.intf = intf; SNPRINTF(icmpConnB.sieveLayer->infoTag, PCKT_SIEVE_INFOTAG_LEN, "ICMP (ping)"); return icmpConnB; }