Skip to content

Commit

Permalink
Move route state into it's own flag.
Browse files Browse the repository at this point in the history
Instead of setting the interface MTU directly, set the MTU for each of the
routes derived from the DHCP message in the same way we do for IPv6 RA.
  • Loading branch information
rsmarples committed Jul 28, 2015
1 parent 67aeb58 commit ca6cdf5
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 100 deletions.
53 changes: 52 additions & 1 deletion dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,23 @@ get_option_uint32(struct dhcpcd_ctx *ctx,
return 0;
}

static int
get_option_uint16(struct dhcpcd_ctx *ctx,
uint16_t *i, const struct dhcp_message *dhcp, uint8_t option)
{
const uint8_t *p;
size_t len;
uint16_t d;

p = get_option(ctx, dhcp, option, &len);
if (!p || len < (ssize_t)sizeof(d))
return -1;
memcpy(&d, p, sizeof(d));
if (i)
*i = ntohs(d);
return 0;
}

static int
get_option_uint8(struct dhcpcd_ctx *ctx,
uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
Expand Down Expand Up @@ -583,7 +600,7 @@ route_netmask(uint32_t ip_in)
/* We need to obey routing options.
* If we have a CSR then we only use that.
* Otherwise we add static routes and then routers. */
struct rt_head *
static struct rt_head *
get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
{
struct if_options *ifo = ifp->options;
Expand Down Expand Up @@ -689,6 +706,40 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
return routes;
}

uint16_t
dhcp_get_mtu(const struct interface *ifp)
{
const struct dhcp_message *dhcp;
uint16_t mtu;

if ((dhcp = D_CSTATE(ifp)->new) == NULL ||
has_option_mask(ifp->options->nomask, DHO_MTU) ||
get_option_uint16(ifp->ctx, &mtu, dhcp, DHO_MTU) == -1)
return 0;
return mtu;
}

/* Grab our routers from the DHCP message and apply any MTU value
* the message contains */
struct rt_head *
dhcp_get_routes(struct interface *ifp)
{
struct rt_head *routes;
uint16_t mtu;
const struct dhcp_message *dhcp;

dhcp = D_CSTATE(ifp)->new;
routes = get_option_routes(ifp, dhcp);
if ((mtu = dhcp_get_mtu(ifp)) != 0) {
struct rt *rt;

TAILQ_FOREACH(rt, routes, next) {
rt->mtu = mtu;
}
}
return routes;
}

#define PUTADDR(_type, _val) \
{ \
*p++ = _type; \
Expand Down
4 changes: 2 additions & 2 deletions dhcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ int get_option_addr(struct dhcpcd_ctx *,struct in_addr *,
const struct dhcp_message *, uint8_t);
#define IS_BOOTP(i, m) ((m) != NULL && \
get_option_uint8((i)->ctx, NULL, (m), DHO_MESSAGETYPE) == -1)
struct rt_head *get_option_routes(struct interface *,
const struct dhcp_message *);
uint16_t dhcp_get_mtu(const struct interface *);
struct rt_head *dhcp_get_routes(struct interface *);
ssize_t dhcp_env(char **, const char *, const struct dhcp_message *,
const struct interface *);

Expand Down
43 changes: 0 additions & 43 deletions dhcpcd-hooks/10-mtu

This file was deleted.

2 changes: 1 addition & 1 deletion dhcpcd-hooks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include ${TOP}/iconfig.mk

SCRIPTSDIR= ${LIBEXECDIR}/dhcpcd-hooks
SCRIPTS= 01-test 02-dump
SCRIPTS+= 10-mtu 10-wpa_supplicant 15-timezone 20-resolv.conf
SCRIPTS+= 10-wpa_supplicant 15-timezone 20-resolv.conf
SCRIPTS+= 29-lookup-hostname 30-hostname
SCRIPTS+= ${HOOKSCRIPTS}

Expand Down
6 changes: 3 additions & 3 deletions dhcpcd.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd July 3, 2015
.Dd July 28, 2015
.Dt DHCPCD 8
.Os
.Sh NAME
Expand Down Expand Up @@ -551,8 +551,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
.Pp
So to stop
.Nm
from touching your DNS or MTU settings you would do:-
.D1 dhcpcd -C resolv.conf -C mtu eth0
from touching your DNS settings you would do:-
.D1 dhcpcd -C resolv.conf eth0
.It Fl G , Fl Fl nogateway
Don't set any default routes.
.It Fl H , Fl Fl xidhwaddr
Expand Down
5 changes: 2 additions & 3 deletions dhcpcd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Most distributions have NTP support.
option ntp_servers
# Respect the network MTU.
# Some interface drivers reset when changing the MTU so disabled by default.
#option interface_mtu
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu

# A ServerID is required by RFC2131.
require dhcp_server_identifier
Expand Down
6 changes: 3 additions & 3 deletions dhcpcd.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd July 22, 2015
.Dd July 28, 2015
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
Expand Down Expand Up @@ -430,8 +430,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
.Pp
So to stop
.Nm dhcpcd
from touching your DNS or MTU settings you would do:-
.D1 nohook resolv.conf, mtu
from touching your DNS settings or starting wpa_supplicant you would do:-
.D1 nohook resolv.conf, wpa_supplicant
.It Ic noipv4
Don't attempt to configure an IPv4 address.
.It Ic noipv4ll
Expand Down
13 changes: 13 additions & 0 deletions if-bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)

