]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpd: listen on Unix socket before forking
authorVincent Bernat <bernat@luffy.cx>
Fri, 11 May 2012 05:53:39 +0000 (07:53 +0200)
committerVincent Bernat <bernat@luffy.cx>
Fri, 11 May 2012 05:53:39 +0000 (07:53 +0200)
This way, lldpd Unix socket is ready to operate when lldpd detaches
itself from the terminal. This mean that lldpctl can be used right
away.

This change also removes the need to create this socket using
privilege separation operations.

src/lldpd.c
src/lldpd.h
src/priv.c

index 52e04574f37f3f5ae5662f3fbb8943f226c2e2e6..8595b45396457a5c9639116f1ad391fa50d30b03 100644 (file)
@@ -34,6 +34,8 @@
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 #include <net/if_arp.h>
+#include <pwd.h>
+#include <grp.h>
 
 static void             usage(void);
 
@@ -1037,6 +1039,13 @@ lldpd_main(int argc, char *argv[])
        char *lsb_release = NULL;
        int smart = 15;
        int receiveonly = 0;
+       int ctl;
+
+       /* Non privileged user */
+       struct passwd *user;
+       struct group *group;
+       uid_t uid;
+       gid_t gid;
 
        saved_argv = argv;
 
@@ -1141,6 +1150,29 @@ lldpd_main(int argc, char *argv[])
        log_init(debug, __progname);
        tzset();                /* Get timezone info before chroot */
 
+       /* Grab uid and gid to use for priv sep */
+       if ((user = getpwnam(PRIVSEP_USER)) == NULL)
+               fatal("no " PRIVSEP_USER " user for privilege separation");
+       uid = user->pw_uid;
+       if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
+               fatal("no " PRIVSEP_GROUP " group for privilege separation");
+       gid = group->gr_gid;
+
+       /* Create and setup socket */
+       if ((ctl = ctl_create(LLDPD_CTL_SOCKET)) == -1) {
+               LLOG_WARN ("unable to create control socket");
+               LLOG_WARNX("If another instance is running, please stop it.");
+               LLOG_WARNX("Otherwise, remove " LLDPD_CTL_SOCKET);
+               fatalx("Giving up");
+       }
+       if (chown(LLDPD_CTL_SOCKET, uid, gid) == -1)
+               LLOG_WARN("unable to chown control socket");
+       if (chmod(LLDPD_CTL_SOCKET,
+               S_IRUSR | S_IWUSR | S_IXUSR |
+               S_IRGRP | S_IWGRP | S_IXGRP) == -1)
+               LLOG_WARN("unable to chmod control socket");
+
+       /* Detach if needed */
        if (!debug) {
                int pid;
                char *spid;
@@ -1164,13 +1196,14 @@ lldpd_main(int argc, char *argv[])
                lsb_release = lldpd_get_lsb_release();
        }
 
-       priv_init(PRIVSEP_CHROOT);
+       priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
 
        /* Initialization of global configuration */
        if ((cfg = (struct lldpd *)
            calloc(1, sizeof(struct lldpd))) == NULL)
                fatal(NULL);
 
+       cfg->g_ctl = ctl;
        cfg->g_mgmt_pattern = mgmtp;
        cfg->g_cid_pattern = cidp;
        cfg->g_interfaces = interfaces;
@@ -1234,10 +1267,6 @@ lldpd_main(int argc, char *argv[])
        TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
        lchassis->c_refcount++; /* We should always keep a reference to local chassis */
 
-       /* Create socket */
-       if ((cfg->g_ctl = priv_ctl_create()) == -1)
-               fatalx("unable to create control socket " LLDPD_CTL_SOCKET);
-
        /* Main loop */
        levent_loop(cfg);
        lldpd_exit(cfg);
index cec7b85a1dace6e088f5eea84b590d29406b07da..431001b8f2e1afa0814103c7320dc655dfa44c09 100644 (file)
@@ -608,8 +608,7 @@ int  client_handle_client(struct lldpd *, int,
     enum hmsg_type, void *, int);
 
 /* priv.c */
-void    priv_init(char*);
-int     priv_ctl_create(void);
+void    priv_init(char*, int, uid_t, gid_t);
 void    priv_ctl_cleanup(void);
 char           *priv_gethostbyname(void);
 int             priv_open(char*);
index 9e57532f622c21eb0a1176a5c7838e54210da30c..6466f0b6eaff8aeb5557e212f15359540a1da42f 100644 (file)
@@ -30,7 +30,6 @@
 #include <sys/un.h>
 #include <regex.h>
 #include <fcntl.h>
