summaryrefslogtreecommitdiff
path: root/pand/main.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-02-26 00:09:26 +0000
committerMarcel Holtmann <marcel@holtmann.org>2007-02-26 00:09:26 +0000
commit6d7bf9b20d5e2bcf93d8a50de710f668fcbafbf3 (patch)
treed57542ffac709f3b870c256a87794fefeae28f86 /pand/main.c
parent7c4d415701998b6155c8e51285c05148388bbdb3 (diff)
Add devdown option
Diffstat (limited to 'pand/main.c')
-rw-r--r--pand/main.c145
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;