Solved sysctl 'kern.bootp_cookie' is not being set by DHCP Option 134 (pxe vendor specific) related to existing src/sys/nfs/bootp_subr.c - Send help please!

I have a DHCP Server which is sending DHCP option 134 (a simple string of "this that something else"), and an altered MTU (1300) using dnsmasq:
Code:
dhcp-option-force=FREEBSD,26,1300
dhcp-option-force=FREEBSD,134,this that something else
Code:
dnsmasq-dhcp: 1 sent size:  2 option: 26 mtu  1300
dnsmasq-dhcp: 1 sent size: 24 option:134   74:68:69:73:20:74:68:61:74:20:73:6f:6d:65...

I have also confirmed that both, the UEFI (not BIOS) PXE client, and the second DHCP request from the FreeBSD loader (loader.efi), are being sent the above with their leases using tcpdump -n -vvvv port 67 or port 68.

The interface mtu is being set correctly, but the sysctl kern.bootp_cookie is not set.

In /usr/src/sys/nfs/bootp_subr.c it has two sections relating to this:
Code:
(Line 217)
#define TAG_COOKIE    134    /* ascii info for userland, via sysctl */
....
(Line 237)
static char bootp_cookie[128];
static struct socket *bootp_so;
SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
    bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
....
Code:
(Line 1462) bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
...
    }
    p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, TAG_COOKIE);
    if (p != NULL) {        /* store in a sysctl variable */
        int i, l = sizeof(bootp_cookie) - 1;
        for (i = 0; i < l && p[i] != '\0'; i++)
            bootp_cookie[i] = p[i];
        p[i] = '\0';
    }

    p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, TAG_INTF_MTU);
    if (p != NULL) {
        ifctx->mtu = be16dec(p);
    }
...
}

So the code is there and the mtu is set correctly and is after the bootp_cookie code.

One strange thing is, that while that code is there, when I issue sysctl kern.bootp_cookie, it responds with:
Code:
sysctl: unknown oid 'kern.bootp_cookie'
!!!

Seems like the function SYSCTL_STRING is not being compiled into GENERIC?

Can anyone shead any light as to why I am getting unknown oid for 'kern.bootp_cookie', i.e. why the oid is missing, and as to why the code isn't behaving as expected?

Thanks in advance,
James.
 
Ah, I see now.

The fact that the BOOTP protocol is being used to boot the machine is completely independent of which code block FreeBSD uses: diskless() code or (I presume) the older BOOTP code.

There is indeed an option BOOTP twiddle in the kernel configuration, which causes the FreeBSD to issue a 3rd DHCP request on the first found interface (or the interface name as set within the kernel CONF file at build time; ouch). The first interface or 'build locked interface to use' approach is not very flexible on multi-NIC machines with a varied environment.

As background, the 1st DHCP Request is from the 'BIOS/UEFI PXE Client' to find the TFTP server details, and the 2nd is either pxeboot or loader.efi finding the kernel via the NFS Root.

When option BOOTP is not in the KERNCONF file for the kernel (option BOOTP is not in the GENERIC kernel) only two DHCP requests are issued during boot.

I can also see why diskless() is preferred over the option BOOTP approach which is very fixed, rigid and potentially fragile to environmental change.

And also (happily) I found the data I was looking for using kenv() once I understood where the decision to use either diskless() or BOOTP code was made and where to look in the codebase.
  • INFO: Any DHCP options that are unrecognised by FreeBSD during the chaining of loader.efi passing control over to the kernel are nicely passed through as part of the kernel boot environment, so DHCP Option 134 is stored in kenv dhcp.option-134 for userland to pick up accordingly. Nice.
Thanks for the pointer covacat, very helpful.
 
Back
Top