Dear readers,

  since 5.8 i ve been carrying around patches to manage :
* crazy server sending hostname like "crazy ISP name with space" ( in
one case the ignore or supersede failed to workaround the problem ),
it  is a bit hard to test, and it looks like some improvement was made
to crash fatal on all invalid network information,
* and a bridging case, which is more realistic :

Assuming the EGRESS is Bridged to a vether, a pair or something to
serve the same LAN to a VM or something else, the first dhclient will eat
the paquet in the BPF filter because MAC are ignored.

MAC are ignored for some obscure historic case where the dhcp server responded
with broadcast or something.

To see the problem , assuming em0 is egress like :

# ifconfig  em0
em0: 
flags=808b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST,AUTOCONF4>
mtu 1500
        lladdr 00:ff:18:0b:4a:ee
        index 1 priority 0 llprio 3
        groups: egress
        media: Ethernet autoselect (100baseTX full-duplex,rxpause,txpause)
        status: active
        inet 172.16.1.4 netmask 0xffffff00 broadcast 172.16.1.255

Bridge it to something

ifconfig  vether0 create
ifconfig  vether0 rdomain 1
ifconfig  bridge0 create
ifconfig  bridge0 add em0
ifconfig  bridge0 add vether0
#safety net
echo <<< EOF >> /etc/dhclient
interface "vether1" {
    send host-name "bridged-sub-host-1";
    send dhcp-lease-time 3600;
    ignore domain-name-servers,routers;
    require subnet-mask,domain-name-servers;
}
#testing
ifconfig  bridge0 up
route -T 1 exec dhclient vether0

No lease ! because dhclient on em0 is actually filtering them at bpf level
A year ago the hw_addr was kept inside the daemon so i am not sure how
to apply my bpf filter.

To not break something the path add a -m option to dhclient that
enable mac bpf filter awareness,

In configure_bpf_sock, I added a  ` uint8_t *  ether_addr_octet` param
that is not null
and setup in case -m is passed to fill in a slightly different filter.

        /* Set up the bpf filter program structure. */
        p.bf_len = dhcp_bpf_mac_filter_len;
        p.bf_insns = dhcp_bpf_mac_filter;
        dhcp_bpf_mac_filter[8].k = LOCAL_PORT;
        memcpy(&bits16, ether_addr_octet, sizeof(bits16));
        dhcp_bpf_mac_filter[10].k = ntohs(bits16);
        memcpy(&bits, ether_addr_octet + 2, sizeof(bits));
        dhcp_bpf_mac_filter[12].k = ntohl(bits);

with the filter :

struct bpf_insn dhcp_bpf_mac_filter[] = {
    /* Make sure this is an IP packet. */
    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),

    /* Make sure it's a UDP packet. */
    BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),

    /* Make sure this isn't a fragment. */
    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
    BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 8, 0),

    /* Get the IP header length. */
    BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),

    /* Make sure it's to the right port. */
    BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),      /* patch */

    /* check bootp.hw.addr 2 bytes */
    BPF_STMT(BPF_LD + BPF_H + BPF_IND, 50),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 0, 3),      /* patch */
    /* check bootp.hw.addr 4 bytes */
    BPF_STMT(BPF_LD + BPF_W + BPF_IND, 52),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x00000000, 0, 1),  /* patch */

    /* If we passed all the tests, ask for the whole packet. */
    BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1),

    /* Otherwise, drop it. */
    BPF_STMT(BPF_RET+BPF_K, 0),
};

int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn);
int dhcp_bpf_mac_filter_len = sizeof(dhcp_bpf_mac_filter) /
sizeof(struct bpf_insn);

I would gladly test an officially made diff because this is becoming
hard to maintain,
and there should be use cases out there.

The only workaround I know is to put egress in a vether behind the bridges,
certainly something that could break anyway.

Thanks for reading up to there !

-- 
--
---------------------------------------------------------------------------------------------------------------------
Knowing is not enough; we must apply. Willing is not enough; we must do

Reply via email to