Mercurial > hg > dhcpcd
changeset 2168:6133c1c25912 draft
Read the embedded config into global values rather than each time
per interface.
Add config toggles to build dhcpcd-embedded.conf into dhcpcd or
to read it at runtime. The build process will now build .c and .h
files based on dhcpcd-embedded.conf and provide defines to reduce
the number or re-allocs if it grows (ie has the full DHCP option list).
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Fri, 29 Nov 2013 11:15:03 +0000 |
| parents | 1a0a80db36d6 |
| children | 97267d7f1321 |
| files | .gitignore Makefile README configure defs.h dhcp.c dhcp.h dhcp6.c dhcp6.h dhcpcd-embedded.conf dhcpcd-embedded.h.in dhcpcd.c dhcpcd.conf.5.in genembedc genembedh if-options.c if-options.h |
| diffstat | 17 files changed, 435 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/.gitignore Wed Nov 27 21:35:45 2013 +0000 +++ b/.gitignore Fri Nov 29 11:15:03 2013 +0000 @@ -9,5 +9,7 @@ dhcpcd.conf.5 dhcpcd.core dhcpcd.8 +dhcpcd-embedded.c +dhcpcd-embedded.h dhcpcd-run-hooks dhcpcd-run-hooks.8
--- a/Makefile Wed Nov 27 21:35:45 2013 +0000 +++ b/Makefile Fri Nov 29 11:15:03 2013 +0000 @@ -52,6 +52,8 @@ DISTPREFIX?= ${PROG}-${VERSION} DISTFILE?= ${DISTPREFIX}.tar.bz2 +HOST_SH?= /bin/sh + CLEANFILES+= *.tar.bz2 .PHONY: import import-bsd dev @@ -73,6 +75,16 @@ .c.o: ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ +CLEANFILES+= dhcpcd-embedded.h dhcpcd-embedded.c + +dhcpcd-embedded.h: genembedh dhcpcd-embedded.conf dhcpcd-embedded.h.in + ${HOST_SH} ${.ALLSRC} $^ > $@ + +dhcpcd-embedded.c: genembedc dhcpcd-embedded.conf + ${HOST_SH} ${.ALLSRC} $^ > $@ + +if-options.c: dhcpcd-embedded.h + .depend: ${SRCS} ${COMPAT_SRCS} ${CC} ${CPPFLAGS} -MM ${SRCS} ${COMPAT_SRCS} > .depend @@ -81,6 +93,10 @@ ${PROG}: ${DEPEND} ${OBJS} ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} +_embeddedinstall: dhcpcd-embedded.conf + ${INSTALL} -d ${DESTDIR}${SCRIPTSDIR} + ${INSTALL} -m ${CONFMODE} dhcpcd-embedded.conf ${DESTDIR}${SCRIPTSDIR} + _proginstall: ${PROG} ${INSTALL} -d ${DESTDIR}${SBINDIR} ${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR} @@ -89,9 +105,8 @@ _scriptsinstall: ${SCRIPTS} ${INSTALL} -d ${DESTDIR}${SCRIPTSDIR} ${INSTALL} -m ${BINMODE} ${SCRIPTS} ${DESTDIR}${SCRIPTSDIR} - ${INSTALL} -m ${CONFMODE} dhcpcd-embedded.conf ${DESTDIR}${SCRIPTSDIR} -proginstall: _proginstall _scriptsinstall +proginstall: _proginstall _scriptsinstall ${EMBEDDEDINSTALL} for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done _maninstall: ${MAN5} ${MAN8} @@ -105,8 +120,7 @@ test -e ${DESTDIR}${SYSCONFDIR}/dhcpcd.conf || \ ${INSTALL} -m ${CONFMODE} dhcpcd.conf ${DESTDIR}${SYSCONFDIR} -install: _proginstall _scriptsinstall _maninstall _confinstall - for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done +install: proginstall _maninstall _confinstall clean: rm -f ${OBJS} ${PROG} ${PROG}.core ${CLEANFILES} @@ -118,10 +132,10 @@ dist: git archive --prefix=${DISTPREFIX}/ ${GITREF} | bzip2 > ${DISTFILE} -import: +import: ${SRCS} rm -rf /tmp/${DISTPREFIX} ${INSTALL} -d /tmp/${DISTPREFIX} - cp ${SRCS} dhcpcd.conf *.in /tmp/${DISTPREFIX} + cp ${SRCS} dhcpcd.conf dhcpcd-embedded.conf *.in /tmp/${DISTPREFIX} cp $$(${CC} ${CPPFLAGS} -MM ${SRCS} | \ sed -e 's/^.*\.c //g' -e 's/.*\.c$$//g' -e 's/\\//g' | \ tr ' ' '\n' | \ @@ -176,6 +190,7 @@ for x in \ /tmp/${DISTPREFIX}/dhcpcd-run-hooks.in \ /tmp/${DISTPREFIX}/dhcpcd.conf \ + /tmp/${DISTPREFIX}/dhcpcd-embedded.conf \ ; do \ if test -e "$$x"; then \ if test "$$(sed -ne 1p $$x)" = "#!/bin/sh" \
--- a/README Wed Nov 27 21:35:45 2013 +0000 +++ b/README Fri Nov 29 11:15:03 2013 +0000 @@ -52,6 +52,16 @@ can use an interface. As of the time of writing only udev support is included. You can disable this with --without-dev, or without-udev +To shrink dhcpcd you can disable IPv4 or IPv6: + --disable-inet + --disable-inet6 + +You can also move the embedded extended configuration from the dhcpcd binary +to an external file (LIBEXECDIR/dhcpcd-embedded.conf) + --disable-embedded +If dhcpcd cannot load this file at runtime, dhcpcd will work but will not be +able to decode any DHCP/DHCPv6 options present within the file. + To prepare dhcpcd for import into a platform source tree (like NetBSD) you can use the make import target to create /tmp/dhcpcd-$version and populate it with all the source files and hooks needed.
--- a/configure Wed Nov 27 21:35:45 2013 +0000 +++ b/configure Fri Nov 29 11:15:03 2013 +0000 @@ -19,6 +19,7 @@ STATIC= INCLUDEDIR= DEVS= +EMBEDDED= for x do opt=${x%%=*} @@ -38,6 +39,8 @@ --enable-ipv4) INET=yes;; --disable-ipv6) INET6=no;; --enable-ipv6) INET6=yes;; + --disable-embedded) EMBEDDED=no;; + --enable-embedded) EMBEDDED=no;; --prefix) PREFIX=$var;; --sysconfdir) SYSCONFDIR=$var;; --bindir|--sbindir) SBINDIR=$var;; @@ -137,6 +140,8 @@ done : ${SED:=sed} +: ${GREP:=grep} +: ${WC:=wc} : ${FORK:=yes} : ${SYSCONFDIR:=$PREFIX/etc} @@ -312,6 +317,23 @@ EOF fi +if [ -z "$EMBEDDED" -o "$EMBEDDED" = yes ]; then + echo "dhcpcd-embedded.conf will be embedded in dhcpcd itself" + echo "SRCS+= dhcpcd-embedded.c" >>$CONFIG_MK +else + echo "dhcpcd-embedded.conf will be installed to $LIBEXECDIR" + echo "CFLAGS+= -DEMBEDDED_CONFIG=\\\"$LIBEXECDIR/dhcpcd-embedded.conf\\\"" >>$CONFIG_MK + echo "EMBEDDEDINSTALL= _embeddedinstall" >>$CONFIG_MK +fi +printf %s "Estimating initial embedded defines ... " +INITDEFINES=$($GREP "^define " dhcpcd-embedded.conf | $WC -l) +echo $INITDEFINES +echo "#define INITDEFINES $INITDEFINES" >>$CONFIG_H +printf %s "Estimating initial embedded define6s ... " +INITDEFINE6S=$($GREP "^define6 " dhcpcd-embedded.conf | $WC -l) +echo $INITDEFINE6S +echo "#define INITDEFINE6S $INITDEFINE6S" >>$CONFIG_H + if [ -n "$FORK" -a "$FORK" != yes -a "$FORK" != true ]; then echo "There is no fork" echo "CPPFLAGS+= -DTHERE_IS_NO_FORK" >>$CONFIG_MK @@ -770,7 +792,7 @@ printf "Checking for ypind ... " YPBIND=$(_which ypbind) if [ -n "$YPBIND" ]; then - if strings "$YPBIND" | grep -q yp.conf; then + if strings "$YPBIND" | $GREP -q yp.conf; then YPHOOK="50-yp.conf" else YPHOOK="50-ypbind"
--- a/defs.h Wed Nov 27 21:35:45 2013 +0000 +++ b/defs.h Fri Nov 29 11:15:03 2013 +0000 @@ -33,9 +33,6 @@ #ifndef CONFIG # define CONFIG SYSCONFDIR "/" PACKAGE ".conf" #endif -#ifndef EMBEDDED_CONFIG -# define EMBEDDED_CONFIG LIBEXECDIR "/" PACKAGE "-embedded.conf" -#endif #ifndef SCRIPT # define SCRIPT LIBEXECDIR "/" PACKAGE "-run-hooks" #endif
--- a/dhcp.c Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcp.c Fri Nov 29 11:15:03 2013 +0000 @@ -222,6 +222,10 @@ struct udphdr udp; struct dhcp_message dhcp; }; + +struct dhcp_opt *dhcp_eopts = NULL; +size_t dhcp_eopts_len = 0; + static const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); static int dhcp_open(struct interface *); @@ -1126,7 +1130,7 @@ } static const struct dhcp_opt * -dhcp_getoverride(const struct if_options *ifo, uint16_t o) +dhcp_getoverride(const struct if_options *ifo, uint16_t o, int e) { size_t i; const struct dhcp_opt *opt; @@ -1138,10 +1142,18 @@ if (opt->option == o) return opt; } + if (e) { + for (i = 0, opt = dhcp_eopts; + i < dhcp_eopts_len; + i++, opt++) + { + if (opt->option == o) + return opt; + } + } return NULL; } - static const uint8_t * dhcp_getoption(int *len, int option, const uint8_t *od, int ol) { @@ -1188,7 +1200,7 @@ continue; if (has_option_mask(ifo->nomask, opt->option)) continue; - if (dhcp_getoverride(ifo, opt->option)) + if (dhcp_getoverride(ifo, opt->option, 1)) continue; p = get_option(dhcp, opt->option, &pl, NULL); if (!p) @@ -1202,10 +1214,26 @@ e++; if (*dhcp->servername && !(overl & 2)) e++; + for (oi = 0, opt = dhcp_eopts; + oi < dhcp_eopts_len; + oi++, opt++) + { + if (has_option_mask(ifo->nomask, opt->option)) + continue; + if (dhcp_getoverride(ifo, opt->option, 0)) + continue; + p = get_option(dhcp, opt->option, &pl, NULL); + if (!p) + continue; + e += dhcp_envoption(NULL, prefix, "", ifp->name, + opt, dhcp_getoption, p, pl); + } for (oi = 0, opt = ifo->dhcp_override; oi < ifo->dhcp_override_len; oi++, opt++) { + if (has_option_mask(ifo->nomask, opt->option)) + continue; p = get_option(dhcp, opt->option, &pl, NULL); if (!p) continue; @@ -1245,7 +1273,7 @@ continue; if (has_option_mask(ifo->nomask, opt->option)) continue; - if (dhcp_getoverride(ifo, opt->option)) + if (dhcp_getoverride(ifo, opt->option, 1)) continue; p = get_option(dhcp, opt->option, &pl, NULL); if (!p) @@ -1260,6 +1288,19 @@ opt, dhcp_getoption, p, pl); } + for (oi = 0, opt = dhcp_eopts; + oi < dhcp_eopts_len; + oi++, opt++) + { + if (has_option_mask(ifo->nomask, opt->option)) + continue; + if (dhcp_getoverride(ifo, opt->option, 0)) + continue; + if ((p = get_option(dhcp, opt->option, &pl, NULL))) + ep += dhcp_envoption(ep, prefix, "", ifp->name, + opt, dhcp_getoption, p, pl); + } + for (oi = 0, opt = ifo->dhcp_override; oi < ifo->dhcp_override_len; oi++, opt++)
--- a/dhcp.h Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcp.h Fri Nov 29 11:15:03 2013 +0000 @@ -240,6 +240,9 @@ #ifdef INET extern const struct dhcp_opt dhcp_opts[]; +extern struct dhcp_opt *dhcp_eopts; +extern size_t dhcp_eopts_len; + char *decode_rfc3361(int dl, const uint8_t *data); ssize_t decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p); ssize_t decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p);
--- a/dhcp6.c Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcp6.c Fri Nov 29 11:15:03 2013 +0000 @@ -129,6 +129,9 @@ }; #undef O +struct dhcp_opt *dhcp6_eopts = NULL; +size_t dhcp6_eopts_len = 0; + struct dhcp_compat { uint8_t dhcp_opt; uint16_t dhcp6_opt; @@ -2571,7 +2574,7 @@ } static const struct dhcp_opt * -dhcp6_getoverride(const struct if_options *ifo, uint16_t o) +dhcp6_getoverride(const struct if_options *ifo, uint16_t o, int e) { size_t i; const struct dhcp_opt *opt; @@ -2583,6 +2586,15 @@ if (opt->option == o) return opt; } + if (e != 0) { + for (i = 0, opt = dhcp6_eopts; + i < dhcp6_eopts_len; + i++, opt++) + { + if (opt->option == o) + return opt; + } + } return NULL; } @@ -2609,7 +2621,7 @@ continue; if (has_option_mask(ifo->nomask6, opt->option)) continue; - if (dhcp6_getoverride(ifo, opt->option)) + if (dhcp6_getoverride(ifo, opt->option, 1)) continue; o = dhcp6_getmoption(opt->option, m, mlen); if (o == NULL) @@ -2672,6 +2684,24 @@ } } + for (oi = 0, opt = dhcp6_eopts; + oi < dhcp6_eopts_len; + oi++, opt++) + { + if (has_option_mask(ifo->nomask, opt->option)) + continue; + if (dhcp6_getoverride(ifo, opt->option, 0)) + continue; + + o = dhcp6_getmoption(opt->option, m, mlen); + if (o == NULL) + continue; + ol = ntohs(o->len); + od = D6_COPTION_DATA(o); + n += dhcp_envoption(env == NULL ? NULL : &env[n], + prefix, "_dhcp6", ifp->name, opt, dhcp6_getoption, od, ol); + } + for (oi = 0, opt = ifo->dhcp6_override; oi < ifo->dhcp6_override_len; oi++, opt++)
--- a/dhcp6.h Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcp6.h Fri Nov 29 11:15:03 2013 +0000 @@ -222,6 +222,9 @@ ((const uint8_t *)(o) + sizeof(struct dhcp6_option)) #ifdef INET6 +extern struct dhcp_opt *dhcp6_eopts; +extern size_t dhcp6_eopts_len; + void dhcp6_printoptions(void); int dhcp6_addrexists(const struct ipv6_addr *); int dhcp6_find_delegates(struct interface *);
--- a/dhcpcd-embedded.conf Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcpcd-embedded.conf Fri Nov 29 11:15:03 2013 +0000 @@ -16,4 +16,4 @@ define6 56 encap encap 1 ip6address ntp_server_addr encap 2 ip6address ntp_mcast_addr -encap 3 ip6address ntp_fqdn +encap 3 ip6address ntp_server_fqdn
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dhcpcd-embedded.h.in Fri Nov 29 11:15:03 2013 +0000 @@ -0,0 +1,31 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2013 Roy Marples <roy@marples.name> + * 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. + */ + +#define INITDEFINES @INITDEFINES@ +#define INITDEFINE6S @INITDEFINE6S@ + +extern const char *dhcpcd_embedded_conf[];
--- a/dhcpcd.c Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcpcd.c Fri Nov 29 11:15:03 2013 +0000 @@ -136,11 +136,35 @@ } static void +free_globals(void) +{ + int i; + size_t n; + + for (i = 0; i < ifac; i++) + free(ifav[i]); + free(ifav); + for (i = 0; i < ifdc; i++) + free(ifdv[i]); + free(ifdv); + +#ifdef INET + for (n = 0; n < dhcp_eopts_len; n++) + free_dhcp_opt_embenc(&dhcp_eopts[n]); + free(dhcp_eopts); +#endif +#ifdef INET6 + for (n = 0; n < dhcp6_eopts_len; n++) + free_dhcp_opt_embenc(&dhcp6_eopts[n]); + free(dhcp6_eopts); +#endif +} + +static void cleanup(void) { #ifdef DEBUG_MEMORY struct interface *ifp; - int i; free(duid); free_options(if_options); @@ -153,12 +177,7 @@ free(ifaces); } - for (i = 0; i < ifac; i++) - free(ifav[i]); - free(ifav); - for (i = 0; i < ifdc; i++) - free(ifdv[i]); - free(ifdv); + free_globals(); #endif if (!(options & DHCPCD_FORKED)) @@ -807,21 +826,16 @@ { siginfo_t *siginfo = arg; struct if_options *ifo; - int i; syslog(LOG_INFO, "received SIGALRM from PID %d, rebinding", (int)siginfo->si_pid); - for (i = 0; i < ifac; i++) - free(ifav[i]); - free(ifav); + free_globals(); ifav = NULL; ifac = 0; - for (i = 0; i < ifdc; i++) - free(ifdv[i]); - free(ifdv); ifdc = 0; ifdv = NULL; + ifo = read_config(cffile, NULL, NULL, NULL); add_options(ifo, margc, margv); /* We need to preserve these two options. */
--- a/dhcpcd.conf.5.in Wed Nov 27 21:35:45 2013 +0000 +++ b/dhcpcd.conf.5.in Fri Nov 29 11:15:03 2013 +0000 @@ -534,6 +534,8 @@ A signed 32bit integer, 4 bytes .It Ic uint32 An unsigned 32bit integer, 4 bytes +.It Ic flag +A fixed value (1) to indicate that the option is present, 0 bytes .It Ic domain A RFC 3397 encoded string .It Ic binhex
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genembedc Fri Nov 29 11:15:03 2013 +0000 @@ -0,0 +1,47 @@ +#!/bin/sh +set -e + +: ${TOOL_SED:=sed} +CONF=${1:-dhcpcd-embedded.conf} + +cat <<EOF +/* + * DO NOT EDIT + * Automatically generated from dhcpcd-embedded.conf + * Ths allows us to simply generate DHCP structure without any C programming + */ + +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2013 Roy Marples <roy@marples.name> + * 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. + */ + +#include <unistd.h> + +const char *dhcpcd_embedded_conf[] = { +EOF + +$TOOL_SED -e 's/#.*$//' -e '/^$/d' -e 's/^/"/g' -e 's/$/\",/g' $CONF +printf "%s\n%s\n" "NULL" "};"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genembedh Fri Nov 29 11:15:03 2013 +0000 @@ -0,0 +1,15 @@ +#!/bin/sh +set -e + +: ${TOOL_SED:=sed} +: ${TOOL_GREP:=grep} +: ${TOOL_WC:=wc} +CONF=${1:-dhcpcd-embedded.conf} +H=${2:-dhcpcd-embedded.h.in} + +INITDEFINES=$($TOOL_GREP "^define " $CONF | $TOOL_WC -l) +INITDEFINE6S=$($TOOL_GREP "^define6 " $CONF | $TOOL_WC -l) +$TOOL_SED \ + -e "s/@INITDEFINES@/$INITDEFINES/" \ + -e "s/@INITDEFINE6S@/$INITDEFINE6S/" \ + $H
--- a/if-options.c Wed Nov 27 21:35:45 2013 +0000 +++ b/if-options.c Fri Nov 29 11:15:03 2013 +0000 @@ -46,6 +46,7 @@ #include "common.h" #include "dhcp.h" #include "dhcp6.h" +#include "dhcpcd-embedded.h" #include "if-options.h" #include "ipv4.h" #include "platform.h" @@ -479,7 +480,7 @@ /* Pointer to last defined option */ static struct dhcp_opt *ldop; -static void +void free_dhcp_opt_embenc(struct dhcp_opt *opt) { size_t i; @@ -499,6 +500,30 @@ opt->encopts = NULL; } +static char * +strwhite(const char *s) +{ + + while (*s != ' ' && *s != '\t') { + if (*s == '\0') + return NULL; + s++; + } + return UNCONST(s); +} + +static char * +strskipwhite(const char *s) +{ + + while (*s == ' ' || *s == '\t') { + if (*s == '\0') + return NULL; + s++; + } + return UNCONST(s); +} + static int parse_option(struct if_options *ifo, int opt, const char *arg) { @@ -852,14 +877,13 @@ strncmp(arg, "classless_static_routes=", strlen("classless_static_routes=")) == 0 || strncmp(arg, "ms_classless_static_routes=", strlen("ms_classless_static_routes=")) == 0) { - fp = np = strchr(p, ' '); + fp = np = strwhite(p); if (np == NULL) { syslog(LOG_ERR, "all routes need a gateway"); return -1; } *np++ = '\0'; - while (*np == ' ') - np++; + np = strskipwhite(np); if (ifo->routes == NULL) { ifo->routes = malloc(sizeof(*ifo->routes)); if (ifo->routes == NULL) { @@ -1059,7 +1083,7 @@ ifo->ia_type = i; if (arg == NULL) break; - fp = strchr(arg, ' '); + fp = strwhite(arg); if (fp) *fp++ = '\0'; if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) @@ -1094,9 +1118,11 @@ if (ifo->ia_type != D6_OPTION_IA_PD) break; for (p = fp; p; p = fp) { - fp = strchr(p, ' '); - if (fp) + fp = strwhite(p); + if (fp) { *fp++ = '\0'; + fp = strskipwhite(fp); + } sla = realloc(ia->sla, sizeof(*ia->sla) * (ia->sla_len + 1)); if (sla == NULL) { @@ -1206,7 +1232,7 @@ if (opt == O_EMBED) /* Embedded options don't have codes */ i = 0; else { - fp = strchr(arg, ' '); + fp = strwhite(arg); if (!fp) { syslog(LOG_ERR, "invalid syntax: %s", arg); return -1; @@ -1214,44 +1240,80 @@ *fp++ = '\0'; if ((i = atoint(arg)) == -1) return -1; - arg = fp; + arg = strskipwhite(fp); } /* type */ - fp = strchr(arg, ' '); - if (fp) + fp = strwhite(arg); + if (fp) + *fp++ = '\0'; + t = 0; + if (strcasecmp(arg, "request") == 0) { + t |= REQUEST; + arg = strskipwhite(fp); + fp = strwhite(arg); + if (fp == NULL) { + syslog(LOG_ERR, "incomplete request type"); + return -1; + } *fp++ = '\0'; + } else if (strcasecmp(arg, "norequest") == 0) { + t |= NOREQ; + arg = strskipwhite(fp); + fp = strwhite(arg); + if (fp == NULL) { + syslog(LOG_ERR, "incomplete request type"); + return -1; + } + *fp++ = '\0'; + } + if (strcasecmp(arg, "array") == 0) { + t |= ARRAY; + arg = strskipwhite(fp); + fp = strwhite(arg); + if (fp == NULL) { + syslog(LOG_ERR, "incomplete array type"); + return -1; + } + *fp++ = '\0'; + } if (strcasecmp(arg, "ipaddress") == 0) - t = ADDRIPV4; + t |= ADDRIPV4; else if (strcasecmp(arg, "ip6address") == 0) - t = ADDRIPV6; + t |= ADDRIPV6; else if (strcasecmp(arg, "string") == 0) - t = STRING; + t |= STRING; else if (strcasecmp(arg, "byte") == 0) - t = UINT8; + t |= UINT8; else if (strcasecmp(arg, "uint16") == 0) - t = UINT16; + t |= UINT16; else if (strcasecmp(arg, "int16") == 0) - t = SINT16; + t |= SINT16; else if (strcasecmp(arg, "uint32") == 0) - t = UINT32; + t |= UINT32; else if (strcasecmp(arg, "int32") == 0) - t = SINT32; + t |= SINT32; + else if (strcasecmp(arg, "flag") == 0) + t |= FLAG; else if (strcasecmp(arg, "domain") == 0) - t = STRING | RFC3397; + t |= STRING | RFC3397; else if (strcasecmp(arg, "binhex") == 0) - t = BINHEX; + t |= BINHEX; else if (strcasecmp(arg, "embed") == 0) t = EMBED; else if (strcasecmp(arg, "encap") == 0) t = ENCAP; + else if (strcasecmp(arg, "rfc3361") ==0) + t = STRING | RFC3361; + else if (strcasecmp(arg, "rfc5969") == 0) + t = RFC5969; else { syslog(LOG_ERR, "unknown type: %s", arg); return -1; } /* variable */ if (fp) { - arg = fp; - fp = strchr(arg, ' '); + arg = strskipwhite(fp); + fp = strwhite(arg); if (fp) *fp++ = '\0'; np = strdup(arg); @@ -1269,15 +1331,17 @@ np = NULL; } if (opt == O_EMBED) - dl = 0; + dl = *dop_len; else { for (dl = 0; dl < *dop_len; dl++) { ndop = &(*dop)[dl]; - if (ndop->option == i) + /* type 0 seems freshly malloced struct + * for us to use */ + if (ndop->option == i || ndop->type == 0) break; } } - if (dl <= *dop_len) { + if (dl >= *dop_len) { if ((ndop = realloc(*dop, sizeof(**dop) * ((*dop_len) + 1))) == NULL) { syslog(LOG_ERR, "%s: %m", __func__); @@ -1285,13 +1349,13 @@ } *dop = ndop; ndop = &(*dop)[(*dop_len)++]; - ndop->option = i; ndop->embopts = NULL; ndop->embopts_len = 0; ndop->encopts = NULL; ndop->encopts_len = 0; } else free_dhcp_opt_embenc(ndop); + ndop->option = i; /* could have been 0 */ ndop->type = t; ndop->v.dvar = np; /* Save the define for embed and encap options */ @@ -1352,6 +1416,10 @@ FILE *f; char *line, *option, *p; int skip = 0, have_profile = 0; +#ifndef EMBEDDED_CONFIG + const char **e; + size_t linel, ol; +#endif /* Seed our default options */ ifo = calloc(1, sizeof(*ifo)); @@ -1380,12 +1448,53 @@ memcpy(ifo->vendorclassid + 1, vendor, ifo->vendorclassid[0]); /* Parse our embedded options file */ - f = fopen(EMBEDDED_CONFIG, "r"); - if (f == NULL) { - if (errno != ENOENT) - syslog(LOG_ERR, "fopen `%s': %m", file); - } else { - while ((line = get_line(f))) { + if (ifname == NULL) { + /* Space for initial estimates */ +#if defined(INET) && defined(INITDEFINES) + ifo->dhcp_override = + calloc(INITDEFINES, sizeof(*ifo->dhcp_override)); + if (ifo->dhcp_override == NULL) + syslog(LOG_ERR, "%s: %m", __func__); + else + ifo->dhcp_override_len = INITDEFINES; +#endif + +#if defined(INET6) && defined(INITDEFINE6S) + ifo->dhcp6_override = + calloc(INITDEFINE6S, sizeof(*ifo->dhcp6_override)); + if (ifo->dhcp6_override == NULL) + syslog(LOG_ERR, "%s: %m", __func__); + else + ifo->dhcp6_override_len = INITDEFINES; +#endif + + /* Now load our embedded config */ +#ifdef EMBEDDED_CONFIG + f = fopen(EMBEDDED_CONFIG, "r"); + if (f == NULL) + syslog(LOG_ERR, "fopen `%s': %m", EMBEDDED_CONFIG); + + while (f && (line = get_line(f))) { +#else + linel = 80; + line = malloc(linel); + if (line == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return NULL; + } + for (e = dhcpcd_embedded_conf; *e; e++) { + ol = strlen(*e) + 1; + if (ol > linel) { + free(line); + linel = ol; + line = malloc(linel); + if (line == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return NULL; + } + } + memcpy(line, *e, ol); +#endif option = strsep(&line, " \t"); /* Trim trailing whitespace */ if (line && *line) { @@ -1396,8 +1505,36 @@ *p-- = '\0'; } parse_config_line(ifo, option, line); + } - fclose(f); + +#ifdef EMBEDDED_CONFIG + if (f) + fclose(f); +#else + free(line); +#endif +#ifdef INET + dhcp_eopts = ifo->dhcp_override; + dhcp_eopts_len = ifo->dhcp_override_len; +#else + for (i = 0; i < ifo->dhcp_override_len; i++) + free_dhcp_opt_embenc(&ifo->dhcp_override[i]); + free(ifo->dhcp_override); +#endif + ifo->dhcp_override = NULL; + ifo->dhcp_override_len = 0; + +#ifdef INET6 + dhcp6_eopts = ifo->dhcp6_override; + dhcp6_eopts_len = ifo->dhcp6_override_len; +#else + for (i = 0; i < ifo->dhcp6_override_len; i++) + free_dhcp_opt_embenc(&ifo->dhcp6_override[i]); + free(ifo->dhcp6_override); +#endif + ifo->dhcp6_override = NULL; + ifo->dhcp6_override_len = 0; } /* Parse our options file */
--- a/if-options.h Wed Nov 27 21:35:45 2013 +0000 +++ b/if-options.h Fri Nov 29 11:15:03 2013 +0000 @@ -173,6 +173,7 @@ struct if_options *read_config(const char *, const char *, const char *, const char *); int add_options(struct if_options *, int, char **); +void free_dhcp_opt_embenc(struct dhcp_opt *); void free_options(struct if_options *); #endif
