Re: [systemd-devel] [PATCH 1/2] dhcp-network: add check for DHCP.chaddr

2014-07-07 Thread Michal Sekletar
On Tue, Jun 24, 2014 at 03:54:54PM +0200, Tom Gundersen wrote:
 On Tue, Jun 24, 2014 at 12:58 PM, Michal Sekletar msekl...@redhat.com wrote:
  On Thu, Jun 19, 2014 at 12:02:39PM -0500, Dan Williams wrote:
  On Thu, 2014-06-19 at 18:59 +0200, Michal Sekletar wrote:
   Check that received DHCP packets actually include our MAC address in
   chaddr field. BPF interpreter has 32 bit wide registers but MAC address
   is 48 bits long so we have to do check in two steps.
 
  And if the MAC address is not 48 bits (Infiniband) or the interface type
  doesn't really have a MAC address (PPP/PPPoE)?  DHCP can be used in both
  cases...  If anything, the code that uses the MAC address should be
  if-ed so it only executes when a MAC address is provided.
 
  I reconsidered. In filter code I can very easily find out type of device to 
  which
  filter is attached and skip ethernet specific bits or fallback to something
  else. However filter already assumes ethernet data-link type moreover there 
  is a ton of
  code in networkd which does likewise.
 
  I think we should merge patch as is right now. If somebody will hack up 
  patches
  for supporting various data-link types I will be happy to patch filter
  accordingly.
 
 Ok. I'm fine with that. Please push.

Applied!

 
 Just to make clear: I'd be happy if anyone wanted to turn all our libs
 to work also on non-ethernet (and test it!), and would merge such
 patches.
 
 Cheers,
 
 Tom
 
src/libsystemd-network/dhcp-internal.h|  3 ++-
src/libsystemd-network/dhcp-network.c | 15 +--
src/libsystemd-network/sd-dhcp-client.c   |  4 ++--
src/libsystemd-network/test-dhcp-client.c |  2 +-
4 files changed, 18 insertions(+), 6 deletions(-)
  
   diff --git a/src/libsystemd-network/dhcp-internal.h 
   b/src/libsystemd-network/dhcp-internal.h
   index 03cc824..fd86a70 100644
   --- a/src/libsystemd-network/dhcp-internal.h
   +++ b/src/libsystemd-network/dhcp-internal.h
   @@ -24,12 +24,13 @@
  
#include stdint.h
#include linux/if_packet.h
   +#include net/ethernet.h
  
#include socket-util.h
  
#include dhcp-protocol.h
  
   -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
   uint32_t xid);
   +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
   uint32_t xid, struct ether_addr mac_addr);
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
int dhcp_network_send_raw_socket(int s, const union sockaddr_union 
   *link,
 const void *packet, size_t len);
   diff --git a/src/libsystemd-network/dhcp-network.c 
   b/src/libsystemd-network/dhcp-network.c
   index d7ba0ef..e5fd6a8 100644
   --- a/src/libsystemd-network/dhcp-network.c
   +++ b/src/libsystemd-network/dhcp-network.c
   @@ -33,7 +33,7 @@
#include dhcp-internal.h
  
int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
   - uint32_t xid) {
   + uint32_t xid, struct ether_addr 
   mac_addr) {
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),  
  /* A - packet length */
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 
   0), /* packet = DHCPPacket ? */
   @@ -56,7 +56,18 @@ int dhcp_network_bind_raw_socket(int index, union 
   sockaddr_union *link,
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
   dhcp.xid)),/* A - client identifier */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), 
  /* client identifier == xid ? */
