"Fossies" - the Fresh Open Source Software Archive

Member "dhcpcd-9.4.1/src/dev.c" (22 Oct 2021, 4721 Bytes) of package /linux/misc/dhcpcd-9.4.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dev.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.4.0_vs_9.4.1.

    1 /* SPDX-License-Identifier: BSD-2-Clause */
    2 /*
    3  * dhcpcd - DHCP client daemon
    4  * Copyright (c) 2006-2021 Roy Marples <roy@marples.name>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <dirent.h>
   29 #include <dlfcn.h>
   30 #include <stdio.h>
   31 #include <stdlib.h>
   32 #include <string.h>
   33 
   34 #define _INDEV
   35 #include "common.h"
   36 #include "dev.h"
   37 #include "eloop.h"
   38 #include "dhcpcd.h"
   39 #include "logerr.h"
   40 
   41 int
   42 dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
   43 {
   44 
   45 #ifdef PRIVSEP
   46     if (ctx->options & DHCPCD_PRIVSEP &&
   47         !(ctx->options & DHCPCD_PRIVSEPROOT))
   48         return ps_root_dev_initialised(ctx, ifname);
   49 #endif
   50 
   51     if (ctx->dev == NULL)
   52         return 1;
   53     return ctx->dev->initialised(ifname);
   54 }
   55 
   56 int
   57 dev_listening(struct dhcpcd_ctx *ctx)
   58 {
   59 
   60 #ifdef PRIVSEP
   61     if (ctx->options & DHCPCD_PRIVSEP &&
   62         !(ctx->options & DHCPCD_PRIVSEPROOT))
   63         return ps_root_dev_listening(ctx);
   64 #endif
   65 
   66     if (ctx->dev == NULL)
   67         return 0;
   68     return ctx->dev->listening();
   69 }
   70 
   71 static void
   72 dev_stop1(struct dhcpcd_ctx *ctx, int stop)
   73 {
   74 
   75     if (ctx->dev) {
   76         if (stop)
   77             logdebugx("dev: unloaded %s", ctx->dev->name);
   78         eloop_event_delete(ctx->eloop, ctx->dev_fd);
   79         ctx->dev->stop();
   80         free(ctx->dev);
   81         ctx->dev = NULL;
   82         ctx->dev_fd = -1;
   83     }
   84     if (ctx->dev_handle) {
   85         dlclose(ctx->dev_handle);
   86         ctx->dev_handle = NULL;
   87     }
   88 }
   89 
   90 void
   91 dev_stop(struct dhcpcd_ctx *ctx)
   92 {
   93 
   94     dev_stop1(ctx, !(ctx->options & DHCPCD_FORKED));
   95 }
   96 
   97 static int
   98 dev_start2(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd,
   99     const char *name)
  100 {
  101     char file[PATH_MAX];
  102     void *h;
  103     void (*fptr)(struct dev *, const struct dev_dhcpcd *);
  104     int r;
  105 
  106     snprintf(file, sizeof(file), DEVDIR "/%s", name);
  107     h = dlopen(file, RTLD_LAZY);
  108     if (h == NULL) {
  109         logerrx("dlopen: %s", dlerror());
  110         return -1;
  111     }
  112     fptr = dlsym(h, "dev_init");
  113     if (fptr == NULL) {
  114         logerrx("dlsym: %s", dlerror());
  115         dlclose(h);
  116         return -1;
  117     }
  118     if ((ctx->dev = calloc(1, sizeof(*ctx->dev))) == NULL) {
  119         logerr("%s: calloc", __func__);
  120         dlclose(h);
  121         return -1;
  122     }
  123     fptr(ctx->dev, dev_dhcpcd);
  124     if (ctx->dev->start  == NULL || (r = ctx->dev->start()) == -1) {
  125         free(ctx->dev);
  126         ctx->dev = NULL;
  127         dlclose(h);
  128         return -1;
  129     }
  130     loginfox("dev: loaded %s", ctx->dev->name);
  131     ctx->dev_handle = h;
  132     return r;
  133 }
  134 
  135 static int
  136 dev_start1(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd)
  137 {
  138     DIR *dp;
  139     struct dirent *d;
  140     int r;
  141 
  142     if (ctx->dev) {
  143         logerrx("dev: already started %s", ctx->dev->name);
  144         return -1;
  145     }
  146 
  147     if (ctx->dev_load)
  148         return dev_start2(ctx, dev_dhcpcd, ctx->dev_load);
  149 
  150     dp = opendir(DEVDIR);
  151     if (dp == NULL) {
  152         logdebug("dev: %s", DEVDIR);
  153         return 0;
  154     }
  155 
  156     r = 0;
  157     while ((d = readdir(dp))) {
  158         if (d->d_name[0] == '.')
  159             continue;
  160 
  161         r = dev_start2(ctx, dev_dhcpcd, d->d_name);
  162         if (r != -1)
  163             break;
  164     }
  165     closedir(dp);
  166     return r;
  167 }
  168 
  169 static void
  170 dev_handle_data(void *arg)
  171 {
  172     struct dhcpcd_ctx *ctx;
  173 
  174     ctx = arg;
  175     if (ctx->dev->handle_device(arg) == -1) {
  176         /* XXX: an error occured. should we restart dev? */
  177     }
  178 }
  179 
  180 int
  181 dev_start(struct dhcpcd_ctx *ctx, int (*handler)(void *, int, const char *))
  182 {
  183     struct dev_dhcpcd dev_dhcpcd = {
  184         .handle_interface = handler,
  185     };
  186 
  187     if (ctx->dev_fd != -1) {
  188         logerrx("%s: already started on fd %d", __func__, ctx->dev_fd);
  189         return ctx->dev_fd;
  190     }
  191 
  192     ctx->dev_fd = dev_start1(ctx, &dev_dhcpcd);
  193     if (ctx->dev_fd != -1) {
  194         if (eloop_event_add(ctx->eloop, ctx->dev_fd,
  195             dev_handle_data, ctx) == -1)
  196         {
  197             logerr(__func__);
  198             dev_stop1(ctx, 1);
  199             return -1;
  200         }
  201     }
  202 
  203     return ctx->dev_fd;
  204 }