1 /*- 2 * Copyright (c) 2002-2010 M. Warner Losh. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * my_system is a variation on lib/libc/stdlib/system.c: 27 * 28 * Copyright (c) 1988, 1993 29 * The Regents of the University of California. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 4. Neither the name of the University nor the names of its contributors 40 * may be used to endorse or promote products derived from this software 41 * without specific prior written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 */ 55 56 /* 57 * DEVD control daemon. 58 */ 59 60 // TODO list: 61 // o devd.conf and devd man pages need a lot of help: 62 // - devd needs to document the unix domain socket 63 // - devd.conf needs more details on the supported statements. 64 65 #include <sys/cdefs.h> 66 __FBSDID("$FreeBSD$"); 67 68 #include <sys/param.h> 69 #include <sys/socket.h> 70 #include <sys/stat.h> 71 #include <sys/sysctl.h> 72 #include <sys/types.h> 73 #include <sys/wait.h> 74 #include <sys/un.h> 75 76 #include <cctype> 77 #include <cerrno> 78 #include <cstdlib> 79 #include <cstdio> 80 #include <csignal> 81 #include <cstring> 82 #include <cstdarg> 83 84 #include <dirent.h> 85 #include <err.h> 86 #include <fcntl.h> 87 #include <libutil.h> 88 #include <paths.h> 89 #include <poll.h> 90 #include <regex.h> 91 #include <syslog.h> 92 #include <unistd.h> 93 94 #include <algorithm> 95 #include <map> 96 #include <string> 97 #include <list> 98 #include <vector> 99 100 #include "devd.h" /* C compatible definitions */ 101 #include "devd.hh" /* C++ class definitions */ 102 103 #define PIPE "/var/run/devd.pipe" 104 #define CF "/etc/devd.conf" 105 #define SYSCTL "hw.bus.devctl_queue" 106 107 /* 108 * Since the client socket is nonblocking, we must increase its send buffer to 109 * handle brief event storms. On FreeBSD, AF_UNIX sockets don't have a receive 110 * buffer, so the client can't increate the buffersize by itself. 111 * 112 * For example, when creating a ZFS pool, devd emits one 165 character 113 * resource.fs.zfs.statechange message for each vdev in the pool. A 64k 114 * buffer has enough space for almost 400 drives, which would be very large but 115 * not impossibly large pool. A 128k buffer has enough space for 794 drives, 116 * which is more than can fit in a rack with modern technology. 117 */ 118 #define CLIENT_BUFSIZE 131072 119 120 using namespace std; 121 122 extern FILE *yyin; 123 extern int lineno; 124 125 static const char notify = '!'; 126 static const char nomatch = '?'; 127 static const char attach = '+'; 128 static const char detach = '-'; 129 130 static struct pidfh *pfh; 131 132 static int no_daemon = 0; 133 static int daemonize_quick = 0; 134 static int quiet_mode = 0; 135 static unsigned total_events = 0; 136 static volatile sig_atomic_t got_siginfo = 0; 137 static volatile sig_atomic_t romeo_must_die = 0; 138 139 static const char *configfile = CF; 140 141 static void devdlog(int priority, const char* message, ...) 142 __printflike(2, 3); 143 static void event_loop(void); 144 static void usage(void); 145 146 template <class T> void 147 delete_and_clear(vector<T *> &v) 148 { 149 typename vector<T *>::const_iterator i; 150 151 for (i = v.begin(); i != v.end(); ++i) 152 delete *i; 153 v.clear(); 154 } 155 156 config cfg; 157 158 event_proc::event_proc() : _prio(-1) 159 { 160 _epsvec.reserve(4); 161 } 162 163 event_proc::~event_proc() 164 { 165 delete_and_clear(_epsvec); 166 } 167 168 void 169 event_proc::add(eps *eps) 170 { 171 _epsvec.push_back(eps); 172 } 173 174 bool 175 event_proc::matches(config &c) const 176 { 177 vector<eps *>::const_iterator i; 178 179 for (i = _epsvec.begin(); i != _epsvec.end(); ++i) 180 if (!(*i)->do_match(c)) 181 return (false); 182 return (true); 183 } 184 185 bool 186 event_proc::run(config &c) const 187 { 188 vector<eps *>::const_iterator i; 189 190 for (i = _epsvec.begin(); i != _epsvec.end(); ++i) 191 if (!(*i)->do_action(c)) 192 return (false); 193 return (true); 194 } 195 196 action::action(const char *cmd) 197 : _cmd(cmd) 198 { 199 // nothing 200 } 201 202 action::~action() 203 { 204 // nothing 205 } 206 207 static int 208 my_system(const char *command) 209 { 210 pid_t pid, savedpid; 211 int pstat; 212 struct sigaction ign, intact, quitact; 213 sigset_t newsigblock, oldsigblock; 214 215 if (!command) /* just checking... */ 216 return (1); 217 218 /* 219 * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save 220 * existing signal dispositions. 221 */ 222 ign.sa_handler = SIG_IGN; 223 ::sigemptyset(&ign.sa_mask); 224 ign.sa_flags = 0; 225 ::sigaction(SIGINT, &ign, &intact); 226 ::sigaction(SIGQUIT, &ign, &quitact); 227 ::sigemptyset(&newsigblock); 228 ::sigaddset(&newsigblock, SIGCHLD); 229 ::sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); 230 switch (pid = ::fork()) { 231 case -1: /* error */ 232 break; 233 case 0: /* child */ 234 /* 235 * Restore original signal dispositions and exec the command. 236 */ 237 ::sigaction(SIGINT, &intact, NULL); 238 ::sigaction(SIGQUIT, &quitact, NULL); 239 ::sigprocmask(SIG_SETMASK, &oldsigblock, NULL); 240 /* 241 * Close the PID file, and all other open descriptors. 242 * Inherit std{in,out,err} only. 243 */ 244 cfg.close_pidfile(); 245 ::closefrom(3); 246 ::execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); 247 ::_exit(127); 248 default: /* parent */ 249 savedpid = pid; 250 do { 251 pid = ::wait4(savedpid, &pstat, 0, (struct rusage *)0); 252 } while (pid == -1 && errno == EINTR); 253 break; 254 } 255 ::sigaction(SIGINT, &intact, NULL); 256 ::sigaction(SIGQUIT, &quitact, NULL); 257 ::sigprocmask(SIG_SETMASK, &oldsigblock, NULL); 258 return (pid == -1 ? -1 : pstat); 259 } 260 261 bool 262 action::do_action(config &c) 263 { 264 string s = c.expand_string(_cmd.c_str()); 265 devdlog(LOG_INFO, "Executing '%s'\n", s.c_str()); 266 my_system(s.c_str()); 267 return (true); 268 } 269 270 match::match(config &c, const char *var, const char *re) : 271 _inv(re[0] == '!'), 272 _var(var), 273 _re(c.expand_string(_inv ? re + 1 : re, "^", "$")) 274 { 275 regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE); 276 } 277 278 match::~match() 279 { 280 regfree(&_regex); 281 } 282 283 bool 284 match::do_match(config &c) 285 { 286 const string &value = c.get_variable(_var); 287 bool retval; 288 289 /* 290 * This function gets called WAY too often to justify calling syslog() 291 * each time, even at LOG_DEBUG. Because if syslogd isn't running, it 292 * can consume excessive amounts of systime inside of connect(). Only 293 * log when we're in -d mode. 294 */ 295 if (no_daemon) { 296 devdlog(LOG_DEBUG, "Testing %s=%s against %s, invert=%d\n", 297 _var.c_str(), value.c_str(), _re.c_str(), _inv); 298 } 299 300 retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0); 301 if (_inv == 1) 302 retval = (retval == 0) ? 1 : 0; 303 304 return (retval); 305 } 306 307 #include <sys/sockio.h> 308 #include <net/if.h> 309 #include <net/if_media.h> 310 311 media::media(config &, const char *var, const char *type) 312 : _var(var), _type(-1) 313 { 314 static struct ifmedia_description media_types[] = { 315 { IFM_ETHER, "Ethernet" }, 316 { IFM_TOKEN, "Tokenring" }, 317 { IFM_FDDI, "FDDI" }, 318 { IFM_IEEE80211, "802.11" }, 319 { IFM_ATM, "ATM" }, 320 { -1, "unknown" }, 321 { 0, NULL }, 322 }; 323 for (int i = 0; media_types[i].ifmt_string != NULL; ++i) 324 if (strcasecmp(type, media_types[i].ifmt_string) == 0) { 325 _type = media_types[i].ifmt_word; 326 break; 327 } 328 } 329 330 media::~media() 331 { 332 } 333 334 bool 335 media::do_match(config &c) 336 { 337 string value; 338 struct ifmediareq ifmr; 339 bool retval; 340 int s; 341 342 // Since we can be called from both a device attach/detach 343 // context where device-name is defined and what we want, 344 // as well as from a link status context, where subsystem is 345 // the name of interest, first try device-name and fall back 346 // to subsystem if none exists. 347 value = c.get_variable("device-name"); 348 if (value.empty()) 349 value = c.get_variable("subsystem"); 350 devdlog(LOG_DEBUG, "Testing media type of %s against 0x%x\n", 351 value.c_str(), _type); 352 353 retval = false; 354 355 s = socket(PF_INET, SOCK_DGRAM, 0); 356 if (s >= 0) { 357 memset(&ifmr, 0, sizeof(ifmr)); 358 strncpy(ifmr.ifm_name, value.c_str(), sizeof(ifmr.ifm_name)); 359 360 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 && 361 ifmr.ifm_status & IFM_AVALID) { 362 devdlog(LOG_DEBUG, "%s has media type 0x%x\n", 363 value.c_str(), IFM_TYPE(ifmr.ifm_active)); 364 retval = (IFM_TYPE(ifmr.ifm_active) == _type); 365 } else if (_type == -1) { 366 devdlog(LOG_DEBUG, "%s has unknown media type\n", 367 value.c_str()); 368 retval = true; 369 } 370 close(s); 371 } 372 373 return (retval); 374 } 375 376 const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_"; 377 const string var_list::nothing = ""; 378 379 const string & 380 var_list::get_variable(const string &var) const 381 { 382 map<string, string>::const_iterator i; 383 384 i = _vars.find(var); 385 if (i == _vars.end()) 386 return (var_list::bogus); 387 return (i->second); 388 } 389 390 bool 391 var_list::is_set(const string &var) const 392 { 393 return (_vars.find(var) != _vars.end()); 394 } 395 396 void 397 var_list::set_variable(const string &var, const string &val) 398 { 399 /* 400 * This function gets called WAY too often to justify calling syslog() 401 * each time, even at LOG_DEBUG. Because if syslogd isn't running, it 402 * can consume excessive amounts of systime inside of connect(). Only 403 * log when we're in -d mode. 404 */ 405 if (no_daemon) 406 devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str()); 407 _vars[var] = val; 408 } 409 410 void 411 config::reset(void) 412 { 413 _dir_list.clear(); 414 delete_and_clear(_var_list_table); 415 delete_and_clear(_attach_list); 416 delete_and_clear(_detach_list); 417 delete_and_clear(_nomatch_list); 418 delete_and_clear(_notify_list); 419 } 420 421 void 422 config::parse_one_file(const char *fn) 423 { 424 devdlog(LOG_DEBUG, "Parsing %s\n", fn); 425 yyin = fopen(fn, "r"); 426 if (yyin == NULL) 427 err(1, "Cannot open config file %s", fn); 428 lineno = 1; 429 if (yyparse() != 0) 430 errx(1, "Cannot parse %s at line %d", fn, lineno); 431 fclose(yyin); 432 } 433 434 void 435 config::parse_files_in_dir(const char *dirname) 436 { 437 DIR *dirp; 438 struct dirent *dp; 439 char path[PATH_MAX]; 440 441 devdlog(LOG_DEBUG, "Parsing files in %s\n", dirname); 442 dirp = opendir(dirname); 443 if (dirp == NULL) 444 return; 445 readdir(dirp); /* Skip . */ 446 readdir(dirp); /* Skip .. */ 447 while ((dp = readdir(dirp)) != NULL) { 448 if (strcmp(dp->d_name + dp->d_namlen - 5, ".conf") == 0) { 449 snprintf(path, sizeof(path), "%s/%s", 450 dirname, dp->d_name); 451 parse_one_file(path); 452 } 453 } 454 closedir(dirp); 455 } 456 457 class epv_greater { 458 public: 459 int operator()(event_proc *const&l1, event_proc *const&l2) const 460 { 461 return (l1->get_priority() > l2->get_priority()); 462 } 463 }; 464 465 void 466 config::sort_vector(vector<event_proc *> &v) 467 { 468 stable_sort(v.begin(), v.end(), epv_greater()); 469 } 470 471 void 472 config::parse(void) 473 { 474 vector<string>::const_iterator i; 475 476 parse_one_file(configfile); 477 for (i = _dir_list.begin(); i != _dir_list.end(); ++i) 478 parse_files_in_dir((*i).c_str()); 479 sort_vector(_attach_list); 480 sort_vector(_detach_list); 481 sort_vector(_nomatch_list); 482 sort_vector(_notify_list); 483 } 484 485 void 486 config::open_pidfile() 487 { 488 pid_t otherpid; 489 490 if (_pidfile.empty()) 491 return; 492 pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid); 493 if (pfh == NULL) { 494 if (errno == EEXIST) 495 errx(1, "devd already running, pid: %d", (int)otherpid); 496 warn("cannot open pid file"); 497 } 498 } 499 500 void 501 config::write_pidfile() 502 { 503 504 pidfile_write(pfh); 505 } 506 507 void 508 config::close_pidfile() 509 { 510 511 pidfile_close(pfh); 512 } 513 514 void 515 config::remove_pidfile() 516 { 517 518 pidfile_remove(pfh); 519 } 520 521 void 522 config::add_attach(int prio, event_proc *p) 523 { 524 p->set_priority(prio); 525 _attach_list.push_back(p); 526 } 527 528 void 529 config::add_detach(int prio, event_proc *p) 530 { 531 p->set_priority(prio); 532 _detach_list.push_back(p); 533 } 534 535 void 536 config::add_directory(const char *dir) 537 { 538 _dir_list.push_back(string(dir)); 539 } 540 541 void 542 config::add_nomatch(int prio, event_proc *p) 543 { 544 p->set_priority(prio); 545 _nomatch_list.push_back(p); 546 } 547 548 void 549 config::add_notify(int prio, event_proc *p) 550 { 551 p->set_priority(prio); 552 _notify_list.push_back(p); 553 } 554 555 void 556 config::set_pidfile(const char *fn) 557 { 558 _pidfile = fn; 559 } 560 561 void 562 config::push_var_table() 563 { 564 var_list *vl; 565 566 vl = new var_list(); 567 _var_list_table.push_back(vl); 568 devdlog(LOG_DEBUG, "Pushing table\n"); 569 } 570 571 void 572 config::pop_var_table() 573 { 574 delete _var_list_table.back(); 575 _var_list_table.pop_back(); 576 devdlog(LOG_DEBUG, "Popping table\n"); 577 } 578 579 void 580 config::set_variable(const char *var, const char *val) 581 { 582 _var_list_table.back()->set_variable(var, val); 583 } 584 585 const string & 586 config::get_variable(const string &var) 587 { 588 vector<var_list *>::reverse_iterator i; 589 590 for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); ++i) { 591 if ((*i)->is_set(var)) 592 return ((*i)->get_variable(var)); 593 } 594 return (var_list::nothing); 595 } 596 597 bool 598 config::is_id_char(char ch) const 599 { 600 return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || 601 ch == '-')); 602 } 603 604 void 605 config::expand_one(const char *&src, string &dst) 606 { 607 int count; 608 string buffer; 609 610 src++; 611 // $$ -> $ 612 if (*src == '$') { 613 dst += *src++; 614 return; 615 } 616 617 // $(foo) -> $(foo) 618 // Not sure if I want to support this or not, so for now we just pass 619 // it through. 620 if (*src == '(') { 621 dst += '$'; 622 count = 1; 623 /* If the string ends before ) is matched , return. */ 624 while (count > 0 && *src) { 625 if (*src == ')') 626 count--; 627 else if (*src == '(') 628 count++; 629 dst += *src++; 630 } 631 return; 632 } 633 634 // $[^A-Za-z] -> $\1 635 if (!isalpha(*src)) { 636 dst += '$'; 637 dst += *src++; 638 return; 639 } 640 641 // $var -> replace with value 642 do { 643 buffer += *src++; 644 } while (is_id_char(*src)); 645 dst.append(get_variable(buffer)); 646 } 647 648 const string 649 config::expand_string(const char *src, const char *prepend, const char *append) 650 { 651 const char *var_at; 652 string dst; 653 654 /* 655 * 128 bytes is enough for 2427 of 2438 expansions that happen 656 * while parsing config files, as tested on 2013-01-30. 657 */ 658 dst.reserve(128); 659 660 if (prepend != NULL) 661 dst = prepend; 662 663 for (;;) { 664 var_at = strchr(src, '$'); 665 if (var_at == NULL) { 666 dst.append(src); 667 break; 668 } 669 dst.append(src, var_at - src); 670 src = var_at; 671 expand_one(src, dst); 672 } 673 674 if (append != NULL) 675 dst.append(append); 676 677 return (dst); 678 } 679 680 bool 681 config::chop_var(char *&buffer, char *&lhs, char *&rhs) const 682 { 683 char *walker; 684 685 if (*buffer == '\0') 686 return (false); 687 walker = lhs = buffer; 688 while (is_id_char(*walker)) 689 walker++; 690 if (*walker != '=') 691 return (false); 692 walker++; // skip = 693 if (*walker == '"') { 694 walker++; // skip " 695 rhs = walker; 696 while (*walker && *walker != '"') 697 walker++; 698 if (*walker != '"') 699 return (false); 700 rhs[-2] = '\0'; 701 *walker++ = '\0'; 702 } else { 703 rhs = walker; 704 while (*walker && !isspace(*walker)) 705 walker++; 706 if (*walker != '\0') 707 *walker++ = '\0'; 708 rhs[-1] = '\0'; 709 } 710 while (isspace(*walker)) 711 walker++; 712 buffer = walker; 713 return (true); 714 } 715 716 717 char * 718 config::set_vars(char *buffer) 719 { 720 char *lhs; 721 char *rhs; 722 723 while (1) { 724 if (!chop_var(buffer, lhs, rhs)) 725 break; 726 set_variable(lhs, rhs); 727 } 728 return (buffer); 729 } 730 731 void 732 config::find_and_execute(char type) 733 { 734 vector<event_proc *> *l; 735 vector<event_proc *>::const_iterator i; 736 const char *s; 737 738 switch (type) { 739 default: 740 return; 741 case notify: 742 l = &_notify_list; 743 s = "notify"; 744 break; 745 case nomatch: 746 l = &_nomatch_list; 747 s = "nomatch"; 748 break; 749 case attach: 750 l = &_attach_list; 751 s = "attach"; 752 break; 753 case detach: 754 l = &_detach_list; 755 s = "detach"; 756 break; 757 } 758 devdlog(LOG_DEBUG, "Processing %s event\n", s); 759 for (i = l->begin(); i != l->end(); ++i) { 760 if ((*i)->matches(*this)) { 761 (*i)->run(*this); 762 break; 763 } 764 } 765 766 } 767 768 769 static void 770 process_event(char *buffer) 771 { 772 char type; 773 char *sp; 774 775 sp = buffer + 1; 776 devdlog(LOG_INFO, "Processing event '%s'\n", buffer); 777 type = *buffer++; 778 cfg.push_var_table(); 779 // No match doesn't have a device, and the format is a little 780 // different, so handle it separately. 781 switch (type) { 782 case notify: 783 sp = cfg.set_vars(sp); 784 break; 785 case nomatch: 786 //? at location pnp-info on bus 787 sp = strchr(sp, ' '); 788 if (sp == NULL) 789 return; /* Can't happen? */ 790 *sp++ = '\0'; 791 while (isspace(*sp)) 792 sp++; 793 if (strncmp(sp, "at ", 3) == 0) 794 sp += 3; 795 sp = cfg.set_vars(sp); 796 while (isspace(*sp)) 797 sp++; 798 if (strncmp(sp, "on ", 3) == 0) 799 cfg.set_variable("bus", sp + 3); 800 break; 801 case attach: /*FALLTHROUGH*/ 802 case detach: 803 sp = strchr(sp, ' '); 804 if (sp == NULL) 805 return; /* Can't happen? */ 806 *sp++ = '\0'; 807 cfg.set_variable("device-name", buffer); 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 } 819 820 cfg.find_and_execute(type); 821 cfg.pop_var_table(); 822 } 823 824 int 825 create_socket(const char *name) 826 { 827 int fd, slen; 828 struct sockaddr_un sun; 829 830 if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) 831 err(1, "socket"); 832 bzero(&sun, sizeof(sun)); 833 sun.sun_family = AF_UNIX; 834 strlcpy(sun.sun_path, name, sizeof(sun.sun_path)); 835 slen = SUN_LEN(&sun); 836 unlink(name); 837 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) 838 err(1, "fcntl"); 839 if (::bind(fd, (struct sockaddr *) & sun, slen) < 0) 840 err(1, "bind"); 841 listen(fd, 4); 842 chown(name, 0, 0); /* XXX - root.wheel */ 843 chmod(name, 0666); 844 return (fd); 845 } 846 847 unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */ 848 unsigned int num_clients; 849 list<int> clients; 850 851 void 852 notify_clients(const char *data, int len) 853 { 854 list<int>::iterator i; 855 856 /* 857 * Deliver the data to all clients. Throw clients overboard at the 858 * first sign of trouble. This reaps clients who've died or closed 859 * their sockets, and also clients who are alive but failing to keep up 860 * (or who are maliciously not reading, to consume buffer space in 861 * kernel memory or tie up the limited number of available connections). 862 */ 863 for (i = clients.begin(); i != clients.end(); ) { 864 if (write(*i, data, len) != len) { 865 --num_clients; 866 close(*i); 867 i = clients.erase(i); 868 devdlog(LOG_WARNING, "notify_clients: write() failed; " 869 "dropping unresponsive client\n"); 870 } else 871 ++i; 872 } 873 } 874 875 void 876 check_clients(void) 877 { 878 int s; 879 struct pollfd pfd; 880 list<int>::iterator i; 881 882 /* 883 * Check all existing clients to see if any of them have disappeared. 884 * Normally we reap clients when we get an error trying to send them an 885 * event. This check eliminates the problem of an ever-growing list of 886 * zombie clients because we're never writing to them on a system 887 * without frequent device-change activity. 888 */ 889 pfd.events = 0; 890 for (i = clients.begin(); i != clients.end(); ) { 891 pfd.fd = *i; 892 s = poll(&pfd, 1, 0); 893 if ((s < 0 && s != EINTR ) || 894 (s > 0 && (pfd.revents & POLLHUP))) { 895 --num_clients; 896 close(*i); 897 i = clients.erase(i); 898 devdlog(LOG_NOTICE, "check_clients: " 899 "dropping disconnected client\n"); 900 } else 901 ++i; 902 } 903 } 904 905 void 906 new_client(int fd) 907 { 908 int s; 909 int sndbuf_size; 910 911 /* 912 * First go reap any zombie clients, then accept the connection, and 913 * shut down the read side to stop clients from consuming kernel memory 914 * by sending large buffers full of data we'll never read. 915 */ 916 check_clients(); 917 s = accept(fd, NULL, NULL); 918 if (s != -1) { 919 sndbuf_size = CLIENT_BUFSIZE; 920 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, 921 sizeof(sndbuf_size))) 922 err(1, "setsockopt"); 923 shutdown(s, SHUT_RD); 924 clients.push_back(s); 925 ++num_clients; 926 } else 927 err(1, "accept"); 928 } 929 930 static void 931 event_loop(void) 932 { 933 int rv; 934 int fd; 935 char buffer[DEVCTL_MAXBUF]; 936 int once = 0; 937 int server_fd, max_fd; 938 int accepting; 939 timeval tv; 940 fd_set fds; 941 942 fd = open(PATH_DEVCTL, O_RDONLY | O_CLOEXEC); 943 if (fd == -1) 944 err(1, "Can't open devctl device %s", PATH_DEVCTL); 945 server_fd = create_socket(PIPE); 946 accepting = 1; 947 max_fd = max(fd, server_fd) + 1; 948 while (!romeo_must_die) { 949 if (!once && !no_daemon && !daemonize_quick) { 950 // Check to see if we have any events pending. 951 tv.tv_sec = 0; 952 tv.tv_usec = 0; 953 FD_ZERO(&fds); 954 FD_SET(fd, &fds); 955 rv = select(fd + 1, &fds, &fds, &fds, &tv); 956 // No events -> we've processed all pending events 957 if (rv == 0) { 958 devdlog(LOG_DEBUG, "Calling daemon\n"); 959 cfg.remove_pidfile(); 960 cfg.open_pidfile(); 961 daemon(0, 0); 962 cfg.write_pidfile(); 963 once++; 964 } 965 } 966 /* 967 * When we've already got the max number of clients, stop 968 * accepting new connections (don't put server_fd in the set), 969 * shrink the accept() queue to reject connections quickly, and 970 * poll the existing clients more often, so that we notice more 971 * quickly when any of them disappear to free up client slots. 972 */ 973 FD_ZERO(&fds); 974 FD_SET(fd, &fds); 975 if (num_clients < max_clients) { 976 if (!accepting) { 977 listen(server_fd, max_clients); 978 accepting = 1; 979 } 980 FD_SET(server_fd, &fds); 981 tv.tv_sec = 60; 982 tv.tv_usec = 0; 983 } else { 984 if (accepting) { 985 listen(server_fd, 0); 986 accepting = 0; 987 } 988 tv.tv_sec = 2; 989 tv.tv_usec = 0; 990 } 991 rv = select(max_fd, &fds, NULL, NULL, &tv); 992 if (got_siginfo) { 993 devdlog(LOG_NOTICE, "Events received so far=%u\n", 994 total_events); 995 got_siginfo = 0; 996 } 997 if (rv == -1) { 998 if (errno == EINTR) 999 continue; 1000 err(1, "select"); 1001 } else if (rv == 0) 1002 check_clients(); 1003 if (FD_ISSET(fd, &fds)) { 1004 rv = read(fd, buffer, sizeof(buffer) - 1); 1005 if (rv > 0) { 1006 total_events++; 1007 if (rv == sizeof(buffer) - 1) { 1008 devdlog(LOG_WARNING, "Warning: " 1009 "available event data exceeded " 1010 "buffer space\n"); 1011 } 1012 notify_clients(buffer, rv); 1013 buffer[rv] = '\0'; 1014 while (buffer[--rv] == '\n') 1015 buffer[rv] = '\0'; 1016 process_event(buffer); 1017 } else if (rv < 0) { 1018 if (errno != EINTR) 1019 break; 1020 } else { 1021 /* EOF */ 1022 break; 1023 } 1024 } 1025 if (FD_ISSET(server_fd, &fds)) 1026 new_client(server_fd); 1027 } 1028 close(fd); 1029 } 1030 1031 /* 1032 * functions that the parser uses. 1033 */ 1034 void 1035 add_attach(int prio, event_proc *p) 1036 { 1037 cfg.add_attach(prio, p); 1038 } 1039 1040 void 1041 add_detach(int prio, event_proc *p) 1042 { 1043 cfg.add_detach(prio, p); 1044 } 1045 1046 void 1047 add_directory(const char *dir) 1048 { 1049 cfg.add_directory(dir); 1050 free(const_cast<char *>(dir)); 1051 } 1052 1053 void 1054 add_nomatch(int prio, event_proc *p) 1055 { 1056 cfg.add_nomatch(prio, p); 1057 } 1058 1059 void 1060 add_notify(int prio, event_proc *p) 1061 { 1062 cfg.add_notify(prio, p); 1063 } 1064 1065 event_proc * 1066 add_to_event_proc(event_proc *ep, eps *eps) 1067 { 1068 if (ep == NULL) 1069 ep = new event_proc(); 1070 ep->add(eps); 1071 return (ep); 1072 } 1073 1074 eps * 1075 new_action(const char *cmd) 1076 { 1077 eps *e = new action(cmd); 1078 free(const_cast<char *>(cmd)); 1079 return (e); 1080 } 1081 1082 eps * 1083 new_match(const char *var, const char *re) 1084 { 1085 eps *e = new match(cfg, var, re); 1086 free(const_cast<char *>(var)); 1087 free(const_cast<char *>(re)); 1088 return (e); 1089 } 1090 1091 eps * 1092 new_media(const char *var, const char *re) 1093 { 1094 eps *e = new media(cfg, var, re); 1095 free(const_cast<char *>(var)); 1096 free(const_cast<char *>(re)); 1097 return (e); 1098 } 1099 1100 void 1101 set_pidfile(const char *name) 1102 { 1103 cfg.set_pidfile(name); 1104 free(const_cast<char *>(name)); 1105 } 1106 1107 void 1108 set_variable(const char *var, const char *val) 1109 { 1110 cfg.set_variable(var, val); 1111 free(const_cast<char *>(var)); 1112 free(const_cast<char *>(val)); 1113 } 1114 1115 1116 1117 static void 1118 gensighand(int) 1119 { 1120 romeo_must_die = 1; 1121 } 1122 1123 /* 1124 * SIGINFO handler. Will print useful statistics to the syslog or stderr 1125 * as appropriate 1126 */ 1127 static void 1128 siginfohand(int) 1129 { 1130 got_siginfo = 1; 1131 } 1132 1133 /* 1134 * Local logging function. Prints to syslog if we're daemonized; stderr 1135 * otherwise. 1136 */ 1137 static void 1138 devdlog(int priority, const char* fmt, ...) 1139 { 1140 va_list argp; 1141 1142 va_start(argp, fmt); 1143 if (no_daemon) 1144 vfprintf(stderr, fmt, argp); 1145 else if ((! quiet_mode) || (priority <= LOG_WARNING)) 1146 vsyslog(priority, fmt, argp); 1147 va_end(argp); 1148 } 1149 1150 static void 1151 usage() 1152 { 1153 fprintf(stderr, "usage: %s [-dnq] [-l connlimit] [-f file]\n", 1154 getprogname()); 1155 exit(1); 1156 } 1157 1158 static void 1159 check_devd_enabled() 1160 { 1161 int val = 0; 1162 size_t len; 1163 1164 len = sizeof(val); 1165 if (sysctlbyname(SYSCTL, &val, &len, NULL, 0) != 0) 1166 errx(1, "devctl sysctl missing from kernel!"); 1167 if (val == 0) { 1168 warnx("Setting " SYSCTL " to 1000"); 1169 val = 1000; 1170 sysctlbyname(SYSCTL, NULL, NULL, &val, sizeof(val)); 1171 } 1172 } 1173 1174 /* 1175 * main 1176 */ 1177 int 1178 main(int argc, char **argv) 1179 { 1180 int ch; 1181 1182 check_devd_enabled(); 1183 while ((ch = getopt(argc, argv, "df:l:nq")) != -1) { 1184 switch (ch) { 1185 case 'd': 1186 no_daemon = 1; 1187 break; 1188 case 'f': 1189 configfile = optarg; 1190 break; 1191 case 'l': 1192 max_clients = MAX(1, strtoul(optarg, NULL, 0)); 1193 break; 1194 case 'n': 1195 daemonize_quick = 1; 1196 break; 1197 case 'q': 1198 quiet_mode = 1; 1199 break; 1200 default: 1201 usage(); 1202 } 1203 } 1204 1205 cfg.parse(); 1206 if (!no_daemon && daemonize_quick) { 1207 cfg.open_pidfile(); 1208 daemon(0, 0); 1209 cfg.write_pidfile(); 1210 } 1211 signal(SIGPIPE, SIG_IGN); 1212 signal(SIGHUP, gensighand); 1213 signal(SIGINT, gensighand); 1214 signal(SIGTERM, gensighand); 1215 signal(SIGINFO, siginfohand); 1216 event_loop(); 1217 return (0); 1218 } 1219