summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authoreadler <eadler@FreeBSD.org>2018-03-19 04:16:37 +0000
committereadler <eadler@FreeBSD.org>2018-03-19 04:16:37 +0000
commit34f7cc9b1c76103ddf6f40d437bbfb51a83e407c (patch)
tree4d2cbb126b9f704b5508d8cff0caae6185bcb83e /sbin
parente4436279bbf4e3f7296982960550cf35fa4e9d53 (diff)
downloadFreeBSD-src-34f7cc9b1c76103ddf6f40d437bbfb51a83e407c.zip
FreeBSD-src-34f7cc9b1c76103ddf6f40d437bbfb51a83e407c.tar.gz
MFC r305306:
dhclient: add support for interface-mtu (26) Make dhclient set interface MTU if it was provided. This version implements MTU setting in dhclient itself before it runs dhclient-script. PR: 206721
Diffstat (limited to 'sbin')
-rw-r--r--sbin/dhclient/clparse.c2
-rw-r--r--sbin/dhclient/dhclient.c15
-rw-r--r--sbin/dhclient/dhcpd.h2
-rw-r--r--sbin/dhclient/dispatch.c44
-rw-r--r--sbin/dhclient/privsep.c8
-rw-r--r--sbin/dhclient/privsep.h3
6 files changed, 73 insertions, 1 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
index 3101ef5..ac80db5 100644
--- a/sbin/dhclient/clparse.c
+++ b/sbin/dhclient/clparse.c
@@ -104,6 +104,8 @@ read_client_conf(void)
[top_level_config.requested_option_count++] = DHO_HOST_NAME;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_DOMAIN_SEARCH;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_INTERFACE_MTU;
if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) {
do {
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 4512771..c0332b9 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "privsep.h"
#include <sys/capsicum.h>
+#include <sys/endian.h>
#include <net80211/ieee80211_freebsd.h>
@@ -138,6 +139,9 @@ int fork_privchld(int, int);
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+/* Minimum MTU is 68 as per RFC791, p. 24 */
+#define MIN_MTU 68
+
static time_t scripttime;
int
@@ -820,9 +824,20 @@ dhcpack(struct packet *packet)
void
bind_lease(struct interface_info *ip)
{
+ struct option_data *opt;
+
/* Remember the medium. */
ip->client->new->medium = ip->client->medium;
+ opt = &ip->client->new->options[DHO_INTERFACE_MTU];
+ if (opt->len == sizeof(u_int16_t)) {
+ u_int16_t mtu = be16dec(opt->data);
+ if (mtu < MIN_MTU)
+ warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
+ else
+ interface_set_mtu_unpriv(privfd, mtu);
+ }
+
/* Write out the new lease. */
write_client_lease(ip, ip->client->new, 0);
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index eb96f45..e44a98c 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -321,6 +321,8 @@ void cancel_timeout(void (*)(void *), void *);
void add_protocol(char *, int, void (*)(struct protocol *), void *);
void remove_protocol(struct protocol *);
int interface_link_status(char *);
+void interface_set_mtu_unpriv(int, u_int16_t);
+void interface_set_mtu_priv(char *, u_int16_t);
/* hash.c */
struct hash_table *new_hash(void);
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index 25de52a..327ecaf 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -45,6 +45,7 @@
__FBSDID("$FreeBSD$");
#include "dhcpd.h"
+#include "privsep.h"
#include <sys/ioctl.h>
@@ -499,3 +500,46 @@ interface_link_status(char *ifname)
}
return (1);
}
+
+void
+interface_set_mtu_unpriv(int privfd, u_int16_t mtu)
+{
+ struct imsg_hdr hdr;
+ struct buf *buf;
+ int errs = 0;
+
+ hdr.code = IMSG_SET_INTERFACE_MTU;
+ hdr.len = sizeof(hdr) +
+ sizeof(u_int16_t);
+
+ if ((buf = buf_open(hdr.len)) == NULL)
+ error("buf_open: %m");
+
+ errs += buf_add(buf, &hdr, sizeof(hdr));
+ errs += buf_add(buf, &mtu, sizeof(mtu));
+ if (errs)
+ error("buf_add: %m");
+
+ if (buf_close(privfd, buf) == -1)
+ error("buf_close: %m");
+}
+
+void
+interface_set_mtu_priv(char *ifname, u_int16_t mtu)
+{
+ struct ifreq ifr;
+ int sock;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ error("Can't create socket");
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(sock, SIOCSIFMTU, &ifr) == -1)
+ warning("SIOCSIFMTU failed (%d): %s", mtu,
+ strerror(errno));
+ close(sock);
+}
diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c
index 5d09c0a..e5d183c 100644
--- a/sbin/dhclient/privsep.c
+++ b/sbin/dhclient/privsep.c
@@ -112,6 +112,7 @@ dispatch_imsg(struct interface_info *ifi, int fd)
struct client_lease lease;
int ret, i;
struct buf *buf;
+ u_int16_t mtu;
buf_read(fd, &hdr, sizeof(hdr));
@@ -236,6 +237,13 @@ dispatch_imsg(struct interface_info *ifi, int fd)
case IMSG_SEND_PACKET:
send_packet_priv(ifi, &hdr, fd);
break;
+ case IMSG_SET_INTERFACE_MTU:
+ if (hdr.len < sizeof(hdr) + sizeof(u_int16_t))
+ error("corrupted message received");
+
+ buf_read(fd, &mtu, sizeof(u_int16_t));
+ interface_set_mtu_priv(ifi->name, mtu);
+ break;
default:
error("received unknown message, code %d", hdr.code);
}
diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h
index d464da4..e1a7338 100644
--- a/sbin/dhclient/privsep.h
+++ b/sbin/dhclient/privsep.h
@@ -36,7 +36,8 @@ enum imsg_code {
IMSG_SCRIPT_WRITE_PARAMS,
IMSG_SCRIPT_GO,
IMSG_SCRIPT_GO_RET,
- IMSG_SEND_PACKET
+ IMSG_SEND_PACKET,
+ IMSG_SET_INTERFACE_MTU,
};
struct imsg_hdr {
OpenPOWER on IntegriCloud