[PATCH v2 6/6] dhcpcd: Add hooks

Chris Johns chrisj at rtems.org
Fri May 4 00:42:11 UTC 2018


On 03/05/2018 16:49, Sebastian Huber wrote:
> ---
>  dhcpcd/dhcpcd.c                 |  9 +++++++
>  dhcpcd/namespace.h              |  1 +
>  dhcpcd/script.c                 | 56 +++++++++++++++++++++++++++++++++++++++++
>  dhcpcd/script.h                 |  6 +----
>  libbsd.py                       |  1 +
>  rtemsbsd/include/rtems/dhcpcd.h | 22 ++++++++++++++++
>  testsuite/dhcpcd01/test_main.c  | 21 +++++++++++++++-
>  7 files changed, 110 insertions(+), 6 deletions(-)
> 
> diff --git a/dhcpcd/dhcpcd.c b/dhcpcd/dhcpcd.c
> index 59562d635..c75aafa5e 100644
> --- a/dhcpcd/dhcpcd.c
> +++ b/dhcpcd/dhcpcd.c
> @@ -1599,3 +1599,12 @@ main(int argc, char **argv)
>  	eloop_start(&dhcpcd_sigset);
>  	exit(EXIT_SUCCESS);
>  }
> +#ifdef __rtems__
> +int
> +dhcpcd_script_runreason_do_nothing(const struct interface *ifp,
> +    const char *reason)
> +{
> +	return 0;
> +}
> +__weak_reference(dhcpcd_script_runreason_do_nothing, script_runreason);

What is the use case to override this call?

> +#endif /* __rtems__ */
> diff --git a/dhcpcd/namespace.h b/dhcpcd/namespace.h
> index efff909ad..c9f5fb1fa 100644
> --- a/dhcpcd/namespace.h
> +++ b/dhcpcd/namespace.h
> @@ -156,6 +156,7 @@ extern rtems_recursive_mutex dhcpcd_mutex;
>  #define print_string dhcpcd_print_string
>  #define read_config dhcpcd_read_config
>  #define read_lease dhcpcd_read_lease
> +#define script_runreason dhcpcd_script_runreason
>  #define select_profile dhcpcd_select_profile
>  #define set_cloexec dhcpcd_set_cloexec
>  #define set_nonblock dhcpcd_set_nonblock
> diff --git a/dhcpcd/script.c b/dhcpcd/script.c
> index 2de1e6347..2c184c248 100644
> --- a/dhcpcd/script.c
> +++ b/dhcpcd/script.c
> @@ -51,7 +51,30 @@
>  #include "ipv6nd.h"
>  #include "net.h"
>  #include "script.h"
> +#ifdef __rtems__
> +#include <rtems/dhcpcd.h>
>  
> +static SLIST_HEAD(, rtems_dhcpcd_hook) dhcpcd_hooks =
> +  SLIST_HEAD_INITIALIZER(dhcpcd_hooks);
> +
> +void
> +rtems_dhcpcd_add_hook(rtems_dhcpcd_hook *hook)
> +{
> +	rtems_recursive_mutex_lock(&dhcpcd_mutex);
> +	SLIST_INSERT_HEAD(&dhcpcd_hooks, hook, node);
> +	rtems_recursive_mutex_unlock(&dhcpcd_mutex);
> +}
> +
> +void
> +rtems_dhcpcd_remove_hook(rtems_dhcpcd_hook *hook)
> +{
> +	rtems_recursive_mutex_lock(&dhcpcd_mutex);
> +	SLIST_REMOVE(&dhcpcd_hooks, hook, rtems_dhcpcd_hook, node);
> +	rtems_recursive_mutex_unlock(&dhcpcd_mutex);
> +}
> +#endif /* __rtems__ */

This seems like a common issue we will face with FreeBSD, I am sure callouts
which normally exec's something would be needed else where. I am thinking of wifi?

Could this be made a common base type struct and used here?