BPF_STMT(BPF_RET + BPF_K, 0),   
  /* ignore */
   -/* TODO: match chaddr */
   +BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) 
   mac_addr))),/* A - 4 bytes of client's MAC */
   +BPF_STMT(BPF_MISC + BPF_TAX, 0),
  /* X - A */
   +BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
   dhcp.chaddr)), /* A - 4 bytes of MAC from dhcp.chaddr */
   +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), 
  /* A xor X */
   +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),   
  /* A == 0 ? */
   +BPF_STMT(BPF_RET + BPF_K, 0),   
  /* ignore */
   +BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) 
   (((char *) mac_addr) + 4, /* A - remainder of client's MAC */
   +BPF_STMT(BPF_MISC + BPF_TAX, 0),
  /* X - A */
   +BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, 
   dhcp.chaddr) + 4), /* A - remainder of MAC 

Re: [systemd-devel] [PATCH 1/2] dhcp-network: add check for DHCP.chaddr

2014-06-24 Thread Michal Sekletar
On Thu, Jun 19, 2014 at 12:02:39PM -0500, Dan Williams wrote:
 On Thu, 2014-06-19 at 18:59 +0200, Michal Sekletar wrote:
  Check that received DHCP packets actually include our MAC address in
  chaddr field. BPF interpreter has 32 bit wide registers but MAC address
  is 48 bits long so we have to do check in two steps.
 
 And if the MAC address is not 48 bits (Infiniband) or the interface type
 doesn't really have a MAC address (PPP/PPPoE)?  DHCP can be used in both
 cases...  If anything, the code that uses the MAC address should be
 if-ed so it only executes when a MAC address is provided.

I reconsidered. In filter code I can very easily find out type of device to 
which
filter is attached and skip ethernet specific bits or fallback to something
else. However filter already assumes ethernet data-link type moreover there is 
a ton of
code in networkd which does likewise.

I think we should merge patch as is right now. If somebody will hack up patches
for supporting various data-link types I will be happy to patch filter
accordingly.
 
 
 Dan

Michal

 
  ---
   src/libsystemd-network/dhcp-internal.h|  3 ++-
   src/libsystemd-network/dhcp-network.c | 15 +--
   src/libsystemd-network/sd-dhcp-client.c   |  4 ++--
   src/libsystemd-network/test-dhcp-client.c |  2 +-
   4 files changed, 18 insertions(+), 6 deletions(-)
  
  diff --git a/src/libsystemd-network/dhcp-internal.h 
  b/src/libsystemd-network/dhcp-internal.h
  index 03cc824..fd86a70 100644
  --- a/src/libsystemd-network/dhcp-internal.h
  +++ b/src/libsystemd-network/dhcp-internal.h
  @@ -24,12 +24,13 @@
   
   #include stdint.h
   #include linux/if_packet.h
  +#include net/ethernet.h
   
   #include socket-util.h
   
   #include dhcp-protocol.h
   
  -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid);
  +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid, struct ether_addr mac_addr);
   int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
   int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
  diff --git a/src/libsystemd-network/dhcp-network.c 
  b/src/libsystemd-network/dhcp-network.c
  index d7ba0ef..e5fd6a8 100644
  --- a/src/libsystemd-network/dhcp-network.c
  +++ b/src/libsystemd-network/dhcp-network.c
  @@ -33,7 +33,7 @@
   #include dhcp-internal.h
   
   int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
  - uint32_t xid) {
  + uint32_t xid, struct ether_addr mac_addr) 
  {
   struct sock_filter filter[] = {
   BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), 
  /* A - packet length */
   BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), 
  /* packet = DHCPPacket ? */
  @@ -56,7 +56,18 @@ int dhcp_network_bind_raw_socket(int index, union 
  sockaddr_union *link,
   BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.xid)),/* A - client identifier */
   BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),
  /* client identifier == xid ? */
   BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
  -/* TODO: match chaddr */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) 
  mac_addr))),/* A - 4 bytes of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),   
  /* X - A */
  +BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr)), /* A - 4 bytes of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),
  /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),  
  /* A == 0 ? */
  +BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) 
  (((char *) mac_addr) + 4, /* A - remainder of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),   
  /* X - A */
  +BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr) + 4), /* A - remainder of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),
  /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),  
  /* A == 0 ? */
  +BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
   BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 

