卡常大赛
查看原帖
卡常大赛
679581
MrPython小河狸贝瓦楼主2024/4/20 13:40

https://hydro.ac/d/MrPython/record/6623352606b752f13369790d https://www.luogu.com.cn/record/156427661

本地 5.6s hydro 7.4s 洛谷 8s 跑不完

赛时原题评测还是开了 O3 的

是不是开点时限补偿一下()

#include<bits/stdc++.h>
#include<arpa/inet.h>
#ifndef ONLINE_JUDGE
std::ifstream fin("./data/P10348.in",std::ifstream::binary);
std::ofstream fout("./data/P10348.out",std::ofstream::binary);
#else
std::istream& fin=std::cin;
std::ostream& fout=std::cout;
#endif

using Buf=std::vector<uint8_t>;
using Bufp=Buf::const_iterator;
using MacT=std::array<uint8_t,6>;

template<typename T,size_t n> const auto array_hash=[](std::array<T,n> const& f){
    return std::_Hash_impl::hash(f.data(),f.size());
};
constexpr uint32_t genIP(uint8_t a,uint8_t b,uint8_t c,uint8_t d){
    return (a<<24)+(b<<16)+(c<<8)+(d<<0);
}

std::unordered_map<uint32_t,MacT> const eths({
        {genIP(10,2,1,1),{0x98,0x01,0x29,0x00,0x00,1}},
        {genIP(10,2,2,1),{0x98,0x01,0x29,0x00,0x00,2}},
        {genIP(10,2,3,1),{0x98,0x01,0x29,0x00,0x00,3}},
        {genIP(10,2,4,1),{0x98,0x01,0x29,0x00,0x00,4}},
        {genIP(10,2,5,1),{0x98,0x01,0x29,0x00,0x00,5}},
        {genIP(10,2,6,1),{0x98,0x01,0x29,0x00,0x00,6}},
        {genIP(10,2,7,1),{0x98,0x01,0x29,0x00,0x00,7}},
        {genIP(10,2,8,1),{0x98,0x01,0x29,0x00,0x00,8}},
        {genIP(10,2,9,1),{0x98,0x01,0x29,0x00,0x00,9}},
        {genIP(10,2,10,1),{0x98,0x01,0x29,0x00,0x00,10}},
        {genIP(10,2,11,1),{0x98,0x01,0x29,0x00,0x00,11}},
        {genIP(10,2,12,1),{0x98,0x01,0x29,0x00,0x00,12}},
        {genIP(10,2,13,1),{0x98,0x01,0x29,0x00,0x00,13}},
        {genIP(10,2,14,1),{0x98,0x01,0x29,0x00,0x00,14}},
        {genIP(10,2,15,1),{0x98,0x01,0x29,0x00,0x00,15}},
        {genIP(10,2,16,1),{0x98,0x01,0x29,0x00,0x00,16}},
    });
std::unordered_map<MacT,uint32_t,decltype(array_hash<uint8_t,6>)> const macs({
        {{0x98,0x01,0x29,0x00,0x00,1},genIP(10,2,1,1)},
        {{0x98,0x01,0x29,0x00,0x00,2},genIP(10,2,2,1)},
        {{0x98,0x01,0x29,0x00,0x00,3},genIP(10,2,3,1)},
        {{0x98,0x01,0x29,0x00,0x00,4},genIP(10,2,4,1)},
        {{0x98,0x01,0x29,0x00,0x00,5},genIP(10,2,5,1)},
        {{0x98,0x01,0x29,0x00,0x00,6},genIP(10,2,6,1)},
        {{0x98,0x01,0x29,0x00,0x00,7},genIP(10,2,7,1)},
        {{0x98,0x01,0x29,0x00,0x00,8},genIP(10,2,8,1)},
        {{0x98,0x01,0x29,0x00,0x00,9},genIP(10,2,9,1)},
        {{0x98,0x01,0x29,0x00,0x00,10},genIP(10,2,10,1)},
        {{0x98,0x01,0x29,0x00,0x00,11},genIP(10,2,11,1)},
        {{0x98,0x01,0x29,0x00,0x00,12},genIP(10,2,12,1)},
        {{0x98,0x01,0x29,0x00,0x00,13},genIP(10,2,13,1)},
        {{0x98,0x01,0x29,0x00,0x00,14},genIP(10,2,14,1)},
        {{0x98,0x01,0x29,0x00,0x00,15},genIP(10,2,15,1)},
        {{0x98,0x01,0x29,0x00,0x00,16},genIP(10,2,16,1)},
    },0,array_hash<uint8_t,6>);