> +
> +#ifndef __rtems__
>  #define DEFAULT_PATH	"PATH=/usr/bin:/usr/sbin:/bin:/sbin"
>  
>  static const char * const if_params[] = {
> @@ -75,10 +98,12 @@ if_printoptions(void)
>  	for (p = if_params; *p; p++)
>  		printf(" -  %s\n", *p);
>  }
> +#endif /* __rtems__ */
>  
>  static int
>  exec_script(char *const *argv, char *const *env)
>  {
> +#ifndef __rtems__
>  	pid_t pid;
>  	posix_spawnattr_t attr;
>  	short flags;
> @@ -103,6 +128,20 @@ exec_script(char *const *argv, char *const *env)
>  		return -1;
>  	}
>  	return pid;
> +#else /* __rtems__ */
> +	rtems_dhcpcd_hook *hook;
> +	rtems_dhcpcd_hook *hook2;
> +
> +	rtems_recursive_mutex_lock(&dhcpcd_mutex);
> +
> +	SLIST_FOREACH_SAFE(hook, &dhcpcd_hooks, node, hook2) {
> +		(*hook->handler)(env);
> +	}
> +
> +	rtems_recursive_mutex_unlock(&dhcpcd_mutex);
> +
> +	return 0;
> +#endif /* __rtems__ */
>  }
>  
>  #ifdef INET
> @@ -168,6 +207,7 @@ append_config(char ***env, ssize_t *len,
>  }
>  #endif
>  
> +#ifndef __rtems__
>  static size_t
>  arraytostr(const char *const *argv, char **s)
>  {
> @@ -191,6 +231,7 @@ arraytostr(const char *const *argv, char **s)
>  	}
>  	return len;
>  }
> +#endif /* __rtems__ */
>  
>  static ssize_t
>  make_env(const struct interface *ifp, const char *reason, char ***argv)
> @@ -435,6 +476,7 @@ eexit:
>  	return -1;
>  }
>  
> +#ifndef __rtems__
>  static int
>  send_interface1(int fd, const struct interface *iface, const char *reason)
>  {
> @@ -507,29 +549,37 @@ send_interface(int fd, const struct interface *iface)
>  	}
>  	return retval;
>  }
> +#endif /* __rtems__ */
>  
>  int
>  script_runreason(const struct interface *ifp, const char *reason)
>  {
>  	char *const argv[2] = { UNCONST(ifp->options->script), NULL };
>  	char **env = NULL, **ep;
> +#ifndef __rtems__
>  	char *path, *bigenv;
> +#endif /* __rtems__ */
>  	ssize_t e, elen = 0;
>  	pid_t pid;
>  	int status = 0;
> +#ifndef __rtems__
>  	const struct fd_list *fd;
>  	struct iovec iov[2];
> +#endif /* __rtems__ */
>  
>  	if (ifp->options->script == NULL ||
>  	    ifp->options->script[0] == '\0' ||
>  	    strcmp(ifp->options->script, "/dev/null") == 0)
>  		return 0;
>  
> +#ifndef __rtems__
>  	syslog(LOG_DEBUG, "%s: executing `%s' %s",
>  	    ifp->name, argv[0], reason);
> +#endif /* __rtems__ */

Is there any ability to get some indication a hooked handler is being called?

If this due to the exec being removed?

>  
>  	/* Make our env */
>  	elen = make_env(ifp, reason, &env);
> +#ifndef __rtems__
>  	ep = realloc(env, sizeof(char *) * (elen + 2));
>  	if (ep == NULL) {
>  		elen = -1;
> @@ -554,8 +604,10 @@ script_runreason(const struct interface *ifp, const char *reason)
>  		}
>  	}
>  	env[++elen] = NULL;
> +#endif /* __rtems__ */
>  
>  	pid = exec_script(argv, env);
> +#ifndef __rtems__
>  	if (pid == -1)
>  		syslog(LOG_ERR, "%s: %s: %m", __func__, argv[0]);
>  	else if (pid != 0) {

Are you expecting no errors? Why not leave this in and use the result in the way
it is intended?

> @@ -596,6 +648,10 @@ script_runreason(const struct interface *ifp, const char *reason)
>  	free(bigenv);
>  
>  out:
> +#else /* __rtems__ */
> +	(void)e;
> +	(void)pid;
> +#endif /* __rtems__ */
>  	/* Cleanup */
>  	ep = env;
>  	while (*ep)
> diff --git a/dhcpcd/script.h b/dhcpcd/script.h
> index dfd4a1726..9c5fd4d4e 100644
> --- a/dhcpcd/script.h
> +++ b/dhcpcd/script.h
> @@ -33,16 +33,12 @@
>  void if_printoptions(void);
>  #ifndef __rtems__
>  int send_interface(int, const struct interface *);
> -int script_runreason(const struct interface *, const char *);
>  #else /* __rtems__ */
>  static inline int send_interface(int fd, const struct interface *iface)
>  {
>  	return 0;
>  }
> -static inline int script_runreason(const struct interface *ifp, const char *reason)
> -{
> -	return 0;
> -}
>  #endif /* __rtems__ */
> +int script_runreason(const struct interface *, const char *);
>  
>  #endif
> diff --git a/libbsd.py b/libbsd.py
> index a62581faa..c842534b5 100644
> --- a/libbsd.py
> +++ b/libbsd.py
> @@ -4582,6 +4582,7 @@ class dhcpcd(builder.Module):
>                  'dhcpcd/ipv6nd.c',
>                  'dhcpcd/net.c',
>                  'dhcpcd/platform-bsd.c',
> +                'dhcpcd/script.c',
>                  'dhcpcd/compat/pselect.c',
>                  'dhcpcd/crypt/hmac_md5.c',
>              ],
> diff --git a/rtemsbsd/include/rtems/dhcpcd.h b/rtemsbsd/include/rtems/dhcpcd.h
> index 324c8a90b..c5c5cb54f 100644
> --- a/rtemsbsd/include/rtems/dhcpcd.h
> +++ b/rtemsbsd/include/rtems/dhcpcd.h
> @@ -40,6 +40,9 @@
>  #ifndef _RTEMS_DHCPCD_H_
>  #define _RTEMS_DHCPCD_H_
>  
> +#include <sys/cdefs.h>
> +#include <sys/queue.h>
> +
>  #include <rtems.h>
>  
>  #ifdef __cplusplus
> @@ -75,6 +78,25 @@ typedef struct rtems_dhcpcd_config {
>   */
>  rtems_status_code rtems_dhcpcd_start(const rtems_dhcpcd_config *config);
>  
> +typedef struct rtems_dhcpcd_hook {
> +	void (*handler)(char *const *env);
> +	SLIST_ENTRY(rtems_dhcpcd_hook) node;
> +} rtems_dhcpcd_hook;

This looks to me like it would be useful elsewhere.

> +
> +/**
> + * @brief Adds a DHCP client hook.
> + *
> + * The hook handler is invoked with an environment list (NULL terminated) of
> + * strings ('\0' terminated).  Each string of the environment list has usually
> + * the format "key=value", e.g. "interface=eth0", "reason=BOUND".
> + */
> +void rtems_dhcpcd_add_hook(rtems_dhcpcd_hook *hook);
> +
> +/**
> + * @brief Removes a DHCP client hook.
> + */
> +void rtems_dhcpcd_remove_hook(rtems_dhcpcd_hook *hook);
> +
>  /** @} */
>  
>  #ifdef __cplusplus
> diff --git a/testsuite/dhcpcd01/test_main.c b/testsuite/dhcpcd01/test_main.c
> index 181f92ae1..5d8facc28 100644
> --- a/testsuite/dhcpcd01/test_main.c
> +++ b/testsuite/dhcpcd01/test_main.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
> + * Copyright (c) 2013, 2018 embedded brains GmbH.  All rights reserved.
>   *
>   *  embedded brains GmbH
>   *  Dornierstr. 4
> @@ -30,14 +30,33 @@
>   */
>  
>  #include <assert.h>
> +#include <stdio.h>
>  
>  #include <rtems.h>
> +#include <rtems/dhcpcd.h>
>  
>  #define TEST_NAME "LIBBSD DHCPCD 1"
>  
>  static void
> +dhcpcd_hook_handler(char *const *env)
> +{
> +
> +	while (*env != NULL) {
> +		printf("%s\n", *env);
> +		++env;
> +	}
> +}
> +
> +static rtems_dhcpcd_hook dhcpcd_hook = {
> +	.handler = dhcpcd_hook_handler
> +};
> +
> +static void
>  test_main(void)
>  {
> +
> +	rtems_dhcpcd_add_hook(&dhcpcd_hook);
> +
>  	rtems_task_delete(RTEMS_SELF);
>  	assert(0);
>  }
> 


More information about the devel mailing list