diff options
author | Samuel Tan <samueltan@google.com> | 2015-08-13 16:41:21 -0700 |
---|---|---|
committer | Samuel Tan <samueltan@google.com> | 2015-08-18 13:46:52 -0700 |
commit | a3595821594453ea89ef8e6790927694b0a1adf1 (patch) | |
tree | 5592cd518978b8199fa080709e7a50bfb5f1d5ca | |
parent | dd90b01b5502dc66e00ea6a4d00ebdf77ea1eddc (diff) | |
download | dhcpcd-6.8.2-a3595821594453ea89ef8e6790927694b0a1adf1.tar.gz |
[PATCH] dhcpcd: Allow lease file to be set on command line
Cherry-picked from
https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/
master/net-misc/dhcpcd/files/patches/dhcpcd-6.8.2-Allow-lease-file-to-be-
set-on-command-line.patch.
Currently, dhcpcd names its lease files using the interface name
as the unique part of the name. There are a couple reasons why
this may not work well: firstly if "eth0" can have different MAC
addresses (multiple USB-Ethernet dongles for example) leases for
one interface aren't valid for the other. Secondly, when using
a wireless interface, it would be convenient to hold multiple
leases in parallel for each SSID one is connected to.
This change adds a suffix to each interface argument (dhcpcd can
accept multiple interface arguments) that specifies the identifier
to use to save lease files with. By default, the behavior is
identical.
The second CL (https://gerrit.chromium.org/gerrit/22170) for fixing
pid file formating bug originally introduced by this CL is not needed
anymore since this bug doesn't exist/apply in the updated implementation.
BUG: 22956197
Change-Id: Id04168daa965065ca50e60f55c4cdc80f751c9c3
Reviewed-on: https://gerrit.chromium.org/gerrit/21991
Reviewed-on: https://gerrit.chromium.org/gerrit/22170
-rw-r--r-- | dhcp-common.c | 8 | ||||
-rw-r--r-- | dhcp.h | 2 | ||||
-rw-r--r-- | dhcpcd.8.in | 6 | ||||
-rw-r--r-- | dhcpcd.c | 22 | ||||
-rw-r--r-- | dhcpcd.h | 2 | ||||
-rw-r--r-- | if.c | 65 | ||||
-rw-r--r-- | if.h | 2 |
7 files changed, 88 insertions, 19 deletions
diff --git a/dhcp-common.c b/dhcp-common.c index 2936b55..39d9787 100644 --- a/dhcp-common.c +++ b/dhcp-common.c @@ -741,6 +741,14 @@ dhcp_set_leasefile(char *leasefile, size_t len, int family, return 0; } + if (strlen(ifp->lease_identifier) > 0) { + /* Only supports lease identifier for IPv4 for now. */ + if (family == AF_INET) { + return snprintf(leasefile, len, LEASEFILE, + ifp->lease_identifier, "", ""); + } + } + switch (family) { case AF_INET: case AF_INET6: @@ -228,7 +228,7 @@ struct dhcp_state { struct in_addr dst; uint8_t added; - char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDSIZE * 4)]; + char leasefile[PATH_MAX]; time_t start_uptime; unsigned char *clientid; diff --git a/dhcpcd.8.in b/dhcpcd.8.in index a67626a..e815620 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -191,6 +191,12 @@ changes the routes to use the interface with the same route and the lowest metric. See options below for controlling which interfaces we allow and deny through the use of patterns. +.Pp +If an interface name is suffixed by an equal-sign, the text following the +equal sign will be used instead of the interface name as the unique identifier +for the DHCP lease file. Doing so allows the caller to specify different +lease files for the same interface (e.g, when switching the same wireless +interface between different 802.11 networks). .Ss Hooking into events .Nm runs @@ -1362,6 +1362,7 @@ main(int argc, char **argv) int sig; const char *siga; #endif + char ifn[IF_NAMESIZE]; /* Test for --help and --version */ if (argc > 1) { @@ -1523,13 +1524,15 @@ main(int argc, char **argv) * instance for that interface. */ if (optind == argc - 1 && !(ctx.options & DHCPCD_MASTER)) { const char *per; - - if (strlen(argv[optind]) > IF_NAMESIZE) { + int intf_len = strlen(argv[optind]); + split_interface_lease(argv[optind], &intf_len, NULL); + if (intf_len > IF_NAMESIZE) { logger(&ctx, LOG_ERR, "%s: interface name too long", argv[optind]); goto exit_failure; } + strlcpy(ifn, argv[optind], intf_len + 1); /* Allow a dhcpcd interface per address family */ switch(family) { case AF_INET: @@ -1542,7 +1545,7 @@ main(int argc, char **argv) per = ""; } snprintf(ctx.pidfile, sizeof(ctx.pidfile), - PIDFILE, "-", argv[optind], per); + PIDFILE, "-", ifn, per); } else { snprintf(ctx.pidfile, sizeof(ctx.pidfile), PIDFILE, "", "", ""); @@ -1780,10 +1783,19 @@ main(int argc, char **argv) goto exit_failure; } for (i = 0; i < ctx.ifc; i++) { - if (if_find(ctx.ifaces, ctx.ifv[i]) == NULL) + int intf_len = strlen(ctx.ifv[i]); + split_interface_lease(ctx.ifv[i], &intf_len, NULL); + if (intf_len > IF_NAMESIZE) { logger(&ctx, LOG_ERR, - "%s: interface not found or invalid", + "%s: interface name too long", ctx.ifv[i]); + continue; + } + strlcpy(ifn, ctx.ifv[i], intf_len + 1); + if (if_find(ctx.ifaces, ifn) == NULL) + logger(&ctx, LOG_ERR, + "%s: interface not found or invalid", + ifn); } if (TAILQ_FIRST(ctx.ifaces) == NULL) { if (ctx.ifc == 0) @@ -40,6 +40,7 @@ #define IF_SSIDSIZE 33 #define PROFILE_LEN 64 #define SECRET_LEN 64 +#define LEASE_IDENTIFIER_LEN (PATH_MAX - sizeof(LEASEFILE)) #define LINK_UP 1 #define LINK_UNKNOWN 0 @@ -73,6 +74,7 @@ struct interface { int wireless; uint8_t ssid[IF_SSIDSIZE]; unsigned int ssid_len; + char lease_identifier[LEASE_IDENTIFIER_LEN]; char profile[PROFILE_LEN]; struct if_options *options; @@ -74,6 +74,34 @@ #undef IFLR_ACTIVE #endif +int +split_interface_lease(const char *ifname, int *interface_name_len, + const char **lease_identifier) +{ + int ret = 0; + int len; + const char *lease_ptr = ifname; + const char *p = strchr(ifname, '='); + + if (interface_name_len) + len = *interface_name_len; + else + len = strlen(ifname); + + if (p) { + lease_ptr = p + 1; + if (len > p - ifname) + len = p - ifname; + ret = 1; + } + + if (interface_name_len) + *interface_name_len = len; + if (lease_identifier) + *lease_identifier = lease_ptr; + return ret; +} + void if_free(struct interface *ifp) { @@ -229,9 +257,13 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) int i; struct if_head *ifs; struct interface *ifp; -#ifdef __linux__ + const char *lease_identifier; char ifn[IF_NAMESIZE]; + +#ifdef __linux__ + char alias[IF_NAMESIZE]; #endif + #ifdef AF_LINK const struct sockaddr_dl *sdl; #ifdef SIOCGIFPRIORITY @@ -287,28 +319,31 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) if (ifp) continue; + lease_identifier = NULL; if (argc > 0) { for (i = 0; i < argc; i++) { + int intf_len = strlen(argv[i]); + split_interface_lease(argv[i], &intf_len, + &lease_identifier); + if (intf_len > IF_NAMESIZE) + continue; + strlcpy(ifn, argv[i], intf_len + 1); #ifdef __linux__ + strlcpy(alias, argv[i], intf_len + 1); /* Check the real interface name */ - strlcpy(ifn, argv[i], sizeof(ifn)); p = strchr(ifn, ':'); if (p) *p = '\0'; +#endif if (strcmp(ifn, ifa->ifa_name) == 0) break; -#else - if (strcmp(argv[i], ifa->ifa_name) == 0) - break; -#endif } if (i == argc) continue; - p = argv[i]; } else { - p = ifa->ifa_name; -#ifdef __linux__ strlcpy(ifn, ifa->ifa_name, sizeof(ifn)); +#ifdef __linux + strlcpy(alias, ifa->ifa_name, sizeof(alias)); #endif /* -1 means we're discovering against a specific * interface, but we still need the below rules @@ -316,6 +351,8 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0) continue; } + p = ifn; + for (i = 0; i < ctx->ifdc; i++) if (!fnmatch(ctx->ifdv[i], p, 0)) break; @@ -351,11 +388,13 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) } ifp->ctx = ctx; #ifdef __linux__ - strlcpy(ifp->name, ifn, sizeof(ifp->name)); - strlcpy(ifp->alias, p, sizeof(ifp->alias)); -#else - strlcpy(ifp->name, p, sizeof(ifp->name)); + strlcpy(ifp->alias, alias, sizeof(ifp->alias)); #endif + strlcpy(ifp->name, p, sizeof(ifp->name)); + if (lease_identifier) { + strlcpy(ifp->lease_identifier, lease_identifier, + sizeof(ifp->lease_identifier)); + } ifp->flags = ifa->ifa_flags; ifp->carrier = if_carrier(ifp); @@ -105,6 +105,8 @@ int if_domtu(const char *, short int); #define if_getmtu(iface) if_domtu(iface, 0) #define if_setmtu(iface, mtu) if_domtu(iface, mtu) int if_carrier(struct interface *); +int split_interface_lease(const char *ifname, int *ifname_len, + const char **lease_identifier); /* The below functions are provided by if-KERNEL.c */ int if_conf(struct interface *); |