2

I am currently writing a python program that needs to discover other instances of itself on LAN. It uses UDP broadcasts for discovery (255.255.255.255).

The problem is that if the computer has multiple network adapters (is connected to multiple networks) then only one of those networks will receive the broadcast. My initial idea was to enumerate through all network addresses assigned to local networks and send a broadcast packet for each one (for example 192.168.0.255 and 192.168.1.255). However, there seems to be no reliable way to detect all the local network addresses as everything I found and tried either relies on python-2-only library or returns only 127.0.1.1 on my linux virtual machine (which has 192.168.0.100 and some others).

How can I broadcast to all available networks in this case?

I'm using Python 3 and am looking for platform-independent way to do it, and without big third-party libraries. A library that correctly displays all network interfaces would do the job.

stormbreaker
  • 848
  • 13
  • 22
  • Sorry, I'm not aware of any Python library that would do this for you. For what is worth: on Windows you can parse the outout of `ipconfig /all`, on Linux look at `ip addr` and `ip link`. – E.Z. Jun 17 '13 at 09:49
  • 1
    Worst advice you can give. There are modules intended to to the work. Always avoid launching external commands - it's bad practice. – Michał Fita Jun 17 '13 at 10:08
  • 1
    If you send a UDP packet to `255.255.255.255` it should be sent to all network interfaces by default, although there are supposedly [some issues](http://serverfault.com/questions/72112/how-to-alter-the-global-broadcast-address-255-255-255-255-behavior-on-windows) with the implementation in Windows. – Aya Jun 17 '13 at 10:36
  • Okay, that seems to be bogus. Given that any call to `sendto()` can only generate a single packet, and even if you can frob the routing table correctly, there's no way it can have the correct source IP address on all interfaces. FWIW, if you can enumerate the local interfaces, you can do a separate `bind()` to each interface, and still `sendto(..., ('255.255.255.255', ...))` if that's what you want to do. – Aya Jun 17 '13 at 11:10
  • 1
    If you can't find a working cross-platform library, you could use [`ctypes`](http://docs.python.org/2/library/ctypes.html) to hit either [`getifaddrs(3)`](http://linux.die.net/man/3/getifaddrs) or [`GetIpAddrTable()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365949%28v=vs.85%29.aspx) directly (depending on platform). See also [this forum thread](http://developerweb.net/viewtopic.php?id=5085). – Aya Jun 17 '13 at 11:12
  • 1
    Related: [UDP-Broadcast on all interfaces](http://stackoverflow.com/questions/683624/udp-broadcast-on-all-interfaces) – Aya Jun 17 '13 at 11:17
  • @Aya thanks for the links. Finding a working cross-platform library for address enumeration is what I want to do essentially. I was hoping I wouldn't have to use low-level C APIs. – stormbreaker Jun 17 '13 at 11:23
  • Well, a quick google for `python getifaddrs` yields a couple of examples for using `getifaddrs(3)` with `ctypes`, although I couldn't (quickly) find a corresponding example for `GetIpAddrTable()`. Either way, it's probably easier than recompiling `netifaces` for Python 3.x, particularly if you don't have a C compiler for Win32. – Aya Jun 17 '13 at 11:34

2 Answers2

0

Try nmap. There is python-nmap here https://pypi.python.org/pypi/python-nmap for your needs

NOTE: the 0.2.7 version number is for python-nmap, not python itself, so it works in python3).

neko_ua
  • 440
  • 3
  • 7
0

Interesting problem. However:

  1. Until you have your application installed on every node don't expect answer from every machine in the network. For security reasons answering to broadcasts is forbidden in certain types of devices and systems.
  2. You can try following code to obtain local addresses:

    import socket
    myips = socket.gethostbyname_ex(socket.gethostname())[2]
    [ip for ip in myips if not ip.startswith("127.")][:1]
    

    The problem with detecting the netmask set for that IP remains.

  3. Use netifaces module available on pypi as well. Examples on the page are enough to explain how to use the module.

Michał Fita
  • 1,183
  • 1
  • 7
  • 24
  • Thanks for the answer. 1. I know, my application will listen for broadcasts and respond. Problem is sending those. 2. Problem is this one doesn't work correctly on my linux VM. It returns only one, unrelated ['127.0.1.1'] even though iptables shows 192.168.0.100 properly. 3. netifaces seems to be a python-2-only lib. – stormbreaker Jun 17 '13 at 10:16
  • I think the code is simple enough to correct it to Python 3. It uses standard system calls inside. – Michał Fita Jun 17 '13 at 10:21
  • I found a port, but it doesn't install on windows as there is C code that needs to be compiled etc... – stormbreaker Jun 17 '13 at 10:33
  • I want my program to be as portable as possible. Requiring a compiler to be installed on every client is not my intention. – stormbreaker Jun 17 '13 at 10:51
  • Ask author of the module to provide binary for Windows' Python 3. – Michał Fita Jun 17 '13 at 11:00