If there is only one NIC in the system that is up and running, the
interface specifier on the command line can be ommited. Besides of this, the bpf is being reused for each machine that has to be woken up. Submitted by: Marc Balmer <marc@msys.ch>
This commit is contained in:
parent
31615ef723
commit
66df920cc9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203686
@ -1,7 +1,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $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
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
.\" purpose with or without fee is hereby granted, provided that the above
|
.\" 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
|
.Nd send Wake on LAN frames to hosts on a local Ethernet network
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Ar interface
|
.Op Ar interface
|
||||||
.Ar lladdr
|
.Ar lladdr
|
||||||
.Op Ar lladdr ...
|
.Op Ar lladdr ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -37,21 +37,27 @@ and can be used to power on machines from a remote system without
|
|||||||
having physical access to them.
|
having physical access to them.
|
||||||
.Pp
|
.Pp
|
||||||
.Ar interface
|
.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
|
.Ar lladdr
|
||||||
are the link layer addresses of the remote machines
|
is the link layer address of the remote machine.
|
||||||
and can be specified as the actual hardware address
|
This can be specified as the actual hardware address
|
||||||
(six hexadecimal numbers separated by colons)
|
(six hexadecimal numbers separated by colons)
|
||||||
or a hostname entry in
|
or as a hostname entry in
|
||||||
.Pa /etc/ethers .
|
.Pa /etc/ethers .
|
||||||
Link layer addresses can be determined and set on
|
.Nm
|
||||||
.Fx
|
accepts multiple
|
||||||
machines using
|
.Ar lladdr
|
||||||
|
addresses.
|
||||||
|
Link layer addresses can be determined and set using
|
||||||
.Xr ifconfig 8 .
|
.Xr ifconfig 8 .
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/ethers" -compact
|
.Bl -tag -width "/etc/ethers" -compact
|
||||||
.It /etc/ethers
|
.It /etc/ethers
|
||||||
Ethernet host name database.
|
Ethernet host name data base.
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr ethers 5 ,
|
.Xr ethers 5 ,
|
||||||
|
@ -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.
|
* Copyright (C) 2000 Eugene M. Kim. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,11 +32,14 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <net/bpf.h>
|
#include <net/bpf.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/if_ether.h>
|
#include <netinet/if_ether.h>
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -53,38 +56,29 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int bind_if_to_bpf(char const *ifname, int bpf);
|
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 get_ether(char const *text, struct ether_addr *addr);
|
||||||
static int send_wakeup(int bpf, struct ether_addr const *addr);
|
static int send_wakeup(int bpf, struct ether_addr const *addr);
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
static int wake(const char *iface, const char *host);
|
static int wake(int bpf, const char *host);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void)fprintf(stderr, "usage: wake interface lladdr [lladdr ...]\n");
|
(void)fprintf(stderr, "usage: wake [interface] lladdr [lladdr ...]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wake(const char *iface, const char *host)
|
wake(int bpf, const char *host)
|
||||||
{
|
{
|
||||||
struct ether_addr macaddr;
|
struct ether_addr macaddr;
|
||||||
int bpf, res;
|
|
||||||
|
|
||||||
bpf = open(_PATH_BPF, O_RDWR);
|
if (get_ether(host, &macaddr) == -1)
|
||||||
if (bpf == -1) {
|
|
||||||
warn("no bpf");
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
|
||||||
if (bind_if_to_bpf(iface, bpf) == -1 ||
|
return send_wakeup(bpf, &macaddr);
|
||||||
get_ether(host, &macaddr) == -1) {
|
|
||||||
(void)close(bpf);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
res = send_wakeup(bpf, &macaddr);
|
|
||||||
(void)close(bpf);
|
|
||||||
return (res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -94,25 +88,49 @@ bind_if_to_bpf(char const *ifname, int bpf)
|
|||||||
u_int dlt;
|
u_int dlt;
|
||||||
|
|
||||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
|
||||||
sizeof(ifr.ifr_name)) {
|
sizeof(ifr.ifr_name))
|
||||||
warnx("interface name too long: %s", ifname);
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
|
||||||
if (ioctl(bpf, BIOCSETIF, &ifr) == -1) {
|
if (ioctl(bpf, BIOCSETIF, &ifr) == -1)
|
||||||
warn("ioctl(%s)", "BIOCSETIF");
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
|
||||||
if (ioctl(bpf, BIOCGDLT, &dlt) == -1) {
|
if (ioctl(bpf, BIOCGDLT, &dlt) == -1)
|
||||||
warn("ioctl(%s)", "BIOCGDLT");
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
|
||||||
if (dlt != DLT_EN10MB) {
|
if (dlt != DLT_EN10MB)
|
||||||
warnx("incompatible media");
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
|
||||||
return (0);
|
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
|
static int
|
||||||
get_ether(char const *text, struct ether_addr *addr)
|
get_ether(char const *text, struct ether_addr *addr)
|
||||||
{
|
{
|
||||||
@ -165,14 +183,31 @@ send_wakeup(int bpf, struct ether_addr const *addr)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int n;
|
int bpf, n;
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
|
||||||
if (argc < 3)
|
if (argc < 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
for (n = 2; n < argc; n++)
|
if ((bpf = open(_PATH_BPF, O_RDWR)) == -1)
|
||||||
if (wake(argv[1], argv[n]))
|
err(1, "Cannot open bpf interface");
|
||||||
warnx("error sending Wake on LAN frame over %s to %s",
|
|
||||||
argv[1], argv[n]);
|
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 (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]);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user