From: Roy Marples Date: Fri, 18 Apr 2008 23:12:44 +0000 (+0000) Subject: dhcpcd can now read a basic config file! Add a default dhcpcd.conf and matching man... X-Git-Tag: v4.0.2~472 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba9dfb7aaeb7eb870cfc1c93c4e519d58f082b75;p=thirdparty%2Fdhcpcd.git dhcpcd can now read a basic config file! Add a default dhcpcd.conf and matching man page. Add dhcpcd.sh man page. dhcpcd can now report variables it can send to dhcpcd.sh as well. --- diff --git a/Makefile b/Makefile index c9db0cc1..2338ff14 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,12 @@ SRCS= common.c dhcp.c dhcpcd.c logger.c net.c signal.c SRCS+= configure.c client.c SRCS+= ${SRC_IF} ${SRC_SOCKET} SCRIPT= dhcpcd.sh -MAN= dhcpcd.8 +CONF= dhcpcd.conf +MAN5= dhcpcd.conf.5 +MAN8= dhcpcd.8 dhcpcd.sh.8 -VERSION= 4.0.0-alpha1 -CLEANFILES= dhcpcd.sh dhcpcd.8 +VERSION= 4.0.0-alpha2 +CLEANFILES= dhcpcd.sh dhcpcd.8 dhcpcd.sh.8 BINDIR= ${PREFIX}/sbin SYSCONFDIR?= ${PREFIX}/etc/${PROG} diff --git a/config.h b/config.h index bda7efb8..87df1ea7 100644 --- a/config.h +++ b/config.h @@ -60,6 +60,7 @@ #endif #define RESOLVFILE "/etc/resolv.conf" +#define CONFIGFILE SYSCONFDIR "/" PACKAGE ".conf" #define DEFAULTSCRIPT SYSCONFDIR "/" PACKAGE ".sh" #define DUIDFILE SYSCONFDIR "/" PACKAGE ".duid" #define LEASEFILE DBDIR "/" PACKAGE "-%s.lease" diff --git a/dhcp.c b/dhcp.c index e1791a0e..ad3b8b33 100644 --- a/dhcp.c +++ b/dhcp.c @@ -145,11 +145,24 @@ const struct dhcp_option dhcp_options[] = { { 114, STRING, "default_url" }, { 118, IPV4, "subnet_selection" }, { 119, STRING | RFC3397, "domain_search" }, - { 121, RFC3442, "classless_static_routes" }, + { 121, RFC3442 | REQUEST, "classless_static_routes" }, + { 249, RFC3442, "ms-classless_static_routes" }, { 0, 0, NULL } }; -int make_reqmask(struct options *options, char **opts) +void +print_options(void) +{ + unsigned int i; + + for (i = 0; i < sizeof(dhcp_options) / sizeof(dhcp_options[0]); i++) + if (dhcp_options[i].var) + printf("%03d %s\n", + dhcp_options[i].option, + dhcp_options[i].var); +} + +int make_reqmask(struct options *options, char **opts, int add) { char *token; char *p = *opts; @@ -157,13 +170,19 @@ int make_reqmask(struct options *options, char **opts) const char *v; int max = sizeof(dhcp_options) / sizeof(dhcp_options[0]); - while ((token = strsep(&p, ","))) { + while ((token = strsep(&p, ", "))) { + if (*token == '\0') + continue; for (i = 0; i < max; i++) { if (!(v = dhcp_options[i].var)) continue; if (strcmp(v, token) == 0) { - add_reqmask(options->reqmask, - dhcp_options[i].option); + if (add == 1) + add_reqmask(options->reqmask, + dhcp_options[i].option); + else + del_reqmask(options->reqmask, + dhcp_options[i].option); break; } } @@ -769,15 +788,9 @@ make_message(struct dhcp_message **message, if (type == DHCP_INFORM) continue; break; - case DHCP_CSR: - if (options->domscsr > 1) - continue; - break; } *p++ = o; } - if (options->domscsr) - *p++ = DHCP_MSCSR; *n_params = p - n_params - 1; } *p++ = DHCP_END; diff --git a/dhcp.h b/dhcp.h index 20e8ca17..b92b9608 100644 --- a/dhcp.h +++ b/dhcp.h @@ -160,8 +160,10 @@ struct dhcp_lease { }; #define add_reqmask(var, val) (var[val >> 3] |= 1 << (val & 7)) +#define del_reqmask(var, val) (var[val >> 3] &= ~(1 << (val & 7))) #define has_reqmask(var, val) (var[val >> 3] & (1 << (val & 7))) -int make_reqmask(struct options *options, char **opts); +int make_reqmask(struct options *, char **, int); +void print_options(void); const uint8_t *get_option(const struct dhcp_message *, uint8_t); char *get_option_string(const struct dhcp_message *, uint8_t); int get_option_addr(uint32_t *, const struct dhcp_message *, uint8_t); diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 12f0b83a..d187e8f8 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -29,7 +29,7 @@ .Nd an RFC 2131 compliant DHCP client .Sh SYNOPSIS .Nm -.Op Fl dknpAEGHOLNRSTY +.Op Fl dknpAEGLSTV .Op Fl c , -script Ar script .Op Fl h , -hostname Ar hostname .Op Fl i , -classid Ar classid @@ -41,6 +41,7 @@ .Op Fl u , -userclass Ar class .Op Fl F , -fqdn Ar FQDN .Op Fl I , -clientid Ar clientid +.Op Fl O , -nooption Ar option .Ar interface .Nm .Fl k , -release @@ -68,16 +69,6 @@ will then write DNS information to .Xr resolvconf 8 , if available, otherwise directly to .Pa /etc/resolv.conf . -.Nm -will also configure -.Pa /etc/yp.conf -and -.Pa /etc/ntpd.conf -with NIS and NTP information if the DHCP server provided them. -If those file contents changed, then -.Nm -will also attempt to restart the respective services to notify them of the -change. If the hostname is currenly blank, (null) or localhost then .Nm will set the hostname to the one supplied by the DHCP server, or look it up @@ -113,10 +104,13 @@ option. .Nm will run @SYSCONFDIR@/dhcpcd.sh, or the script specified by the .Fl c , -script -option. It will set $1 to a shell compatible file that holds various -configuration settings obtained from the DHCP server and $2 to either -up, down or new depending on the state of -.Nm . +option. This script will configure +.Pa /etc/resolv.conf +and the +.Xr hostname 3 +if possible. It will also run custom hook scripts if defined. See +.Xr dhcpcd.sh 8 +for more details. .Nm ignores the exist code of the script. .Ss Fine tuning @@ -228,7 +222,7 @@ Tags the DHCP message with the userclass .Ar class . DHCP servers use this give memebers of the class DHCP options other than the default, without having to know things like hardware address or hostname. -.If Fl F , -fqdn Ar fqdn +.It Fl F , -fqdn Ar fqdn Requests that the DHCP server updates DNS using FQDN instead of just a hostname. Valid values for .Ar fqdn @@ -248,16 +242,6 @@ the first byte. Ethernet is 01, and the hardware address in the example is is a blank string, then we disable DUID support and use a .Ar clientid as shown above. -.It Fl S, -mscsr -Microsoft have their own code for Classless Static Routes -.Po -RFC 3442 -.Pc . -You can use this option to request this as well as the normal CSR. Another -instace of this option only requests the Microsoft CSR to prevent DHCP message -over-running its maximum size. DHCP server administrators should update their -CSR code from the Microsoft specific one to the RFC compliant one as the -content is fully compatible. .El .Ss Restriciting behaviour .Nm @@ -270,29 +254,19 @@ off. Don't request or claim the address by ARP. .It Fl G , -nogateway Don't set any default routes. -.It Fl H , -nohostname -Don't request a hostname. If the current hostname is blank, localhost or -(none) then the hostnam will be looked up in DNS and set to that. .It Fl L , -noipv4ll Don't use IPv4LL at all. -.It Fl N , -nontp -Don't touch -.Pa /etc/ntpd.conf -or restart the ntp service. -.It Fl O , -nooptions -Don't request any options beyond what is needed to configure the interface. -.It Fl R , -nodns -Don't send DNS information to resolvconf or touch -.Pa /etc/resolv.conf . +.It Fl O , -nooption Ar option +Don't request the specified option. If no option given, then don't request +any options other than those to configure the interface and routing. .It Fl T, -test On receipt of discover messages we just call @SYSCONFDIR@/dhcpcd.sh with the reason of TEST which echo's the DHCP variables found in the message to the console. The interface configuration isn't touched and neither are any configuration files. -.It Fl Y , -nonis -Don't touch -.Pa /etc/yp.conf -or restart the ypbind service. +.It Fl V, -variables +Display a list of option codes and the associated variable for use in +.Xr dhcpcd.sh 8 . .El .Sh NOTES Because @@ -334,11 +308,10 @@ The actual DHCP message send by the server. We use this when reading the last lease and use the files mtime as when it was issued. .El .Sh SEE ALSO -.Xr ntp 1 , +.Xr dhcpcd.conf 5 , +.Xr dhcpcd.sh 8 , .Xr resolv.conf 5 , .Xr resolvconf 8 , -.Xr yp.conf 5 , -.Xr ypbind 8 .Sh STANDARDS RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3361, RFC 3397, RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702. diff --git a/dhcpcd.c b/dhcpcd.c index 09bd9b27..98eaa024 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -51,7 +51,6 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; static int doversion = 0; static int dohelp = 0; -#define EXTRA_OPTS static const struct option longopts[] = { {"arp", no_argument, NULL, 'a'}, {"script", required_argument, NULL, 'c'}, @@ -62,7 +61,7 @@ static const struct option longopts[] = { {"leasetime", required_argument, NULL, 'l'}, {"metric", required_argument, NULL, 'm'}, {"renew", no_argument, NULL, 'n'}, - {"option", required_argument, NULL, 'o'}, + {"option", required_argument, NULL, 'o'}, {"persistent", no_argument, NULL, 'p'}, {"inform", optional_argument, NULL, 's'}, {"request", optional_argument, NULL, 'r'}, @@ -72,20 +71,23 @@ static const struct option longopts[] = { {"lastlease", no_argument, NULL, 'E'}, {"fqdn", optional_argument, NULL, 'F'}, {"nogateway", no_argument, NULL, 'G'}, - {"nohostname", no_argument, NULL, 'H'}, {"clientid", optional_argument, NULL, 'I'}, {"noipv4ll", no_argument, NULL, 'L'}, - {"nontp", no_argument, NULL, 'N'}, - {"nooptions", no_argument, NULL, 'O'}, - {"nodns", no_argument, NULL, 'R'}, - {"msscr", no_argument, NULL, 'S'}, + {"nooption", optional_argument, NULL, 'O'}, {"test", no_argument, NULL, 'T'}, - {"nonis", no_argument, NULL, 'Y'}, + {"variables", no_argument, NULL, 'V'}, {"help", no_argument, &dohelp, 1}, {"version", no_argument, &doversion, 1}, #ifdef THERE_IS_NO_FORK {"daemonised", no_argument, NULL, 'f'}, {"skiproutes", required_argument, NULL, 'g'}, +#endif +#ifdef CMDLINE_COMPAT + {"nohostname", no_argument, NULL, 'H'}, + {"nodns", no_argument, NULL, 'R'}, + {"nontp", no_argument, NULL, 'N'}, + {"nonis", no_argument, NULL, 'Y'}, + {"msscr", no_argument, NULL, 'S'}, #endif {NULL, 0, NULL, 0} }; @@ -95,8 +97,13 @@ char dhcpcd[PATH_MAX]; char **dhcpcd_argv = NULL; int dhcpcd_argc = 0; char *dhcpcd_skiproutes = NULL; -#undef EXTRA_OPTS #define EXTRA_OPTS "fg:" +#elif CMDLINE_COMAPT +# define EXTRA_OPTS "NRSY" +#endif + +#ifndef EXTRA_OPTS +# define EXTRA_OPTS #endif static int @@ -137,29 +144,203 @@ read_pid(const char *pidfile) static void usage(void) { - printf("usage: "PACKAGE" [-adknpEGHNORSTY] [-c script] [-h hostname] [-i classID]\n" + printf("usage: "PACKAGE" [-adknpEGHLOSTV] [-c script] [-h hostname] [-i classID]\n" " [-l leasetime] [-m metric] [-o option] [-r ipaddress]\n" " [-s ipaddress] [-t timeout] [-u userclass] [-F none | ptr | both]\n" " [-I clientID] \n"); } +static int +parse_option(int opt, char *oarg, struct options *options) +{ + static int userclasses = 0; + int i; + int j; + char *p; + + switch(opt) { + case 'h': + if (!oarg) + *options->hostname = '\0'; + else if (strlen(oarg) > MAXHOSTNAMELEN) { + logger(LOG_ERR, + "`%s' too long for HostName string, max is %d", + oarg, MAXHOSTNAMELEN); + return -1; + } else + strlcpy(options->hostname, oarg, + sizeof(options->hostname)); + break; + case 'i': + if (!oarg) { + *options->classid = '\0'; + } else if (strlen(oarg) > CLASS_ID_MAX_LEN) { + logger(LOG_ERR, + "`%s' too long for ClassID string, max is %d", + oarg, CLASS_ID_MAX_LEN); + return -1; + } else + strlcpy(options->classid, oarg, + sizeof(options->classid)); + break; + case 'l': + if (*oarg == '-') { + logger(LOG_ERR, + "leasetime must be a positive value"); + return -1; + } + errno = 0; + options->leasetime = (uint32_t)strtol(oarg, NULL, 0); + if (errno == EINVAL || errno == ERANGE) { + logger(LOG_ERR, "`%s' out of range", oarg); + return -1; + } + break; + case 'm': + options->metric = atoint(oarg); + if (options->metric < 0) { + logger(LOG_ERR, "metric must be a positive value"); + return -1; + } + break; + case 'o': + if (make_reqmask(options, &oarg, 1) != 0) { + logger(LOG_ERR, "unknown option `%s'", oarg); + return -1; + } + break; + case 'p': + options->options |= DHCPCD_PERSISTENT; + break; + case 's': + options->options |= DHCPCD_INFORM; + options->options &= ~DHCPCD_ARP; + if (!oarg || strlen(optarg) == 0) { + options->request_address.s_addr = 0; + break; + } else { + if ((p = strchr(oarg, '/'))) { + /* nullify the slash, so the -r option + * can read the address */ + *p++ = '\0'; + if (sscanf(p, "%d", &i) != 1 || + inet_cidrtoaddr(i, &options->request_netmask) != 0) + { + logger(LOG_ERR, + "`%s' is not a valid CIDR", + p); + return -1; + } + } + } + /* FALLTHROUGH */ + case 'r': + if (!(options->options & DHCPCD_INFORM)) + options->options |= DHCPCD_REQUEST; + if (strlen(oarg) > 0 && + !inet_aton(oarg, &options->request_address)) + { + logger(LOG_ERR, "`%s' is not a valid IP address", + oarg); + return -1; + } + break; + case 't': + options->timeout = atoint(oarg); + if (options->timeout < 0) { + logger (LOG_ERR, "timeout must be a positive value"); + return -1; + } + break; + case 'u': + j = 0; + for (i = 0; i < userclasses; i++) + j += (int)options->userclass[j] + 1; + if (j + 1 + strlen(oarg) > USERCLASS_MAX_LEN) { + logger(LOG_ERR, + "userclass overrun, max is %d", + USERCLASS_MAX_LEN); + return -1; + } + userclasses++; + memcpy(options->userclass + j + 1 , + oarg, strlen(optarg)); + options->userclass[j] = strlen(oarg); + options->userclass_len += (strlen(oarg)) + 1; + break; + case 'A': + options->options &= ~DHCPCD_ARP; + /* IPv4LL requires ARP */ + options->options &= ~DHCPCD_IPV4LL; + break; + case 'E': + options->options |= DHCPCD_LASTLEASE; + break; + case 'F': + if (!oarg) { + options->fqdn = FQDN_BOTH; + break; + } + if (strncmp(oarg, "none", strlen(optarg)) == 0) + options->fqdn = FQDN_NONE; + else if (strncmp(oarg, "ptr", strlen(optarg)) == 0) + options->fqdn = FQDN_PTR; + else if (strncmp(oarg, "both", strlen(optarg)) == 0) + options->fqdn = FQDN_BOTH; + else { + logger(LOG_ERR, "invalid value `%s' for FQDN", + oarg); + return -1; + } + break; + case 'G': + options->options &= ~DHCPCD_GATEWAY; + break; + case 'I': + if (oarg) { + if (strlen(oarg) > CLIENT_ID_MAX_LEN) { + logger(LOG_ERR, "`%s' is too long for" + " ClientID, max is %d", + oarg, CLIENT_ID_MAX_LEN); + return -1; + } + if (strlcpy(options->clientid, oarg, + sizeof(options->clientid)) == 0) + /* empty string disabled duid */ + options->options &= ~DHCPCD_DUID; + } else { + memset(options->clientid, 0, + sizeof(options->clientid)); + options->options &= ~DHCPCD_DUID; + } + break; + case 'L': + options->options &= ~DHCPCD_IPV4LL; + break; + default: + return 0; + } + + return 1; +} + int main(int argc, char **argv) { struct options *options; - int userclasses = 0; int opt; int option_index = 0; char *prefix; pid_t pid; int debug = 0; - int i; - int j; + int i, r; + unsigned int u; int pidfd = -1; int sig = 0; int retval = EXIT_FAILURE; - char *p; - int doopts = 1, dodns = 1, dohostname = 1, donis = 1, dontp = 1; + char *line, *option, *buffer = NULL; + size_t len = 0; + FILE *f; /* Close any un-needed fd's */ for (i = getdtablesize() - 1; i >= 3; --i) @@ -181,10 +362,53 @@ main(int argc, char **argv) strcmp(options->hostname, "localhost") == 0) *options->hostname = '\0'; + /* Parse our options file */ + f = fopen(CONFIGFILE, "r"); + if (f) { + while ((get_line(&buffer, &len, f))) { + line = buffer; + option = strsep(&line, " "); + if (!option || *option == '\0' || *option == '#') + continue; + for (u = 0; u < sizeof(longopts) / sizeof(longopts[0]); + u++) + { + if (strcmp(longopts[u].name, option) == 0) { + r = parse_option(longopts[u].val, line, + options); + if (r == 1) + break; + free(buffer); + fclose(f); + if (r == 0) + usage(); + goto abort; + } + } + } + free(buffer); + fclose(f); + } else { + if (errno != ENOENT) { + logger(LOG_ERR, "fopen `%s': %s", CONFIGFILE, + strerror(errno)); + goto abort; + } + } + +#ifdef CMDLINE_COMAPT + add_reqmask(options->reqmask, DHCP_DNSSERVER); + add_reqmask(options->reqmask, DHCP_DNSDOMAIN); + add_reqmask(options->reqmask, DHCP_DNSSEARCH); + add_reqmask(options->reqmask, DHCP_NISSERVER); + add_reqmask(options->reqmask, DHCP_NISDOMAIN); + add_reqmask(options->reqmask, DHCP_NTPSERVER); +#endif + /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ while ((opt = getopt_long(argc, argv, EXTRA_OPTS - "c:dh:i:kl:m:no:pr:s:t:u:xAEF:GHI:LNORSTY", + "c:dh:i:kl:m:no:pr:s:t:u:xAEF:GHI:LO:STV", longopts, &option_index)) != -1) { switch (opt) { @@ -194,18 +418,15 @@ main(int argc, char **argv) logger(LOG_ERR, "option `%s' should set a flag", longopts[option_index].name); goto abort; - case 'c': - options->script = optarg; - break; case 'd': debug++; switch (debug) { - case 1: - setloglevel(LOG_DEBUG); - break; - case 2: - options->options &= ~DHCPCD_DAEMONISE; - break; + case 1: + setloglevel(LOG_DEBUG); + break; + case 2: + options->options &= ~DHCPCD_DAEMONISE; + break; } break; #ifdef THERE_IS_NO_FORK @@ -217,205 +438,55 @@ main(int argc, char **argv) dhcpcd_skiproutes = xstrdup(optarg); break; #endif - case 'h': - if (!optarg) - *options->hostname = '\0'; - else if (strlen(optarg) > MAXHOSTNAMELEN) { - logger(LOG_ERR, - "`%s' too long for HostName string," - " max is %d", optarg, MAXHOSTNAMELEN); - goto abort; - } else - strlcpy(options->hostname, optarg, - sizeof(options->hostname)); - break; - case 'i': - if (!optarg) { - *options->classid = '\0'; - } else if (strlen(optarg) > CLASS_ID_MAX_LEN) { - logger(LOG_ERR, - "`%s' too long for ClassID string," - " max is %d", optarg, CLASS_ID_MAX_LEN); - goto abort; - } else - strlcpy(options->classid, optarg, - sizeof(options->classid)); - break; case 'k': sig = SIGHUP; break; - case 'l': - if (*optarg == '-') { - logger(LOG_ERR, - "leasetime must be a positive value"); - goto abort; - } - errno = 0; - options->leasetime = (uint32_t)strtol(optarg, NULL, 0); - if (errno == EINVAL || errno == ERANGE) { - logger(LOG_ERR, "`%s' out of range", optarg); - goto abort; - } - break; - case 'm': - options->metric = atoint(optarg); - if (options->metric < 0) { - logger(LOG_ERR, - "metric must be a positive value"); - goto abort; - } - break; case 'n': sig = SIGALRM; break; - case 'o': - if (make_reqmask(options, &optarg) != 0) { - logger(LOG_ERR, "unknown option `%s'", optarg); - goto abort; - } - break; - case 'p': - options->options |= DHCPCD_PERSISTENT; - break; - case 's': - options->options |= DHCPCD_INFORM; - options->options &= ~DHCPCD_ARP; - if (!optarg || strlen(optarg) == 0) { - options->request_address.s_addr = 0; - break; - } else { - if ((p = strchr(optarg, '/'))) { - /* nullify the slash, so the -r option - * can read the address */ - *p++ = '\0'; - if (sscanf(p, "%d", &i) != 1 || - inet_cidrtoaddr(i, &options->request_netmask) != 0) - { - logger(LOG_ERR, - "`%s' is not a valid CIDR", - p); - goto abort; - } - } - } - /* FALLTHROUGH */ - case 'r': - if (!(options->options & DHCPCD_INFORM)) - options->options |= DHCPCD_REQUEST; - if (strlen(optarg) > 0 && - !inet_aton(optarg, &options->request_address)) - { - logger(LOG_ERR, - "`%s' is not a valid IP address", - optarg); - goto abort; - } - break; - case 't': - options->timeout = atoint(optarg); - if (options->timeout < 0) { - logger (LOG_ERR, "timeout must be a positive value"); - goto abort; - } - break; - case 'u': - j = 0; - for (i = 0; i < userclasses; i++) - j += (int)options->userclass[j] + 1; - if (j + 1 + strlen(optarg) > USERCLASS_MAX_LEN) { - logger(LOG_ERR, - "userclass overrun, max is %d", - USERCLASS_MAX_LEN); - goto abort; - } - userclasses++; - memcpy(options->userclass + j + 1 , - optarg, strlen(optarg)); - options->userclass[j] = strlen(optarg); - options->userclass_len += (strlen(optarg)) + 1; - break; case 'x': sig = SIGTERM; break; - case 'A': -#ifndef ENABLE_ARP - logger (LOG_ERR, "arp not compiled into dhcpcd"); - goto abort; -#endif - options->options &= ~DHCPCD_ARP; - /* IPv4LL requires ARP */ - options->options &= ~DHCPCD_IPV4LL; - break; - case 'E': - options->options |= DHCPCD_LASTLEASE; - break; - case 'F': - if (!optarg) { - options->fqdn = FQDN_BOTH; - break; - } - if (strncmp(optarg, "none", strlen(optarg)) == 0) - options->fqdn = FQDN_NONE; - else if (strncmp(optarg, "ptr", strlen(optarg)) == 0) - options->fqdn = FQDN_PTR; - else if (strncmp(optarg, "both", strlen(optarg)) == 0) - options->fqdn = FQDN_BOTH; - else { - logger(LOG_ERR, "invalid value `%s' for FQDN", - optarg); - goto abort; + case 'O': + if (make_reqmask(options, &optarg, -1) != 0) { + logger(LOG_ERR, "unknown option `%s'", optarg); + return -1; } break; - case 'G': - options->options &= ~DHCPCD_GATEWAY; + case 'T': + options->options |= DHCPCD_TEST | DHCPCD_PERSISTENT; break; + case 'V': + print_options(); + goto abort; +#ifdef CMDLINE_COMPAT case 'H': - dohostname = 0; - break; - case 'I': - if (optarg) { - if (strlen(optarg) > CLIENT_ID_MAX_LEN) { - logger(LOG_ERR, "`%s' is too long for" - " ClientID, max is %d", - optarg, CLIENT_ID_MAX_LEN); - goto abort; - } - if (strlcpy(options->clientid, optarg, - sizeof(options->clientid)) == 0) - /* empty string disabled duid */ - options->options &= ~DHCPCD_DUID; - } else { - memset(options->clientid, 0, - sizeof(options->clientid)); - options->options &= ~DHCPCD_DUID; - } - break; - case 'L': - options->options &= ~DHCPCD_IPV4LL; break; case 'N': - dontp = 0; - break; - case 'O': - doopts = 0; + del_reqmask(options->reqmask, DHCP_NTPSERVER); break; case 'R': - dodns = 0; + del_reqmask(options->reqmask, DHCP_DNSSERVER); + del_reqmask(options->reqmask, DHCP_DNSDOMAIN); + del_reqmask(options->reqmask, DHCP_DNSSEARCH); break; case 'S': - options->domscsr++; - break; - case 'T': - options->options |= DHCPCD_TEST | DHCPCD_PERSISTENT; + add_mask(options->requmask, DHCP_MSCR); break; case 'Y': - donis = 0; + del_reqmask(options->reqmask, DHCP_NISSERVER); + del_reqmask(options->reqmask, DHCP_NISDOMAIN); break; +#endif case '?': usage(); goto abort; default: - usage(); + i = parse_option(opt, optarg, options); + if (i == 1) + break; + if (i == 0) + usage(); goto abort; } } @@ -428,9 +499,6 @@ main(int argc, char **argv) #ifdef ENABLE_DUID " DUID" #endif -#ifdef ENABLE_INFO_COMPAT - " INFO_COMPAT" -#endif #ifdef ENABLE_IPV4LL " IPV4LL" #endif @@ -443,22 +511,6 @@ main(int argc, char **argv) if (dohelp) usage(); - if (doopts) { - if (dodns) { - add_reqmask(options->reqmask, DHCP_DNSSERVER); - add_reqmask(options->reqmask, DHCP_DNSDOMAIN); - add_reqmask(options->reqmask, DHCP_DNSSEARCH); - } - if (dohostname) - add_reqmask(options->reqmask, DHCP_HOSTNAME); - if (donis) { - add_reqmask(options->reqmask, DHCP_NISSERVER); - add_reqmask(options->reqmask, DHCP_NISDOMAIN); - } - if (dontp) - add_reqmask(options->reqmask, DHCP_NTPSERVER); - } - #ifdef THERE_IS_NO_FORK dhcpcd_argv = argv; dhcpcd_argc = argc; diff --git a/dhcpcd.conf b/dhcpcd.conf new file mode 100644 index 00000000..17832540 --- /dev/null +++ b/dhcpcd.conf @@ -0,0 +1,8 @@ +# A sample configuration for dhcpcd. +# See dhcpcd.conf(5) for details. + +# dhcpcd.sh uses these options. +option domain_name_servers, domain_name, domain_search, host_name + +# Most distros have ntp support. +option ntp_servers diff --git a/dhcpcd.conf.5 b/dhcpcd.conf.5 new file mode 100644 index 00000000..9b95fba1 --- /dev/null +++ b/dhcpcd.conf.5 @@ -0,0 +1,87 @@ +.\" Copyright 2006-2008 Roy Marples +.\" All rights reserved +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd Apr 18, 2008 +.Dt DHCPCD.CONF 5 SMM +.Sh NAME +.Nm dhcpcd.conf +.Nd dhcpcd configuration file +.Sh DESCRIPTION +Although +.Nm dhcpcd +can do everything from the command line, there are cases where it's just easier +to do it once in a configuration file. Most of the options found in +.Xr dhcpcd 8 +can be used here. The first word on the line is the option and the rest of the +line is the value. Blank lines and lines starting with # are ignored. +.Pp +Here's a list of available options: +.Bl -tag -width indent +.It Ic option Ar dhcp-option +Requests the +.Ar dhcp-option +from the server. It can be a variable to be used in +.Xr dhcpcd.sh 8 +or the numerical value. You can specify more seperated by commas, spaces or +more option lines. +.It Ic hostname Ar name +Sends specified hostname to the DHCP server so it can be registered in DNS. +.It Ic leasetime Ar seconds +Request a leasetime of +.Ar seconds . +.It Ic timeout Ar seconds +The default timeout for waiting for a DHCP response is 20 seconds which may +be too long or too short and can be changed here. +.It Ic classid Ar string +Change the default classid sent from dhcpcd-version. If not set then none +is sent. +.It Ic clientid Ar string +By default, +.Nm dhcpcd +sends a Client Node Identifier +.Rs +.%T "RFC 4361" +.Re +as the ClientID. Not setting anything causes the interface MAC address to +be sent instead. Otherwise, it sends the string specified. If the string +is of the format 01:02:03 then it encodes it. +.It Ic userclass Ar string +Tag the DHCP messages with the userclass. You can specify more than one. +.It Ic noarp +Don't send any ARP requests. This also disables IPv4LL. +.It Ic nogateway +Don't install any default routes. +.It Ic noipv4ll +Don't attempt to obtain an IPv4LL address if we failed to get one via DHCP. +See +.Rs +.%T "RFC 3927" +.Re +.Sh SEE ALSO +.Xr dhcpcd.sh 8 , +.Xr dhcpcd 8 +.Sh AUTHORS +.An "Roy Marples" Aq roy@marples.name +.Sh BUGS +Please report them to http://bugs.marples.name diff --git a/dhcpcd.h b/dhcpcd.h index 3685a5a6..b04d3aa8 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -81,7 +81,6 @@ struct options { time_t timeout; int metric; int options; - int domscsr; struct in_addr request_address; struct in_addr request_netmask; diff --git a/dhcpcd.sh.8.in b/dhcpcd.sh.8.in new file mode 100644 index 00000000..c76f4920 --- /dev/null +++ b/dhcpcd.sh.8.in @@ -0,0 +1,98 @@ +.\" Copyright 2006-2008 Roy Marples +.\" All rights reserved +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd Apr 18, 2008 +.Dt DHCPCD.SH 8 SMM +.Sh NAME +.Nm dhcpcd.sh +.Nd DHCP client configuration script +.Sh DESCRIPTION +.Nm +is used by +.Xr dhcpcd 8 +to configure +.Pa /etc/resolv.conf +and run any system or user defined hook scripts. +Each time +.Nm +is invoked, +.Ev $interface +is set to the interface that +.Nm dhcpcd +is run on and +.Ev $reason +is to the reason why +.Nm +was invoked. DHCP information to be configured is held in variables starting +with the word new_ and old DHCP information to be removed is held in variables +starting with the word old_. +.Nm dhcpcd +can display the full list of variables it knows how about by using the +.Fl V , -variables +argument. +.Pp +Here's a list of reasons why +.Nm +could be invoked: +.Bl -tag -width indent +.It Dv BOUND +dhcpcd obtained a new lease from a DHCP server. +.It Dv RENEW +dhcpcd renewed it's lease. +.It Dv REBIND +dhcpcd has rebound to a new DHCP server. +.It Dv REBOOT +dhcpcd successfully requested a lease from a DHCP server. +.It Dv EXPIRE +dhcpcd's lease expired and it failed to obtain a new one. +.It Dv IPV4LL +dhcpcd failed to contact any DHCP servers but did obtain an IPV4LL address. +.It Dv FAIL +dhcpcd failed to contact any DHCP servers or use an old lease. +.It Dv TIMEOUT +dhcpcd failed to contact any DHCP servers but was able to use an old lease. +.It Dv TEST +dhcpcd received an OFFER from a DHCP server but will not configure the +interface. This is primarily used to test the variables are filled correctly +for the script to process them. +.El +.Sh FILES +Before +.Nm +runs, it loads +.Pa @SYSCONFDIR/dhcpcd-enter-hook +and any scripts found in +.Pa @SYSCONFDIR/dhcpcd-enter-hook.d . +Then it runs itself, configuring +.Pa /etc/resolv.conf . +Finally it loads +.Pa @SYSCONFDIR/dhcpcd-exit-hook +and any scripts found in +.Pa @SYSCONFDIR/dhcpcd-exit-hook.d . +.Sh SEE ALSO +.Xr dhcpcd 8 +.Sh AUTHORS +.An "Roy Marples" Aq roy@marples.name +.Sh BUGS +Please report them to http://bugs.marples.name diff --git a/dhcpcd.sh.in b/dhcpcd.sh.in index fd168554..9b3cb415 100644 --- a/dhcpcd.sh.in +++ b/dhcpcd.sh.in @@ -106,8 +106,8 @@ lookup_hostname() set_hostname() { - if [ -n "${oldhostname}" ] || need_hostname; then - local name="${new_hostname}" + if [ -n "${old_host_name}" ] || need_hostname; then + local name="${new_host_name}" [ -z "${name}" ] && name="$(lookup_hostname)" [ -n "${name}" ] && hostname "${name}" fi diff --git a/mk/man.mk b/mk/man.mk index 5d9bf261..5e12f085 100644 --- a/mk/man.mk +++ b/mk/man.mk @@ -4,11 +4,11 @@ MANPREFIX?= /usr/share MANDIR?= ${MANPREFIX}/man/man MANMODE?= 0444 -MINSTALL?= ${INSTALL} -m ${MANMODE} -man: ${MAN} +man: ${MAN5} ${MAN8} -# We cheat as all our pages go into section 8 maninstall: man + ${INSTALL} -d ${DESTDIR}${MANDIR}5 + ${INSTALL} -m ${MANMODE} ${MAN8} ${DESTDIR}${MANDIR}5 ${INSTALL} -d ${DESTDIR}${MANDIR}8 - for man in ${MAN}; do ${MINSTALL} $$man ${DESTDIR}${MANDIR}8; done + ${INSTALL} -m ${MANMODE} ${MAN8} ${DESTDIR}${MANDIR}8 diff --git a/mk/prog.mk b/mk/prog.mk index ae9a987f..03f356e4 100644 --- a/mk/prog.mk +++ b/mk/prog.mk @@ -10,6 +10,7 @@ BINDIR?= ${PREFIX}/usr/bin BINMODE?= 0755 OBJS+= ${SRCS:.c=.o} +CONFMODE?= 0644 SYSCONFDIR?= ${PREFIX}/etc INSTALL?= install @@ -37,11 +38,15 @@ _scriptinstall: ${SCRIPT} ${INSTALL} -d ${DESTDIR}${SYSCONFDIR} ${INSTALL} -m ${BINMODE} ${SCRIPT} ${DESTDIR}${SYSCONFDIR} +_confinstall: ${CONF} + ${INSTALL} -d ${DESTDIR}${SYSCONFDIR} + ${INSTALL} -m ${CONFMODE} ${CONF} ${DESTDIR}${SYSCONFDIR} + include ${MK}/depend.mk include ${MK}/man.mk include ${MK}/dist.mk -install: _proginstall _scriptinstall maninstall +install: _proginstall _scriptinstall _confinstall maninstall clean: rm -f ${OBJS} ${PROG} _${PROG}.c _${PROG}.o ${CLEANFILES}