static int run_script(const char *action) { char *env_PREVIOUS, *env_CURRENT; char *argv[5]; int r; bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); argv[0] = (char*) G.script_name; argv[1] = (char*) G.iface; argv[2] = (char*) action; argv[3] = (char*) G.extra_arg; argv[4] = NULL; env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status)); putenv(env_PREVIOUS); env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_CURRENT, strstatus(G.iface_last_status)); putenv(env_CURRENT); /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ r = spawn_and_wait(argv); unsetenv(IFPLUGD_ENV_PREVIOUS); unsetenv(IFPLUGD_ENV_CURRENT); free(env_PREVIOUS); free(env_CURRENT); bb_error_msg("exit code: %d", r & 0xff); return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; }
cryptkeyres * key_decrypt_1_svc_prog(uid_t uid, cryptkeyarg *arg) { static cryptkeyres res; if (debugging) { fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid, arg->remotename, arg->deskey.key.high, arg->deskey.key.low); } res.cryptkeyres_u.deskey = arg->deskey; res.status = pk_decrypt(uid, arg->remotename, NULL, &res.cryptkeyres_u.deskey); if (debugging) { if (res.status == KEY_SUCCESS) { fprintf(stderr, "%08x%08x\n", res.cryptkeyres_u.deskey.key.high, res.cryptkeyres_u.deskey.key.low); } else { fprintf(stderr, "%s\n", strstatus(res.status)); } fflush(stderr); } return (&res); }
getcredres * key_getcred_1_svc_prog(uid_t uid, netnamestr *name) { static getcredres res; static u_int gids[NGROUPS]; struct unixcred *cred; cred = &res.getcredres_u.cred; cred->gids.gids_val = gids; if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid, (int *)&cred->gids.gids_len, (gid_t *)gids)) { res.status = KEY_UNKNOWN; } else { res.status = KEY_SUCCESS; } if (debugging) { fprintf(stderr, "getcred(%s) = ", *name); if (res.status == KEY_SUCCESS) { fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n", cred->uid, cred->gid, cred->gids.gids_len); } else { fprintf(stderr, "%s\n", strstatus(res.status)); } fflush(stderr); } return (&res); }
static List *backq(Node *ifs, Node *n) { int p[2], sp; pid_t pid; List *bq; struct termios t; if (n == NULL) return NULL; if (pipe(p) < 0) { uerror("pipe"); rc_error(NULL); } if (interactive) tcgetattr(0, &t); if ((pid = rc_fork()) == 0) { mvfd(p[1], 1); close(p[0]); redirq = NULL; walk(n, FALSE); exit(getstatus()); } close(p[1]); bq = bqinput(glom(ifs), p[0]); close(p[0]); rc_wait4(pid, &sp, TRUE); if (interactive && WIFSIGNALED(sp)) tcsetattr(0, TCSANOW, &t); statprint(-1, sp); varassign("bqstatus", word(strstatus(sp), NULL), FALSE); sigchk(); return bq; }
interface_status_t detect_beat(int fd, char*iface) { interface_status_t status; static interface_status_t last_status = (interface_status_t) -1; if (disabled) return IFSTATUS_DOWN; if ((status = detect_beat_func(fd, iface)) == IFSTATUS_ERR) status = failure_status; if (status == IFSTATUS_ERR && detect_beat_func == detect_beat_auto) daemon_log(LOG_INFO, "Failed to detect plug status of %s", interface); if (status != last_status) { setenv(IFPLUGD_ENV_PREVIOUS, strstatus(last_status), 1); setenv(IFPLUGD_ENV_CURRENT, strstatus(status), 1); last_status = status; } return status; }
extern List *sgetstatus() { List *r = NULL; int i; for (i = 0; i < pipelength; i++) { List *q = nnew(List); q->w = strstatus(statuses[i]); q->m = NULL; q->n = r; r = q; } return r; }
static smallint detect_link(void) { smallint status; if (!G.iface_exists) return (option_mask32 & FLAG_MONITOR) ? IFSTATUS_DOWN : IFSTATUS_ERR; /* Some drivers can't detect link status when the interface is down. * I imagine detect_link_iff() is the most vulnerable. * That's why -a "noauto" in an option, not a hardwired behavior. */ if (!(option_mask32 & FLAG_NO_AUTO)) up_iface(); status = G.detect_link_func(); if (status == IFSTATUS_ERR) { if (option_mask32 & FLAG_IGNORE_FAIL) status = IFSTATUS_DOWN; if (option_mask32 & FLAG_IGNORE_FAIL_POSITIVE) status = IFSTATUS_UP; } if (status == IFSTATUS_ERR && G.detect_link_func == detect_link_auto ) { bb_error_msg("failed to detect link status"); } if (status != G.iface_last_status) { //TODO: is it safe to repeatedly do this? setenv(IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status), 1); setenv(IFPLUGD_ENV_CURRENT, strstatus(status), 1); G.iface_last_status = status; } return status; }
keystatus * key_set_1_svc_prog(uid_t uid, keybuf key) { static keystatus status; if (debugging) { fprintf(stderr, "set(%ld, %.*s) = ", uid, (int) sizeof (keybuf), key); } status = pk_setkey(uid, key); if (debugging) { fprintf(stderr, "%s\n", strstatus(status)); fflush(stderr); } return (&status); }
keystatus * key_net_put_2_svc_prog(uid_t uid, key_netstarg *arg) { static keystatus status; if (debugging) { fprintf(stderr, "net_put(%s, %.*s, %.*s) = ", arg->st_netname, (int)sizeof (arg->st_pub_key), arg->st_pub_key, (int)sizeof (arg->st_priv_key), arg->st_priv_key); }; status = pk_netput(uid, arg); if (debugging) { fprintf(stderr, "%s\n", strstatus(status)); fflush(stderr); } return (&status); }
async_write_response_op(Stream & stream, int status, const response_opts & _opts, Handler handler) : m_stream(stream), m_handler(handler) { response_opts opts = _opts; m_headers = boost::make_shared<boost::asio::streambuf>(); std::ostream out(m_headers.get()); if (opts.find(avhttpd::http_options::http_version)=="HTTP/1.1") out << "HTTP/1.1 "; else out << "HTTP "; opts.remove(avhttpd::http_options::http_version); out << status << " " << strstatus(status) << "\r\n"; if (opts.size()) out << opts.header_string(); out << "\r\n"; boost::asio::async_write(m_stream, *m_headers, *this); };
cryptkeyres * key_get_conv_2_svc_prog(uid_t uid, keybuf arg) { static cryptkeyres res; if (debugging) fprintf(stderr, "get_conv(%ld, %.*s) = ", uid, (int)sizeof (arg), arg); res.status = pk_get_conv_key(uid, arg, &res); if (debugging) { if (res.status == KEY_SUCCESS) { fprintf(stderr, "%08x%08x\n", res.cryptkeyres_u.deskey.key.high, res.cryptkeyres_u.deskey.key.low); } else { fprintf(stderr, "%s\n", strstatus(res.status)); } fflush(stderr); } return (&res); }
int ifplugd_main(int argc UNUSED_PARAM, char **argv) { int iface_status; int delay_time; const char *iface_status_str; struct pollfd netlink_pollfd[1]; unsigned opts; const char *api_mode_found; #if ENABLE_FEATURE_PIDFILE char *pidfile_name; pid_t pid_from_pidfile; #endif INIT_G(); opt_complementary = "t+:u+:d+"; opts = getopt32(argv, OPTION_STR, &G.iface, &G.script_name, &G.poll_time, &G.delay_up, &G.delay_down, &G.api_mode, &G.extra_arg); G.poll_time *= 1000; applet_name = xasprintf("ifplugd(%s)", G.iface); #if ENABLE_FEATURE_PIDFILE pidfile_name = xasprintf(CONFIG_PID_FILE_PATH "/ifplugd.%s.pid", G.iface); pid_from_pidfile = read_pid(pidfile_name); if (opts & FLAG_KILL) { if (pid_from_pidfile > 0) /* Upstream tool use SIGINT for -k */ kill(pid_from_pidfile, SIGINT); return EXIT_SUCCESS; } if (pid_from_pidfile > 0 && kill(pid_from_pidfile, 0) == 0) bb_error_msg_and_die("daemon already running"); #endif api_mode_found = strchr(api_modes, G.api_mode[0]); if (!api_mode_found) bb_error_msg_and_die("unknown API mode '%s'", G.api_mode); G.api_method_num = api_mode_found - api_modes; if (!(opts & FLAG_NO_DAEMON)) bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd); if (opts & FLAG_MONITOR) { struct sockaddr_nl addr; int fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_LINK; addr.nl_pid = getpid(); xbind(fd, (struct sockaddr*)&addr, sizeof(addr)); xmove_fd(fd, netlink_fd); } write_pidfile(pidfile_name); /* this can't be moved before socket creation */ if (!(opts & FLAG_NO_SYSLOG)) { openlog(applet_name, 0, LOG_DAEMON); logmode |= LOGMODE_SYSLOG; } bb_signals(0 | (1 << SIGINT ) | (1 << SIGTERM) | (1 << SIGQUIT) | (1 << SIGHUP ) /* why we ignore it? */ /* | (1 << SIGCHLD) - run_script does not use it anymore */ , record_signo); bb_error_msg("started: %s", bb_banner); if (opts & FLAG_MONITOR) { struct ifreq ifrequest; set_ifreq_to_ifname(&ifrequest); G.iface_exists = (network_ioctl(SIOCGIFINDEX, &ifrequest, NULL) == 0); } if (G.iface_exists) maybe_up_new_iface(); iface_status = detect_link(); if (iface_status == IFSTATUS_ERR) goto exiting; iface_status_str = strstatus(iface_status); if (opts & FLAG_MONITOR) { bb_error_msg("interface %s", G.iface_exists ? "exists" : "doesn't exist, waiting"); } /* else we assume it always exists, but don't mislead user * by potentially lying that it really exists */ if (G.iface_exists) { bb_error_msg("link is %s", iface_status_str); } if ((!(opts & FLAG_NO_STARTUP) && iface_status == IFSTATUS_UP ) || (opts & FLAG_INITIAL_DOWN) ) { if (run_script(iface_status_str) != 0) goto exiting; } /* Main loop */ netlink_pollfd[0].fd = netlink_fd; netlink_pollfd[0].events = POLLIN; delay_time = 0; while (1) { int iface_status_old; int iface_exists_old; switch (bb_got_signal) { case SIGINT: case SIGTERM: bb_got_signal = 0; goto cleanup; case SIGQUIT: bb_got_signal = 0; goto exiting; default: bb_got_signal = 0; break; } if (poll(netlink_pollfd, (opts & FLAG_MONITOR) ? 1 : 0, G.poll_time ) < 0 ) { if (errno == EINTR) continue; bb_perror_msg("poll"); goto exiting; } iface_status_old = iface_status; iface_exists_old = G.iface_exists; if ((opts & FLAG_MONITOR) && (netlink_pollfd[0].revents & POLLIN) ) { G.iface_exists = check_existence_through_netlink(); if (G.iface_exists < 0) /* error */ goto exiting; if (iface_exists_old != G.iface_exists) { bb_error_msg("interface %sappeared", G.iface_exists ? "" : "dis"); if (G.iface_exists) maybe_up_new_iface(); } } /* note: if !G.iface_exists, returns DOWN */ iface_status = detect_link(); if (iface_status == IFSTATUS_ERR) { if (!(opts & FLAG_MONITOR)) goto exiting; iface_status = IFSTATUS_DOWN; } iface_status_str = strstatus(iface_status); if (iface_status_old != iface_status) { bb_error_msg("link is %s", iface_status_str); if (delay_time) { /* link restored its old status before * we run script. don't run the script: */ delay_time = 0; } else { delay_time = monotonic_sec(); if (iface_status == IFSTATUS_UP) delay_time += G.delay_up; if (iface_status == IFSTATUS_DOWN) delay_time += G.delay_down; if (delay_time == 0) delay_time++; } } if (delay_time && (int)(monotonic_sec() - delay_time) >= 0) { delay_time = 0; if (run_script(iface_status_str) != 0) goto exiting; } } /* while (1) */ cleanup: if (!(opts & FLAG_NO_SHUTDOWN) && (iface_status == IFSTATUS_UP || (iface_status == IFSTATUS_DOWN && delay_time) ) ) { setenv(IFPLUGD_ENV_PREVIOUS, strstatus(iface_status), 1); setenv(IFPLUGD_ENV_CURRENT, strstatus(-1), 1); run_script("down\0up"); /* reusing string */ } exiting: remove_pidfile(pidfile_name); bb_error_msg_and_die("exiting"); }
static int pstatus(char *arg) { struct ioc_vol v; struct ioc_read_subchannel ss; struct cd_sub_channel_info data; int rc, trk, m, s, f; int what = 0; char *p, vmcn[(4 * 15) + 1]; while ((p = strtok(arg, " \t"))) { arg = 0; if (!strncasecmp(p, "audio", strlen(p))) what |= STATUS_AUDIO; else if (!strncasecmp(p, "media", strlen(p))) what |= STATUS_MEDIA; else if (!strncasecmp(p, "volume", strlen(p))) what |= STATUS_VOLUME; else { warnx("invalid command arguments"); return 0; } } if (!what) what = STATUS_AUDIO|STATUS_MEDIA|STATUS_VOLUME; if (what & STATUS_AUDIO) { rc = status (&trk, &m, &s, &f); if (rc >= 0) if (verbose) printf ("Audio status = %d<%s>, current track = %d, current position = %d:%02d.%02d\n", rc, strstatus (rc), trk, m, s, f); else printf ("%d %d %d:%02d.%02d\n", rc, trk, m, s, f); else printf ("No current status info available\n"); } if (what & STATUS_MEDIA) { bzero (&ss, sizeof (ss)); ss.data = &data; ss.data_len = sizeof (data); ss.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT; ss.data_format = CD_MEDIA_CATALOG; rc = ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &ss); if (rc >= 0) { printf("Media catalog is %sactive", ss.data->what.media_catalog.mc_valid ? "": "in"); if (ss.data->what.media_catalog.mc_valid && ss.data->what.media_catalog.mc_number[0]) { strvisx (vmcn, ss.data->what.media_catalog.mc_number, (sizeof (vmcn) - 1) / 4, VIS_OCTAL | VIS_NL); printf(", number \"%.*s\"", (int)sizeof (vmcn), vmcn); } putchar('\n'); } else printf("No media catalog info available\n"); } if (what & STATUS_VOLUME) { rc = ioctl (fd, CDIOCGETVOL, &v); if (rc >= 0) if (verbose) printf ("Left volume = %d, right volume = %d\n", v.vol[0], v.vol[1]); else printf ("%d %d\n", v.vol[0], v.vol[1]); else printf ("No volume level info available\n"); } return(0); }
char* iface_read_state(struct rbus_t *rbus, char* buf) { struct interface_state *iface = rbus->native; return strstatus(iface->status); };
void work(void) { interface_status_t status; int fd = -1; fd_set fds; int sigfd; time_t t = 0; int send_retval = 1; int paused = 0; static char log_ident[256]; snprintf(log_ident, sizeof(log_ident), "ifplugd(%s)", interface); daemon_log_ident = log_ident; daemon_log(LOG_INFO, "ifplugd "VERSION" initializing%s.", use_ifmonitor ? ", using NETLINK device monitoring" : ""); if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file %s.", daemon_pid_file_proc()); goto finish; } if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2, -1) < 0) { daemon_log(LOG_ERR, "Could not register signal handler: %s", strerror(errno)); goto finish; } switch (api_mode) { case API_ETHTOOL: detect_beat_func = interface_detect_beat_ethtool; break; case API_MII: detect_beat_func = interface_detect_beat_mii; break; case API_PRIVATE: detect_beat_func = interface_detect_beat_priv; break; case API_WLAN: detect_beat_func = interface_detect_beat_wlan; break; case API_IFF: detect_beat_func = interface_detect_beat_iff; break; default: detect_beat_func = detect_beat_auto; interface_do_message = 0; break; } if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { daemon_log(LOG_ERR, "socket(): %s", strerror(errno)); goto finish; } if (use_ifmonitor) { int b; if ((b = is_iface_available(fd, interface)) < 0) { daemon_log(LOG_ERR, "Failed to check interface availabilty!"); goto finish; } disabled = !b; if (nlapi_open(RTMGRP_LINK) < 0) goto finish; if (ifmonitor_init(ifmonitor_cb) < 0) goto finish; } else disabled = 0; if (!disabled) { if (welcome_iface(fd, interface) < 0) goto finish; } if ((status = detect_beat(fd, interface)) == IFSTATUS_ERR) goto finish; daemon_log(LOG_INFO, "Initialization complete, link beat %sdetected%s.", status == IFSTATUS_UP ? "" : "not ", use_ifmonitor ? (disabled ? ", interface disabled" : ", interface enabled") : ""); beep(status == IFSTATUS_UP ? 0 : 1); if ((!no_startup_script && status == IFSTATUS_UP) || initial_down) if (action(status) < 0) goto finish; if (send_retval && daemonize && wait_on_fork) { char c = status == IFSTATUS_UP ? 2 : (status == IFSTATUS_DOWN ? 3 : 1); daemon_retval_send(c); send_retval = 0; } FD_ZERO(&fds); sigfd = daemon_signal_fd(); FD_SET(sigfd, &fds); if (use_ifmonitor) FD_SET(nlapi_fd, &fds); for (;;) { interface_status_t s; fd_set qfds = fds; int d; struct timeval tv; tv.tv_sec = polltime; tv.tv_usec = 0; if (select(FD_SETSIZE, &qfds, NULL, NULL, &tv) < 0) { if (errno == EINTR) continue; daemon_log(LOG_ERR, "select(): %s", strerror(errno)); goto finish; } //daemon_log(LOG_INFO, "select()"); d = disabled; s = status; if (use_ifmonitor) { if (FD_ISSET(nlapi_fd, &qfds)) { if (nlapi_work(0) < 0) goto finish; } if (d && !disabled) { daemon_log(LOG_INFO, "Interface enabled"); welcome_iface(fd, interface); status = IFSTATUS_DOWN; } if (!d && disabled) { daemon_log(LOG_INFO, "Interface disabled"); status = IFSTATUS_DOWN; } } if (!paused && !disabled) { //daemon_log(LOG_INFO, "detect"); if ((status = detect_beat(fd, interface)) == IFSTATUS_ERR) { if (!use_ifmonitor) goto finish; status = IFSTATUS_DOWN; } } if (status != s) { daemon_log(LOG_INFO, "Link beat %s.", status == IFSTATUS_DOWN ? "lost" : "detected"); beep(status == IFSTATUS_UP ? 0 : 1); if (t) t = 0; else { t = time(NULL); if (status == IFSTATUS_UP) t += delay_up; if (status == IFSTATUS_DOWN) t += delay_down; } } if (FD_ISSET(sigfd, &qfds)) { int sig; if ((sig = daemon_signal_next()) < 0) { daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno)); goto finish; } switch (sig) { case SIGINT: case SIGTERM: goto cleanup; case SIGQUIT: goto finish; case SIGCHLD: break; case SIGHUP: daemon_log(LOG_INFO, "SIGHUP: %s, link detected on %s: %s", paused ? "Suspended" : "Running", interface, status == IFSTATUS_DOWN ? "no" : "yes"); if (use_ifmonitor) daemon_log(LOG_INFO, "SIGHUP: Interface %s", disabled ? "disabled" : "enabled"); break; case SIGUSR1: daemon_log(LOG_INFO, "SIGUSR1: Daemon suspended (#%i)", ++paused); break; case SIGUSR2: if (paused > 0) { daemon_log(LOG_INFO, "SIGUSR2: Daemon resumed (#%i)", paused); paused --; } break; default: daemon_log(LOG_INFO, "Ignoring unknown signal %s", strsignal(sig)); break; } } if (t && t < time(NULL)) { t = 0; if (action(status) < 0) goto finish; } } cleanup: if (!no_shutdown_script && (status == IFSTATUS_UP || (status == IFSTATUS_DOWN && t))) { setenv(IFPLUGD_ENV_PREVIOUS, strstatus(status), 1); setenv(IFPLUGD_ENV_CURRENT, strstatus(-1), 1); action(IFSTATUS_DOWN); beep(1); } finish: if (fd >= 0) close(fd); if (use_ifmonitor) nlapi_close(); if (send_retval && daemonize && wait_on_fork) daemon_retval_send(255); daemon_pid_file_remove(); daemon_signal_done(); daemon_log(LOG_INFO, "Exiting."); }