Skip to content

Commit

Permalink
Option 77 Additions to dhclient
Browse files Browse the repository at this point in the history
These changes were present in the dhclient used in pfSense 2.3, they
seem not to have made it into FreeBSD 11 as used in pfSense 2.4.

I have merely taken the changes and applied them to the FreeBSD 11
dhclient. Users who require this have tested it and confirm it is
working fine.

Reworked-by: Franco Fichtner <franco@opnsense.org>
  • Loading branch information
marjohn56 authored and fichtner committed Dec 30, 2017
1 parent 5f9b491 commit c24697c
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 22 deletions.
43 changes: 30 additions & 13 deletions sbin/dhclient/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,47 @@ if_register_bpf(struct interface_info *info, int flags)
* 'ip and udp and src port bootps and dst port (bootps or bootpc)'
*/
struct bpf_insn dhcp_bpf_wfilter[] = {
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12),
/*
* BROKEN/WIP: must also check (and pass) if packet has 802.1q encapsulation
*/
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),

/* 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, 10),
/* Set indexing offset to 0 */
BPF_STMT(BPF_LDX + BPF_B + BPF_IMM, 0),

/* Load Ethernet type */
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 12),

/* Check if it is an IP packet */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 2, 0),

/* If not, check if it is a 802.1q packet */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_VLAN, 0, 10),
/* If it is, change offset for further tests */
BPF_STMT(BPF_LDX + BPF_B + BPF_IMM, 4),

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

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

/*
* IP checks
*/
/* Move index to accumulator */
BPF_STMT(BPF_MISC + BPF_TXA, 0),

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

/* Add it to the base offset */
BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0),
/* Store it in X */
BPF_STMT(BPF_MISC + BPF_TAX, 0),

/* Make sure it's from the right port... */
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3),
Expand Down Expand Up @@ -152,12 +175,6 @@ if_register_send(struct interface_info *info)
p.bf_len = dhcp_bpf_wfilter_len;
p.bf_insns = dhcp_bpf_wfilter;

if (dhcp_bpf_wfilter[7].k == 0x1fff)
dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK);

if (ioctl(info->wfdesc, BIOCSETWF, &p) < 0)
error("Can't install write filter program: %m");

if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0)
error("Cannot lock bpf");

Expand Down
6 changes: 6 additions & 0 deletions sbin/dhclient/conflex.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ intern(char *atom, int dfv)
case 's':
if (!strcasecmp(atom + 1, "earch"))
return (SEARCH);
if (!strcasecmp(atom + 1, "end-interface"))
return (SEND_INTERFACE);
if (!strcasecmp(atom + 1, "tarts"))
return (STARTS);
if (!strcasecmp(atom + 1, "iaddr"))
Expand Down Expand Up @@ -519,6 +521,10 @@ intern(char *atom, int dfv)
case 'v':
if (!strcasecmp(atom + 1, "endor-class"))
return (VENDOR_CLASS);
if (!strcasecmp(atom + 1, "lan-id"))
return (VLAN_ID);
if (!strcasecmp(atom + 1, "lan-pcp"))
return (VLAN_PCP);
break;
case 'y':
if (!strcasecmp(atom + 1, "iaddr"))
Expand Down
3 changes: 3 additions & 0 deletions sbin/dhclient/dhcpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ struct client_config {
u_int8_t required_options[256];
u_int8_t requested_options[256];
int requested_option_count;
int vlan_id;
int vlan_pcp;
char *send_interface;
time_t timeout;
time_t initial_interval;
time_t retry_interval;
Expand Down
3 changes: 3 additions & 0 deletions sbin/dhclient/dhctoken.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
#define AUTHORITATIVE 333
#define TOKEN_NOT 334
#define ALWAYS_REPLY_RFC1048 335
#define VLAN_ID 336
#define VLAN_PCP 337
#define SEND_INTERFACE 338

#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) != STRING && \
Expand Down
16 changes: 15 additions & 1 deletion sbin/dhclient/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static int interface_status(struct interface_info *ifinfo);
void
discover_interfaces(struct interface_info *iface)
{
char *sname = iface->client->config->send_interface;
struct ifaddrs *ifap, *ifa;
struct sockaddr_in foo;
struct ifreq *tif;
Expand Down Expand Up @@ -124,7 +125,20 @@ discover_interfaces(struct interface_info *iface)

/* Register the interface... */
if_register_receive(iface);
if_register_send(iface);
if (sname != NULL) {
char rname[IFNAMSIZ];

/* Change interface name for bpf registration */
strlcpy(rname, iface->name, IFNAMSIZ);
strlcpy(iface->ifp->ifr_name, sname, IFNAMSIZ);

if_register_send(iface);

/* Change name back to original */
strlcpy(iface->ifp->ifr_name, rname, IFNAMSIZ);
} else {
if_register_send(iface);
}
add_protocol(iface->name, iface->rfdesc, got_one, iface);
freeifaddrs(ifap);
}
Expand Down
26 changes: 18 additions & 8 deletions sbin/dhclient/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,29 @@ void
assemble_hw_header(struct interface_info *interface, unsigned char *buf,
int *bufix)
{
struct ether_header eh;
int vlpcp = interface->client->config->vlan_pcp;
int vlid = interface->client->config->vlan_id;
int plen = ETHER_HEADER_SIZE;
struct ether_vlan_header eh;

memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost));
memset(eh.evl_dhost, 0xff, sizeof(eh.evl_dhost));
if (interface->hw_address.hlen == sizeof(eh.ether_shost))
memcpy(eh.ether_shost, interface->hw_address.haddr,
sizeof(eh.ether_shost));
memcpy(eh.evl_shost, interface->hw_address.haddr,
sizeof(eh.evl_shost));
else
memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost));
memset(eh.evl_shost, 0x00, sizeof(eh.evl_shost));

eh.evl_encap_proto = htons(ETHERTYPE_IP);

eh.ether_type = htons(ETHERTYPE_IP);
if (vlid != 0) {
eh.evl_tag = htons(EVL_MAKETAG(vlid, vlpcp, 0));
eh.evl_encap_proto = htons(ETHERTYPE_VLAN);
eh.evl_proto = htons(ETHERTYPE_IP);
plen += ETHER_VLAN_ENCAP_LEN;
}

memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE);
*bufix += ETHER_HEADER_SIZE;
memcpy(&buf[*bufix], &eh, plen);
*bufix += plen;
}

void
Expand Down

0 comments on commit c24697c

Please sign in to comment.