Re: [systemd-devel] [PATCH 1/2] dhcp-network: add check for DHCP.chaddr

2014-06-24 Thread Tom Gundersen
On Tue, Jun 24, 2014 at 12:58 PM, Michal Sekletar msekl...@redhat.com wrote:
 On Thu, Jun 19, 2014 at 12:02:39PM -0500, Dan Williams wrote:
 On Thu, 2014-06-19 at 18:59 +0200, Michal Sekletar wrote:
  Check that received DHCP packets actually include our MAC address in
  chaddr field. BPF interpreter has 32 bit wide registers but MAC address
  is 48 bits long so we have to do check in two steps.

 And if the MAC address is not 48 bits (Infiniband) or the interface type
 doesn't really have a MAC address (PPP/PPPoE)?  DHCP can be used in both
 cases...  If anything, the code that uses the MAC address should be
 if-ed so it only executes when a MAC address is provided.

 I reconsidered. In filter code I can very easily find out type of device to 
 which
 filter is attached and skip ethernet specific bits or fallback to something
 else. However filter already assumes ethernet data-link type moreover there 
 is a ton of
 code in networkd which does likewise.

 I think we should merge patch as is right now. If somebody will hack up 
 patches
 for supporting various data-link types I will be happy to patch filter
 accordingly.

Ok. I'm fine with that. Please push.

Just to make clear: I'd be happy if anyone wanted to turn all our libs
to work also on non-ethernet (and test it!), and would merge such
patches.

Cheers,

