[PATCH v2 6/6] dhcpcd: Add hooks

Chris Johns chrisj at rtems.org
Mon May 7 07:31:20 UTC 2018


On 07/05/2018 17:04, Sebastian Huber wrote:
> On 04/05/18 02:42, Chris Johns wrote:
>> On 03/05/2018 16:49, Sebastian Huber wrote:
>>
>>> +#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?
> 
> I am not sure if the handler signature will be the same.

There is some historical logic behind scripts with argc/argv and that is it's
common interface of a command line. The rc.conf code provides a way to manage
argc/argv which can be reused.

Given this interface is to replace exec'ing a script why not call with
argc/argv? There must be exiting support to do this?

> 
>>
>>> +
>>> +#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?
> 
> You can do whatever you want in your hook handler.
> 

OK, let me rephrase the question, please do not remove the syslog messages? I
have clearly stated before the ability to use the command to debug the client is
important and these messages are part of that.

>>
>> If this due to the exec being removed?
> 
> We don't execute a script here.
> 

Sigh, yes that answer is correct given the question.

Please use 'argc/argv for the hook and please make them generic. Please add the
generic support in a way it can be reused in other parts of the stack. Thanks.

>>
>>>         /* 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?
> 
> The pid is normally returned by posix_spawn() which we don't have in RTEMS.

How can the hook say something has gone wrong?

Please make the hooks return a status.

> 
>>
>>> @@ -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);
          ^^ return something.  ^^ use argc/argv
>>> +    SLIST_ENTRY(rtems_dhcpcd_hook) node;
>>> +} rtems_dhcpcd_hook;
>> This looks to me like it would be useful elsewhere.
> 
> The handler signature looks quite special to me.
> 

It can be made reusable and made to work.

Chris


More information about the devel mailing list