[klibc] PATCH: command line argument for ipconfig to require a dhcp option

Άλκης Άλκης
Thu Oct 9 09:24:56 PDT 2008


Στις 08-10-2008, ημέρα Τετ, και ώρα 10:56 -0700, ο/η H. Peter Anvin
έγραψε:
> (1) is probably best simply by having precedence in dhclient.

I implemented this for a single dhcp option, I'm sending (I hope) the
git diff as an attachment.
When one doesn't use the new command line argument, he/she shouldn't be
observing *anything* different (no delays etc).

Kind regards,
Alkis Georgopoulos
-------------- next part --------------
commit 07e87cd45cf5e71c8709fad1c885507271d73b02
Author: Άλκης Γεωργόπουλος <alkisg at gmail.com>
Date:   Thu Oct 9 19:10:51 2008 +0300

    Signed-off-by: Alkis Georgopoulos <alkisg at gmail.com>
    
    Patch to provide a command line argument for ipconfig to ignore offers that do not contain a specified DHCP option.

diff --git a/usr/kinit/ipconfig/README b/usr/kinit/ipconfig/README
index 5c8227a..0db4c65 100644
--- a/usr/kinit/ipconfig/README
+++ b/usr/kinit/ipconfig/README
@@ -3,8 +3,8 @@ BOOTP/DHCP client for klibc
 
 Usage:
 
-ipconfig [-c proto] [-d interface] [-i identifier]
-	 [-n] [-p port] [-t timeout] [interface ...]
+ipconfig [-c proto] [-d interface] [-i identifier] [-n]
+	 [-p port] [-t timeout] [-r option] [interface ...]
 
 -c proto	Use PROTO as the configuration protocol for all
 		interfaces, unless overridden by specific interfaces.
@@ -15,6 +15,8 @@ ipconfig [-c proto] [-d interface] [-i identifier]
 		be performed.
 -p port		Send bootp/dhcp broadcasts from PORT, to PORT - 1.
 -t timeout	Give up on all unconfigured interfaces after TIMEOUT secs.
+-r option	Require that dhcp offers include a specific dhcp
+		OPTION (0-254) in order to get accepted.
 
 You can configure multiple interfaces by passing multiple interface
 specs on the command line, or by using the special interface name
diff --git a/usr/kinit/ipconfig/bootp_proto.c b/usr/kinit/ipconfig/bootp_proto.c
index 236bde9..b138e0f 100644
--- a/usr/kinit/ipconfig/bootp_proto.c
+++ b/usr/kinit/ipconfig/bootp_proto.c
@@ -61,6 +61,9 @@ int bootp_send_request(struct netdev *dev)
 int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
 		uint8_t *exts, int extlen)
 {
+	int got_required_option = 0;
+	uint8_t type = 0;
+	
 	dev->bootp.gateway	= hdr->giaddr;
 	dev->ip_addr		= hdr->yiaddr;
 	dev->ip_server		= hdr->siaddr;
@@ -82,6 +85,9 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
 			int len;
 			uint8_t opt = *ext++;
 
+			if (opt == required_option)
+				got_required_option = 1;
+
 			if (opt == 0)
 				continue;
 			else if (opt == 255)
@@ -135,10 +141,19 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
 				memcpy(&dev->nisdomainname, ext, len);
 				dev->nisdomainname[len] = '\0';
 				break;
+			case 53:	/* DHCP message type */
+				type = *ext;
+				break;
 			case 54:	/* server identifier */
 				if (len == 4 && !dev->ip_server)
 					memcpy(&dev->ip_server, ext, 4);
 				break;
+			case 67:	/* bootfile name, when option overload is set */
+				if (len > sizeof(dev->filename) - 1)
+					len = sizeof(dev->filename) - 1;
+				memcpy(&dev->filename, ext, len);
+				dev->filename[len] = '\0';
+				break;
 			}
 
 			ext += len;
@@ -146,9 +161,23 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
 	}
 
 	/*
-	 * Got packet.
+	 * If we got a DHCP_OFFER message type, and the required_option was not
+	 * set, return 0 (=the message is to be ignored), else return 1.
 	 */
-	return 1;
+	if (type == 2) {
+		/* 
+		 * Check for the equivalent of some required_options inside the header.
+		 * Options sname=66 and file=67 may be either in the header, or, when
+		 * option overload is set, in the variable options field.
+		 */
+		if ((required_option == 66 && hdr->server_name[0] != '\0') ||
+		    (required_option == 67 && hdr->boot_file[0] != '\0'))
+			got_required_option = 1;
+
+		return got_required_option;
+	} 
+	else
+		return 1;
 }
 
 /*
diff --git a/usr/kinit/ipconfig/ipconfig.h b/usr/kinit/ipconfig/ipconfig.h
index 6d776e0..32b5183 100644
--- a/usr/kinit/ipconfig/ipconfig.h
+++ b/usr/kinit/ipconfig/ipconfig.h
@@ -10,6 +10,8 @@
 extern uint16_t cfg_local_port;
 extern uint16_t cfg_remote_port;
 
+extern int required_option;
+
 extern char vendor_class_identifier[];
 extern int vendor_class_identifier_len;
 
diff --git a/usr/kinit/ipconfig/main.c b/usr/kinit/ipconfig/main.c
index 2ded0f3..e7d7c03 100644
--- a/usr/kinit/ipconfig/main.c
+++ b/usr/kinit/ipconfig/main.c
@@ -31,6 +31,9 @@ static int loop_timeout = -1;
 static int configured;
 static int bringup_first = 0;
 
+/* Require this DHCP option. Defaults to 255 = End Option, always present. */
+int required_option = 255;
+
 /* DHCP vendor class identifier */
 char vendor_class_identifier[260];
 int vendor_class_identifier_len;
@@ -723,7 +726,7 @@ int ipconfig_main(int argc, char *argv[])
 	set_vendor_identifier("Linux ipconfig");
 
 	do {
-		c = getopt(argc, argv, "c:d:i:onp:t:");
+		c = getopt(argc, argv, "c:d:i:onp:t:r:");
 		if (c == EOF)
 			break;
 
@@ -751,6 +754,15 @@ int ipconfig_main(int argc, char *argv[])
 				longjmp(abort_buf, 1);
 			}
 			break;
+		case 'r':
+			required_option = atoi(optarg);
+			if (required_option < 0 || required_option > 254) {
+				fprintf(stderr,
+					"%s: invalid required option %d\n",
+					progname, required_option);
+				longjmp(abort_buf, 1);
+			}
+			break;
 		case 'i':
 			set_vendor_identifier(optarg);
 			break;


More information about the klibc mailing list