2

Is there any such thing as a file linking MAC addresses to IP addresses / DNS names for use with wakeonlan on Linux? Something like this:

$ cat /etc/machosts
00:1f:d0:34:e0:ea 192.168.0.5
00:1f:d0:34:a1:06 192.168.0.7
$ cat /etc/hosts
192.168.0.5 mypc
$ wakeonlan mypc

Thanks.

1
  • 1
    The said file is /etc/ethers
    – hookenz
    Jan 10, 2013 at 1:58

7 Answers 7

4

Some minor bash:

$ cat /path/to/machosts
macs[mypc1]=00:1f:d0:34:e0:ea 
macs[mypc2]=00:1f:d0:34:a1:06 

$ cat wakeonlan.sh
#!/bin/bash

. /path/to/machosts

echo wakeonlan ${macs[$1]}

$ ./wakeonlan.sh mypc1
wakeonlan 00:1f:d0:34:a1:06

This uses bash arrays: http://tldp.org/LDP/abs/html/arrays.html

The unix.stackexchange.com site can probably help more with doing this script and the one that processes arp output.

4
  • Nice. I'll modify that script to my needs and paste the result in a new answer. Aug 8, 2012 at 19:36
  • Something like this can populate the first file: /sbin/arp -a | awk '{print "macs[" $1 "]=" $4 }'
    – cjc
    Aug 8, 2012 at 19:37
  • There are only about four that need doing so that's okay! Aug 8, 2012 at 19:42
  • 1
    No need for a custom file and script. etherwake uses /etc/ethers by default. Populate that file, and you can run etherwake myhostname.
    – mivk
    Jan 9, 2013 at 22:20
3

The etherwake utility (upstream seems to be dead) can read MAC addresses from /etc/ethers (or another kind of ethers database specified in /etc/nsswitch.conf).

0
2

I created my own bash script for it:

#!/bin/bash

die () {
  echo >&2 "$@"
  exit 1
}

# we need one parameter - the hostname or IP address
[ "$#" -eq 1 ] || die "1 argument required, $# provided"

if [[ ! -f "/etc/machosts" ]]; then
  die "Can't find /etc/machosts file!"
fi

host="$1"

# if argument isn't an IPv4 address, try to resolve it
if [[ ! $host =~ ^([0-2]?[0-9]{1,2}\.){3}([0-2]?[0-9]{1,2})$ ]]; then
  echo "Attempting to identify IP from name: $host..."
  host=$(getent ahosts $host | head -n 1 | cut -d" " -f1)
fi

if [[ ! $host =~ ^([0-2]?[0-9]{1,2}\.){3}([0-2]?[0-9]{1,2})$ ]]; then
  die "Invalid hostname"
fi

mac=""

# read /etc/machosts line by line
while read line
do
  if [[ !(${line:0:1} == "#") && ( -n "$line" ) ]]; then
    ip=$(echo $line | cut -d" " -f2)
    addr=$(echo $line | cut -d" " -f1)

    if [[ $ip == $host ]]; then
      mac=$addr
      break
    fi
  fi
done < "/etc/machosts"

if [[ -z $mac ]]; then
  die "No MAC address asociated with that host!"
fi

wakeonlan $mac

exit 0

My /etc/machosts looks like this:

# here the MAC hosts are defined
#
# e.g. 50:e7:24:ab:c0:d3 10.3.12.5

50:e5:49:1a:8c:9c 192.168.0.4
00:1f:d0:34:e0:ea 192.168.0.5
00:25:22:b1:f6:be 192.168.0.6
00:1f:d0:34:a1:06 192.168.0.7
5
  • 3
    What you're calling "machosts" is called "ethers" on Linux and most UNIXes. The ethers(5) man page on FreeBSD says the hostname (the second field of each line) should match an entry in /etc/hosts, while ethers(5) on Linux says it should be resolvable using DNS or a numeric IP address. Aug 8, 2012 at 21:39
  • If I do man ethers it tells me I should have an /etc/ethers file, but it doesn't exist. The man page seems to come with the net-tools package. Aug 8, 2012 at 22:36
  • Which OS are you using? Some still include it by default (Red Hat, SUSE) but many don't (Debian, OS X, Solaris). (Just to be clear, you can call the file anything you'd like. It's your system. I'm just pointing out that there's an established name and format for what you're trying to store.) Aug 9, 2012 at 15:33
  • Ah, okay then. I'm running Debian so that explains it. Might as well keep it as machosts for now, but I'll change it if the need arises. Aug 9, 2012 at 20:45
  • /etc/ethers is used by the rarp daemon. However rarp support was removed from the linux kernel from version 2.3. A replacement daemon package is available.
    – hookenz
    Jan 10, 2013 at 2:00
