ell.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Denis Kenzior <denkenz@gmail.com>
To: ell@lists.01.org
Subject: Re: [PATCH 3/8] dhcp-server: Respect client's broadcast flag
Date: Wed, 28 Jul 2021 10:47:32 -0500	[thread overview]
Message-ID: <30283874-160a-eb89-cf8a-008e06288bcc@gmail.com> (raw)
In-Reply-To: <20210723182331.135123-3-andrew.zaborowski@intel.com>

[-- Attachment #1: Type: text/plain, Size: 6064 bytes --]

Hi Andrew,

On 7/23/21 1:23 PM, Andrew Zaborowski wrote:
> Follow notes in RFC2131 4.1, 4.3.2 and 4.4.4 when deciding whether we
> can use unicast for a given message.  We want to prefer unicast when
> possible but we should follow the spec on the broadcast flag and the
> destination address.
> ---
>   ell/dhcp-private.h |  3 ++
>   ell/dhcp-server.c  | 90 +++++++++++++++++++++++++++++++++++-----------
>   2 files changed, 72 insertions(+), 21 deletions(-)
> 
> diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
> index c422322..f761162 100644
> --- a/ell/dhcp-private.h
> +++ b/ell/dhcp-private.h
> @@ -66,6 +66,9 @@ enum dhcp_option_overload {
>   #define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 /* Section 9.10 */
>   #define DHCP_OPTION_CLIENT_IDENTIFIER 61 /* Section 9.14 */
>   
> +/* RFC 2131, Figure 2 */
> +#define DHCP_FLAG_BROADCAST (1 << 15)
> +
>   /* RFC 2131, Figure 1 */
>   struct dhcp_message {
>   	uint8_t op;
> diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
> index 9f4703c..fb26e29 100644
> --- a/ell/dhcp-server.c
> +++ b/ell/dhcp-server.c
> @@ -420,6 +420,71 @@ static void server_message_init(struct l_dhcp_server *server,
>   	reply->ciaddr = client_msg->ciaddr;
>   }
>   
> +static bool server_message_send(struct l_dhcp_server *server,
> +				struct dhcp_message *reply, size_t len,
> +				uint8_t type)
> +{
> +	uint32_t daddr;
> +	uint16_t dport;
> +	const uint8_t *dest_mac;
> +
> +	/*
> +	 * RFC2131 Section 4.1: "If the 'giaddr' field in a DHCP message from
> +	 * a client is non-zero, the server sends any return messages to the
> +	 * 'DHCP server' port on the BOOTP relay agent whose address appears
> +	 * in 'giaddr'. If the 'giaddr' field is zero and the 'ciaddr' field
> +	 * is nonzero, then the server unicasts DHCPOFFER and DHCPACK messages
> +	 * to the address in 'ciaddr'.  If 'giaddr' is zero and 'ciaddr' is
> +	 * zero, and the broadcast bit is set, then the server broadcasts
> +	 * DHCPOFFER and DHCPACK messages to 0xffffffff. If the broadcast bit
> +	 * is not set and 'giaddr' is zero and 'ciaddr' is zero, then the
> +	 * server unicasts DHCPOFFER and DHCPACK messages to the client's
> +	 * hardware address and 'yiaddr' address.  In all cases, when 'giaddr'
> +	 * is zero, the server broadcasts any DHCPNAK messages to 0xffffffff."
> +	 *
> +	 * 4.3.2: "If 'giaddr' is set in the DHCPREQUEST message, the client
> +	 * is on a different subnet.  The server MUST set the broadcast bit in
> +	 * the DHCPNAK, so that the relay agent will broadcast the DHCPNAK to
> +	 * the client, because the client may not have a correct network
> +	 * address or subnet mask, and the client may not be answering ARP
> +	 * requests."
> +	 */
> +	if (reply->giaddr) {
> +		dport = DHCP_PORT_SERVER;
> +		daddr = reply->giaddr;
> +		dest_mac = reply->chaddr;
> +
> +		if (type == DHCP_MESSAGE_TYPE_NAK)
> +			reply->flags |= L_CPU_TO_BE16(DHCP_FLAG_BROADCAST);
> +	} else {
> +		dport = DHCP_PORT_CLIENT;
> +
> +		if (type == DHCP_MESSAGE_TYPE_NAK) {
> +			daddr = 0xffffffff;
> +			dest_mac = MAC_BCAST_ADDR;
> +		} else if (reply->ciaddr) {
> +			daddr = reply->ciaddr;
> +			dest_mac = reply->chaddr;
> +		} else if (L_BE16_TO_CPU(reply->flags) & DHCP_FLAG_BROADCAST) {
> +			daddr = 0xffffffff;
> +			dest_mac = MAC_BCAST_ADDR;
> +		} else {
> +			daddr = reply->yiaddr;
> +			dest_mac = reply->chaddr;
> +		}
> +	}
> +
> +	if (server->transport->l2_send(server->transport, server->address,
> +					DHCP_PORT_SERVER, daddr, dport,
> +					dest_mac, reply, len) < 0) {
> +		SERVER_DEBUG("Failed to send %s",
> +				_dhcp_message_type_to_string(type));
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
>   static void add_server_options(struct l_dhcp_server *server,
>   				struct dhcp_message_builder *builder)
>   {
> @@ -491,11 +556,7 @@ static void send_offer(struct l_dhcp_server *server,
>   	SERVER_DEBUG("Sending OFFER of "NIPQUAD_FMT " to "MAC,
>   			NIPQUAD(reply->yiaddr),	MAC_STR(reply->chaddr));
>   
> -	if (server->transport->l2_send(server->transport, server->address,
> -					DHCP_PORT_SERVER,
> -					reply->ciaddr, DHCP_PORT_CLIENT,
> -					reply->chaddr, reply, len) < 0)
> -		SERVER_DEBUG("Failed to send OFFER");
> +	server_message_send(server, reply, len, DHCP_MESSAGE_TYPE_OFFER);
>   }
>   
>   static void send_inform(struct l_dhcp_server *server,
> @@ -515,11 +576,7 @@ static void send_inform(struct l_dhcp_server *server,
>   
>   	_dhcp_message_builder_finalize(&builder, &len);
>   
> -	if (server->transport->l2_send(server->transport, server->address,
> -					DHCP_PORT_SERVER, reply->ciaddr,
> -					DHCP_PORT_CLIENT, reply->chaddr,
> -					reply, len) < 0)
> -		SERVER_DEBUG("Failed to send INFORM");
> +	server_message_send(server, reply, len, DHCP_MESSAGE_TYPE_ACK);

Inform?

>   }
>   
>   static void send_nak(struct l_dhcp_server *server,
> @@ -537,11 +594,7 @@ static void send_nak(struct l_dhcp_server *server,
>   
>   	_dhcp_message_builder_finalize(&builder, &len);
>   
> -	if (server->transport->l2_send(server->transport, server->address,
> -					DHCP_PORT_SERVER, reply->ciaddr,
> -					DHCP_PORT_CLIENT, MAC_BCAST_ADDR,
> -					reply, len) < 0)
> -		SERVER_DEBUG("Failed to send NACK");
> +	server_message_send(server, reply, len, DHCP_MESSAGE_TYPE_NAK);
>   }
>   
>   static void send_ack(struct l_dhcp_server *server,
> @@ -574,13 +627,8 @@ static void send_ack(struct l_dhcp_server *server,
>   
>   	SERVER_DEBUG("Sending ACK to "NIPQUAD_FMT, NIPQUAD(reply->yiaddr));
>   
> -	if (server->transport->l2_send(server->transport, server->address,
> -					DHCP_PORT_SERVER, reply->ciaddr,
> -					DHCP_PORT_CLIENT,
> -					reply->chaddr, reply, len) < 0) {
> -		SERVER_DEBUG("Failed to send ACK");
> +	if (!server_message_send(server, reply, len, DHCP_MESSAGE_TYPE_ACK))
>   		return;
> -	}
>   
>   	lease = add_lease(server, false, reply->chaddr, reply->yiaddr);
>   
> 

Regards,
-Denis

  reply	other threads:[~2021-07-28 15:47 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-23 18:23 [PATCH 1/8] dhcp-server: Add "authoritative" mode Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 2/8] dhcp-server: Handle DHCPDECLINE for active leases Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 3/8] dhcp-server: Respect client's broadcast flag Andrew Zaborowski
2021-07-28 15:47   ` Denis Kenzior [this message]
2021-07-28 17:57     ` Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 4/8] dhcp-lease: Check duplicate options in _dhcp_lease_parse_options Andrew Zaborowski
2021-07-28 15:50   ` Denis Kenzior
2021-07-23 18:23 ` [PATCH 5/8] dhcp-server: Look up leases by client identifier option Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 6/8] dhcp-server: Copy client identifier from the client message Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 7/8] dhcp-server: Support RFC4039 Rapid Commit Andrew Zaborowski
2021-07-23 18:23 ` [PATCH 8/8] dhcp: " Andrew Zaborowski
2021-07-28 15:42 ` [PATCH 1/8] dhcp-server: Add "authoritative" mode Denis Kenzior
2021-07-28 17:51   ` Andrew Zaborowski
2021-07-28 18:39     ` Denis Kenzior
2021-07-28 19:29       ` Andrew Zaborowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=30283874-160a-eb89-cf8a-008e06288bcc@gmail.com \
    --to=denkenz@gmail.com \
    --cc=ell@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).