I totally forgot about demime, shame on me.. :-)

Index: ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.173
diff -u -r1.173 ifconfig.8
--- ifconfig.8  12 Dec 2008 22:09:26 -0000      1.173
+++ ifconfig.8  10 Feb 2009 22:50:27 -0000
@@ -412,6 +412,15 @@
 It happens automatically when setting the first address on an interface.
 If the interface was reset when previously marked down,
 the hardware will be re-initialized.
+.It Cm wake Ar etheraddr
+Sends a Wake on LAN (WoL) frame over a local Ethernet network using a
+link-layer (hardware) address.
+.Ar etheraddr
+is the link layer address of the remote machine
+and can be specified as an actual hardware address
+(six hexadecimal numbers separated by colons)
+or as a hostname entry in
+.Pa /etc/ethers .
 .El
 .Pp
 .Nm
@@ -1237,6 +1246,7 @@
 .Xr hostname.if 5 ,
 .Xr hosts 5 ,
 .Xr networks 5 ,
+.Xr ethers 5 ,
 .Xr rc 8 ,
 .Xr tcpdump 8
 .Sh HISTORY
Index: ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.211
diff -u -r1.211 ifconfig.c
--- ifconfig.c  6 Feb 2009 22:07:04 -0000       1.211
+++ ifconfig.c  10 Feb 2009 22:50:28 -0000
@@ -64,6 +64,9 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>

+#ifndef SMALL
+#include <net/bpf.h>
+#endif /* SMALL */
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_media.h>
@@ -98,6 +101,9 @@
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
+#ifndef SMALL
+#include <fcntl.h>
+#endif /* SMALL */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -240,7 +246,22 @@
 void   unsetpflow_sender(const char *, int);
 void   setpflow_receiver(const char *, int);
 void   unsetpflow_receiver(const char *, int);
+
+#ifndef BPF_PATH_FORMAT
+#define BPF_PATH_FORMAT "/dev/bpf%u"
+#endif
+#ifndef SYNC_LEN
+#define SYNC_LEN 6
 #endif
+#ifndef DESTADDR_COUNT
+#define DESTADDR_COUNT 16
+#endif
+void   wolhandler(const char *, int);
+int    get_bpf(void);
+int    bind_if_to_bpf(char const *, int);
+int    get_ether(char const *, struct ether_addr *);
+int    send_wakeup(int, struct ether_addr const *);
+#endif /* SMALL */

 /*
  * Media stuff.  Whenever a media command is first performed, the
@@ -409,7 +430,8 @@
        { "-flowsrc",   1,              0,              unsetpflow_sender },
        { "flowdst",    NEXTARG,        0,              setpflow_receiver },
        { "-flowdst", 1,                0,              unsetpflow_receiver },
-#endif
+       { "wake",       NEXTARG,        0,              wolhandler },
+#endif /* SMALL */
        { NULL, /*src*/ 0,              0,              setifaddr },
        { NULL, /*dst*/ 0,              0,              setifdstaddr },
        { NULL, /*illegal*/0,           0,              NULL },
@@ -4572,3 +4594,104 @@
                warn("SIOCSIFLLADDR");
 }

+#ifndef SMALL
+void
+wolhandler(const char *addr, int param)
+{
+       int bpf;
+       struct ether_addr macaddr;
+
+       bpf = get_bpf();
+       if (bpf == -1 ||
+           bind_if_to_bpf(name, bpf) == -1 ||
+           get_ether(addr, &macaddr) == -1 ||
+           send_wakeup(bpf, &macaddr) == -1) {
+               warn("error sending Wake on LAN frame over %s to %s",
+                   name, addr);
+       }
+       (void)close(bpf);
+       return;
+}
+
+int
+get_bpf(void)
+{
+       int i, fd;
+       char path[MAXPATHLEN];
+
+       for (i = 0;; i++) {
+               if (snprintf(path, sizeof(path), BPF_PATH_FORMAT, i) == -1)
+                       return -1;
+
+               fd = open(path, O_RDWR);
+               if (fd != -1)
+                       return fd;
+               if (errno == EBUSY)
+                       continue;
+               break;
+       }
+       return -1;
+}
+
+int
+bind_if_to_bpf(char const *ifname, int bpf)
+{
+       struct ifreq ifr;
+       u_int dlt;
+
+       if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
+           sizeof(ifr.ifr_name))
+               return -1;
+       if (ioctl(bpf, BIOCSETIF, &ifr) == -1)
+               return -1;
+       if (ioctl(bpf, BIOCGDLT, &dlt) == -1)
+               return -1;
+       if (dlt != DLT_EN10MB)
+               return -1;
+       return 0;
+}
+
+int
+get_ether(char const *text, struct ether_addr *addr)
+{
+       struct ether_addr *paddr;
+       paddr = ether_aton(text);
+       if (paddr != NULL) {
+               *addr = *paddr;
+               return 0;
+       }
+       if (ether_hostton(text, addr))
+               return -1;
+       return 0;
+}
+
+int
+send_wakeup(int bpf, struct ether_addr const *addr)
+{
+       struct {
+               struct ether_header hdr;
+               u_char data[SYNC_LEN + ETHER_ADDR_LEN * DESTADDR_COUNT];
+       } pkt;
+       u_char *p;
+       int i;
+       ssize_t bw;
+       ssize_t len;
+
+       (void)memset(pkt.hdr.ether_dhost, 0xff, sizeof(pkt.hdr.ether_dhost));
+       pkt.hdr.ether_type = htons(0);
+       (void)memset(pkt.data, 0xff, SYNC_LEN);
+       for (p = pkt.data + SYNC_LEN, i = 0; i < DESTADDR_COUNT;
+           p += ETHER_ADDR_LEN, i++)
+               bcopy(addr->ether_addr_octet, p, ETHER_ADDR_LEN);
+       p = (u_char *)&pkt;
+       len = sizeof(pkt);
+       bw = 0;
+       while (len) {
+               if ((bw = write(bpf, &pkt, sizeof(pkt))) == -1)
+                       return -1;
+               len -= bw;
+               p += bw;
+       }
+       return 0;
+}
+#endif /* SMALL */

Reply via email to