1

"Is there [...] a file linking MAC addresses to IP addresses [...] on Linux?"

Yes, sort of: /proc/net/arp. But of course, that is not a real permanent file.

The standard file for your purpose is /etc/ethers, but you have to create and populate it. Doing it by hand is boring, but writing a command-line to do it for you is fun.

You can either

  • ping all hosts and parse /proc/net/arp (or arp -n if not on Linux),

  • or you can use nmap (sudo apt-get install nmap ?) to scan the local network for you, and give you both the IP and MAC addresses.

The first solution could be something like this :

for i in `seq 1 254`; do
    ip=192.168.1.$i
    if ping -c 1 -w 1 $ip >/dev/null; then
        mac=$(grep "^$ip" /proc/net/arp | awk '{print $4}')
        echo "$mac  $ip"
    fi
done

The nmap solution, which should be faster, could look like this:

sudo nmap -sP -n -oN - 192.168.1.0/24 | \
perl -nle 'if (/ \b ([0-9\.]{7,15}) \b /x) {$ip=$1} elsif (/ ([0-9A-F:]{17}) /i) {print "$1  $ip"}'

To also get the DNS names, you could pipe the output from above through something like

| while read mac ip; do name=$(dig -x $ip +short | grep -v '^;'); [ -n "$name" ] && ip=$name; echo "$mac  $ip"; done

(With the nmap solution, you could also remove the -n option, and adapt the regex to get the name. If you really enjoy regular expressions).

1

A tool that will handle the majority of this is arpwatch. By default (on Debian, at least) is that it writes to /var/lib/arpwatch/arp.dat. This file is flushed and updated each time arpwatch is stopped.

The file contains entries of this form:

52:54:00:aa:bb:cc  192.168.1.2  1452252063  somehostname  eth0

The /etc/ethers file requires only the MAC address and either the IP address or resolvable hostname:

52:54:00:aa:bb:cc  192.168.1.2

It is then quite straightforward to keep /etc/ethers updated and in sync with a small script, run daily from crontab:

#!/bin/bash

# Flush arp.dat
service arpwatch restart

# Save a copy
test -f /etc/ethers || touch /etc/ethers
cp -fp /etc/ethers /etc/ethers.old

# Check to see if anything new has arrived. If so rebuild the file
(
    echo '# This file is updated automatically from /var/lib/arpwatch/arp.dat'
    echo '# Take care when editing'
    echo '#'
    (
        awk '{print $1,$2}' /var/lib/arpwatch/arp.dat
        grep -v '^#' /etc/ethers.old
    ) |
        sort -u
) >/etc/ethers.tmp

# Update ethers with the new file
cmp -s /etc/ethers.tmp /etc/ethers || cat /etc/ethers.tmp >/etc/ethers
rm -f /etc/ethers.tmp

# All done
exit 0
0

arp -a will list the ARP cache table on your system which should show the MAC addresses for IP addresses on your computer's local subnet that you have recently accessed. However for your intended use, this table may not be useful as entries in that table can and will get removed after some period of time. This period of time is OS TCP stack implementation dependent.

Of course it would be possible to have a constantly running script that periodically performs the arp -a command and updates a file with the new information retrieved.

1
  • I don't mind manually creating / editing the file. The trouble is actually accessing the file and extracting the MAC address. Do you think I would have to write this myself? The only language I really know is PHP! - mind you, I don't mind learning a bit of bash in order to solve a problem. Aug 8, 2012 at 18:53
0

I've written a little script that retrieves the mac-address and hostname or ip-address from the dhcpd.conf and then construct the wakeup packet (improved version of someone else' perl script). If you want, I can put it on pastebin.com or such.

1
  • You could for others, but I'm doing my own bash script now. Aug 8, 2012 at 19:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .