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