diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2007-02-26 00:09:26 +0000 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2007-02-26 00:09:26 +0000 |
commit | 6d7bf9b20d5e2bcf93d8a50de710f668fcbafbf3 (patch) | |
tree | d57542ffac709f3b870c256a87794fefeae28f86 /pand/main.c | |
parent | 7c4d415701998b6155c8e51285c05148388bbdb3 (diff) |
Add devdown option
Diffstat (limited to 'pand/main.c')
-rw-r--r-- | pand/main.c | 145 |
1 files changed, 94 insertions, 51 deletions
diff --git a/pand/main.c b/pand/main.c index f24437033..8c3ba7475 100644 --- a/pand/main.c +++ b/pand/main.c @@ -73,6 +73,7 @@ static struct { static char netdev[16] = "bnep%d"; static char *pidfile = NULL; static char *devupcmd = NULL; +static char *devdowncmd = NULL; static bdaddr_t src_addr = *BDADDR_ANY; static int src_dev = -1; @@ -89,15 +90,22 @@ enum { KILL } modes; -static void run_devup(char *dev, char *dst, int sk, int nsk) +struct script_arg { + char dev[20]; + char dst[20]; + int sk; + int nsk; +}; + +static void run_script(char *script, char *dev, char *dst, int sk, int nsk) { char *argv[4]; struct sigaction sa; - if (!devupcmd) + if (!script) return; - if (access(devupcmd, R_OK | X_OK)) + if (access(script, R_OK | X_OK)) return; if (fork()) @@ -114,16 +122,69 @@ static void run_devup(char *dev, char *dst, int sk, int nsk) sigaction(SIGCHLD, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); - argv[0] = devupcmd; + argv[0] = script; argv[1] = dev; argv[2] = dst; argv[3] = NULL; - execv(devupcmd, argv); + execv(script, argv); exit(1); } +/* Wait for disconnect or error condition on the socket */ +static int w4_hup(int sk, struct script_arg *down_cmd) +{ + struct pollfd pf; + sigset_t sigs; + int n; + + sigfillset(&sigs); + sigdelset(&sigs, SIGCHLD); + sigdelset(&sigs, SIGPIPE); + sigdelset(&sigs, SIGTERM); + sigdelset(&sigs, SIGINT); + sigdelset(&sigs, SIGHUP); + + while (!terminate) { + pf.fd = sk; + pf.events = POLLERR | POLLHUP; + + n = ppoll(&pf, 1, NULL, &sigs); + + if (n < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + + syslog(LOG_ERR, "Poll failed. %s(%d)", + strerror(errno), errno); + + return 1; + } + + if (n) { + int err = 0; + socklen_t olen = sizeof(err); + + getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &olen); + + syslog(LOG_INFO, "%s disconnected%s%s", netdev, + err ? " : " : "", err ? strerror(err) : ""); + + if (down_cmd) + run_script(devdowncmd, + down_cmd->dev, down_cmd->dst, + down_cmd->sk, down_cmd->nsk); + + close(sk); + + return 0; + } + } + + return 0; +} + static int do_listen(void) { struct l2cap_options l2o; @@ -207,12 +268,21 @@ static int do_listen(void) if (!bnep_accept_connection(nsk, role, devname)) { char str[40]; + struct script_arg down_cmd; + ba2str(&l2a.l2_bdaddr, str); syslog(LOG_INFO, "New connection from %s %s", - str, devname); + str, netdev); + + run_script(devupcmd, devname, str, sk, nsk); - run_devup(devname, str, sk, nsk); + memset(&down_cmd, 0, sizeof(struct script_arg)); + strncpy(down_cmd.dev, devname, strlen(devname) + 1); + strncpy(down_cmd.dst, str, strlen(str) + 1); + down_cmd.sk = sk; + down_cmd.nsk = nsk; + w4_hup(nsk, &down_cmd); } else { syslog(LOG_ERR, "Connection failed. %s(%d)", strerror(errno), errno); @@ -224,46 +294,7 @@ static int do_listen(void) if (use_sdp) bnep_sdp_unregister(); - return 0; -} - -/* Wait for disconnect or error condition on the socket */ -static int w4_hup(int sk) -{ - struct pollfd pf; - sigset_t sigs; - int n; - - sigfillset(&sigs); - sigdelset(&sigs, SIGCHLD); - sigdelset(&sigs, SIGPIPE); - sigdelset(&sigs, SIGTERM); - sigdelset(&sigs, SIGINT); - sigdelset(&sigs, SIGHUP); - - while (!terminate) { - pf.fd = sk; - pf.events = POLLERR | POLLHUP; - n = ppoll(&pf, 1, NULL, &sigs); - if (n < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - syslog(LOG_ERR, "Poll failed. %s(%d)", - strerror(errno), errno); - return 1; - } - if (n) { - int err = 0; - socklen_t olen = sizeof(err); - getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &olen); - syslog(LOG_INFO, "%s disconnected%s%s", netdev, - err ? " : " : "", err ? strerror(err) : ""); - - close(sk); - return 0; - } - } return 0; } @@ -279,6 +310,7 @@ static int create_connection(char *dst, bdaddr_t *bdaddr) struct sockaddr_l2 l2a; socklen_t olen; int sk, r = 0; + struct script_arg down_cmd; syslog(LOG_INFO, "Connecting to %s", dst); @@ -314,10 +346,15 @@ static int create_connection(char *dst, bdaddr_t *bdaddr) syslog(LOG_INFO, "%s connected", netdev); - run_devup(netdev, dst, sk, -1); + run_script(devupcmd, netdev, dst, sk, -1); - if (persist) { - w4_hup(sk); + if (persist || devdowncmd) { + memset(&down_cmd, 0, sizeof(struct script_arg)); + strncpy(down_cmd.dev, netdev, strlen(netdev) + 1); + strncpy(down_cmd.dst, dst, strlen(dst) + 1); + down_cmd.sk = sk; + down_cmd.nsk = -1; + w4_hup(sk, &down_cmd); if (terminate && cleanup) { syslog(LOG_INFO, "Disconnecting from %s.", dst); @@ -525,11 +562,12 @@ static struct option main_lopts[] = { { "cache", 0, 0, 'C' }, { "pidfile", 1, 0, 'P' }, { "devup", 1, 0, 'u' }, + { "devdown", 1, 0, 'o' }, { "autozap", 0, 0, 'z' }, { 0, 0, 0, 0 } }; -static char main_sopts[] = "hsc:k:Kr:d:e:i:lnp::DQ::AESMC::P:u:z"; +static char main_sopts[] = "hsc:k:Kr:d:e:i:lnp::DQ::AESMC::P:u:o:z"; static char main_help[] = "Bluetooth PAN daemon version " VERSION " \n" @@ -556,7 +594,8 @@ static char main_help[] = "\t--persist -p[interval] Persist mode\n" "\t--cache -C[valid] Cache addresses\n" "\t--pidfile -P <pidfile> Create PID file\n" - "\t--devup -u <script> Script to run when interface comes up\n"; + "\t--devup -u <script> Script to run when interface comes up\n" + "\t--devdown -o <script> Script to run when interface comes down\n"; int main(int argc, char *argv[]) { @@ -661,6 +700,10 @@ int main(int argc, char *argv[]) devupcmd = strdup(optarg); break; + case 'o': + devdowncmd = strdup(optarg); + break; + case 'z': cleanup = 1; break; |