[Dnsmasq-discuss] Re: Support for DHCP option 125

Samium Gromoff _deepfire at feelingofgreen.ru
Fri Dec 5 01:03:36 GMT 2008


On Fri Sep 14 16:31:55 BST 2007, Simon Kelleys wrote:
> The existing support for non-vendor-identifying encapsulated options is 
> in two places. The data gets laid out in the packet in the second half 
> of do_options() in src/rfc2131.c. That's quite hairy code, but it should 
> be extendable to option 125 without too many problems.
>
> dhcp-option lines in the config file and command line are parsed into a 
> linked-list of struct dhcp_opt in parse_dhcp_opt() in src/option.c. 
> That's hairy too (sorry!). option-60 encapsulated options look like:
> 
> dhcp-option=vendor:<some vendor string>,<option data>
> 
> That could be extended to cope with something like
> 
> dhcp-option=vendor-id:<enterprise-number>,<option data>
> From: dnsmasq-discuss-request at lists.thekelleys.org.uk
> Subject: Welcome to the "Dnsmasq-discuss" mailing list
> Date: Thu, 04 Dec 2008 20:48:06 +0000

I have implemented something along these lines, which, in effect, allows
me to add following lines in dnsmasq.conf:

  dhcp-option-force= net:iscsi-client0, net:gpxe, vendor-id:175, 190, "iscsi-client0"
  dhcp-option-force= net:iscsi-client0, net:gpxe, vendor-id:175, 191, "iscsi-client0-secret"

and have the username and password fed to gPXE for iSCSI boot.
(Yes, I know, specifying those via DHCP is a recipe for a breaking.)

The patch works in just that scenario for me, but is otherwise untested.

Feel free to include it, if it looks interesting enough, and/or provide
feedback.

On the future side, it'd be nice to define symbolic names for custom
options and encapsulated options, ala ISC DHCP.


regards, Samium Gromoff
-------------- next part --------------
commit f1b1747ac88ac3dbfe44be9ce8e6c3400a6056dc
Author: Samium Gromoff <deepfire at betelheise.feelingofgreen.ru>
Date:   Fri Dec 5 03:20:37 2008 +0300

    Custom enterprise id support.

diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 24b4204..e7d5847 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -463,7 +463,7 @@ struct dhcp_config {
 #define CONFIG_BANK           2048    /* from dhcp hosts file */
 
 struct dhcp_opt {
-  int opt, len, flags;
+  int opt, encapsulating_opt, len, flags;
   unsigned char *val, *vendor_class;
   struct dhcp_netid *netid;
   struct dhcp_opt *next;
diff --git a/src/option.c b/src/option.c
index 6b336fb..04b7c3f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -19,6 +19,8 @@
 #include "dnsmasq.h"
 #include <setjmp.h>
 
+#define OPTION_VENDOR_CLASS_OPT  43	/* Should be defined elsewhere. */
+
 /* Solaris headers don't have facility names. */
 #ifdef HAVE_SOLARIS_NETWORK
 static const struct {
@@ -673,8 +675,14 @@ static char *parse_dhcp_opt(char *arg, int flags)
 	  /* option:<optname> must follow tag and vendor string. */
 	  break;
 	}
+      else if (strstr(arg, "vendor-id:") == arg)
+	{
+	  new->encapsulating_opt = atoi(arg+10);
+	  new->flags |= DHOPT_ENCAPSULATE;
+	}
       else if (strstr(arg, "vendor:") == arg)
 	{
+	  new->encapsulating_opt = OPTION_VENDOR_CLASS_OPT;
 	  new->vendor_class = (unsigned char *)opt_string_alloc(arg+7);
 	  new->flags |= DHOPT_ENCAPSULATE;
 	}
diff --git a/src/rfc2131.c b/src/rfc2131.c
index e3f50ba..0f53e95 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -1842,9 +1842,9 @@ static void do_options(struct dhcp_context *context,
 
   /* prune encapsulated options based on netid, and look if we're forcing them to be sent */
   for (opt = config_opts; opt; opt = opt->next)
-    if (opt->flags & DHOPT_VENDOR_MATCH)
+    if (opt->flags & DHOPT_ENCAPSULATE)
       {
-	if (!match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
+	if ((opt->flags & DHOPT_VENDOR_MATCH) && !match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
 	  opt->flags &= ~DHOPT_VENDOR_MATCH;
 	else if (opt->flags & DHOPT_FORCE)
 	  force_encap = 1;
@@ -1857,16 +1857,16 @@ static void do_options(struct dhcp_context *context,
 
       /* find size in advance */
       for (start = opt = config_opts; opt; opt = opt->next)
-	if (opt->flags & DHOPT_VENDOR_MATCH)
+	if (opt->flags & DHOPT_ENCAPSULATE)
 	  {
 	    int new = do_opt(opt, NULL, context->local, null_term) + 2;
 	    if (enc_len + new <= 255)
 	      enc_len += new;
 	    else
 	      {
-		p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len);
+		p = free_space(mess, end, opt->encapsulating_opt, enc_len);
 		for (; start && start != opt; start = start->next)
-		  if (p && (start->flags & DHOPT_VENDOR_MATCH))
+		  if (p && (start->flags & DHOPT_ENCAPSULATE))
 		    {
 		      len = do_opt(start, p + 2, context->local, null_term);
 		      *(p++) = start->opt;
@@ -1879,10 +1879,10 @@ static void do_options(struct dhcp_context *context,
 	  }
 	      
       if (enc_len != 0 &&
-	  (p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len + 1)))
+	  (p = free_space(mess, end, start->encapsulating_opt, enc_len + 1)))
 	{
 	  for (; start; start = start->next)
-	    if (start->flags & DHOPT_VENDOR_MATCH)
+	    if (start->flags & DHOPT_ENCAPSULATE)
 	      {
 		 len = do_opt(start, p + 2, context->local, null_term);
 		 *(p++) = start->opt;


More information about the Dnsmasq-discuss mailing list