-#include <pwd.h>
 #include <grp.h>
 #include <sys/utsname.h>
 #include <sys/ioctl.h>
@@ -55,7 +54,6 @@
 
 enum {
        PRIV_PING,
-       PRIV_CREATE_CTL_SOCKET,
        PRIV_DELETE_CTL_SOCKET,
        PRIV_GET_HOSTNAME,
        PRIV_OPEN,
@@ -73,10 +71,6 @@ static int remote;                   /* Other side */
 static int monitored = -1;             /* Child */
 static int sock = -1;
 
-/* UID/GID of unprivileged user */
-static gid_t gid = 0;
-static uid_t uid = 0;
-
 /* Proxies */
 
 static void
@@ -89,20 +83,6 @@ priv_ping()
        LLOG_DEBUG("monitor ready");
 }
 
-/* Proxy for ctl_create, no argument since this is the monitor that decides the
- * location of the socket */
-int
-priv_ctl_create()
-{
-       int cmd, rc;
-       cmd = PRIV_CREATE_CTL_SOCKET;
-       must_write(remote, &cmd, sizeof(int));
-       must_read(remote, &rc, sizeof(int));
-       if (rc == -1)
-               return -1;
-       return receive_fd(remote);
-}
-
 /* Proxy for ctl_cleanup */
 void
 priv_ctl_cleanup()
@@ -206,28 +186,6 @@ asroot_ping()
        must_write(remote, &rc, sizeof(int));
 }
 
-static void
-asroot_ctl_create()
-{
-       int rc;
-       if ((rc = ctl_create(LLDPD_CTL_SOCKET)) == -1) {
-               LLOG_WARN("[priv]: unable to create control socket");
-               LLOG_WARNX("[priv]: If another instance is running, please stop it.");
-               LLOG_WARNX("[priv]: Otherwise, remove " LLDPD_CTL_SOCKET);
-               must_write(remote, &rc, sizeof(int));
-               return;
-       }
-       if (chown(LLDPD_CTL_SOCKET, uid, gid) == -1)
-               LLOG_WARN("[priv]: unable to chown control socket");
-       if (chmod(LLDPD_CTL_SOCKET,
-               S_IRUSR | S_IWUSR | S_IXUSR |
-               S_IRGRP | S_IWGRP | S_IXGRP) == -1)
-               LLOG_WARN("[priv]: unable to chmod control socket");
-       must_write(remote, &rc, sizeof(int));
-       send_fd(remote, rc);
-       close(rc);
-}
-
 static void
 asroot_ctl_cleanup()
 {
@@ -440,7 +398,6 @@ struct dispatch_actions {
 
 static struct dispatch_actions actions[] = {
        {PRIV_PING, asroot_ping},
-       {PRIV_CREATE_CTL_SOCKET, asroot_ctl_create},
        {PRIV_DELETE_CTL_SOCKET, asroot_ctl_cleanup},
        {PRIV_GET_HOSTNAME, asroot_gethostbyname},
        {PRIV_OPEN, asroot_open},
@@ -505,11 +462,10 @@ sig_chld(int sig)
 
 /* Initialization */
 void
-priv_init(char *chrootdir)
+priv_init(char *chrootdir, int ctl, uid_t uid, gid_t gid)
 {
+
        int pair[2];
-       struct passwd *user;
-       struct group *group;
        gid_t gidset[1];
         int status;
 
@@ -517,14 +473,6 @@ priv_init(char *chrootdir)
        if (socketpair(AF_LOCAL, SOCK_DGRAM, PF_UNSPEC, pair) < 0)
                fatal("[priv]: unable to create socket pair for privilege separation");
 
-       /* Get users */
-       if ((user = getpwnam(PRIVSEP_USER)) == NULL)
-               fatal("[priv]: no " PRIVSEP_USER " user for privilege separation");
-       uid = user->pw_uid;
-       if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
-               fatal("[priv]: no " PRIVSEP_GROUP " group for privilege separation");
-       gid = group->gr_gid;
-
        /* Spawn off monitor */
        if ((monitored = fork()) < 0)
                fatal("[priv]: unable to fork monitor");
@@ -552,6 +500,7 @@ priv_init(char *chrootdir)
                break;
        default:
                /* We are in the monitor */
+               if (ctl != -1) close(ctl);
                remote = pair[1];
                close(pair[0]);
                if (atexit(priv_exit) != 0)