Bugzilla – Bug 10184
Add Server's MAC address to server discovery packets or add query for it
Last modified: 2010-01-20 11:06:30 UTC
I am trying to implement WOL on iPeng, but I seem to be unable to figure out a way to determine a server's MAC-Address on iPhone, all the routing APIs have been removed from the kernel there. Right now, I will let the user enter the address, but that's a fudge. Would it be possible for the server to return it's MAC? preferably the MAC of the NIC through which the communication happens (that's probably also the easiest solution), alternatively a list of all MACs.
Felix: have any advice for Joerg on implementing WOL as SB does?
SBC and SB currently check the ARP cache.
Yes, that's what I tried, too. The problem is, all APR related IOCTL code got removed from the kernel on iPhone. We also tried packet sniffing for APR tables and evelyating the routing table. Same result. I will continue to try to find ways to get hold of packets but I'm running out of ideas right now, don't have too much experience with this low level stuff. Hence this enhancement request.
Here is perl code so that the server can return the mac address. On windows, it calls ipconfig /all. On linux & osx, it calls ifconfig -a. On SqueezeOS, it uses IOCTL calls. # Adapted from python code at from: http://code.activestate.com/recipes/439094/ sub IOCTLGetMacAddress { my $interface = shift || "eth0"; socket(my $socket, AF_INET, SOCK_DGRAM, 0); my $buf = pack("a256", $interface); # SIOCGIFHWADDR == 0x8927 ioctl($socket, 0x8927, $buf); close($socket); my $macstr = sprintf("%s%s:%s%s:%s%s:%s%s:%s%s:%s%s",split('',uc unpack("H12",substr($buf, 18, 6)))); return $macstr; } my $max_addrs = 30; # Adapted from http://www.perlmonks.org/?node_id=53660 sub IOCTLGetInterfaces { my %interfaces; socket(my $socket, AF_INET, SOCK_DGRAM, 0); # or die "socket: $!"; { my $ifreqpack = 'a16a16'; my $buf = pack($ifreqpack, '', '') x $max_addrs; my $ifconf = pack('iP', length($buf), $buf); #SIOCGIFCONF == 0x8912 ioctl($socket, 0x8912, $ifconf); my $len = unpack('iP', $ifconf); substr($buf, $len) = ''; %interfaces = unpack("($ifreqpack)*", $buf); unless (keys(%interfaces) < $max_addrs) { # Buffer was too small $max_addrs += 10; redo; } } for my $addr (values %interfaces) { $addr = inet_ntoa((sockaddr_in($addr))[1]); } my @nics; my $interfaceMAC; while( my ($interfaceName, $interfaceIP) = each %interfaces ) { #truncate the interface name.. substr($interfaceName, index($interfaceName, chr(0))) = ''; $interfaceMAC = IOCTLGetMacAddress ($interfaceName); push ( @nics, { interfaceName => $interfaceName, interfaceMAC => $interfaceMAC, interfaceIP => $interfaceIP, }); } return @nics; } sub GetServerMacAddress { #If TinySC, don't make a system call.. if ( defined( &Slim::Utils::OSDetect::isSqueezeOS ) && Slim::Utils::OSDetect::isSqueezeOS() ) { my $my_ip = Slim::Utils::Network::serverAddr(); my @interfaces = IOCTLGetInterfaces(); foreach my $interface (@interfaces) { if ( $my_ip eq $interface->{interfaceIP} ) { return $interface->{interfaceMAC}; } } return 'UNKNOWN'; } my $serverMAC; if ($^O =~ /^m?s?win/i) { ## Windows? $serverMAC = `ipconfig /all`; } else { ## Everything else.. $serverMAC = `ifconfig -a`; #$serverMAC = IOCTLGetMacAddress(); } if ( $serverMAC =~ /((?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2})/i ) { $serverMAC = $1; $serverMAC =~ s/\-/\:/g ; ## Windows ipconfig formats MAC as aa-bb-cc-dd-ee-ff return $serverMAC; } return 'UNKNOWN'; }