dhclient - Add 'egress' command-line option.
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Thu, 2 Aug 2012 17:39:08 +0000 (19:39 +0200)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Wed, 15 Aug 2012 01:22:14 +0000 (03:22 +0200)
- It can be used to refetch a lease without remembering
which interface dhclient was actually active on.

Taken-from: OpenBSD

sbin/dhclient/dhclient.c

index 64d80bb..a9ba670 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.133 2010/03/25 18:37:36 stevesk Exp $        */
+/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.136 2010/09/24 13:44:14 claudio Exp $        */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -52,6 +52,7 @@
  * the shell script can invoke the native tools to accomplish the same
  * purpose.
  */
+#include <sys/ioctl.h>
 
 #include <ctype.h>
 #include <poll.h>
@@ -95,7 +96,7 @@ int            ipv4addrs(char * buf);
 int             res_hnok(const char *dn);
 char           *option_as_string(unsigned int code, unsigned char *data, int len);
 int             fork_privchld(int, int);
-
+void            get_ifname(char *, char *);
 #define        ROUNDUP(a) \
            ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 #define        ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
@@ -315,8 +316,7 @@ main(int argc, char *argv[])
        if (config == NULL)
                error("config calloc");
 
-       if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
-               error("Interface name too long");
+       get_ifname(ifi->name, argv[0]);
        if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
            _PATH_DHCLIENT_DB, ifi->name) == -1)
                error("asprintf");
@@ -2185,3 +2185,45 @@ fork_privchld(int fd, int fd2)
                dispatch_imsg(fd);
        }
 }
+
+void
+get_ifname(char *ifname, char *arg)
+{
+       struct ifgroupreq ifgr;
+       struct ifg_req *ifg;
+       int s, len;
+
+       if (!strcmp(arg, "egress")) {
+               s = socket(AF_INET, SOCK_DGRAM, 0);
+               if (s == -1)
+                       error("socket error");
+               bzero(&ifgr, sizeof(ifgr));
+               strlcpy(ifgr.ifgr_name, "egress", sizeof(ifgr.ifgr_name));
+               if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
+                       if (errno == ENOENT)
+                               error("no interface in group egress found");
+                       error("ioctl SIOCGIFGMEMB: %m");
+               }
+               len = ifgr.ifgr_len;
+               if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
+                       error("get_ifname");
+               if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
+                       error("ioctl SIOCGIFGMEMB: %m");
+
+               arg = NULL;
+               for (ifg = ifgr.ifgr_groups;
+                    ifg && len >= sizeof(struct ifg_req); ifg++) {
+                       len -= sizeof(struct ifg_req);
+                       if (arg)
+                               error("too many interfaces in group egress");
+                       arg = ifg->ifgrq_member;
+               }
+
+               if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ)
+                       error("Interface name too long: %m");
+
+               free(ifgr.ifgr_groups);
+               close(s);
+       } else if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ)
+               error("Interface name too long");
+}