Skip to content

Commit abf5bff

Browse files
fichtnermarkjdb
authored andcommitted
dhclient: support VID 0 (no vlan) decapsulation
VLAN ID 0 is supposed to be interpreted as having no VLAN with a bit of priority on the side, but the kernel is not able to decapsulate this on the fly so dhclient needs to take care of it. Reviewed by: markj MFC after: 3 weeks Differential Revision: https://reviews.freebsd.org/D31515
1 parent 9958999 commit abf5bff

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

sbin/dhclient/bpf.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/*-
66
* SPDX-License-Identifier: BSD-3-Clause
77
*
8+
* Copyright (c) 2021 Franco Fichtner <franco@opnsense.org>
89
* Copyright (c) 1995, 1996, 1998, 1999
910
* The Internet Software Consortium. All rights reserved.
1011
*
@@ -187,20 +188,58 @@ if_register_send(struct interface_info *info)
187188
* Packet filter program...
188189
*/
189190
static const struct bpf_insn dhcp_bpf_filter[] = {
191+
/* Use relative index (0) for IP packet... */
192+
BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, 0),
193+
194+
/*
195+
* Test whether this is a VLAN packet...
196+
*
197+
* In case the server packet is using a VLAN ID
198+
* of 0, meaning an untagged priority was set, the
199+
* response shall be read and replied to.
200+
*/
201+
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 12),
202+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_VLAN, 0, 4),
203+
204+
/* Test whether it has a VID of 0 */
205+
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14),
206+
BPF_STMT(BPF_ALU + BPF_AND + BPF_K, EVL_VLID_MASK),
207+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 17),
208+
209+
/* Correct the relative index for VLAN packet (4)... */
210+
BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, 4),
211+
190212
/* Make sure this is an IP packet... */
191-
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
192-
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
213+
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 12),
214+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 14),
193215

194216
/* Make sure it's a UDP packet... */
195-
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
196-
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
217+
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 23),
218+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 12),
197219

198220
/* Make sure this isn't a fragment... */
199-
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
200-
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, IP_MF|IP_OFFMASK, 4, 0),
221+
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 20),
222+
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, IP_MF|IP_OFFMASK, 10, 0),
201223

202-
/* Get the IP header length... */
224+
/*
225+
* Get the IP header length...
226+
*
227+
* To find the correct position of the IP header
228+
* length field store the index (0 or 4) in the
229+
* accumulator and compare it with 0.
230+
*/
231+
BPF_STMT(BPF_MISC + BPF_TXA, 0),
232+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 2),
233+
/* Store IP header length of IP packet in index. */
203234
BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
235+
/* Skip over following VLAN handling instruction. */
236+
BPF_JUMP(BPF_JMP + BPF_JA, 1, 0, 0),
237+
/* Store IP header length of VLAN packet in index. */
238+
BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 18),
239+
/* Add IP header length to previous relative index. */
240+
BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0),
241+
/* Move result back to index to reach UDP header below. */
242+
BPF_STMT(BPF_MISC + BPF_TAX, 0),
204243

205244
/* Make sure it's to the right port... */
206245
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),

sbin/dhclient/packet.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ decode_hw_header(unsigned char *buf, int bufix, struct hardware *from)
157157
from->htype = ARPHRD_ETHER;
158158
from->hlen = sizeof(eh.ether_shost);
159159

160-
return (sizeof(eh));
160+
return (sizeof(eh) + (ntohs(eh.ether_type) == ETHERTYPE_VLAN ?
161+
ETHER_VLAN_ENCAP_LEN : 0));
161162
}
162163

163164
ssize_t

0 commit comments

Comments
 (0)