1e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/*
2e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * dhcpcd - DHCP client daemon
3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
4e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * All rights reserved
5e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
6e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Redistribution and use in source and binary forms, with or without
7e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * modification, are permitted provided that the following conditions
8e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * are met:
9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 1. Redistributions of source code must retain the above copyright
10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer.
11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 2. Redistributions in binary form must reproduce the above copyright
12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer in the
13e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    documentation and/or other materials provided with the distribution.
14e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *
15e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * SUCH DAMAGE.
26e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt */
27e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <linux/socket.h>
29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/stat.h>
30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/un.h>
31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <errno.h>
33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdio.h>
34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdlib.h>
35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <string.h>
36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <time.h>
37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <unistd.h>
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "config.h"
40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h"
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "dhcpcd.h"
42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "control.h"
43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h"
44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int fd = -1;
46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char buffer[1024];
47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *argvp[255];
48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct sockaddr_un sun;
50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct fd_list *fds = NULL;
51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
52e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
53e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtremove_control_data(void *arg)
54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct fd_list *l, *last = NULL;
56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (l = fds; l != NULL; l = l->next) {
58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (l == arg) {
59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			close(l->fd);
60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			delete_event(l->fd);
61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (last == NULL)
62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				fds = l->next;
63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				last->next = l->next;
65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free(l);
66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last = l;
69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_control_data(void *arg)
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct fd_list *l = arg;
76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ssize_t bytes;
77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int argc;
78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *e, *p;
79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char **ap;
80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	bytes = read(l->fd, buffer, sizeof(buffer) - 1);
82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (bytes == -1 || bytes == 0) {
83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		remove_control_data(l);
84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	buffer[bytes] = '\0';
87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p = buffer;
88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	e = buffer + bytes;
89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	argc = 0;
90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	ap = argvp;
91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (p < e && (size_t)argc < sizeof(argvp)) {
92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		argc++;
93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		*ap++ = p;
94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		p += strlen(p) + 1;
95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	handle_args(l, argc, argvp);
97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */
100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_control(_unused void *arg)
102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct sockaddr_un run;
104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	socklen_t len;
105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct fd_list *l;
106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int f;
107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	len = sizeof(run);
109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((f = accept(fd, (struct sockaddr *)&run, &len)) == -1)
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	l = xmalloc(sizeof(*l));
112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	l->fd = f;
113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	l->listener = 0;
114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	l->next = fds;
115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	fds = l;
116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_event(l->fd, handle_control_data, l);
117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmake_sock(void)
121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memset(&sun, 0, sizeof(sun));
125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	sun.sun_family = AF_UNIX;
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	strlcpy(sun.sun_path, CONTROLSOCKET, sizeof(sun.sun_path));
127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return sizeof(sun.sun_family) + strlen(sun.sun_path) + 1;
128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_control(void)
132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int len;
134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((len = make_sock()) == -1)
136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	unlink(CONTROLSOCKET);
138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (bind(fd, (struct sockaddr *)&sun, len) == -1 ||
139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    chmod(CONTROLSOCKET,
140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 ||
141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    set_cloexec(fd) == -1 ||
142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    set_nonblock(fd) == -1 ||
143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	    listen(fd, sizeof(fds)) == -1)
144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	{
145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		close(fd);
146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_event(fd, handle_control, NULL);
149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return fd;
150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstop_control(void)
154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int retval = 0;
156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct fd_list *l, *ll;
157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_event(fd);
159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (shutdown(fd, SHUT_RDWR) == -1)
160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		retval = 1;
161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	fd = -1;
162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (unlink(CONTROLSOCKET) == -1)
163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		retval = -1;
164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	l = fds;
166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (l != NULL) {
167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		ll = l->next;
168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		delete_event(l->fd);
169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		shutdown(l->fd, SHUT_RDWR);
170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(l);
171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		l = ll;
172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return retval;
175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtopen_control(void)
179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int len;
181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if ((len = make_sock()) == -1)
183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return connect(fd, (struct sockaddr *)&sun, len);
185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint
188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_control(int argc, char * const *argv)
189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	char *p = buffer;
191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int i;
192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	size_t len;
193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (argc > 255) {
195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		errno = ENOBUFS;
196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return -1;
197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (i = 0; i < argc; i++) {
199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		len = strlen(argv[i]) + 1;
200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if ((p - buffer) + len > sizeof(buffer)) {
201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			errno = ENOBUFS;
202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return -1;
203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		memcpy(p, argv[i], len);
205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		p += len;
206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return write(fd, buffer, p - buffer);
208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
209