/*
 * dhcpcd - DHCP client daemon
 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
 *
 * 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 <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define _INDEV
#include "common.h"
#include "dev.h"
#include "eloop.h"
#include "dhcpcd.h"

int
dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
{

	if (ctx->dev == NULL)
		return 1;
	return ctx->dev->initialized(ifname);
}

int
dev_listening(struct dhcpcd_ctx *ctx)
{

	if (ctx->dev == NULL)
		return 0;
	return ctx->dev->listening();
}

static void
dev_stop1(struct dhcpcd_ctx *ctx, int stop)
{

	if (ctx->dev) {
		if (stop)
			logger(ctx, LOG_DEBUG,
			    "dev: unloaded %s", ctx->dev->name);
		eloop_event_delete(ctx->eloop, ctx->dev_fd, 0);
		ctx->dev->stop();
		free(ctx->dev);
		ctx->dev = NULL;
		ctx->dev_fd = -1;
	}
	if (ctx->dev_handle) {
		dlclose(ctx->dev_handle);
		ctx->dev_handle = NULL;
	}
}

void
dev_stop(struct dhcpcd_ctx *ctx)
{

	dev_stop1(ctx,!(ctx->options & DHCPCD_FORKED));
}

static int
dev_start2(struct dhcpcd_ctx *ctx, const char *name)
{
	char file[PATH_MAX];
	void *h;
	void (*fptr)(struct dev *, const struct dev_dhcpcd *);
	int r;
	struct dev_dhcpcd dev_dhcpcd;

	snprintf(file, sizeof(file), DEVDIR "/%s", name);
	h = dlopen(file, RTLD_LAZY);
	if (h == NULL) {
		logger(ctx, LOG_ERR, "dlopen: %s", dlerror());
		return -1;
	}
	fptr = (void (*)(struct dev *, const struct dev_dhcpcd *))
	    dlsym(h, "dev_init");
	if (fptr == NULL) {
		logger(ctx, LOG_ERR, "dlsym: %s", dlerror());
		dlclose(h);
		return -1;
	}
	ctx->dev = calloc(1, sizeof(*ctx->dev));
	dev_dhcpcd.handle_interface = &dhcpcd_handleinterface;
	fptr(ctx->dev, &dev_dhcpcd);
	if (ctx->dev->start  == NULL || (r = ctx->dev->start()) == -1) {
		free(ctx->dev);
		ctx->dev = NULL;
		dlclose(h);
		return -1;
	}
	logger(ctx, LOG_INFO, "dev: loaded %s", ctx->dev->name);
	ctx->dev_handle = h;
	return r;
}

static int
dev_start1(struct dhcpcd_ctx *ctx)
{
	DIR *dp;
	struct dirent *d;
	int r;

	if (ctx->dev) {
		logger(ctx, LOG_ERR, "dev: already started %s", ctx->dev->name);
		return -1;
	}

	if (ctx->dev_load)
		return dev_start2(ctx, ctx->dev_load);

	dp = opendir(DEVDIR);
	if (dp == NULL) {
		logger(ctx, LOG_DEBUG, "dev: %s: %m", DEVDIR);
		return 0;
	}

	r = 0;
	while ((d = readdir(dp))) {
		if (d->d_name[0] == '.')
			continue;

		r = dev_start2(ctx, d->d_name);
		if (r != -1)
			break;
	}
	closedir(dp);
	return r;
}

static void
dev_handle_data(void *arg)
{
	struct dhcpcd_ctx *ctx;

	ctx = arg;
	if (ctx->dev->handle_device(arg) == -1) {
		/* XXX: an error occured. should we restart dev? */
	}
}

int
dev_start(struct dhcpcd_ctx *ctx)
{

	if (ctx->dev_fd != -1) {
		logger(ctx, LOG_ERR, "%s: already started on fd %d", __func__,
		    ctx->dev_fd);
		return ctx->dev_fd;
	}

	ctx->dev_fd = dev_start1(ctx);
	if (ctx->dev_fd != -1) {
		if (eloop_event_add(ctx->eloop,
			ctx->dev_fd, dev_handle_data, ctx, NULL, NULL) == -1)
		{
			logger(ctx, LOG_ERR,
			    "%s: eloop_event_add: %m", __func__);
			dev_stop1(ctx, 1);
			return -1;
		}
	}

	return ctx->dev_fd;
}
