Browse Source

odhcp6c: add -K option to set packet kernel priority

This adds a command line option (-K) to set the packet kernel
priority.

This makes it straightforward to set some VLAN priority for DHCP
requests through an egress qos map. (Avoiding the need for firewall
matching and marking through iptables, which prevents using flow
offloading).

(Such priority tag is a hard requirement for some ISPs, such as Orange
in France).

Signed-off-by: Pacien TRAN-GIRARD <pacien.trangirard@pacien.net>
pacien 1 year ago
parent
commit
bcd283632a
3 changed files with 13 additions and 4 deletions
  1. 4 1
      src/dhcpv6.c
  2. 8 2
      src/odhcp6c.c
  3. 1 1
      src/odhcp6c.h

+ 4 - 1
src/dhcpv6.c

@@ -194,7 +194,7 @@ static char *dhcpv6_status_code_to_str(uint16_t code)
 	return "Unknown";
 }
 
-int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout)
+int init_dhcpv6(const char *ifname, unsigned int options, int sk_prio, int sol_timeout)
 {
 	client_options = options;
 	dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout;
@@ -289,6 +289,9 @@ int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout)
 	if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0)
 		goto failure;
 
+	if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &sk_prio, sizeof(sk_prio)) < 0)
+		goto failure;
+
 	struct sockaddr_in6 client_addr = { .sin6_family = AF_INET6,
 		.sin6_port = htons(DHCPV6_CLIENT_PORT), .sin6_flowinfo = 0 };
 

+ 8 - 2
src/odhcp6c.c

@@ -178,6 +178,7 @@ int main(_unused int argc, char* const argv[])
 	bool stateful_only_mode = 0;
 	struct odhcp6c_opt *opt;
 	int ia_pd_iaid_index = 0;
+	int sk_prio = 0;
 	int sol_timeout = DHCPV6_SOL_MAX_RT;
 	int verbosity = 0;
 	bool help = false, daemonize = false;
@@ -187,7 +188,7 @@ int main(_unused int argc, char* const argv[])
 	unsigned int ra_options = RA_RDNSS_DEFAULT_LIFETIME;
 	unsigned int ra_holdoff_interval = RA_MIN_ADV_INTERVAL;
 
-	while ((c = getopt(argc, argv, "S::DN:V:P:FB:c:i:r:Ru:Ux:s:kt:m:Lhedp:fav")) != -1) {
+	while ((c = getopt(argc, argv, "S::DN:V:P:FB:c:i:r:Ru:Ux:s:kK:t:m:Lhedp:fav")) != -1) {
 		switch (c) {
 		case 'S':
 			allow_slaac_only = (optarg) ? atoi(optarg) : -1;
@@ -345,6 +346,10 @@ int main(_unused int argc, char* const argv[])
 			release = false;
 			break;
 
+		case 'K':
+			sk_prio = atoi(optarg);
+			break;
+
 		case 't':
 			sol_timeout = atoi(optarg);
 			break;
@@ -417,7 +422,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, client_options, sol_timeout) ||
+			init_dhcpv6(ifname, client_options, sk_prio, sol_timeout) ||
 			ra_init(ifname, &ifid, ra_options, ra_holdoff_interval) ||
 			script_init(script, ifname)) {
 		syslog(LOG_ERR, "failed to initialize: %s", strerror(errno));
@@ -627,6 +632,7 @@ static int usage(void)
 	"	-a		Don't send Accept Reconfigure option\n"
 	"	-f		Don't send Client FQDN option\n"
 	"	-k		Don't send a RELEASE when stopping\n"
+	"	-K <sk-prio>	Set packet kernel priority (0)\n"
 	"	-t <seconds>	Maximum timeout for DHCPv6-SOLICIT (120)\n"
 	"	-m <seconds>	Minimum time between accepting RA updates (3)\n"
 	"	-L		Ignore default lifetime for RDNSS records\n"

+ 1 - 1
src/odhcp6c.h

@@ -392,7 +392,7 @@ struct odhcp6c_opt {
 	const char *str;
 };
 
-int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout);
+int init_dhcpv6(const char *ifname, unsigned int client_options, int sk_prio, int sol_timeout);
 int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only);
 int dhcpv6_request(enum dhcpv6_msg type);
 int dhcpv6_poll_reconfigure(void);