devd.cc revision 293695
11558Srgrimes/*-
21558Srgrimes * Copyright (c) 2002-2010 M. Warner Losh.
31558Srgrimes * All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes *
141558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241558Srgrimes * SUCH DAMAGE.
251558Srgrimes *
261558Srgrimes * my_system is a variation on lib/libc/stdlib/system.c:
271558Srgrimes *
281558Srgrimes * Copyright (c) 1988, 1993
291558Srgrimes *	The Regents of the University of California.  All rights reserved.
301558Srgrimes *
311558Srgrimes * Redistribution and use in source and binary forms, with or without
3250476Speter * modification, are permitted provided that the following conditions
331558Srgrimes * are met:
34306991Ssevan * 1. Redistributions of source code must retain the above copyright
351558Srgrimes *    notice, this list of conditions and the following disclaimer.
3679530Sru * 2. Redistributions in binary form must reproduce the above copyright
371558Srgrimes *    notice, this list of conditions and the following disclaimer in the
381558Srgrimes *    documentation and/or other materials provided with the distribution.
391558Srgrimes * 4. Neither the name of the University nor the names of its contributors
401558Srgrimes *    may be used to endorse or promote products derived from this software
4168960Sru *    without specific prior written permission.
4268960Sru *
4347998Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4447998Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4547998Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4647998Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
471558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
481558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4937417Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5099501Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
511558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
521558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5347998Sru * SUCH DAMAGE.
541558Srgrimes */
551558Srgrimes
5637417Scharnier/*
5747998Sru * DEVD control daemon.
581558Srgrimes */
591558Srgrimes
6037417Scharnier// TODO list:
6199501Scharnier//	o devd.conf and devd man pages need a lot of help:
621558Srgrimes//	  - devd needs to document the unix domain socket
631558Srgrimes//	  - devd.conf needs more details on the supported statements.
6447998Sru
651558Srgrimes#include <sys/cdefs.h>
661558Srgrimes__FBSDID("$FreeBSD: stable/10/sbin/devd/devd.cc 293695 2016-01-11 20:24:56Z asomers $");
671558Srgrimes
681558Srgrimes#include <sys/param.h>
691558Srgrimes#include <sys/socket.h>
7037417Scharnier#include <sys/stat.h>
711558Srgrimes#include <sys/sysctl.h>
721558Srgrimes#include <sys/types.h>
731558Srgrimes#include <sys/wait.h>
741558Srgrimes#include <sys/un.h>
751558Srgrimes
7637417Scharnier#include <cctype>
771558Srgrimes#include <cerrno>
781558Srgrimes#include <cstdlib>
7947998Sru#include <cstdio>
8047998Sru#include <csignal>
811558Srgrimes#include <cstring>
8237417Scharnier#include <cstdarg>
8347998Sru
841558Srgrimes#include <dirent.h>
8579754Sdd#include <err.h>
8637417Scharnier#include <fcntl.h>
8747998Sru#include <libutil.h>
8847998Sru#include <paths.h>
891558Srgrimes#include <poll.h>
90149766Sgarys#include <regex.h>
91149766Sgarys#include <syslog.h>
92149766Sgarys#include <unistd.h>
9337417Scharnier
9418882Sbde#include <algorithm>
9518882Sbde#include <map>
9637417Scharnier#include <string>
9765773Ssheldonh#include <list>
98101810Sru#include <vector>
9965803Ssheldonh
10065773Ssheldonh#include "devd.h"		/* C compatible definitions */
10165773Ssheldonh#include "devd.hh"		/* C++ class definitions */
10265773Ssheldonh
1031558Srgrimes#define STREAMPIPE "/var/run/devd.pipe"
10465773Ssheldonh#define SEQPACKETPIPE "/var/run/devd.seqpacket.pipe"
10579754Sdd#define CF "/etc/devd.conf"
106122506Skensmith#define SYSCTL "hw.bus.devctl_queue"
10765773Ssheldonh
1081558Srgrimes/*
109122506Skensmith * Since the client socket is nonblocking, we must increase its send buffer to
110122506Skensmith * handle brief event storms.  On FreeBSD, AF_UNIX sockets don't have a receive
111129327Sru * buffer, so the client can't increase the buffersize by itself.
112122506Skensmith *
113165730Srse * For example, when creating a ZFS pool, devd emits one 165 character
114122506Skensmith * resource.fs.zfs.statechange message for each vdev in the pool.  The kernel
115149766Sgarys * allocates a 4608B mbuf for each message.  Modern technology places a limit of
116122506Skensmith * roughly 450 drives/rack, and it's unlikely that a zpool will ever be larger
117122506Skensmith * than that.
118122506Skensmith *
119122506Skensmith * 450 drives * 165 bytes / drive = 74250B of data in the sockbuf
120122506Skensmith * 450 drives * 4608B / drive = 2073600B of mbufs in the sockbuf
121122506Skensmith *
12279754Sdd * We can't directly set the sockbuf's mbuf limit, but we can do it indirectly.
12337417Scharnier * The kernel sets it to the minimum of a hard-coded maximum value and sbcc *
1241558Srgrimes * kern.ipc.sockbuf_waste_factor, where sbcc is the socket buffer size set by
1251558Srgrimes * the user.  The default value of kern.ipc.sockbuf_waste_factor is 8.  If we
1261558Srgrimes * set the bufsize to 256k and use the kern.ipc.sockbuf_waste_factor, then the
12799501Scharnier * kernel will set the mbuf limit to 2MB, which is just large enough for 450
12899501Scharnier * drives.  It also happens to be the same as the hardcoded maximum value.
12999501Scharnier */
13054199Ssheldonh#define CLIENT_BUFSIZE 262144
13154199Ssheldonh
13254199Ssheldonhusing namespace std;
13354199Ssheldonh
1341558Srgrimestypedef struct client {
1351558Srgrimes	int fd;
13615135Smpp	int socktype;
1371558Srgrimes} client_t;
1381558Srgrimes
1391558Srgrimesextern FILE *yyin;
14015135Smppextern int lineno;
1411558Srgrimes
1421558Srgrimesstatic const char notify = '!';
14315135Smppstatic const char nomatch = '?';
1441558Srgrimesstatic const char attach = '+';
145131488Srustatic const char detach = '-';
146131488Sru
1471558Srgrimesstatic struct pidfh *pfh;
1481558Srgrimes
149231534Sedstatic int no_daemon = 0;
1501558Srgrimesstatic int daemonize_quick = 0;
15115135Smppstatic int quiet_mode = 0;
1521558Srgrimesstatic unsigned total_events = 0;
1531558Srgrimesstatic volatile sig_atomic_t got_siginfo = 0;
15499501Scharnierstatic volatile sig_atomic_t romeo_must_die = 0;
15599501Scharnier
15699501Scharnierstatic const char *configfile = CF;
15754199Ssheldonh
15854199Ssheldonhstatic void devdlog(int priority, const char* message, ...)
15954199Ssheldonh	__printflike(2, 3);
16054199Ssheldonhstatic void event_loop(void);
16154199Ssheldonhstatic void usage(void);
16254199Ssheldonh
16354199Ssheldonhtemplate <class T> void
16454199Ssheldonhdelete_and_clear(vector<T *> &v)
16554199Ssheldonh{
16654199Ssheldonh	typename vector<T *>::const_iterator i;
1671558Srgrimes
1681558Srgrimes	for (i = v.begin(); i != v.end(); ++i)
16915135Smpp		delete *i;
1701558Srgrimes	v.clear();
1711558Srgrimes}
1721558Srgrimes
17337417Scharnierconfig cfg;
1741558Srgrimes
1751558Srgrimesevent_proc::event_proc() : _prio(-1)
1761558Srgrimes{
17737417Scharnier	_epsvec.reserve(4);
1781558Srgrimes}
17915135Smpp
1801558Srgrimesevent_proc::~event_proc()
1811558Srgrimes{
18215135Smpp	delete_and_clear(_epsvec);
18337417Scharnier}
1841558Srgrimes
1851558Srgrimesvoid
1861558Srgrimesevent_proc::add(eps *eps)
18715135Smpp{
1881558Srgrimes	_epsvec.push_back(eps);
18937417Scharnier}
19054199Ssheldonh
19154199Ssheldonhbool
1921558Srgrimesevent_proc::matches(config &c) const
19379754Sdd{
19437417Scharnier	vector<eps *>::const_iterator i;
1951558Srgrimes
1961558Srgrimes	for (i = _epsvec.begin(); i != _epsvec.end(); ++i)
19715135Smpp		if (!(*i)->do_match(c))
19837417Scharnier			return (false);
1991558Srgrimes	return (true);
2001558Srgrimes}
20199501Scharnier
20299501Scharnierbool
20399501Scharnierevent_proc::run(config &c) const
2041558Srgrimes{
2051558Srgrimes	vector<eps *>::const_iterator i;
2061558Srgrimes
2071558Srgrimes	for (i = _epsvec.begin(); i != _epsvec.end(); ++i)
2081558Srgrimes		if (!(*i)->do_action(c))
2091558Srgrimes			return (false);
21037417Scharnier	return (true);
2111558Srgrimes}
2121558Srgrimes
2131558Srgrimesaction::action(const char *cmd)
21499501Scharnier	: _cmd(cmd)
21599501Scharnier{
21699501Scharnier	// nothing
2171558Srgrimes}
2181558Srgrimes
21981449Sruaction::~action()
2201558Srgrimes{
2211558Srgrimes	// nothing
22247998Sru}
2231558Srgrimes
2241558Srgrimesstatic int
2251558Srgrimesmy_system(const char *command)
2261558Srgrimes{
2271558Srgrimes	pid_t pid, savedpid;
22899501Scharnier	int pstat;
22999501Scharnier	struct sigaction ign, intact, quitact;
23099501Scharnier	sigset_t newsigblock, oldsigblock;
2312323Snate
2322323Snate	if (!command)		/* just checking... */
23381449Sru		return (1);
2342323Snate
2352323Snate	/*
23621945Sadam	 * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
2372323Snate	 * existing signal dispositions.
23899501Scharnier	 */
23999501Scharnier	ign.sa_handler = SIG_IGN;
24099501Scharnier	::sigemptyset(&ign.sa_mask);
24147962Sru	ign.sa_flags = 0;
24247962Sru	::sigaction(SIGINT, &ign, &intact);
24347998Sru	::sigaction(SIGQUIT, &ign, &quitact);
24447962Sru	::sigemptyset(&newsigblock);
24547962Sru	::sigaddset(&newsigblock, SIGCHLD);
24647962Sru	::sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
24737055Sjkoshy	switch (pid = ::fork()) {
24837417Scharnier	case -1:			/* error */
24927837Sdavidn		break;
25027837Sdavidn	case 0:				/* child */
25157668Ssheldonh		/*
25257668Ssheldonh		 * Restore original signal dispositions and exec the command.
25327837Sdavidn		 */
25427837Sdavidn		::sigaction(SIGINT, &intact, NULL);
25527837Sdavidn		::sigaction(SIGQUIT,  &quitact, NULL);
256150154Srse		::sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
257150154Srse		/*
258152568Sru		 * Close the PID file, and all other open descriptors.
259152568Sru		 * Inherit std{in,out,err} only.
260150154Srse		 */
261150154Srse		cfg.close_pidfile();
262150154Srse		::closefrom(3);
26327837Sdavidn		::execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
2641558Srgrimes		::_exit(127);
26537417Scharnier	default:			/* parent */
2661558Srgrimes		savedpid = pid;
2671558Srgrimes		do {
2681558Srgrimes			pid = ::wait4(savedpid, &pstat, 0, (struct rusage *)0);
26937417Scharnier		} while (pid == -1 && errno == EINTR);
2701558Srgrimes		break;
27147998Sru	}
27247998Sru	::sigaction(SIGINT, &intact, NULL);
27348395Sru	::sigaction(SIGQUIT,  &quitact, NULL);
27447998Sru	::sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
27547998Sru	return (pid == -1 ? -1 : pstat);
27647998Sru}
277131488Sru
27847998Srubool
27947998Sruaction::do_action(config &c)
28047998Sru{
28147998Sru	string s = c.expand_string(_cmd.c_str());
28281251Sru	devdlog(LOG_NOTICE, "Executing '%s'\n", s.c_str());
28347998Sru	my_system(s.c_str());
28447998Sru	return (true);
28547998Sru}
286233510Sjoel
287289506Straszmatch::match(config &c, const char *var, const char *re) :
28847998Sru	_inv(re[0] == '!'),
28947998Sru	_var(var),
29047998Sru	_re(c.expand_string(_inv ? re + 1 : re, "^", "$"))
29147998Sru{
29247998Sru	regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
29347998Sru}
29447998Sru
29547998Srumatch::~match()
2961558Srgrimes{
297232977Sed	regfree(&_regex);
2981558Srgrimes}
29937417Scharnier
3001558Srgrimesbool
30137417Scharniermatch::do_match(config &c)
30237417Scharnier{
3031558Srgrimes	const string &value = c.get_variable(_var);
30437417Scharnier	bool retval;
3051558Srgrimes
30637417Scharnier	/*
30727837Sdavidn	 * This function gets called WAY too often to justify calling syslog()
30837417Scharnier	 * each time, even at LOG_DEBUG.  Because if syslogd isn't running, it
309232977Sed	 * can consume excessive amounts of systime inside of connect().  Only
310232977Sed	 * log when we're in -d mode.
311232977Sed	 */
312232977Sed	if (no_daemon) {
3131558Srgrimes		devdlog(LOG_DEBUG, "Testing %s=%s against %s, invert=%d\n",
314140415Sru		    _var.c_str(), value.c_str(), _re.c_str(), _inv);
315140415Sru	}
316140415Sru
317140415Sru	retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0);
318140415Sru	if (_inv == 1)
319140415Sru		retval = (retval == 0) ? 1 : 0;
320140415Sru
321140415Sru	return (retval);
322140415Sru}
323140415Sru
324140415Sru#include <sys/sockio.h>
325140415Sru#include <net/if.h>
326140415Sru#include <net/if_media.h>
327140415Sru
328140415Srumedia::media(config &, const char *var, const char *type)
329140415Sru	: _var(var), _type(-1)
330140415Sru{
3311558Srgrimes	static struct ifmedia_description media_types[] = {
33221635Swosch		{ IFM_ETHER,		"Ethernet" },
3331558Srgrimes		{ IFM_TOKEN,		"Tokenring" },
3341558Srgrimes		{ IFM_FDDI,		"FDDI" },
3351558Srgrimes		{ IFM_IEEE80211,	"802.11" },
336152568Sru		{ IFM_ATM,		"ATM" },
3371558Srgrimes		{ -1,			"unknown" },
33821635Swosch		{ 0, NULL },
339122506Skensmith	};
3401558Srgrimes	for (int i = 0; media_types[i].ifmt_string != NULL; ++i)
3411558Srgrimes		if (strcasecmp(type, media_types[i].ifmt_string) == 0) {
34237055Sjkoshy			_type = media_types[i].ifmt_word;
34337055Sjkoshy			break;
3441558Srgrimes		}
34547962Sru}
3461558Srgrimes
34799501Scharniermedia::~media()
348306991Ssevan{
34937055Sjkoshy}
3501558Srgrimes
351116035Scharnierbool
3521558Srgrimesmedia::do_match(config &c)
35337055Sjkoshy{
35479754Sdd	string value;
35579754Sdd	struct ifmediareq ifmr;
35679754Sdd	bool retval;
357131488Sru	int s;
358131488Sru
35979754Sdd	// Since we can be called from both a device attach/detach
36079754Sdd	// context where device-name is defined and what we want,
36137055Sjkoshy	// as well as from a link status context, where subsystem is
362	// the name of interest, first try device-name and fall back
363	// to subsystem if none exists.
364	value = c.get_variable("device-name");
365	if (value.empty())
366		value = c.get_variable("subsystem");
367	devdlog(LOG_DEBUG, "Testing media type of %s against 0x%x\n",
368		    value.c_str(), _type);
369
370	retval = false;
371
372	s = socket(PF_INET, SOCK_DGRAM, 0);
373	if (s >= 0) {
374		memset(&ifmr, 0, sizeof(ifmr));
375		strncpy(ifmr.ifm_name, value.c_str(), sizeof(ifmr.ifm_name));
376
377		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 &&
378		    ifmr.ifm_status & IFM_AVALID) {
379			devdlog(LOG_DEBUG, "%s has media type 0x%x\n",
380				    value.c_str(), IFM_TYPE(ifmr.ifm_active));
381			retval = (IFM_TYPE(ifmr.ifm_active) == _type);
382		} else if (_type == -1) {
383			devdlog(LOG_DEBUG, "%s has unknown media type\n",
384				    value.c_str());
385			retval = true;
386		}
387		close(s);
388	}
389
390	return (retval);
391}
392
393const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_";
394const string var_list::nothing = "";
395
396const string &
397var_list::get_variable(const string &var) const
398{
399	map<string, string>::const_iterator i;
400
401	i = _vars.find(var);
402	if (i == _vars.end())
403		return (var_list::bogus);
404	return (i->second);
405}
406
407bool
408var_list::is_set(const string &var) const
409{
410	return (_vars.find(var) != _vars.end());
411}
412
413void
414var_list::set_variable(const string &var, const string &val)
415{
416	/*
417	 * This function gets called WAY too often to justify calling syslog()
418	 * each time, even at LOG_DEBUG.  Because if syslogd isn't running, it
419	 * can consume excessive amounts of systime inside of connect().  Only
420	 * log when we're in -d mode.
421	 */
422	if (no_daemon)
423		devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str());
424	_vars[var] = val;
425}
426
427void
428config::reset(void)
429{
430	_dir_list.clear();
431	delete_and_clear(_var_list_table);
432	delete_and_clear(_attach_list);
433	delete_and_clear(_detach_list);
434	delete_and_clear(_nomatch_list);
435	delete_and_clear(_notify_list);
436}
437
438void
439config::parse_one_file(const char *fn)
440{
441	devdlog(LOG_DEBUG, "Parsing %s\n", fn);
442	yyin = fopen(fn, "r");
443	if (yyin == NULL)
444		err(1, "Cannot open config file %s", fn);
445	lineno = 1;
446	if (yyparse() != 0)
447		errx(1, "Cannot parse %s at line %d", fn, lineno);
448	fclose(yyin);
449}
450
451void
452config::parse_files_in_dir(const char *dirname)
453{
454	DIR *dirp;
455	struct dirent *dp;
456	char path[PATH_MAX];
457
458	devdlog(LOG_DEBUG, "Parsing files in %s\n", dirname);
459	dirp = opendir(dirname);
460	if (dirp == NULL)
461		return;
462	readdir(dirp);		/* Skip . */
463	readdir(dirp);		/* Skip .. */
464	while ((dp = readdir(dirp)) != NULL) {
465		if (strcmp(dp->d_name + dp->d_namlen - 5, ".conf") == 0) {
466			snprintf(path, sizeof(path), "%s/%s",
467			    dirname, dp->d_name);
468			parse_one_file(path);
469		}
470	}
471	closedir(dirp);
472}
473
474class epv_greater {
475public:
476	int operator()(event_proc *const&l1, event_proc *const&l2) const
477	{
478		return (l1->get_priority() > l2->get_priority());
479	}
480};
481
482void
483config::sort_vector(vector<event_proc *> &v)
484{
485	stable_sort(v.begin(), v.end(), epv_greater());
486}
487
488void
489config::parse(void)
490{
491	vector<string>::const_iterator i;
492
493	parse_one_file(configfile);
494	for (i = _dir_list.begin(); i != _dir_list.end(); ++i)
495		parse_files_in_dir((*i).c_str());
496	sort_vector(_attach_list);
497	sort_vector(_detach_list);
498	sort_vector(_nomatch_list);
499	sort_vector(_notify_list);
500}
501
502void
503config::open_pidfile()
504{
505	pid_t otherpid;
506
507	if (_pidfile.empty())
508		return;
509	pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid);
510	if (pfh == NULL) {
511		if (errno == EEXIST)
512			errx(1, "devd already running, pid: %d", (int)otherpid);
513		warn("cannot open pid file");
514	}
515}
516
517void
518config::write_pidfile()
519{
520
521	pidfile_write(pfh);
522}
523
524void
525config::close_pidfile()
526{
527
528	pidfile_close(pfh);
529}
530
531void
532config::remove_pidfile()
533{
534
535	pidfile_remove(pfh);
536}
537
538void
539config::add_attach(int prio, event_proc *p)
540{
541	p->set_priority(prio);
542	_attach_list.push_back(p);
543}
544
545void
546config::add_detach(int prio, event_proc *p)
547{
548	p->set_priority(prio);
549	_detach_list.push_back(p);
550}
551
552void
553config::add_directory(const char *dir)
554{
555	_dir_list.push_back(string(dir));
556}
557
558void
559config::add_nomatch(int prio, event_proc *p)
560{
561	p->set_priority(prio);
562	_nomatch_list.push_back(p);
563}
564
565void
566config::add_notify(int prio, event_proc *p)
567{
568	p->set_priority(prio);
569	_notify_list.push_back(p);
570}
571
572void
573config::set_pidfile(const char *fn)
574{
575	_pidfile = fn;
576}
577
578void
579config::push_var_table()
580{
581	var_list *vl;
582
583	vl = new var_list();
584	_var_list_table.push_back(vl);
585	devdlog(LOG_DEBUG, "Pushing table\n");
586}
587
588void
589config::pop_var_table()
590{
591	delete _var_list_table.back();
592	_var_list_table.pop_back();
593	devdlog(LOG_DEBUG, "Popping table\n");
594}
595
596void
597config::set_variable(const char *var, const char *val)
598{
599	_var_list_table.back()->set_variable(var, val);
600}
601
602const string &
603config::get_variable(const string &var)
604{
605	vector<var_list *>::reverse_iterator i;
606
607	for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); ++i) {
608		if ((*i)->is_set(var))
609			return ((*i)->get_variable(var));
610	}
611	return (var_list::nothing);
612}
613
614bool
615config::is_id_char(char ch) const
616{
617	return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' ||
618	    ch == '-'));
619}
620
621void
622config::expand_one(const char *&src, string &dst)
623{
624	int count;
625	string buffer;
626
627	src++;
628	// $$ -> $
629	if (*src == '$') {
630		dst += *src++;
631		return;
632	}
633
634	// $(foo) -> $(foo)
635	// Not sure if I want to support this or not, so for now we just pass
636	// it through.
637	if (*src == '(') {
638		dst += '$';
639		count = 1;
640		/* If the string ends before ) is matched , return. */
641		while (count > 0 && *src) {
642			if (*src == ')')
643				count--;
644			else if (*src == '(')
645				count++;
646			dst += *src++;
647		}
648		return;
649	}
650
651	// $[^A-Za-z] -> $\1
652	if (!isalpha(*src)) {
653		dst += '$';
654		dst += *src++;
655		return;
656	}
657
658	// $var -> replace with value
659	do {
660		buffer += *src++;
661	} while (is_id_char(*src));
662	dst.append(get_variable(buffer));
663}
664
665const string
666config::expand_string(const char *src, const char *prepend, const char *append)
667{
668	const char *var_at;
669	string dst;
670
671	/*
672	 * 128 bytes is enough for 2427 of 2438 expansions that happen
673	 * while parsing config files, as tested on 2013-01-30.
674	 */
675	dst.reserve(128);
676
677	if (prepend != NULL)
678		dst = prepend;
679
680	for (;;) {
681		var_at = strchr(src, '$');
682		if (var_at == NULL) {
683			dst.append(src);
684			break;
685		}
686		dst.append(src, var_at - src);
687		src = var_at;
688		expand_one(src, dst);
689	}
690
691	if (append != NULL)
692		dst.append(append);
693
694	return (dst);
695}
696
697bool
698config::chop_var(char *&buffer, char *&lhs, char *&rhs) const
699{
700	char *walker;
701
702	if (*buffer == '\0')
703		return (false);
704	walker = lhs = buffer;
705	while (is_id_char(*walker))
706		walker++;
707	if (*walker != '=')
708		return (false);
709	walker++;		// skip =
710	if (*walker == '"') {
711		walker++;	// skip "
712		rhs = walker;
713		while (*walker && *walker != '"')
714			walker++;
715		if (*walker != '"')
716			return (false);
717		rhs[-2] = '\0';
718		*walker++ = '\0';
719	} else {
720		rhs = walker;
721		while (*walker && !isspace(*walker))
722			walker++;
723		if (*walker != '\0')
724			*walker++ = '\0';
725		rhs[-1] = '\0';
726	}
727	while (isspace(*walker))
728		walker++;
729	buffer = walker;
730	return (true);
731}
732
733
734char *
735config::set_vars(char *buffer)
736{
737	char *lhs;
738	char *rhs;
739
740	while (1) {
741		if (!chop_var(buffer, lhs, rhs))
742			break;
743		set_variable(lhs, rhs);
744	}
745	return (buffer);
746}
747
748void
749config::find_and_execute(char type)
750{
751	vector<event_proc *> *l;
752	vector<event_proc *>::const_iterator i;
753	const char *s;
754
755	switch (type) {
756	default:
757		return;
758	case notify:
759		l = &_notify_list;
760		s = "notify";
761		break;
762	case nomatch:
763		l = &_nomatch_list;
764		s = "nomatch";
765		break;
766	case attach:
767		l = &_attach_list;
768		s = "attach";
769		break;
770	case detach:
771		l = &_detach_list;
772		s = "detach";
773		break;
774	}
775	devdlog(LOG_DEBUG, "Processing %s event\n", s);
776	for (i = l->begin(); i != l->end(); ++i) {
777		if ((*i)->matches(*this)) {
778			(*i)->run(*this);
779			break;
780		}
781	}
782
783}
784
785
786static void
787process_event(char *buffer)
788{
789	char type;
790	char *sp;
791
792	sp = buffer + 1;
793	devdlog(LOG_INFO, "Processing event '%s'\n", buffer);
794	type = *buffer++;
795	cfg.push_var_table();
796	// No match doesn't have a device, and the format is a little
797	// different, so handle it separately.
798	switch (type) {
799	case notify:
800		sp = cfg.set_vars(sp);
801		break;
802	case nomatch:
803		//? at location pnp-info on bus
804		sp = strchr(sp, ' ');
805		if (sp == NULL)
806			return;	/* Can't happen? */
807		*sp++ = '\0';
808		while (isspace(*sp))
809			sp++;
810		if (strncmp(sp, "at ", 3) == 0)
811			sp += 3;
812		sp = cfg.set_vars(sp);
813		while (isspace(*sp))
814			sp++;
815		if (strncmp(sp, "on ", 3) == 0)
816			cfg.set_variable("bus", sp + 3);
817		break;
818	case attach:	/*FALLTHROUGH*/
819	case detach:
820		sp = strchr(sp, ' ');
821		if (sp == NULL)
822			return;	/* Can't happen? */
823		*sp++ = '\0';
824		cfg.set_variable("device-name", buffer);
825		while (isspace(*sp))
826			sp++;
827		if (strncmp(sp, "at ", 3) == 0)
828			sp += 3;
829		sp = cfg.set_vars(sp);
830		while (isspace(*sp))
831			sp++;
832		if (strncmp(sp, "on ", 3) == 0)
833			cfg.set_variable("bus", sp + 3);
834		break;
835	}
836
837	cfg.find_and_execute(type);
838	cfg.pop_var_table();
839}
840
841int
842create_socket(const char *name, int socktype)
843{
844	int fd, slen;
845	struct sockaddr_un sun;
846
847	if ((fd = socket(PF_LOCAL, socktype, 0)) < 0)
848		err(1, "socket");
849	bzero(&sun, sizeof(sun));
850	sun.sun_family = AF_UNIX;
851	strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
852	slen = SUN_LEN(&sun);
853	unlink(name);
854	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
855	    	err(1, "fcntl");
856	if (::bind(fd, (struct sockaddr *) & sun, slen) < 0)
857		err(1, "bind");
858	listen(fd, 4);
859	chown(name, 0, 0);	/* XXX - root.wheel */
860	chmod(name, 0666);
861	return (fd);
862}
863
864unsigned int max_clients = 10;	/* Default, can be overridden on cmdline. */
865unsigned int num_clients;
866
867list<client_t> clients;
868
869void
870notify_clients(const char *data, int len)
871{
872	list<client_t>::iterator i;
873
874	/*
875	 * Deliver the data to all clients.  Throw clients overboard at the
876	 * first sign of trouble.  This reaps clients who've died or closed
877	 * their sockets, and also clients who are alive but failing to keep up
878	 * (or who are maliciously not reading, to consume buffer space in
879	 * kernel memory or tie up the limited number of available connections).
880	 */
881	for (i = clients.begin(); i != clients.end(); ) {
882		int flags;
883		if (i->socktype == SOCK_SEQPACKET)
884			flags = MSG_EOR;
885		else
886			flags = 0;
887
888		if (send(i->fd, data, len, flags) != len) {
889			--num_clients;
890			close(i->fd);
891			i = clients.erase(i);
892			devdlog(LOG_WARNING, "notify_clients: send() failed; "
893			    "dropping unresponsive client\n");
894		} else
895			++i;
896	}
897}
898
899void
900check_clients(void)
901{
902	int s;
903	struct pollfd pfd;
904	list<client_t>::iterator i;
905
906	/*
907	 * Check all existing clients to see if any of them have disappeared.
908	 * Normally we reap clients when we get an error trying to send them an
909	 * event.  This check eliminates the problem of an ever-growing list of
910	 * zombie clients because we're never writing to them on a system
911	 * without frequent device-change activity.
912	 */
913	pfd.events = 0;
914	for (i = clients.begin(); i != clients.end(); ) {
915		pfd.fd = i->fd;
916		s = poll(&pfd, 1, 0);
917		if ((s < 0 && s != EINTR ) ||
918		    (s > 0 && (pfd.revents & POLLHUP))) {
919			--num_clients;
920			close(i->fd);
921			i = clients.erase(i);
922			devdlog(LOG_NOTICE, "check_clients:  "
923			    "dropping disconnected client\n");
924		} else
925			++i;
926	}
927}
928
929void
930new_client(int fd, int socktype)
931{
932	client_t s;
933	int sndbuf_size;
934
935	/*
936	 * First go reap any zombie clients, then accept the connection, and
937	 * shut down the read side to stop clients from consuming kernel memory
938	 * by sending large buffers full of data we'll never read.
939	 */
940	check_clients();
941	s.socktype = socktype;
942	s.fd = accept(fd, NULL, NULL);
943	if (s.fd != -1) {
944		sndbuf_size = CLIENT_BUFSIZE;
945		if (setsockopt(s.fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
946		    sizeof(sndbuf_size)))
947			err(1, "setsockopt");
948		shutdown(s.fd, SHUT_RD);
949		clients.push_back(s);
950		++num_clients;
951	} else
952		err(1, "accept");
953}
954
955static void
956event_loop(void)
957{
958	int rv;
959	int fd;
960	char buffer[DEVCTL_MAXBUF];
961	int once = 0;
962	int stream_fd, seqpacket_fd, max_fd;
963	int accepting;
964	timeval tv;
965	fd_set fds;
966
967	fd = open(PATH_DEVCTL, O_RDONLY | O_CLOEXEC);
968	if (fd == -1)
969		err(1, "Can't open devctl device %s", PATH_DEVCTL);
970	stream_fd = create_socket(STREAMPIPE, SOCK_STREAM);
971	seqpacket_fd = create_socket(SEQPACKETPIPE, SOCK_SEQPACKET);
972	accepting = 1;
973	max_fd = max(fd, max(stream_fd, seqpacket_fd)) + 1;
974	while (!romeo_must_die) {
975		if (!once && !no_daemon && !daemonize_quick) {
976			// Check to see if we have any events pending.
977			tv.tv_sec = 0;
978			tv.tv_usec = 0;
979			FD_ZERO(&fds);
980			FD_SET(fd, &fds);
981			rv = select(fd + 1, &fds, &fds, &fds, &tv);
982			// No events -> we've processed all pending events
983			if (rv == 0) {
984				devdlog(LOG_DEBUG, "Calling daemon\n");
985				cfg.remove_pidfile();
986				cfg.open_pidfile();
987				daemon(0, 0);
988				cfg.write_pidfile();
989				once++;
990			}
991		}
992		/*
993		 * When we've already got the max number of clients, stop
994		 * accepting new connections (don't put the listening sockets in
995		 * the set), shrink the accept() queue to reject connections
996		 * quickly, and poll the existing clients more often, so that we
997		 * notice more quickly when any of them disappear to free up
998		 * client slots.
999		 */
1000		FD_ZERO(&fds);
1001		FD_SET(fd, &fds);
1002		if (num_clients < max_clients) {
1003			if (!accepting) {
1004				listen(stream_fd, max_clients);
1005				listen(seqpacket_fd, max_clients);
1006				accepting = 1;
1007			}
1008			FD_SET(stream_fd, &fds);
1009			FD_SET(seqpacket_fd, &fds);
1010			tv.tv_sec = 60;
1011			tv.tv_usec = 0;
1012		} else {
1013			if (accepting) {
1014				listen(stream_fd, 0);
1015				listen(seqpacket_fd, 0);
1016				accepting = 0;
1017			}
1018			tv.tv_sec = 2;
1019			tv.tv_usec = 0;
1020		}
1021		rv = select(max_fd, &fds, NULL, NULL, &tv);
1022		if (got_siginfo) {
1023			devdlog(LOG_NOTICE, "Events received so far=%u\n",
1024			    total_events);
1025			got_siginfo = 0;
1026		}
1027		if (rv == -1) {
1028			if (errno == EINTR)
1029				continue;
1030			err(1, "select");
1031		} else if (rv == 0)
1032			check_clients();
1033		if (FD_ISSET(fd, &fds)) {
1034			rv = read(fd, buffer, sizeof(buffer) - 1);
1035			if (rv > 0) {
1036				total_events++;
1037				if (rv == sizeof(buffer) - 1) {
1038					devdlog(LOG_WARNING, "Warning: "
1039					    "available event data exceeded "
1040					    "buffer space\n");
1041				}
1042				notify_clients(buffer, rv);
1043				buffer[rv] = '\0';
1044				while (buffer[--rv] == '\n')
1045					buffer[rv] = '\0';
1046				process_event(buffer);
1047			} else if (rv < 0) {
1048				if (errno != EINTR)
1049					break;
1050			} else {
1051				/* EOF */
1052				break;
1053			}
1054		}
1055		if (FD_ISSET(stream_fd, &fds))
1056			new_client(stream_fd, SOCK_STREAM);
1057		/*
1058		 * Aside from the socket type, both sockets use the same
1059		 * protocol, so we can process clients the same way.
1060		 */
1061		if (FD_ISSET(seqpacket_fd, &fds))
1062			new_client(seqpacket_fd, SOCK_SEQPACKET);
1063	}
1064	close(fd);
1065}
1066
1067/*
1068 * functions that the parser uses.
1069 */
1070void
1071add_attach(int prio, event_proc *p)
1072{
1073	cfg.add_attach(prio, p);
1074}
1075
1076void
1077add_detach(int prio, event_proc *p)
1078{
1079	cfg.add_detach(prio, p);
1080}
1081
1082void
1083add_directory(const char *dir)
1084{
1085	cfg.add_directory(dir);
1086	free(const_cast<char *>(dir));
1087}
1088
1089void
1090add_nomatch(int prio, event_proc *p)
1091{
1092	cfg.add_nomatch(prio, p);
1093}
1094
1095void
1096add_notify(int prio, event_proc *p)
1097{
1098	cfg.add_notify(prio, p);
1099}
1100
1101event_proc *
1102add_to_event_proc(event_proc *ep, eps *eps)
1103{
1104	if (ep == NULL)
1105		ep = new event_proc();
1106	ep->add(eps);
1107	return (ep);
1108}
1109
1110eps *
1111new_action(const char *cmd)
1112{
1113	eps *e = new action(cmd);
1114	free(const_cast<char *>(cmd));
1115	return (e);
1116}
1117
1118eps *
1119new_match(const char *var, const char *re)
1120{
1121	eps *e = new match(cfg, var, re);
1122	free(const_cast<char *>(var));
1123	free(const_cast<char *>(re));
1124	return (e);
1125}
1126
1127eps *
1128new_media(const char *var, const char *re)
1129{
1130	eps *e = new media(cfg, var, re);
1131	free(const_cast<char *>(var));
1132	free(const_cast<char *>(re));
1133	return (e);
1134}
1135
1136void
1137set_pidfile(const char *name)
1138{
1139	cfg.set_pidfile(name);
1140	free(const_cast<char *>(name));
1141}
1142
1143void
1144set_variable(const char *var, const char *val)
1145{
1146	cfg.set_variable(var, val);
1147	free(const_cast<char *>(var));
1148	free(const_cast<char *>(val));
1149}
1150
1151
1152
1153static void
1154gensighand(int)
1155{
1156	romeo_must_die = 1;
1157}
1158
1159/*
1160 * SIGINFO handler.  Will print useful statistics to the syslog or stderr
1161 * as appropriate
1162 */
1163static void
1164siginfohand(int)
1165{
1166	got_siginfo = 1;
1167}
1168
1169/*
1170 * Local logging function.  Prints to syslog if we're daemonized; syslog
1171 * otherwise.
1172 */
1173static void
1174devdlog(int priority, const char* fmt, ...)
1175{
1176	va_list argp;
1177
1178	va_start(argp, fmt);
1179	if (no_daemon)
1180		vfprintf(stderr, fmt, argp);
1181	else if ((! quiet_mode) || (priority <= LOG_WARNING))
1182		vsyslog(priority, fmt, argp);
1183	va_end(argp);
1184}
1185
1186static void
1187usage()
1188{
1189	fprintf(stderr, "usage: %s [-dnq] [-l connlimit] [-f file]\n",
1190	    getprogname());
1191	exit(1);
1192}
1193
1194static void
1195check_devd_enabled()
1196{
1197	int val = 0;
1198	size_t len;
1199
1200	len = sizeof(val);
1201	if (sysctlbyname(SYSCTL, &val, &len, NULL, 0) != 0)
1202		errx(1, "devctl sysctl missing from kernel!");
1203	if (val == 0) {
1204		warnx("Setting " SYSCTL " to 1000");
1205		val = 1000;
1206		sysctlbyname(SYSCTL, NULL, NULL, &val, sizeof(val));
1207	}
1208}
1209
1210/*
1211 * main
1212 */
1213int
1214main(int argc, char **argv)
1215{
1216	int ch;
1217
1218	check_devd_enabled();
1219	while ((ch = getopt(argc, argv, "df:l:nq")) != -1) {
1220		switch (ch) {
1221		case 'd':
1222			no_daemon = 1;
1223			break;
1224		case 'f':
1225			configfile = optarg;
1226			break;
1227		case 'l':
1228			max_clients = MAX(1, strtoul(optarg, NULL, 0));
1229			break;
1230		case 'n':
1231			daemonize_quick = 1;
1232			break;
1233		case 'q':
1234			quiet_mode = 1;
1235			break;
1236		default:
1237			usage();
1238		}
1239	}
1240
1241	cfg.parse();
1242	if (!no_daemon && daemonize_quick) {
1243		cfg.open_pidfile();
1244		daemon(0, 0);
1245		cfg.write_pidfile();
1246	}
1247	signal(SIGPIPE, SIG_IGN);
1248	signal(SIGHUP, gensighand);
1249	signal(SIGINT, gensighand);
1250	signal(SIGTERM, gensighand);
1251	signal(SIGINFO, siginfohand);
1252	event_loop();
1253	return (0);
1254}
1255