uint8_t bitreverse(uint8_t x){
    x=((x&0xaa)>>1)|((x&0x55)<<1);
    x=((x&0xcc)>>2)|((x&0x33)<<2);
    x=((x&0xf0)>>4)|((x&0x0f)<<4);
    return x;
}
uint32_t bitreverse(uint32_t x){
    x=(((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1));
    x=(((x&0xcccccccc)>>2)|((x&0x33333333)<<2));
    x=(((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4));
    x=(((x&0xff00ff00)>>8)|((x&0x00ff00ff)<<8));
    x=(((x&0xffff0000)>>16)|((x&0x0000ffff))<<16);
    return x;
}

struct Throwable{};
struct PackageCheckError:Throwable{};
struct UnknownTargetError:Throwable{};

struct pcap_hdr {
    // 所有字段都是大端序
    uint32_t magic_number;// 用于文件类型识别,始终为 0xA1B2C3D4,
    uint16_t version_major;// 始终为 2
    uint16_t version_minor;// 始终为 4
    int32_t thiszone;// 始终为 0
    uint32_t sigfigs;// 始终为 0
    uint32_t snaplen;// 允许的最大包长度,始终为 262144
    uint32_t network;// 数据类型,本次学习题中始终为 1 (以太网)
    pcap_hdr(void):magic_number(0xA1B2C3D4),version_major(2),
        version_minor(4),thiszone(0),sigfigs(0),snaplen(262144),
        network(1){}
    pcap_hdr(Bufp begin):
        magic_number((begin[0]<<24)+(begin[1]<<16)+(begin[2]<<8)+(begin[3]<<0)),
        version_major((begin[4]<<8)+(begin[5]<<0)),
        version_minor((begin[6]<<8)+(begin[7]<<0)),
        thiszone((begin[8]<<24)+(begin[9]<<16)+(begin[10]<<8)+(begin[11]<<0)),
        sigfigs((begin[12]<<24)+(begin[13]<<16)+(begin[14]<<8)+(begin[15]<<0)),
        snaplen((begin[16]<<24)+(begin[17]<<16)+(begin[18]<<8)+(begin[19]<<0)),
        network((begin[20]<<24)+(begin[21]<<16)+(begin[22]<<8)+(begin[23]<<0)){
        assert(magic_number==0xA1B2C3D4&&
               version_major==2&&
               version_minor==4&&
               thiszone==0&&
               sigfigs==0&&
               snaplen==262144&&
               network==1
        );
    }
    friend std::ostream& operator<<(std::ostream& out,pcap_hdr data){
        data.magic_number=htonl(data.magic_number),
        data.version_major=htons(data.version_major),
        data.version_minor=htons(data.version_minor),
        data.thiszone=htonl(data.thiszone),
        data.sigfigs=htonl(data.sigfigs),
        data.snaplen=htonl(data.snaplen),
        data.network=htonl(data.network);
        out.write((char*)&data,sizeof(pcap_hdr));
        return out;
    }
};
struct pcaprec_hdr{
    // 所有字段都是大端序
    uint32_t ts_sec;// 时间戳(秒)
    uint32_t ts_usec;// 时间戳(微秒)
    uint32_t incl_len;// 该片段的存储长度
    uint32_t orig_len;// 该片段实际的长度
    pcaprec_hdr(size_t len,uint64_t t=0):ts_sec(t/uint64_t(1e6)),ts_usec(t%uint64_t(1e6)),incl_len(len),orig_len(len){}
    pcaprec_hdr(Bufp begin):
        ts_sec((begin[0]<<24)+(begin[1]<<16)+(begin[2]<<8)+(begin[3]<<0)),
        ts_usec((begin[4]<<24)+(begin[5]<<16)+(begin[6]<<8)+(begin[7]<<0)),
        incl_len((begin[8]<<24)+(begin[9]<<16)+(begin[10]<<8)+(begin[11]<<0)),
        orig_len((begin[12]<<24)+(begin[13]<<16)+(begin[14]<<8)+(begin[15]<<0)){
        assert(ts_usec<1e6&&incl_len==orig_len);
    }
    friend std::ostream& operator<<(std::ostream& out,pcaprec_hdr data){
        data.incl_len=htonl(data.incl_len),
        data.orig_len=htonl(data.orig_len),
        data.ts_sec=htonl(data.ts_sec),
        data.ts_usec=htonl(data.ts_usec);
        out.write((char*)&data,sizeof(pcaprec_hdr));
        return out;
    }
    uint64_t get_time(void) const{return ts_sec*int64_t(1e6)+ts_usec;}
};
struct pcaprec{
    pcaprec_hdr header;
    Buf data;
    pcaprec(Buf const& d,uint64_t t=0):
        header(d.size(),t),data(d){}
    pcaprec(Bufp begin):
        header(begin),data(begin+16,begin+16+header.orig_len){}
    friend std::ostream& operator<<(std::ostream& out,pcaprec const& data){
        out<<data.header;
        out.write((char*)data.data.data(),data.header.incl_len);
        return out;
    }
};
struct pcap{
    pcap_hdr header;
    std::vector<pcaprec> data;
    pcap(void):header(),data(){}
    pcap(pcap_hdr const& p):header(p),data(){}
    pcap(Bufp begin,Bufp end):
        header(begin),data(){
        begin+=24;
        while (begin!=end)
            data.emplace_back(begin),
            begin+=data.back().header.orig_len+16;
    }
    friend std::ostream& operator<<(std::ostream& out,pcap const& data){
        out<<data.header;
        for (pcaprec const& i:data.data) out<<i;
        return out;
    }
};
struct ethernet_frame{
    MacT destinationMAC,sourceMAC;
    enum class EtherType:uint16_t{
        ipv4=0x0800,arp=0x0806
    } etherType;
    Buf data;
    uint32_t fcs;

    struct CheckError:PackageCheckError{};
    
    ethernet_frame(std::array<uint8_t,6> const& _desMAC,std::array<uint8_t,6> const& _srcMAC,EtherType _t,Buf const& _d):
        destinationMAC(_desMAC),sourceMAC(_srcMAC),etherType(_t),data(_d),fcs(){ // getbuffer 中直接取了 fcs 的值,直接调用初始化访问未分配内存产生 UB
        fcs=get_fcs(tobuffer());
    }
    ethernet_frame(pcaprec const& f):ethernet_frame(f.data.begin(),f.data.end()){}
    ethernet_frame(Bufp beg,Bufp end):
        destinationMAC{beg[0],beg[1],beg[2],beg[3],beg[4],beg[5]},
        sourceMAC{beg[6],beg[7],beg[8],beg[9],beg[10],beg[11]},
        etherType(EtherType((beg[12]<<8)+(beg[13]<<0))),
        data(beg+14,end-4),
        fcs((end[-4]<<24)+(end[-3]<<16)+(end[-2]<<8)+(end[-1]<<0)) {
        if (!check())
            throw CheckError();
    }
    static uint64_t query_fcs_byte(uint8_t x){
        static std::array<uint64_t,256> mem={};
        static constexpr int64_t G=0b100000100110000010001110110110111;
        if (mem[x]) return mem[x];
        if (x==0) return 0;
        uint8_t y=x;
        for (uint8_t i=7;i<8;--i) if ((x>>i)&1)
            x^=uint8_t(G<<i>>32),
            mem[y]^=G<<i;
        return mem[y];
    }
    static uint32_t get_fcs(Buf f){
        std::fill_n(f.end()-4,4,0);
        for (uint8_t& i:f) i=bitreverse(i);
        f[0]=~f[0],f[1]=~f[1],f[2]=~f[2],f[3]=~f[3];
        for (size_t i=4;i<f.size();++i){
            int64_t x=query_fcs_byte(f[i-4]);
            f[i-4]^=uint8_t(x>>(40-8)),
            f[i-3]^=uint8_t(x>>(40-16)),
            f[i-2]^=uint8_t(x>>(40-24)),
            f[i-1]^=uint8_t(x>>(40-32)),
            f[i-0]^=uint8_t(x>>(40-40));
        }
        uint32_t res=~(
            ((uint32_t)bitreverse(f.rbegin()[3])<<24u)+
            ((uint32_t)bitreverse(f.rbegin()[2])<<16u)+
            ((uint32_t)bitreverse(f.rbegin()[1])<<8u)+
            ((uint32_t)bitreverse(f.rbegin()[0])<<0u)
        );
        return res;
    }
    bool check(void){return fcs==get_fcs(tobuffer());}
    Buf tobuffer(void){
        Buf res{
            destinationMAC[0],destinationMAC[1],destinationMAC[2],destinationMAC[3],destinationMAC[4],destinationMAC[5],
            sourceMAC[0],sourceMAC[1],sourceMAC[2],sourceMAC[3],sourceMAC[4],sourceMAC[5],
            uint8_t(uint16_t(etherType)>>8),uint8_t(uint16_t(etherType)>>0)
        };
        res.insert(res.end(),data.begin(),data.end());
        while (res.size()<64-4) res.push_back(0);  // 长度至少为 64
        res.insert(res.end(),{uint8_t(fcs>>24),uint8_t(fcs>>16),uint8_t(fcs>>8),uint8_t(fcs>>0)});
        return res;
    }
};
struct ipgroup_hdr{
    uint8_t version:4; // 始终为 0b0100
    uint8_t ihl:4;
    uint8_t type; // 始终为 0
    uint16_t total_length;
    uint16_t identification; // 始终为 0
    uint8_t flag:3; // 始终为 0b010
    uint16_t offset:13; // 始终为 0
    uint8_t time_to_live;
    enum class Protocol:uint8_t{
        TCP=0x06,UDP=0x11,ICMP=0x01
    } protocol;
    uint16_t header_checksum;
    uint32_t source_ip,destination_ip;
    Buf options;

    struct CheckError:PackageCheckError{};

    ipgroup_hdr(uint16_t bodylen,Protocol _protocol,uint32_t const& _source_ip,
        uint32_t const& _destination_ip,Buf const& _options={},uint8_t _time_to_live=64):
        version(0b0100),ihl((_options.size()+20)/4),type(),total_length(20+_options.size()+bodylen),identification(0),
        flag(0b010),offset(0),time_to_live(_time_to_live),protocol(_protocol),
        source_ip(_source_ip),destination_ip(_destination_ip),options(_options){
        header_checksum=get_checksum(tobuffer());
    }
    ipgroup_hdr(ethernet_frame const& f):ipgroup_hdr(f.data.begin()){}
    ipgroup_hdr(Bufp beg):
        version(beg[0]>>4),ihl(beg[0]&0xf),type(beg[1]),
        total_length((beg[2]<<8)+(beg[3]<<0)),
        identification((beg[4]<<8)+(beg[5]<<0)),
        flag(beg[6]>>5),
        offset(((beg[6]&0b00011111)<<8)+(beg[7]<<0)),
        time_to_live(beg[8]),protocol(Protocol(beg[9])),
        header_checksum((beg[10]<<8)+(beg[11]<<0)),
        source_ip((beg[12]<<24)+(beg[13]<<16)+(beg[14]<<8)+(beg[15]<<0)),
        destination_ip((beg[16]<<24)+(beg[17]<<16)+(beg[18]<<8)+(beg[19]<<0)),
        options(beg+20,beg+ihl*4){
        assert(
            version==0b0100&&type==0&&
            flag==0b010&&offset==0&&
            identification==0&&ihl>=5&&total_length>=20
        );
        if (!check()) throw CheckError();
    }
    bool check(void){return get_checksum(tobuffer())==header_checksum;}
    static uint16_t get_checksum(Buf const& f){
        size_t n=(f[0]&0xf)*4;
        uint32_t sum=0;
        for (size_t i=0;i<n;i+=2) if (i!=10){
            sum+=(f[i+0]<<8)+(f[i+1]<<0);
            uint16_t x;
            while ((x=(sum>>16))) sum&=0xffff,sum+=x;
        }
        return ~sum;
    }
    Buf tobuffer(void){
        Buf res={
            uint8_t((version<<4)+(ihl<<0)),type,uint8_t(total_length>>8),uint8_t(total_length>>0),
            uint8_t(identification>>8),uint8_t(identification>>0),uint8_t((flag<<5)+(offset>>8)),uint8_t(offset),
            time_to_live,uint8_t(protocol),uint8_t(header_checksum>>8),uint8_t(header_checksum>>0),
            uint8_t(source_ip>>24),uint8_t(source_ip>>16),uint8_t(source_ip>>8),uint8_t(source_ip>>0),
                uint8_t(destination_ip>>24),uint8_t(destination_ip>>16),uint8_t(destination_ip>>8),uint8_t(destination_ip>>0)
        };
        res.insert(res.end(),options.begin(),options.end());
        return res;
    }
};
struct ipgroup{
    ipgroup_hdr header;
    Buf data;
    ipgroup(ethernet_frame const& f):ipgroup(f.data.begin()){}
    ipgroup(ipgroup_hdr const& a,Buf const& b):header(a),data(b){}
    ipgroup(Bufp beg):
        header(beg),data(beg+header.ihl*4,beg+header.total_length){}
    Buf tobuffer(void){
        Buf res=header.tobuffer();
        res.insert(res.end(),data.begin(),data.end());
        return res;
    }
};
struct arp{
    uint16_t hardware_type; // 总是 1
    uint16_t protocol_type; // 总是 0x0800
    uint8_t hlen; // 总是 0x6
    uint8_t plen; // 总是 0x4
    enum class OPCode:uint16_t{request=1,response=2} opcode;
    MacT sha;
    uint32_t spa;
    MacT tha;
    uint32_t tpa;

    struct OPNotRequest:UnknownTargetError{};
    struct IPNotFound:UnknownTargetError{};

    arp(OPCode _type,MacT const& _sha,uint32_t const& _spa,MacT const& _tha,uint32_t const& _tpa):
        hardware_type(1),protocol_type(0x0800),hlen(6),plen(4),
        opcode(_type),sha(_sha),spa(_spa),tha(_tha),tpa(_tpa){}
    arp(ethernet_frame const& f):arp(f.data.begin()){}
    arp(Bufp beg):
        hardware_type((beg[0]<<8)+(beg[1]<<0)),
        protocol_type((beg[2]<<8)+(beg[3]<<0)),
        hlen(beg[4]),plen(beg[5]),
        opcode(OPCode((beg[6]<<8)+(beg[7]<<0))),
        sha{beg[8],beg[9],beg[10],beg[11],beg[12],beg[13]},
        spa((beg[14]<<24)+(beg[15]<<16)+(beg[16]<<8)+(beg[17]<<0)),
        tha{beg[18],beg[19],beg[20],beg[21],beg[22],beg[23]},
        tpa((beg[24]<<24)+(beg[25]<<16)+(beg[26]<<8)+(beg[27]<<0)){
        assert(hardware_type==1&&protocol_type==0x0800&&hlen==6&&plen==4);
    }
    Buf tobuffer(void){
        return {
            uint8_t(hardware_type>>8),uint8_t(hardware_type>>0),
            uint8_t(protocol_type>>8),uint8_t(protocol_type>>0),
            hlen,plen,uint8_t((uint16_t)opcode>>8),uint8_t((uint16_t)opcode>>0),
            sha[0],sha[1],sha[2],sha[3],
            sha[4],sha[5],uint8_t(spa>>24),uint8_t(spa>>16),
            uint8_t(spa>>8),uint8_t(spa>>0),tha[0],tha[1],
            tha[2],tha[3],tha[4],tha[5],
            uint8_t(tpa>>24),uint8_t(tpa>>16),uint8_t(tpa>>8),uint8_t(tpa>>0),
        };
    }
    arp get_response(void){
        if (opcode!=OPCode::request) throw OPNotRequest();
        auto it=eths.find(tpa);
        if (it==eths.end()) throw IPNotFound();
        return arp(OPCode::response,it->second,it->first,sha,spa);
    };
};
struct icmp_hdr{
    enum class Type:uint16_t{ // 简化,将 type 与 code 压到一起
        EchoRequest=(8<<8),
        EchoReply=(0<<8),
        DestinationNetworkUnreachable=(3<<8),
        TimeExceeded=(11<<8),
    } type;
    uint16_t checksum; // 总是 0
    uint32_t rest_of_header; // 总是 0

    struct OPNotRequest:UnknownTargetError{};

    icmp_hdr(Type _t):type(_t),checksum(0),rest_of_header(0){}
    icmp_hdr(Bufp f):type(Type((f[0]<<8)+(f[1]<<0))),checksum((f[2]<<8)+(f[3]<<0)),
        rest_of_header((f[4]<<24)+(f[5]<<16)+(f[6]<<8)+(f[7]<<0)){
        assert(checksum==0&&rest_of_header==0);
    }
    icmp_hdr get_echo_response(void){
        if (type!=Type::EchoRequest) throw OPNotRequest();
        return icmp_hdr(Type::EchoReply);
    }
    Buf tobuffer(void){
        return {
            uint8_t((uint16_t)type>>8),uint8_t((uint16_t)type>>0),uint8_t(checksum>>8),uint8_t(checksum>>0),
            uint8_t(rest_of_header>>24),uint8_t(rest_of_header>>16),uint8_t(rest_of_header>>8),uint8_t(rest_of_header>>0),
        };
    }
};
struct icmp{
    icmp_hdr header;
    Buf data;
    icmp(ipgroup const& x):icmp(x.data.begin(),x.data.end()){}
    icmp(icmp_hdr const& _h,Buf const& _d):header(_h),data(_d){}
    icmp(Bufp beg,Bufp end):header(beg),data(beg+8,end){}
    icmp get_echo_response(void){return icmp(header.get_echo_response(),data);}
    Buf tobuffer(void){
        Buf res=header.tobuffer();
        res.insert(res.end(),data.begin(),data.end());
        return res;
    }
    ipgroup to_ipgroup(uint32_t source_ip,uint32_t dest_ip){
        Buf buf=tobuffer();
        return ipgroup(ipgroup_hdr(
            buf.size(),ipgroup_hdr::Protocol::ICMP,
            source_ip,dest_ip
        ),buf);
    }
};
struct udp_hdr{
    uint16_t source_port,destination_port;
    uint16_t len;
    uint16_t checksum;  // 总是 0
    udp_hdr(Bufp beg):
        source_port((beg[0]<<8)+(beg[1]<<0)),
        destination_port((beg[2]<<8)+(beg[3]<<0)),
        len((beg[4]<<8)+(beg[5]<<0)),
        checksum((beg[6]<<8)+(beg[7]<<0)){
        assert(checksum==0);
    }
};
struct udp{
    udp_hdr header;
    std::vector<uint8_t> data;
    udp(Bufp beg,Bufp end):header(beg),data(beg+8,end){}
    udp(ipgroup const& f):udp(f.data.begin(),f.data.end()){}
};
struct rip_hdr{
    uint8_t command; // 始终为 2
    uint8_t version; // 始终为 2
    uint16_t zero; // 始终为 0
    rip_hdr(Bufp beg):command(beg[0]),version(beg[1]),zero((beg[2]<<8)+(beg[3]<<0)){}
};
struct ripprec{
    uint16_t address_family; // 始终为 2
    uint16_t route_tag; // 始终为 0
    uint32_t ipv4_address,subnet_mask,next_hop,metric;
    ripprec(Bufp beg):
        address_family((beg[0]<<8)+(beg[1]<<0)),route_tag((beg[2]<<8)+(beg[3]<<0)),
        ipv4_address((beg[4]<<24)+(beg[5]<<16)+(beg[6]<<8)+(beg[7]<<0)),
        subnet_mask((beg[8]<<24)+(beg[9]<<16)+(beg[10]<<8)+(beg[11]<<0)),
        next_hop((beg[12]<<24)+(beg[13]<<16)+(beg[14]<<8)+(beg[15]<<0)),
        metric((beg[16]<<24)+(beg[17]<<16)+(beg[18]<<8)+(beg[19]<<0)){
        assert(address_family==2&&route_tag==0);
    }
};
struct rip{
    rip_hdr header;
    std::vector<ripprec> data;
    rip(Bufp beg,Bufp end):header(beg),data(){
        beg+=4;
        while (beg!=end)
            data.emplace_back(beg),
            beg+=20;
    }
    rip(udp const& x):rip(x.data.begin(),x.data.end()){}
};

struct Router{
    struct RouterEmpty{};
    struct treenode{
        uint32_t dest,metric;uint8_t port;bool status;
        std::array<treenode*,2> next;
        treenode(void):status(false),next{}{}
        std::pair<uint32_t,uint8_t> top(){
            return status?std::pair<uint32_t,uint8_t>{dest,port}:throw RouterEmpty();
        }
        void remove(uint32_t ip){status=false;}
        void insert(uint32_t ip,uint32_t d,uint8_t p){
            if (!status) status=true,metric=~0;
            if (d<metric) dest=ip,metric=d+1,port=p;
        }
        treenode* jmp(uint32_t x,uint8_t d){
            if (d==0) return this;
            treenode*& nxt=next[x&1];
            if (!nxt) nxt=new treenode;
            return nxt->jmp(x>>1,d-1);
        }
        template<typename F> void for_each(uint32_t x,uint8_t d,F const& f){
            if (d==0) return;
            treenode*& nxt=next[x&1];
            f(this);
            if (!nxt) return;
            nxt->for_each(x>>1,d-1,f);
        }
        ~treenode(){delete next[0],delete next[1];}
    } root;
    void insert(uint32_t address,uint8_t mask,uint32_t nexthop,uint32_t metric,uint8_t port)
        {root.jmp(bitreverse(address),mask)->insert(nexthop,metric,port);}
    void remove(uint32_t address,uint8_t mask,uint32_t nexthop)
        {root.jmp(bitreverse(address),mask)->remove(nexthop);}
    void op(uint32_t address,uint8_t mask,uint32_t nexthop,uint32_t metric,uint8_t port){
        metric==16?remove(address,mask,nexthop):insert(address,mask,nexthop,metric,port);
    }
    std::pair<uint32_t,uint8_t> find(uint32_t target){
        bool flag=false;std::pair<uint32_t,uint8_t> res;
        root.for_each(bitreverse(target),32,[&flag,&res](treenode* node){
            try{
                res=node->top();
                flag=true;
            }catch(RouterEmpty const&){} // continue
        });
        if (flag==false) throw RouterEmpty();
        return res;
    }
};
namespace RouterTreenodeAlloc{
    // Router::treenode* ptr=(Router::treenode*)operator new(size_t(1.5e7)*sizeof(Router::treenode));
    Router::treenode* allocate(void){
        // new(ptr)(Router::treenode)();
        // return ptr++;
        return new Router::treenode;
    }
}
int main(void){
    std::ios::sync_with_stdio(false),std::cin.tie(nullptr),std::cout.tie(nullptr);
    std::unordered_map<uint32_t,MacT> ip_to_mac;Router router;
    std::vector<uint8_t> buf((std::istreambuf_iterator<char>(fin)),std::istreambuf_iterator<char>());
    pcap f(buf.begin(),buf.end()),g;
    for (auto const& i:f.data)
        try{
            ethernet_frame o(i);
            if (o.destinationMAC==MacT{0x01,0x00,0x5e,0x00,0x00,0x09}){
                ipgroup p(o);
                assert(p.header.destination_ip==genIP(224,0,0,9)&&p.header.protocol==ipgroup_hdr::Protocol::UDP);
                ip_to_mac[p.header.source_ip]=o.sourceMAC;
                rip q(udp{p});
                for (auto const& j:q.data)
                    router.op(
                        j.ipv4_address,[](uint32_t x){
                            uint8_t ans=__builtin_ctzll((1ll<<32)+x);
                            assert((((x>>ans)+1)&(x>>ans))==0);
                            return 32-ans;
                        }(j.subnet_mask),j.next_hop?j.next_hop:p.header.source_ip,j.metric,
                        uint8_t((j.next_hop?j.next_hop:p.header.source_ip)>>8)
                    );
            }else if (macs.count(o.destinationMAC)){
                ipgroup p(o);
                try{
                    auto destIP=router.find(p.header.destination_ip);
                    auto it=ip_to_mac.find(destIP.first);
                    if (it==ip_to_mac.end()) throw Router::RouterEmpty();
                if (p.header.time_to_live>1) // 未过期
                    g.data.emplace_back(ethernet_frame(it->second,{0x98,0x01,0x29,0x00,0x00,destIP.second},
                        ethernet_frame::EtherType::ipv4,
                        ipgroup(ipgroup_hdr(
                            p.data.size(),p.header.protocol,
                            p.header.source_ip,p.header.destination_ip,
                            {},p.header.time_to_live-1
                        ),p.data).tobuffer()).tobuffer()
                    );
                else
                    g.data.emplace_back(ethernet_frame(
                        o.sourceMAC,o.destinationMAC,
                        ethernet_frame::EtherType::ipv4,
                        icmp(icmp_hdr(icmp_hdr::Type::TimeExceeded),[&]{
                                std::vector<uint8_t> res(p.header.tobuffer());
                                res.insert(res.end(),p.data.begin(),p.data.begin()+8);
                                return res;
                            }()).to_ipgroup(macs.at(o.destinationMAC),p.header.source_ip).tobuffer()
                        ).tobuffer()
                    );
                }catch (Router::RouterEmpty const&){
                        g.data.emplace_back(ethernet_frame(
                            o.sourceMAC,o.destinationMAC,
                            ethernet_frame::EtherType::ipv4,
                            icmp(icmp_hdr(icmp_hdr::Type::DestinationNetworkUnreachable),[&]{
                                std::vector<uint8_t> res(p.header.tobuffer());
                                res.insert(res.end(),p.data.begin(),p.data.begin()+8);
                                return res;
                            }()).to_ipgroup(macs.at(o.destinationMAC),p.header.source_ip).tobuffer()
                        ).tobuffer());
                    }
                
            }
        }catch (PackageCheckError const&){}
    fout<<g;
    return 0;
}
2024/4/20 13:40
加载中...