]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcpcd can now read a basic config file! Add a default dhcpcd.conf and matching man...
authorRoy Marples <roy@marples.name>
Fri, 18 Apr 2008 23:12:44 +0000 (23:12 +0000)
committerRoy Marples <roy@marples.name>
Fri, 18 Apr 2008 23:12:44 +0000 (23:12 +0000)
13 files changed:
Makefile
config.h
dhcp.c
dhcp.h
dhcpcd.8.in
dhcpcd.c
dhcpcd.conf [new file with mode: 0644]
dhcpcd.conf.5 [new file with mode: 0644]
dhcpcd.h
dhcpcd.sh.8.in [new file with mode: 0644]
dhcpcd.sh.in
mk/man.mk
mk/prog.mk

index c9db0cc187ac7f25799c9de9c413d66bfb9d2da5..2338ff1481d373736f87209844fc6ffdbe6a50ce 100644 (file)
--- 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}
index bda7efb824da328f3a98d7020b5492fdee7787a4..87df1ea73bd98fee046300692bc18d5a0c11c404 100644 (file)
--- 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 e1791a0e0fb582b3c642068406e2118b7d6c0b37..ad3b8b333ab03764294edabf9d1092f067e5ffc1 100644 (file)
--- 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 20e8ca1750ab0c0658403af991df0ae33ff60e03..b92b960896ed25c6b039c3b1dab6466cb226d76d 100644 (file)
--- 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);
index 12f0b83aa9c4a0a6af980e729befaad33f877d57..d187e8f809add18260ea902c7bb56bb9fbdf97e4 100644 (file)
@@ -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.
index 09bd9b27f41ffeab0f41fe44c0ecae145a9c08d5..98eaa024fd56a91ef3bfad045ba15bca4a74c8d2 100644 (file)
--- 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] <interface>\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 (file)
index 0000000..1783254
--- /dev/null
@@ -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 (file)
index 0000000..9b95fba
--- /dev/null
@@ -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
index 3685a5a6cebff7f814d24552f5d387b636eeb473..b04d3aa8a8bd93ae0b4cab016d1edc587a8bc833 100644 (file)
--- 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 (file)
index 0000000..c76f492
--- /dev/null
@@ -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
index fd16855419b8c53ffb8093812a067fc4f52c0eee..9b3cb4157101e512939f59b4ba3ae57679b16104 100644 (file)
@@ -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
index 5d9bf261849150c5552a4cece80d8e4f06f14d3c..5e12f0857577483fe5158e56db128d9501df7a5a 100644 (file)
--- 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
index ae9a987f30f115cbfa7f8c1289b070f61c701db1..03f356e4670d4c50ccfd4b9520984fe576f99618 100644 (file)
@@ -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}