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