get_addrs(rtm->rtm_addrs, cp, rti_info);
memset(rt, 0, sizeof(*rt));
rt->flags = (unsigned int)rtm->rtm_flags;
COPYOUT(rt->dest, rti_info[RTAX_DST]);
if (rtm->rtm_addrs & RTA_NETMASK)
COPYOUT(rt->net, rti_info[RTAX_NETMASK]);
Expand All @@ -508,6 +509,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
COPYOUT(rt->src, rti_info[RTAX_IFA]);

if (rtm->rtm_inits & RTV_MTU)
rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;

if (rtm->rtm_index)
rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
else if (rtm->rtm_addrs & RTA_IFP) {
Expand All @@ -516,6 +520,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
rt->iface = if_findsdl(ctx, sdl);
}

/* If we don't have an interface and it's a host route, it maybe
* to a local ip via the loopback interface. */
if (rt->iface == NULL &&
Expand Down Expand Up @@ -658,6 +663,11 @@ if_route(unsigned char cmd, const struct rt *rt)

if (rtm.hdr.rtm_addrs & RTA_IFA)
ADDADDR(&state->addr);

if (rt->mtu) {
rtm.hdr.rtm_inits |= RTV_MTU;
rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
}
}

#undef ADDADDR
Expand Down Expand Up @@ -897,6 +907,9 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
ipv6_mask(&rt->net, 128);
COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);

if (rtm->rtm_inits & RTV_MTU)
rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;

if (rtm->rtm_index)
rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
else if (rtm->rtm_addrs & RTA_IFP) {
Expand Down
55 changes: 33 additions & 22 deletions if-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,27 @@ add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
return 0;
}

static int
rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
unsigned short type, uint32_t data)
{
unsigned short len = RTA_LENGTH(sizeof(data));
struct rtattr *subrta;

if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
errno = ENOBUFS;
return -1;
}

subrta = (struct rtattr*)(void *)
(((char*)rta) + RTA_ALIGN(rta->rta_len));
subrta->rta_type = type;
subrta->rta_len = len;
memcpy(RTA_DATA(subrta), &data, sizeof(data));
rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
return 0;
}

#ifdef HAVE_NL80211_H
static struct nlattr *
nla_next(struct nlattr *nla, size_t *rem)
Expand Down Expand Up @@ -1374,6 +1395,17 @@ if_route(unsigned char cmd, const struct rt *rt)
if (rt->metric)
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);

if (cmd != RTM_DELETE && rt->mtu) {
char metricsbuf[32];
struct rtattr *metrics = (void *)metricsbuf;

metrics->rta_type = RTA_METRICS;
metrics->rta_len = RTA_LENGTH(0);
rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics));
}

if (send_netlink(rt->iface->ctx, NULL,
NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
retval = -1;
Expand Down Expand Up @@ -1488,27 +1520,6 @@ if_address6(const struct ipv6_addr *ap, int action)
return retval;
}

static int
rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
unsigned short type, uint32_t data)
{
unsigned short len = RTA_LENGTH(sizeof(data));
struct rtattr *subrta;

if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
errno = ENOBUFS;
return -1;
}

subrta = (struct rtattr*)(void *)
(((char*)rta) + RTA_ALIGN(rta->rta_len));
subrta->rta_type = type;
subrta->rta_len = len;
memcpy(RTA_DATA(subrta), &data, sizeof(data));
rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
return 0;
}

int
if_route6(unsigned char cmd, const struct rt6 *rt)
{
Expand Down Expand Up @@ -1565,7 +1576,7 @@ if_route6(unsigned char cmd, const struct rt6 *rt)
add_attr_32(&nlm.hdr, sizeof(nlm),
RTA_PRIORITY, rt->metric);
}
if (cmd == RTM_ADD && rt->mtu) {
if (cmd != RTM_DELETE && rt->mtu) {
char metricsbuf[32];
struct rtattr *metrics = (void *)metricsbuf;

Expand Down

0 comments on commit ca6cdf5

Please sign in to comment.