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