summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/wake/wake.826
-rw-r--r--usr.sbin/wake/wake.c105
2 files changed, 86 insertions, 45 deletions
diff --git a/usr.sbin/wake/wake.8 b/usr.sbin/wake/wake.8
index 340dd9d..ce30abf 100644
--- a/usr.sbin/wake/wake.8
+++ b/usr.sbin/wake/wake.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.\" Copyright (c) 2009 Marc Balmer <marc@msys.ch>
+.\" Copyright (c) 2009, 2010 Marc Balmer <marc@msys.ch>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -23,7 +23,7 @@
.Nd send Wake on LAN frames to hosts on a local Ethernet network
.Sh SYNOPSIS
.Nm
-.Ar interface
+.Op Ar interface
.Ar lladdr
.Op Ar lladdr ...
.Sh DESCRIPTION
@@ -37,21 +37,27 @@ and can be used to power on machines from a remote system without
having physical access to them.
.Pp
.Ar interface
-is a network interface of the local machine.
+is an Ethernet interface of the local machine and is used to send the
+Wake on LAN frames over it.
+If there is only one Ethernet device available that is up and running, then the
+.Ar interface
+argument can be omitted.
.Ar lladdr
-are the link layer addresses of the remote machines
-and can be specified as the actual hardware address
+is the link layer address of the remote machine.
+This can be specified as the actual hardware address
(six hexadecimal numbers separated by colons)
-or a hostname entry in
+or as a hostname entry in
.Pa /etc/ethers .
-Link layer addresses can be determined and set on
-.Fx
-machines using
+.Nm
+accepts multiple
+.Ar lladdr
+addresses.
+Link layer addresses can be determined and set using
.Xr ifconfig 8 .
.Sh FILES
.Bl -tag -width "/etc/ethers" -compact
.It /etc/ethers
-Ethernet host name database.
+Ethernet host name data base.
.El
.Sh SEE ALSO
.Xr ethers 5 ,
diff --git a/usr.sbin/wake/wake.c b/usr.sbin/wake/wake.c
index 1feda96..d6ba931 100644
--- a/usr.sbin/wake/wake.c
+++ b/usr.sbin/wake/wake.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009 Marc Balmer <marc@msys.ch>
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Marc Balmer <marc@msys.ch>
* Copyright (C) 2000 Eugene M. Kim. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,11 +32,14 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <err.h>
#include <fcntl.h>
+#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -53,38 +56,29 @@ __FBSDID("$FreeBSD$");
#endif
static int bind_if_to_bpf(char const *ifname, int bpf);
+static int find_ether(char *dst, size_t len);
static int get_ether(char const *text, struct ether_addr *addr);
static int send_wakeup(int bpf, struct ether_addr const *addr);
static void usage(void);
-static int wake(const char *iface, const char *host);
+static int wake(int bpf, const char *host);
static void
usage(void)
{
- (void)fprintf(stderr, "usage: wake interface lladdr [lladdr ...]\n");
+ (void)fprintf(stderr, "usage: wake [interface] lladdr [lladdr ...]\n");
exit(1);
}
static int
-wake(const char *iface, const char *host)
+wake(int bpf, const char *host)
{
struct ether_addr macaddr;
- int bpf, res;
- bpf = open(_PATH_BPF, O_RDWR);
- if (bpf == -1) {
- warn("no bpf");
+ if (get_ether(host, &macaddr) == -1)
return (-1);
- }
- if (bind_if_to_bpf(iface, bpf) == -1 ||
- get_ether(host, &macaddr) == -1) {
- (void)close(bpf);
- return (-1);
- }
- res = send_wakeup(bpf, &macaddr);
- (void)close(bpf);
- return (res);
+
+ return send_wakeup(bpf, &macaddr);
}
static int
@@ -94,26 +88,50 @@ bind_if_to_bpf(char const *ifname, int bpf)
u_int dlt;
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
- sizeof(ifr.ifr_name)) {
- warnx("interface name too long: %s", ifname);
+ sizeof(ifr.ifr_name))
return (-1);
- }
- if (ioctl(bpf, BIOCSETIF, &ifr) == -1) {
- warn("ioctl(%s)", "BIOCSETIF");
+
+ if (ioctl(bpf, BIOCSETIF, &ifr) == -1)
return (-1);
- }
- if (ioctl(bpf, BIOCGDLT, &dlt) == -1) {
- warn("ioctl(%s)", "BIOCGDLT");
+
+ if (ioctl(bpf, BIOCGDLT, &dlt) == -1)
return (-1);
- }
- if (dlt != DLT_EN10MB) {
- warnx("incompatible media");
+
+ if (dlt != DLT_EN10MB)
return (-1);
- }
+
return (0);
}
static int
+find_ether(char *dst, size_t len)
+{
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_dl *sdl = NULL;
+ int nifs;
+
+ if (dst == NULL || len == 0)
+ return 0;
+
+ if (getifaddrs(&ifap) != 0)
+ return -1;
+
+ /* XXX also check the link state */
+ for (nifs = 0, ifa = ifap; ifa; ifa = ifa->ifa_next)
+ if (ifa->ifa_addr->sa_family == AF_LINK &&
+ ifa->ifa_flags & IFF_UP && ifa->ifa_flags & IFF_RUNNING) {
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ if (sdl->sdl_type == IFT_ETHER) {
+ strlcpy(dst, ifa->ifa_name, len);
+ nifs++;
+ }
+ }
+
+ freeifaddrs(ifap);
+ return nifs == 1 ? 0 : -1;
+}
+
+static int
get_ether(char const *text, struct ether_addr *addr)
{
struct ether_addr *paddr;
@@ -165,14 +183,31 @@ send_wakeup(int bpf, struct ether_addr const *addr)
int
main(int argc, char *argv[])
{
- int n;
+ int bpf, n;
+ char ifname[IF_NAMESIZE];
+
+ if (argc < 2)
+ usage();
+
+ if ((bpf = open(_PATH_BPF, O_RDWR)) == -1)
+ err(1, "Cannot open bpf interface");
+
+ n = 2;
+ if (bind_if_to_bpf(argv[1], bpf) == -1) {
+ if (find_ether(ifname, sizeof(ifname)))
+ err(1, "Failed to determine ethernet interface");
+ if (bind_if_to_bpf(ifname, bpf) == -1)
+ err(1, "Cannot bind to interface `%s'", ifname);
+ --n;
+ } else
+ strlcpy(ifname, argv[1], sizeof(ifname));
- if (argc < 3)
+ if (n >= argc)
usage();
+ for (; n < argc; n++)
+ if (wake(bpf, argv[n]))
+ warn("Cannot send Wake on LAN frame over `%s' to `%s'",
+ ifname, argv[n]);
- for (n = 2; n < argc; n++)
- if (wake(argv[1], argv[n]))
- warnx("error sending Wake on LAN frame over %s to %s",
- argv[1], argv[n]);
return (0);
}
OpenPOWER on IntegriCloud