From bbcc9cfa44372f58cb33d556d9b7c57f6ee96b61 Mon Sep 17 00:00:00 2001
From: Kaspar Schleiser <kaspar@schleiser.de>
Date: Thu, 9 Jan 2014 15:58:31 +0100
Subject: [PATCH] added command line switch for strict oro

Now "-R" command line switch makes odhcpv6c only request those options
specified by "-r".

Contributed by T-Labs, Deutsche Telekom Innovation Laboratories
---
 src/dhcpv6.c  | 10 ++++++----
 src/odhcp6c.c | 11 ++++++++---
 src/odhcp6c.h |  2 +-
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index dca0ed4..7416f61 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -106,7 +106,7 @@ static bool accept_reconfig = false;
 static uint8_t reconf_key[16];
 
 
-int init_dhcpv6(const char *ifname, int request_pd, int sol_timeout)
+int init_dhcpv6(const char *ifname, int request_pd, bool strict_options, int sol_timeout)
 {
 	request_prefix = request_pd;
 	dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout;
@@ -158,7 +158,8 @@ int init_dhcpv6(const char *ifname, int request_pd, int sol_timeout)
 	}
 
 	// Create ORO
-	uint16_t oro[] = {
+	if (!strict_options) {
+		uint16_t oro[] = {
 			htons(DHCPV6_OPT_SIP_SERVER_D),
 			htons(DHCPV6_OPT_SIP_SERVER_A),
 			htons(DHCPV6_OPT_DNS_SERVERS),
@@ -172,8 +173,9 @@ int init_dhcpv6(const char *ifname, int request_pd, int sol_timeout)
 #ifdef EXT_PREFIX_CLASS
 			htons(DHCPV6_OPT_PREFIX_CLASS),
 #endif
-	};
-	odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
+		};
+		odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
+	}
 
 	// Configure IPv6-options
 	int val = 1;
diff --git a/src/odhcp6c.c b/src/odhcp6c.c
index 2159363..e5e415c 100644
--- a/src/odhcp6c.c
+++ b/src/odhcp6c.c
@@ -71,10 +71,10 @@ int main(_unused int argc, char* const argv[])
 	int bfd_interval = 0, bfd_loss = 3;
 #endif
 
-	bool help = false, daemonize = false;
+	bool help = false, daemonize = false, strict_options = false;
 	int logopt = LOG_PID;
 	int c, request_pd = 0;
-	while ((c = getopt(argc, argv, "S::N:P:FB:c:i:r:s:kt:hedp:")) != -1) {
+	while ((c = getopt(argc, argv, "S::N:P:FB:c:i:r:Rs:kt:hedp:")) != -1) {
 		switch (c) {
 		case 'S':
 			allow_slaac_only = (optarg) ? atoi(optarg) : -1;
@@ -144,6 +144,10 @@ int main(_unused int argc, char* const argv[])
 			}
 			break;
 
+		case 'R':
+			strict_options = true;
+			break;
+
 		case 's':
 			script = optarg;
 			break;
@@ -189,7 +193,7 @@ int main(_unused int argc, char* const argv[])
 	signal(SIGUSR2, sighandler);
 
 	if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 ||
-			init_dhcpv6(ifname, request_pd, sol_timeout) ||
+			init_dhcpv6(ifname, request_pd, strict_options, sol_timeout) ||
 			ra_init(ifname, &ifid) || script_init(script, ifname)) {
 		syslog(LOG_ERR, "failed to initialize: %s", strerror(errno));
 		return 3;
@@ -391,6 +395,7 @@ static int usage(void)
 	"	-c <clientid>	Override client-ID (base-16 encoded)\n"
 	"	-i <iface-id>	Use a custom interface identifier for RA handling\n"
 	"	-r <options>	Options to be requested (comma-separated)\n"
+	"	-R		Do not request any options except those specified with -r\n"
 	"	-s <script>	Status update script (/usr/sbin/odhcp6c-update)\n"
 	"	-k		Don't send a RELEASE when stopping\n"
 	"	-t <seconds>	Maximum timeout for DHCPv6-SOLICIT (120)\n"
diff --git a/src/odhcp6c.h b/src/odhcp6c.h
index e3c6c5e..3f23e64 100644
--- a/src/odhcp6c.h
+++ b/src/odhcp6c.h
@@ -239,7 +239,7 @@ struct odhcp6c_entry {
 };
 
 
-int init_dhcpv6(const char *ifname, int request_pd, int sol_timeout);
+int init_dhcpv6(const char *ifname, int request_pd, bool strict_options, int sol_timeout);
 void dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd);
 int dhcpv6_request(enum dhcpv6_msg type);
 int dhcpv6_poll_reconfigure(void);
-- 
2.39.5