Tom

   src/libsystemd-network/dhcp-internal.h|  3 ++-
   src/libsystemd-network/dhcp-network.c | 15 +--
   src/libsystemd-network/sd-dhcp-client.c   |  4 ++--
   src/libsystemd-network/test-dhcp-client.c |  2 +-
   4 files changed, 18 insertions(+), 6 deletions(-)
 
  diff --git a/src/libsystemd-network/dhcp-internal.h 
  b/src/libsystemd-network/dhcp-internal.h
  index 03cc824..fd86a70 100644
  --- a/src/libsystemd-network/dhcp-internal.h
  +++ b/src/libsystemd-network/dhcp-internal.h
  @@ -24,12 +24,13 @@
 
   #include stdint.h
   #include linux/if_packet.h
  +#include net/ethernet.h
 
   #include socket-util.h
 
   #include dhcp-protocol.h
 
  -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid);
  +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid, struct ether_addr mac_addr);
   int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
   int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
  diff --git a/src/libsystemd-network/dhcp-network.c 
  b/src/libsystemd-network/dhcp-network.c
  index d7ba0ef..e5fd6a8 100644
  --- a/src/libsystemd-network/dhcp-network.c
  +++ b/src/libsystemd-network/dhcp-network.c
  @@ -33,7 +33,7 @@
   #include dhcp-internal.h
 
   int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
  - uint32_t xid) {
  + uint32_t xid, struct ether_addr 
  mac_addr) {
   struct sock_filter filter[] = {
   BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),
   /* A - packet length */
   BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 
  0), /* packet = DHCPPacket ? */
  @@ -56,7 +56,18 @@ int dhcp_network_bind_raw_socket(int index, union 
  sockaddr_union *link,
   BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.xid)),/* A - client identifier */
   BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),   
   /* client identifier == xid ? */
   BPF_STMT(BPF_RET + BPF_K, 0), 
   /* ignore */
  -/* TODO: match chaddr */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) 
  mac_addr))),/* A - 4 bytes of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),  
   /* X - A */
  +BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr)), /* A - 4 bytes of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),   
   /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), 
   /* A == 0 ? */
  +BPF_STMT(BPF_RET + BPF_K, 0), 
   /* ignore */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) 
  (((char *) mac_addr) + 4, /* A - remainder of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),  
   /* X - A */
  +BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr) + 4), /* A - remainder of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),   
   /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + 

Re: [systemd-devel] [PATCH 1/2] dhcp-network: add check for DHCP.chaddr

2014-06-19 Thread Dan Williams
On Thu, 2014-06-19 at 18:59 +0200, Michal Sekletar wrote:
 Check that received DHCP packets actually include our MAC address in
 chaddr field. BPF interpreter has 32 bit wide registers but MAC address
 is 48 bits long so we have to do check in two steps.

And if the MAC address is not 48 bits (Infiniband) or the interface type
doesn't really have a MAC address (PPP/PPPoE)?  DHCP can be used in both
cases...  If anything, the code that uses the MAC address should be
if-ed so it only executes when a MAC address is provided.

Dan

 ---
  src/libsystemd-network/dhcp-internal.h|  3 ++-
  src/libsystemd-network/dhcp-network.c | 15 +--
  src/libsystemd-network/sd-dhcp-client.c   |  4 ++--
  src/libsystemd-network/test-dhcp-client.c |  2 +-
  4 files changed, 18 insertions(+), 6 deletions(-)
 
 diff --git a/src/libsystemd-network/dhcp-internal.h 
 b/src/libsystemd-network/dhcp-internal.h
 index 03cc824..fd86a70 100644
 --- a/src/libsystemd-network/dhcp-internal.h
 +++ b/src/libsystemd-network/dhcp-internal.h
 @@ -24,12 +24,13 @@
  
  #include stdint.h
  #include linux/if_packet.h
 +#include net/ethernet.h
  
  #include socket-util.h
  
  #include dhcp-protocol.h
  
 -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
 uint32_t xid);
 +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
 uint32_t xid, struct ether_addr mac_addr);
  int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
  int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
   const void *packet, size_t len);
 diff --git a/src/libsystemd-network/dhcp-network.c 
 b/src/libsystemd-network/dhcp-network.c
 index d7ba0ef..e5fd6a8 100644
 --- a/src/libsystemd-network/dhcp-network.c
 +++ b/src/libsystemd-network/dhcp-network.c
 @@ -33,7 +33,7 @@
  #include dhcp-internal.h
  
  int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
 - uint32_t xid) {
 + uint32_t xid, struct ether_addr mac_addr) {
  struct sock_filter filter[] = {
  BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),   
   /* A - packet length */
  BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0),   
   /* packet = DHCPPacket ? */
 @@ -56,7 +56,18 @@ int dhcp_network_bind_raw_socket(int index, union 
 sockaddr_union *link,
  BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
 dhcp.xid)),/* A - client identifier */
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),  
   /* client identifier == xid ? */
  BPF_STMT(BPF_RET + BPF_K, 0),
   /* ignore */
 -/* TODO: match chaddr */
 +BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) 
 mac_addr))),/* A - 4 bytes of client's MAC */
 +BPF_STMT(BPF_MISC + BPF_TAX, 0), 
   /* X - A */
 +BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
 dhcp.chaddr)), /* A - 4 bytes of MAC from dhcp.chaddr */
 +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),  
   /* A xor X */
 +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),
   /* A == 0 ? */
 +BPF_STMT(BPF_RET + BPF_K, 0),
   /* ignore */
 +BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char 
 *) mac_addr) + 4, /* A - remainder of client's MAC */
 +BPF_STMT(BPF_MISC + BPF_TAX, 0), 
   /* X - A */
 +BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, 
 dhcp.chaddr) + 4), /* A - remainder of MAC from dhcp.chaddr */
 +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),  
   /* A xor X */
 +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),
   /* A == 0 ? */
 +BPF_STMT(BPF_RET + BPF_K, 0),
   /* ignore */
  BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
 dhcp.magic)),  /* A - DHCP magic cookie */
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0),
   /* cookie == DHCP magic cookie ? */
  BPF_STMT(BPF_RET + BPF_K, 0),
   /* ignore */
 diff --git a/src/libsystemd-network/sd-dhcp-client.c 
 b/src/libsystemd-network/sd-dhcp-client.c
 index c1af6df..d44cad2 100644
 --- a/src/libsystemd-network/sd-dhcp-client.c
 +++ b/src/libsystemd-network/sd-dhcp-client.c
 @@ -719,7 +719,7 @@ static int client_start(sd_dhcp_client *client) {
  
  client-xid = random_u32();
  
 -   

Re: [systemd-devel] [PATCH 1/2] dhcp-network: add check for DHCP.chaddr

2014-06-19 Thread Michal Sekletar
On Thu, Jun 19, 2014 at 12:02:39PM -0500, Dan Williams wrote:
 On Thu, 2014-06-19 at 18:59 +0200, Michal Sekletar wrote:
  Check that received DHCP packets actually include our MAC address in
  chaddr field. BPF interpreter has 32 bit wide registers but MAC address
  is 48 bits long so we have to do check in two steps.
 
 And if the MAC address is not 48 bits (Infiniband) or the interface type
 doesn't really have a MAC address (PPP/PPPoE)?  DHCP can be used in both
 cases...  If anything, the code that uses the MAC address should be
 if-ed so it only executes when a MAC address is provided.

Yep, valid concerns indeed. Will post v2 tomorrow. Thanks!

 
 Dan

Michal

 
  ---
   src/libsystemd-network/dhcp-internal.h|  3 ++-
   src/libsystemd-network/dhcp-network.c | 15 +--
   src/libsystemd-network/sd-dhcp-client.c   |  4 ++--
   src/libsystemd-network/test-dhcp-client.c |  2 +-
   4 files changed, 18 insertions(+), 6 deletions(-)
  
  diff --git a/src/libsystemd-network/dhcp-internal.h 
  b/src/libsystemd-network/dhcp-internal.h
  index 03cc824..fd86a70 100644
  --- a/src/libsystemd-network/dhcp-internal.h
  +++ b/src/libsystemd-network/dhcp-internal.h
  @@ -24,12 +24,13 @@
   
   #include stdint.h
   #include linux/if_packet.h
  +#include net/ethernet.h
   
   #include socket-util.h
   
   #include dhcp-protocol.h
   
  -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid);
  +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, 
  uint32_t xid, struct ether_addr mac_addr);
   int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
   int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
  diff --git a/src/libsystemd-network/dhcp-network.c 
  b/src/libsystemd-network/dhcp-network.c
  index d7ba0ef..e5fd6a8 100644
  --- a/src/libsystemd-network/dhcp-network.c
  +++ b/src/libsystemd-network/dhcp-network.c
  @@ -33,7 +33,7 @@
   #include dhcp-internal.h
   
   int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
  - uint32_t xid) {
  + uint32_t xid, struct ether_addr mac_addr) 
  {
   struct sock_filter filter[] = {
   BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), 
  /* A - packet length */
   BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), 
  /* packet = DHCPPacket ? */
  @@ -56,7 +56,18 @@ int dhcp_network_bind_raw_socket(int index, union 
  sockaddr_union *link,
   BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.xid)),/* A - client identifier */
   BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),
  /* client identifier == xid ? */
   BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
  -/* TODO: match chaddr */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) 
  mac_addr))),/* A - 4 bytes of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),   
  /* X - A */
  +BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr)), /* A - 4 bytes of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),
  /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),  
  /* A == 0 ? */
  +BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
  +BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) 
  (((char *) mac_addr) + 4, /* A - remainder of client's MAC */
  +BPF_STMT(BPF_MISC + BPF_TAX, 0),   
  /* X - A */
  +BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.chaddr) + 4), /* A - remainder of MAC from dhcp.chaddr */
  +BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),
  /* A xor X */
  +BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),  
  /* A == 0 ? */
  +BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
   BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, 
  dhcp.magic)),  /* A - DHCP magic cookie */
   BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0),  
  /* cookie == DHCP magic cookie ? */
   BPF_STMT(BPF_RET + BPF_K, 0),  
  /* ignore */
  diff --git a/src/libsystemd-network/sd-dhcp-client.c 
  b/src/libsystemd-network/sd-dhcp-client.c
  index