source: epoptes/trunk/fuentes/epoptes/core/wol.py @ 295

Last change on this file since 295 was 295, checked in by mabarracus, 4 years ago

copy trusty epoptes code

  • Property svn:executable set to *
File size: 3.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4###########################################################################
5# Wake on LAN.
6#
7# Copyright (C) 2010-2013 Alkis Georgopoulos <alkisg@gmail.com>
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FINESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21#
22# On Debian GNU/Linux systems, the complete text of the GNU General
23# Public License can be found in `/usr/share/common-licenses/GPL".
24###########################################################################
25
26import array
27import fcntl
28import socket
29import struct
30import sys
31
32
33IFNAMSIZ = 16               # interface name size
34# From <bits/ioctls.h>
35SIOCGIFADDR = 0x8915        # get PA address
36SIOCGIFBRDADDR  = 0x8919    # get broadcast PA address
37SIOCGIFCONF = 0x8912        # get iface list
38
39
40# create a socket to communicate with system
41sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
42
43
44def _call(ifname, func, ip = None):
45
46    if ip is None:
47        data = (ifname + '\0'*32)[:32]
48    else:
49        ifreq = (ifname + '\0' * IFNAMSIZ)[:IFNAMSIZ]
50        data = struct.pack("16si4s10x", ifreq, socket.AF_INET, socket.inet_aton(ip))
51
52    try:
53        result = fcntl.ioctl(sockfd.fileno(), func, data)
54    except IOError:
55        return None
56
57    return result
58
59
60def getInterfaceList():
61    """ Get all interface names in a list """
62    # get interface list
63    buffer = array.array('c', '\0' * 1024)
64    ifconf = struct.pack("iP", buffer.buffer_info()[1], buffer.buffer_info()[0])
65    result = fcntl.ioctl(sockfd.fileno(), SIOCGIFCONF, ifconf)
66
67    # loop over interface names
68    iflist = []
69    size, ptr = struct.unpack("iP", result)
70    for idx in range(0, size, 32):
71        ifconf = buffer.tostring()[idx:idx+32]
72        name, dummy = struct.unpack("16s16s", ifconf)
73        name, dummy = name.split('\0', 1)
74        iflist.append(name)
75
76    return iflist
77
78
79def getBroadcast(ifname):
80    """ Get the broadcast addr for an interface """
81    result = _call(ifname, SIOCGIFBRDADDR)
82    return socket.inet_ntoa(result[20:24])
83
84
85def getBroadcastList():
86    brlist = ['<broadcast>']
87    for ifname in getInterfaceList():
88        if ifname != 'lo':
89            brlist.append(getBroadcast(ifname))
90    return brlist
91
92
93def wake_on_lan(macaddress):
94    """ Switches on remote computers using WOL. """
95
96    # Check macaddress format and try to compensate.
97    if len(macaddress) == 12:
98        pass
99    elif len(macaddress) == 12 + 5:
100        sep = macaddress[2]
101        macaddress = macaddress.replace(sep, '')
102    else:
103        raise ValueError('Incorrect MAC address format')
104 
105    print "Sending magic packet to", macaddress
106    # Pad the synchronization stream.
107    data = ''.join(['FFFFFFFFFFFF', macaddress * 20])
108    send_data = '' 
109
110    # Split up the hex values and pack.
111    for i in range(0, len(data), 2):
112        send_data = ''.join([send_data,
113                             struct.pack('B', int(data[i: i + 2], 16))])
114
115    # Broadcast it to the LAN.
116    sockfd.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
117    for br in getBroadcastList():
118        sockfd.sendto(send_data, (br, 9))
119
120if __name__ == '__main__':
121    for mac in sys.argv[1:]:
122        wake_on_lan(mac)
Note: See TracBrowser for help on using the repository browser.