├── netifaces ├── py.typed ├── __init__.py ├── __init__.pyi └── _netifaces.c ├── MANIFEST.in ├── pyproject.toml ├── .gitignore ├── LICENSE ├── setup.cfg ├── test.py ├── .github └── workflows │ └── build-wheels.yml ├── CHANGELOG ├── README.rst └── setup.py /netifaces/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include test.py 3 | -------------------------------------------------------------------------------- /netifaces/__init__.py: -------------------------------------------------------------------------------- 1 | from _netifaces import * 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-requires] 2 | requires = ["setuptools", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | .cache 4 | .eggs 5 | *.egg-info 6 | *.egg 7 | *# 8 | .#* 9 | dist 10 | build 11 | wheelhouse 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2018 Alastair Houghton 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = netifaces-plus 3 | version = 0.12.5 4 | url = https://github.com/tsukumijima/netifaces-plus 5 | description = Portable network interface information (Supports Python 3.6 and higher) 6 | long_description_content_type = text/x-rst 7 | long_description = file: README.rst 8 | license = MIT License 9 | license_files = 10 | LICENSE 11 | classifiers = 12 | Development Status :: 4 - Beta 13 | Intended Audience :: Developers 14 | License :: OSI Approved :: MIT License 15 | Topic :: System :: Networking 16 | Programming Language :: Python :: 3 17 | Programming Language :: Python :: 3.6 18 | Programming Language :: Python :: 3.7 19 | Programming Language :: Python :: 3.8 20 | Programming Language :: Python :: 3.9 21 | Programming Language :: Python :: 3.10 22 | Programming Language :: Python :: 3.11 23 | Programming Language :: Python :: 3.12 24 | Programming Language :: Python :: 3.13 25 | Programming Language :: Python :: 3.14 26 | Programming Language :: Python :: Implementation :: CPython 27 | 28 | [options] 29 | packages = find: 30 | python_requires = >=3.6 31 | 32 | [options.package_data] 33 | * = *.pyi, py.typed 34 | -------------------------------------------------------------------------------- /netifaces/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | AF_12844: int 4 | AF_APPLETALK: int 5 | AF_ASH: int 6 | AF_ATM: int 7 | AF_ATMPVC: int 8 | AF_ATMSVC: int 9 | AF_AX25: int 10 | AF_BAN: int 11 | AF_BLUETOOTH: int 12 | AF_BRIDGE: int 13 | AF_DATAKIT: int 14 | AF_DECnet: int 15 | AF_CCITT: int 16 | AF_CHAOS: int 17 | AF_CLUSTER: int 18 | AF_CNT: int 19 | AF_COIP: int 20 | AF_DLI: int 21 | AF_ECONET: int 22 | AF_ECMA: int 23 | AF_FILE: int 24 | AF_FIREFOX: int 25 | AF_HYLINK: int 26 | AF_IMPLINK: int 27 | AF_INET: int 28 | AF_INET6: int 29 | AF_IPX: int 30 | AF_IRDA: int 31 | AF_ISDN: int 32 | AF_ISO: int 33 | AF_KEY: int 34 | AF_LAT: int 35 | AF_LINK: int 36 | AF_NATM: int 37 | AF_NETBEUI: int 38 | AF_NETBIOS: int 39 | AF_NETDES: int 40 | AF_NETGRAPH: int 41 | AF_NETLINK: int 42 | AF_NETROM: int 43 | AF_NDRV: int 44 | AF_NS: int 45 | AF_PACKET: int 46 | AF_PPP: int 47 | AF_PPPOX: int 48 | AF_PUP: int 49 | AF_ROSE: int 50 | AF_ROUTE: int 51 | AF_SECURITY: int 52 | AF_SIP: int 53 | AF_SNA: int 54 | AF_SYSTEM: int 55 | AF_UNIX: int 56 | AF_UNKNOWN1: int 57 | AF_UNSPEC: int 58 | AF_VOICEVIEW: int 59 | AF_WANPIPE: int 60 | AF_X25: int 61 | IN6_IFF_AUTOCONF: int 62 | IN6_IFF_TEMPORARY: int 63 | IN6_IFF_DYNAMIC: int 64 | IN6_IFF_OPTIMISTIC: int 65 | IN6_IFF_SECURED: int 66 | 67 | address_families: dict[int, str] 68 | version: str 69 | 70 | def gateways() -> dict[Union[str, int], Union[dict[int, tuple[str, str]], list[Union[tuple[str, str], tuple[str, str, bool]]]]]: ... 71 | def ifaddresses(ifname: str, /) -> dict[int, list[dict[str, str]]]: ... 72 | def allifaddresses() -> dict[str, dict[int, list[dict[str, str]]]]: ... 73 | def interfaces() -> list[str]: ... 74 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import netifaces 2 | 3 | print('Found interfaces:') 4 | for iface in netifaces.interfaces(): 5 | print(' %s' % iface) 6 | 7 | print('') 8 | 9 | for iface in netifaces.interfaces(): 10 | allAddrs = netifaces.ifaddresses(iface) 11 | 12 | print('Interface %s:' % iface) 13 | 14 | for family in allAddrs: 15 | addrs = allAddrs[family] 16 | fam_name = netifaces.address_families[family] 17 | print(' Address family: %s' % fam_name) 18 | for addr in addrs: 19 | print(' Address : %s' % addr['addr']) 20 | nmask = addr.get('netmask', None) 21 | if nmask: 22 | print(' Netmask : %s' % nmask) 23 | bcast = addr.get('broadcast', None) 24 | if bcast: 25 | print(' Broadcast: %s' % bcast) 26 | 27 | print('') 28 | 29 | print('Found gateways:') 30 | gateway_info = netifaces.gateways() 31 | for family in gateway_info: 32 | if family == 'default': 33 | continue 34 | 35 | fam_name = netifaces.address_families[family] 36 | print(' Family: %s' % fam_name) 37 | for gateway,interface,default in gateway_info[family]: 38 | if default: 39 | def_text = ', default' 40 | else: 41 | def_text = '' 42 | print(' %s (via %s%s)' % (gateway, interface, def_text)) 43 | print('') 44 | 45 | print('Default gateways:') 46 | default_gateways = gateway_info['default'] 47 | for family in default_gateways: 48 | fam_name = netifaces.address_families[family] 49 | gateway, interface = default_gateways[family] 50 | print(' %s: %s (via %s)' % (fam_name, gateway, interface)) 51 | 52 | print('') 53 | 54 | print('Getting information about all available interfaces: ') 55 | all_interfaces = netifaces.allifaddresses() 56 | for if_name, if_info in all_interfaces.items(): 57 | all_Addrs = netifaces.ifaddresses(if_name) 58 | 59 | if all_Addrs == if_info: 60 | print(' Information for %s from netifaces.allifaddresses()\n' 61 | ' are equal with info from netifaces.ifaddresses(\'%s\')' % (if_name, if_name)) 62 | else: 63 | print(' Information for %s from netifaces.allifaddresses()\n' 64 | ' are NOT EQUAL with info from netifaces.ifaddresses(\'%s\')!!!' % (if_name, if_name)) 65 | print('') -------------------------------------------------------------------------------- /.github/workflows/build-wheels.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish Wheels 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | permissions: 8 | contents: read 9 | id-token: write 10 | 11 | jobs: 12 | build-wheels: 13 | name: Build Wheels on ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [windows-2022, macos-15, ubuntu-24.04, ubuntu-24.04-arm] 17 | include: 18 | - os: windows-2022 19 | archs: [AMD64, x86, ARM64] 20 | - os: macos-15 21 | archs: [x86_64, arm64, universal2] 22 | - os: ubuntu-24.04 23 | archs: [x86_64] 24 | - os: ubuntu-24.04-arm 25 | archs: [aarch64, armv7l] 26 | runs-on: ${{ matrix.os }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | with: 30 | submodules: true 31 | 32 | - name: Set up Python 33 | uses: actions/setup-python@v5 34 | with: 35 | python-version: '3.x' 36 | cache: 'pip' 37 | 38 | - name: Setup cibuildwheel cache 39 | uses: actions/cache@v4 40 | with: 41 | path: | 42 | ~/.cache/pip 43 | ~/.cache/cibuildwheel 44 | ~/Library/Caches/pip 45 | ~/AppData/Local/pip/Cache 46 | key: ${{ runner.os }}-cibuildwheel-${{ hashFiles('**/pyproject.toml', '**/setup.py') }} 47 | restore-keys: | 48 | ${{ runner.os }}-cibuildwheel- 49 | 50 | - name: Setup QEMU for Linux multi-arch 51 | if: runner.os == 'Linux' 52 | uses: docker/setup-qemu-action@v3 53 | with: 54 | platforms: all 55 | 56 | - name: Build Wheels 57 | uses: pypa/cibuildwheel@main 58 | env: 59 | CIBW_ARCHS_LINUX: ${{ contains(matrix.os, 'ubuntu') && join(matrix.archs, ' ') || 'x86_64' }} 60 | CIBW_ARCHS_WINDOWS: ${{ contains(matrix.os, 'windows') && join(matrix.archs, ' ') || 'AMD64' }} 61 | CIBW_ARCHS_MACOS: ${{ (contains(matrix.os, 'macos') && join(matrix.archs, ' ')) || 'x86_64' }} 62 | CIBW_TEST_SKIP: "*-win_arm64" 63 | CIBW_SKIP: pp* *-musllinux* 64 | 65 | - uses: actions/upload-artifact@v4 66 | with: 67 | name: wheels-${{ matrix.os }}-${{ join(matrix.archs, '-') }} 68 | path: ./wheelhouse 69 | retention-days: 5 70 | 71 | build-sdist: 72 | name: Build source distribution 73 | runs-on: ubuntu-latest 74 | steps: 75 | - uses: actions/checkout@v4 76 | with: 77 | submodules: true 78 | 79 | - name: Build sdist 80 | run: pipx run build --sdist 81 | 82 | - uses: actions/upload-artifact@v4 83 | with: 84 | name: wheels-sdist 85 | path: dist/*.tar.gz 86 | retention-days: 5 87 | 88 | publish-wheels: 89 | name: Publish Wheels 90 | needs: [build-wheels, build-sdist] 91 | runs-on: ubuntu-latest 92 | steps: 93 | - uses: actions/download-artifact@v4 94 | with: 95 | pattern: wheels-* 96 | merge-multiple: true 97 | path: ./wheelhouse 98 | 99 | - name: Publish to TestPyPI 100 | uses: pypa/gh-action-pypi-publish@release/v1 101 | if: ${{ !startsWith(github.ref, 'refs/tags') }} 102 | continue-on-error: true 103 | with: 104 | repository-url: https://test.pypi.org/legacy/ 105 | packages-dir: ./wheelhouse 106 | skip-existing: true 107 | password: ${{ secrets.TEST_PYPI_API_TOKEN }} 108 | 109 | - name: Publish to PyPI 110 | uses: pypa/gh-action-pypi-publish@release/v1 111 | if: ${{ startsWith(github.ref, 'refs/tags') }} 112 | with: 113 | packages-dir: ./wheelhouse 114 | skip-existing: true 115 | password: ${{ secrets.PYPI_API_TOKEN }} 116 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-02 Version 0.12.5 (fork as netiface-plus) 2 | 3 | * Added support for Python 3.14. 4 | 5 | 2024-11-29 Version 0.12.4 (fork as netiface-plus) 6 | 7 | * Added support for Linux armv7l architecture. 8 | 9 | 2024-10-22 Version 0.12.3 (fork as netiface-plus) 10 | 11 | * Added support for Python 3.13. 12 | 13 | 2024-06-12 Version 0.12.2 (fork as netiface-plus) 14 | 15 | * Prevent crash when addr->if_addr is NULL for an interface. 16 | 17 | 2023-10-11 Version 0.12.1 (fork as netiface-plus) 18 | 19 | * Added support for Python 3.12. 20 | 21 | 2022-10-01 Version 0.12.0 (fork as netiface-plus) 22 | 23 | * Added support for Python 3.9 and higher. 24 | * Dropped support for Python 3.5 and below. 25 | * Remove legacy build scripts. 26 | * Migrate Wheels builds to GitHub Actions. 27 | * Modernize packaging (thanks James Morris). 28 | * Reorganized package layout (thanks James Morris). 29 | * Added support for type hints (thanks James Morris). 30 | * Added new function for loading info from all interfaces 31 | (thanks LukasMazl). 32 | 33 | 2021-05-31 Version 0.11.0 34 | 35 | * Added notice about needing a new maintainer. 36 | * Fixed link to Travis CI. 37 | * Added test.py to the source distribution. 38 | * Fixed netmask calculation for IPv6. 39 | * Fixes to gateway detection in some edge cases. 40 | * Build CPython 2.7 wheels for 64-bit Windows (yes, you should be 41 | using Python 3 now, but still). 42 | 43 | Thank-you to Thomas Sibley, Rajendra Dendukuri, Harshal Patel, 44 | Jeff Gordon, Sajith Sasidharan and Yuri Sevatz for contributing 45 | to this release. 46 | 47 | 2019-01-02 Version 0.10.9 48 | 49 | * Added missing LICENSE file to MANIFEST.in. 50 | 51 | 2019-01-02 Version 0.10.8 52 | 53 | * Fixed a bug that in certain circumstances could lead to an infinite 54 | loop in netifaces.gateways() (thanks asomers). 55 | * Fixed a memory management bug in an error path (thanks NicoPy). 56 | 57 | 2018-05-08 Version 0.10.7 58 | 59 | * Added LICENSE file 60 | * Automated Windows builds via AppVeyor. 61 | 62 | 2017-06-01 Version 0.10.6 63 | 64 | * Fixed netmask determination on Windows. 65 | * All addresses are now unicode strings on all platforms, 66 | regardless of Python version. 67 | 68 | 2016-08-23 Version 0.10.5 69 | 70 | * Fixed setup.py in case there's no print (thanks Stavros). 71 | * Fixed a potential one-byte stack overwrite (thanks Doug Horn). 72 | * Fixed possible null pointer deference (thanks bastiak). 73 | * Added support for IPv6 address flags on BSD/Mac OS X (thanks 74 | stefann). 75 | * Respect interface priorities when determining default gateway 76 | (on Windows and Linux). 77 | * Use CIDR notation for IPv6 netmasks. 78 | * Ignore broadcast addresses in the 169.254.0.0/16 range (it 79 | appears Cygwin's getaddrinfo() may erroneously generate these). 80 | * Stop using deprecated WSAAddressToStringA() API on Windows 81 | in favour of using WSAAddressToStringW() where available. Falls 82 | back to the older API if required. 83 | 84 | 2014-05-19 Version 0.10.4 85 | 86 | * Fixed a problem with multi-part Netlink messages on Linux. 87 | 88 | 2014-05-06 Version 0.10.3 89 | 90 | * When using Netlink (i.e. Linux), check for the constant 91 | NLM_F_DUMP_INTR, since it only appeared in kernel version 3.1 92 | 93 | 2014-05-03 Version 0.10.2 94 | 95 | * Added a workaround for broken netlink headers on certain Linux 96 | distributions (the problem being that the netlink headers fail to 97 | include , which causes a build failure). 98 | 99 | 2014-05-02 Version 0.10.1 100 | 101 | * Fixed a problem with the gateways() function that caused it a 102 | crash on PyPy. 103 | * The CI system is now set up to build for PyPy as well, so 104 | problems will be found sooner. 105 | 106 | 2014-05-01 Version 0.10.0 107 | 108 | * Python 3 compatibility. 109 | * Improved Windows source code compatibility. 110 | * Added gateway detection via gateways() function. 111 | * New version number format (skipped 0.9.0 due to its use by 112 | the netifaces-merged fork). 113 | 114 | 2012-01-31 Version 0.8 115 | 116 | All changes in this version relate to the ioctl( ) code path, 117 | which is not used on Windows or on any modern UNIX or UNIX-like 118 | system that implements getaddrinfo(). 119 | 120 | * Fixed bit-rot in the ioctl() code path. 121 | * Fixed a problem with setup.py that might manifest itself if the 122 | config.cache file was manually edited. 123 | * Fixed the ioctl() code path to cope with systems that have 124 | sa_len and return longer than normal struct ifreq requests from 125 | SIOCG[L]IFCONF (for instance, Mac OS X). 126 | 127 | 2012-01-30 Version 0.7 128 | 129 | * Dropped support for Win2K and earlier 130 | * Added support for addresses other than IPv4 on Windows 131 | * Removed empty 'addr' entries for interfaces that don't provide 132 | any addresses. 133 | * Fixed problems with setup script that prevented it running on 134 | Windows, and improved the chances of it working with 135 | cross-compilers somewhat. 136 | * Added a verion property to the module that you can test at 137 | runtime. 138 | 139 | 2011-11-04 Version 0.6 140 | 141 | * Added a workaround for a FreeBSD kernel bug (kern/152036). 142 | * Added address_families dictionary to allow code to look up the 143 | symbolic name corresponding to a given numberic address family 144 | code. 145 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | netifaces-plus 0.12.5 2 | ===================== 3 | 4 | | This library is a fork of `al45tair/netifaces `_. 5 | | Since the `al45tair/netifaces `_ repository is archived, Merged unmerged pull requests and useful changes. 6 | 7 | Changes since netifaces 0.11.0 are as follows: 8 | 9 | * Add support for Python 3.9 and higher. 10 | * Drop support for Python 3.5 and below. 11 | * Remove legacy build scripts. 12 | * Migrate Wheels builds to GitHub Actions. 13 | * Modernize packaging (`al45tair/netifaces#77 `_). 14 | * Reorganized package layout (`al45tair/netifaces#77 `_). 15 | * Add support for type hints (`al45tair/netifaces#77 `_). 16 | * Add new function for loading info from all interfaces (`al45tair/netifaces#76 `_). 17 | 18 | I haven't tested it much, but it should probably work. 19 | 20 | | Personally, I recommend using https://pypi.org/project/ifaddr/ instead of this library. 21 | | It is more modern code and built only in Python. 22 | 23 | 1. What is this? 24 | ---------------- 25 | 26 | It's been annoying me for some time that there's no easy way to get the 27 | address(es) of the machine's network interfaces from Python. There is 28 | a good reason for this difficulty, which is that it is virtually impossible 29 | to do so in a portable manner. However, it seems to me that there should 30 | be a package you can easy_install that will take care of working out the 31 | details of doing so on the machine you're using, then you can get on with 32 | writing Python code without concerning yourself with the nitty gritty of 33 | system-dependent low-level networking APIs. 34 | 35 | This package attempts to solve that problem. 36 | 37 | 2. How do I use it? 38 | ------------------- 39 | 40 | First you need to install it, which you can do by typing:: 41 | 42 | pip install netifaces-plus 43 | 44 | **Note that you will need the relevant developer tools for your platform**, 45 | as netifaces is written in C and installing this way will compile the extension. 46 | 47 | Once that's done, you'll need to start Python and do something like the 48 | following:: 49 | 50 | >>> import netifaces 51 | 52 | Then if you enter 53 | 54 | >>> netifaces.interfaces() 55 | ['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0'] 56 | 57 | you'll see the list of interface identifiers for your machine. 58 | 59 | You can ask for the addresses of a particular interface by doing 60 | 61 | >>> netifaces.ifaddresses('lo0') 62 | {18: [{'addr': ''}], 2: [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}], 30: [{'peer': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'addr': '::1'}, {'peer': '', 'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::1%lo0'}]} 63 | 64 | Hmmmm. That result looks a bit cryptic; let's break it apart and explain 65 | what each piece means. It returned a dictionary, so let's look there first:: 66 | 67 | { 18: [...], 2: [...], 30: [...] } 68 | 69 | Each of the numbers refers to a particular address family. In this case, we 70 | have three address families listed; on my system, 18 is ``AF_LINK`` (which means 71 | the link layer interface, e.g. Ethernet), 2 is ``AF_INET`` (normal Internet 72 | addresses), and 30 is ``AF_INET6`` (IPv6). 73 | 74 | But wait! Don't use these numbers in your code. The numeric values here are 75 | system dependent; fortunately, I thought of that when writing netifaces, so 76 | the module declares a range of values that you might need. e.g. 77 | 78 | >>> netifaces.AF_LINK 79 | 18 80 | 81 | Again, on your system, the number may be different. 82 | 83 | So, what we've established is that the dictionary that's returned has one 84 | entry for each address family for which this interface has an address. Let's 85 | take a look at the ``AF_INET`` addresses now: 86 | 87 | >>> addrs = netifaces.ifaddresses('lo0') 88 | >>> addrs[netifaces.AF_INET] 89 | [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}] 90 | 91 | You might be wondering why this value is a list. The reason is that it's 92 | possible for an interface to have more than one address, even within the 93 | same family. I'll say that again: *you can have more than one address of 94 | the same type associated with each interface*. 95 | 96 | *Asking for "the" address of a particular interface doesn't make sense.* 97 | 98 | Right, so, we can see that this particular interface only has one address, 99 | and, because it's a loopback interface, it's point-to-point and therefore 100 | has a *peer* address rather than a broadcast address. 101 | 102 | Let's look at a more interesting interface. 103 | 104 | >>> addrs = netifaces.ifaddresses('en0') 105 | >>> addrs[netifaces.AF_INET] 106 | [{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}] 107 | 108 | This interface has two addresses (see, I told you...) Both of them are 109 | regular IPv4 addresses, although in one case the netmask has been changed 110 | from its default. The netmask *may not* appear on your system if it's set 111 | to the default for the address range. 112 | 113 | Because this interface isn't point-to-point, it also has broadcast addresses. 114 | 115 | Now, say we want, instead of the IP addresses, to get the MAC address; that 116 | is, the hardware address of the Ethernet adapter running this interface. We 117 | can do 118 | 119 | >>> addrs[netifaces.AF_LINK] 120 | [{'addr': '00:12:34:56:78:9a'}] 121 | 122 | Note that this may not be available on platforms without getifaddrs(), unless 123 | they happen to implement ``SIOCGIFHWADDR``. Note also that you just get the 124 | address; it's unlikely that you'll see anything else with an ``AF_LINK`` address. 125 | Oh, and don't assume that all ``AF_LINK`` addresses are Ethernet; you might, for 126 | instance, be on a Mac, in which case: 127 | 128 | >>> addrs = netifaces.ifaddresses('fw0') 129 | >>> addrs[netifaces.AF_LINK] 130 | [{'addr': '00:12:34:56:78:9a:bc:de'}] 131 | 132 | No, that isn't an exceptionally long Ethernet MAC address---it's a FireWire 133 | address. 134 | 135 | As of version 0.10.0, you can also obtain a list of gateways on your 136 | machine: 137 | 138 | >>> netifaces.gateways() 139 | {2: [('10.0.1.1', 'en0', True), ('10.2.1.1', 'en1', False)], 30: [('fe80::1', 'en0', True)], 'default': { 2: ('10.0.1.1', 'en0'), 30: ('fe80::1', 'en0') }} 140 | 141 | This dictionary is keyed on address family---in this case, ``AF_INET``---and 142 | each entry is a list of gateways as ``(address, interface, is_default)`` tuples. 143 | Notice that here we have two separate gateways for IPv4 (``AF_INET``); some 144 | operating systems support configurations like this and can either route packets 145 | based on their source, or based on administratively configured routing tables. 146 | 147 | For convenience, we also allow you to index the dictionary with the special 148 | value ``'default'``, which returns a dictionary mapping address families to the 149 | default gateway in each case. Thus you can get the default IPv4 gateway with 150 | 151 | >>> gws = netifaces.gateways() 152 | >>> gws['default'][netifaces.AF_INET] 153 | ('10.0.1.1', 'en0') 154 | 155 | Do note that there may be no default gateway for any given address family; 156 | this is currently very common for IPv6 and much less common for IPv4 but it 157 | can happen even for ``AF_INET``. 158 | 159 | BTW, if you're trying to configure your machine to have multiple gateways for 160 | the same address family, it's a very good idea to check the documentation for 161 | your operating system *very* carefully, as some systems become extremely 162 | confused or route packets in a non-obvious manner. 163 | 164 | I'm very interested in hearing from anyone (on any platform) for whom the 165 | ``gateways()`` method doesn't produce the expected results. It's quite 166 | complicated extracting this information from the operating system (whichever 167 | operating system we're talking about), and so I expect there's at least one 168 | system out there where this just won't work. 169 | 170 | 3. This is great! What platforms does it work on? 171 | -------------------------------------------------- 172 | 173 | It gets regular testing on OS X, Linux and Windows. It has also been used 174 | successfully on Solaris, and it's expected to work properly on other UNIX-like 175 | systems as well. If you are running something that is not supported, and 176 | wish to contribute a patch, please use Github to send a pull request. 177 | 178 | 4. What license is this under? 179 | ------------------------------ 180 | 181 | It's an MIT-style license. See `LICENSE <./LICENSE>`_. 182 | 183 | 5. Why the jump to 0.10.0? 184 | -------------------------- 185 | 186 | Because someone released a fork of netifaces with the version 0.9.0. 187 | Hopefully skipping the version number should remove any confusion. In 188 | addition starting with 0.10.0 Python 3 is now supported and other 189 | features/bugfixes have been included as well. See the CHANGELOG for a 190 | more complete list of changes. 191 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import sys 5 | import pickle 6 | 7 | import setuptools 8 | from setuptools import setup, Extension 9 | from setuptools.command.build_ext import build_ext 10 | from setuptools.config import read_configuration 11 | from distutils.errors import * 12 | 13 | __version__ = read_configuration('setup.cfg')['metadata']['version'] 14 | 15 | # Disable hard links, otherwise building distributions fails on OS X 16 | try: 17 | del os.link 18 | except: 19 | pass 20 | 21 | # On Windows, we need ws2_32 and iphlpapi 22 | if getattr(sys, 'getwindowsversion', None): 23 | libraries = ['ws2_32', 'iphlpapi'] 24 | def_macros = [('WIN32', 1)] 25 | else: 26 | mos = getattr(sys, 'platform', None) 27 | libraries = [] 28 | if mos.startswith('sunos'): 29 | libraries = ['socket', 'nsl'] 30 | def_macros = [] 31 | 32 | def_macros.append(("NETIFACES_VERSION", __version__)) 33 | 34 | iface_mod = Extension('_netifaces', sources=['netifaces/_netifaces.c'], 35 | libraries=libraries, 36 | define_macros=def_macros) 37 | 38 | 39 | # 40 | # There must be a better way to do this... 41 | # 42 | class my_build_ext(build_ext): 43 | def build_extensions(self): 44 | self.check_requirements() 45 | build_ext.build_extensions(self) 46 | 47 | def test_build(self, contents, link=True, execute=False, libraries=None, 48 | include_dirs=None, library_dirs=None): 49 | name = os.path.join(self.build_temp, 'conftest-%s.c' % self.conftestidx) 50 | self.conftestidx += 1 51 | if os.path.exists(name): 52 | os.unlink(name) 53 | thefile = open(name, 'w') 54 | thefile.write(contents) 55 | thefile.close() 56 | 57 | sys.stdout.flush() 58 | sys.stderr.flush() 59 | mystdout = os.dup(1) 60 | mystderr = os.dup(2) 61 | result = True 62 | try: 63 | os.dup2(self.ctout, 1) 64 | os.dup2(self.ctout, 2) 65 | try: 66 | objects = self.compiler.compile([name], 67 | output_dir=self.build_temp, 68 | include_dirs=include_dirs, 69 | debug=self.debug) 70 | if link: 71 | self.compiler.link_executable(objects, 72 | 'conftest', 73 | output_dir=self.build_temp, 74 | library_dirs=library_dirs, 75 | libraries=libraries, 76 | debug=self.debug) 77 | if execute: 78 | abspath = os.path.abspath(os.path.join(self.build_temp, 79 | 'conftest')) 80 | pipe = os.popen(abspath, 'r') 81 | result = pipe.read().strip() 82 | status = pipe.close() 83 | if status is None: 84 | status = 0 85 | if result == '': 86 | result = True 87 | if status != 0: 88 | result = False 89 | 90 | finally: 91 | os.dup2(mystdout, 1) 92 | os.dup2(mystderr, 2) 93 | except CompileError: 94 | return False 95 | except LinkError: 96 | return False 97 | except DistutilsExecError: 98 | return False 99 | return result 100 | 101 | def check_requirements(self): 102 | # Load the cached config data from a previous run if possible; compiling 103 | # things to test for features is slow 104 | cache_file = os.path.join(self.build_temp, 'config.cache') 105 | if os.path.exists(cache_file): 106 | myfile = open(cache_file, 'rb') 107 | try: 108 | results = pickle.load(myfile) 109 | finally: 110 | myfile.close() 111 | else: 112 | results = {} 113 | 114 | self.conftestidx = 0 115 | 116 | print("checking for getifaddrs...", end='') 117 | 118 | result = results.get('have_getifaddrs', None) 119 | if result is not None: 120 | cached = '(cached)' 121 | else: 122 | cached = '' 123 | 124 | if not os.path.exists(self.build_temp): 125 | os.makedirs(self.build_temp) 126 | outname = os.path.join(self.build_temp, 'conftest.out') 127 | self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) 128 | testrig = """ 129 | #include 130 | #include 131 | #include 132 | int main(void) { 133 | struct ifaddrs *addrs; 134 | int ret; 135 | ret = getifaddrs(&addrs); 136 | freeifaddrs (addrs); 137 | return 0; 138 | } 139 | """ 140 | if self.test_build(testrig): 141 | result = True 142 | else: 143 | result = False 144 | 145 | if result: 146 | print("found. %s" % cached) 147 | self.compiler.define_macro('HAVE_GETIFADDRS', 1) 148 | else: 149 | print("not found. %s" % cached) 150 | 151 | results['have_getifaddrs'] = result 152 | 153 | print("checking for getnameinfo...", end='') 154 | 155 | result = results.get('have_getnameinfo', None) 156 | if result is not None: 157 | cached = '(cached)' 158 | else: 159 | cached = '' 160 | 161 | if not os.path.exists(self.build_temp): 162 | os.makedirs(self.build_temp) 163 | outname = os.path.join(self.build_temp, 'conftest2.out') 164 | self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) 165 | testrig = """ 166 | #include 167 | #include 168 | #include 169 | #include 170 | #include 171 | int main(void) { 172 | struct sockaddr_in sin; 173 | char buffer[256]; 174 | int ret; 175 | 176 | sin.sin_family = AF_INET; 177 | sin.sin_port = 0; 178 | sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 179 | 180 | ret = getnameinfo ((struct sockaddr *)&sin, sizeof (sin), 181 | buffer, sizeof (buffer), 182 | NULL, 0, 183 | NI_NUMERICHOST); 184 | 185 | return 0; 186 | } 187 | """ 188 | if self.test_build(testrig,libraries=libraries): 189 | result = True 190 | else: 191 | result = False 192 | 193 | if result: 194 | print("found. %s" % cached) 195 | self.compiler.define_macro('HAVE_GETNAMEINFO', 1) 196 | else: 197 | print("not found. %s" % cached) 198 | 199 | results['have_getnameinfo'] = result 200 | 201 | if results['have_getifaddrs']: 202 | print("checking for IPv6 socket IOCTLs...", end='') 203 | 204 | result = results.get('have_ipv6_socket_ioctls', None) 205 | if result is not None: 206 | cached = '(cached)' 207 | else: 208 | cached = '' 209 | 210 | if not os.path.exists(self.build_temp): 211 | os.makedirs(self.build_temp) 212 | outname = os.path.join(self.build_temp, 'conftest4.out') 213 | self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) 214 | 215 | result = [] 216 | ioctls = ('SIOCGIFAFLAG_IN6',) 217 | added_includes = "" 218 | if mos.startswith('sunos'): 219 | added_includes = """ 220 | #include 221 | #include 222 | #include 223 | """ 224 | 225 | for ioctl in ioctls: 226 | testrig = """ 227 | #include 228 | #include 229 | #include 230 | #include 231 | #include 232 | #include 233 | #include 234 | %(addedinc)s 235 | int main(void) { 236 | int fd = socket (AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); 237 | struct in6_ifreq ifreq; 238 | 239 | ioctl(fd, %(ioctl)s, &ifreq); 240 | 241 | return 0; 242 | } 243 | """ % { 'ioctl': ioctl , 'addedinc': added_includes} 244 | 245 | if self.test_build(testrig,libraries=libraries): 246 | result.append(ioctl) 247 | 248 | if result: 249 | print("%r. %s" % (result, cached)) 250 | for ioctl in result: 251 | self.compiler.define_macro('HAVE_%s' % ioctl, 1) 252 | self.compiler.define_macro('HAVE_IPV6_SOCKET_IOCTLS', 1) 253 | else: 254 | print("not found. %s" % cached) 255 | 256 | results['have_ipv6_socket_ioctls'] = result 257 | 258 | if not results['have_getifaddrs']: 259 | print("checking for socket IOCTLs...", end='') 260 | 261 | result = results.get('have_socket_ioctls', None) 262 | if result is not None: 263 | cached = '(cached)' 264 | else: 265 | cached = '' 266 | 267 | if not os.path.exists(self.build_temp): 268 | os.makedirs(self.build_temp) 269 | outname = os.path.join(self.build_temp, 'conftest3.out') 270 | self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) 271 | 272 | result = [] 273 | ioctls = ('SIOCGIFCONF', 274 | 'SIOCGSIZIFCONF', 275 | 'SIOCGIFHWADDR', 276 | 'SIOCGIFADDR', 277 | 'SIOCGIFFLAGS', 278 | 'SIOCGIFDSTADDR', 279 | 'SIOCGIFBRDADDR', 280 | 'SIOCGIFNETMASK', 281 | 'SIOCGLIFNUM', 282 | 'SIOCGLIFCONF', 283 | 'SIOCGLIFFLAGS') 284 | added_includes = "" 285 | if mos.startswith('sunos'): 286 | added_includes = """ 287 | #include 288 | #include 289 | #include 290 | """ 291 | 292 | for ioctl in ioctls: 293 | testrig = """ 294 | #include 295 | #include 296 | #include 297 | #include 298 | #include 299 | #include 300 | %(addedinc)s 301 | int main(void) { 302 | int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP); 303 | struct ifreq ifreq; 304 | 305 | ioctl(fd, %(ioctl)s, &ifreq); 306 | 307 | return 0; 308 | } 309 | """ % { 'ioctl': ioctl , 'addedinc': added_includes} 310 | 311 | if self.test_build(testrig,libraries=libraries): 312 | result.append(ioctl) 313 | 314 | if result: 315 | print("%r. %s" % (result, cached)) 316 | for ioctl in result: 317 | self.compiler.define_macro('HAVE_%s' % ioctl, 1) 318 | self.compiler.define_macro('HAVE_SOCKET_IOCTLS', 1) 319 | else: 320 | print("not found. %s" % cached) 321 | 322 | results['have_socket_ioctls'] = result 323 | 324 | print("checking for optional header files...", end='') 325 | 326 | result = results.get('have_headers', None) 327 | if result is not None: 328 | cached = '(cached)' 329 | else: 330 | cached = '' 331 | 332 | result =[] 333 | headers = ('net/if_dl.h', 'netash/ash.h', 334 | 'netatalk/at.h', 'netax25/ax25.h', 335 | 'neteconet/ec.h', 'netipx/ipx.h', 336 | 'netpacket/packet.h', 'netrose/rose.h', 337 | 'linux/irda.h', 'linux/atm.h', 338 | 'linux/llc.h', 'linux/tipc.h', 339 | 'linux/dn.h') 340 | 341 | for header in headers: 342 | testrig = """ 343 | #include 344 | #include 345 | #include 346 | #include <%s> 347 | int main (void) { return 0; } 348 | """ % header 349 | 350 | if self.test_build(testrig, link=False): 351 | result.append(header) 352 | 353 | if result: 354 | print("%s. %s" % (' '.join(result), cached)) 355 | for header in result: 356 | macro = header.upper().replace('.', '_').replace('/', '_') 357 | self.compiler.define_macro('HAVE_%s' % macro, 1) 358 | else: 359 | print("none found. %s" % cached) 360 | 361 | optional_headers = result 362 | results['have_headers'] = result 363 | 364 | print("checking whether struct sockaddr has a length field...", end='') 365 | 366 | result = results.get('have_sockaddr_sa_len', None) 367 | if result is not None: 368 | cached = '(cached)' 369 | else: 370 | cached = '' 371 | 372 | testrig = """ 373 | #include 374 | #include 375 | #include 376 | 377 | int main (void) { 378 | struct sockaddr sa; 379 | sa.sa_len = 5; 380 | return 0; 381 | } 382 | """ 383 | 384 | result = self.test_build(testrig) 385 | 386 | if result: 387 | print('yes. %s' % cached) 388 | self.compiler.define_macro('HAVE_SOCKADDR_SA_LEN', 1) 389 | else: 390 | print('no. %s' % cached) 391 | 392 | results['have_sockaddr_sa_len'] = result 393 | 394 | if not results['have_sockaddr_sa_len']: 395 | # GAK! On certain stupid platforms (Linux), there's no sa_len. 396 | # Macho Linux programmers apparently think that it's not needed, 397 | # however, unfortunately, getifaddrs() doesn't return the 398 | # lengths, because they're in the sa_len field on just about 399 | # everything but Linux. 400 | print("checking which sockaddr_xxx structs are defined...", end='') 401 | 402 | result = results.get('have_sockaddrs', None) 403 | if result is not None: 404 | cached = '(cached)' 405 | else: 406 | cached = '' 407 | 408 | if not os.path.exists(self.build_temp): 409 | os.makedirs(self.build_temp) 410 | outname = os.path.join(self.build_temp, 'conftest5.out') 411 | self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) 412 | 413 | sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6', 414 | 'inarp', 'ipx', 'iso', 'ns', 'un', 'x25', 415 | 'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc', 416 | 'dn', 'irda', 'llc') 417 | result = [] 418 | for sockaddr in sockaddrs: 419 | testrig = """ 420 | #include 421 | #include 422 | #include 423 | #include 424 | #include 425 | %(includes)s 426 | 427 | int main (void) { 428 | struct sockaddr_%(sockaddr)s sa; 429 | return 0; 430 | } 431 | """ % { 'includes': '\n'.join(["#include <%s>" % header 432 | for header 433 | in optional_headers]), 434 | 'sockaddr': sockaddr } 435 | 436 | if self.test_build(testrig): 437 | result.append(sockaddr) 438 | 439 | if result: 440 | print('%s. %s' % (' '.join(result), cached)) 441 | for sockaddr in result: 442 | self.compiler.define_macro('HAVE_SOCKADDR_%s' \ 443 | % sockaddr.upper(), 1) 444 | else: 445 | print('none! %s' % cached) 446 | 447 | results['have_sockaddrs'] = result 448 | 449 | # Reading routing tables is very OS dependent; check for a few 450 | # different approaches. 451 | print("checking for routing socket support...", end='') 452 | 453 | result = results.get('have_pf_route', None) 454 | if result is not None: 455 | cached = '(cached)' 456 | else: 457 | cached = '' 458 | 459 | testrig = """ 460 | #include 461 | #include 462 | #include 463 | 464 | int main (void) { 465 | struct rt_msghdr msg; 466 | int s = socket (PF_ROUTE, SOCK_RAW, 0); 467 | return 0; 468 | } 469 | """ 470 | 471 | result = self.test_build(testrig) 472 | 473 | if result: 474 | print('yes. %s' % cached) 475 | self.compiler.define_macro('HAVE_PF_ROUTE', 1) 476 | else: 477 | print('no. %s' % cached) 478 | 479 | results['have_pf_route'] = result 480 | 481 | print("checking for sysctl(CTL_NET...) support...", end='') 482 | 483 | result = results.get('have_sysctl_ctl_net', None) 484 | if result is not None: 485 | cached = '(cached)' 486 | else: 487 | cached = '' 488 | 489 | testrig = """ 490 | #include 491 | #include 492 | #include 493 | #include 494 | 495 | int main (void) { 496 | int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, 497 | RTF_UP | RTF_GATEWAY }; 498 | return 0; 499 | } 500 | """ 501 | 502 | result = self.test_build(testrig) 503 | 504 | if result: 505 | print('yes. %s' % cached) 506 | self.compiler.define_macro('HAVE_SYSCTL_CTL_NET', 1) 507 | else: 508 | print('no. %s' % cached) 509 | 510 | results['have_sysctl_ctl_net'] = result 511 | 512 | print("checking for netlink support...", end='') 513 | 514 | result = results.get('have_pf_netlink', None) 515 | if result is not None: 516 | cached = '(cached)' 517 | else: 518 | cached = '' 519 | 520 | testrig = """ 521 | #include 522 | #include 523 | #include 524 | #include 525 | 526 | int main (void) { 527 | int s = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 528 | return 0; 529 | } 530 | """ 531 | 532 | result = self.test_build(testrig) 533 | 534 | if result: 535 | print('yes. %s' % cached) 536 | self.compiler.define_macro('HAVE_PF_NETLINK', 1) 537 | else: 538 | print('no. %s' % cached) 539 | 540 | results['have_pf_netlink'] = result 541 | 542 | if results['have_pf_netlink']: 543 | print('will use netlink to read routing table') 544 | elif results['have_sysctl_ctl_net']: 545 | print('will use sysctl() to read routing table') 546 | elif results['have_pf_route']: 547 | print('will use routing socket to read routing table') 548 | 549 | # Save the results to our config.cache file 550 | myfile = open(cache_file, 'wb') 551 | try: 552 | pickle.dump(results, myfile) 553 | finally: 554 | myfile.close() 555 | 556 | 557 | # Don't bother detecting socket ioctls on Windows 558 | if not getattr(sys, 'getwindowsversion', None): 559 | setuptools.command.build_ext.build_ext = my_build_ext 560 | 561 | setup(ext_modules=[iface_mod]) 562 | -------------------------------------------------------------------------------- /netifaces/_netifaces.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Before Python 2.6, PyUnicode_FromString doesn't exist */ 4 | #if PY_MAJOR_VERSION < 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6) 5 | PyObject *PyUnicode_FromString(const char *s) 6 | { 7 | Py_ssize_t len = strlen(s); 8 | if (!len) { 9 | Py_UNICODE uc = 0; 10 | return PyUnicode_FromUnicode(&uc, 0); 11 | } 12 | return PyUnicode_DecodeUTF8(s, len, NULL); 13 | } 14 | #endif 15 | 16 | /* Python 3 compatibility */ 17 | #if PY_MAJOR_VERSION >= 3 18 | #define PyInt_FromLong PyLong_FromLong 19 | 20 | #define MODULE_ERROR NULL 21 | #define MODULE_RETURN(v) return (v) 22 | #define MODULE_INIT(name) PyMODINIT_FUNC PyInit_##name(void) 23 | #define MODULE_DEF(name,doc,methods) \ 24 | static struct PyModuleDef moduledef = { \ 25 | PyModuleDef_HEAD_INIT, (name), (doc), -1, (methods), }; 26 | #define MODULE_CREATE(obj,name,doc,methods) \ 27 | obj = PyModule_Create(&moduledef); 28 | #else /* PY_MAJOR_VERSION < 3 */ 29 | #define MODULE_ERROR 30 | #define MODULE_RETURN(v) 31 | #define MODULE_INIT(name) void init##name(void) 32 | #define MODULE_DEF(name,doc,methods) 33 | #define MODULE_CREATE(obj,name,doc,methods) \ 34 | obj = Py_InitModule3((name), (methods), (doc)); 35 | #endif 36 | 37 | #ifndef WIN32 38 | 39 | # include 40 | # include 41 | # include 42 | # include 43 | 44 | # if HAVE_PF_ROUTE 45 | # include 46 | # endif 47 | 48 | # if HAVE_SYSCTL_CTL_NET 49 | # include 50 | # include 51 | # endif 52 | 53 | /* RTNL_FAMILY_MAX not there yet in old kernels, see linux commit 25239ce */ 54 | # if HAVE_PF_NETLINK 55 | # include 56 | # include 57 | # include 58 | # if !defined(RTNL_FAMILY_MAX) 59 | # include 60 | # define RTNL_FAMILY_MAX NPROTO 61 | # endif 62 | # include 63 | # endif 64 | 65 | # if HAVE_GETIFADDRS 66 | # if HAVE_IPV6_SOCKET_IOCTLS 67 | # include 68 | # include 69 | # include 70 | # endif 71 | # endif 72 | 73 | # if HAVE_SOCKET_IOCTLS 74 | # include 75 | # include 76 | # include 77 | # if defined(__sun) 78 | # include 79 | # include 80 | # include 81 | # endif 82 | # endif /* HAVE_SOCKET_IOCTLS */ 83 | 84 | /* For logical interfaces support we convert all names to same name prefixed 85 | with l */ 86 | #if HAVE_SIOCGLIFNUM 87 | #define CNAME(x) l##x 88 | #else 89 | #define CNAME(x) x 90 | #endif 91 | 92 | #if HAVE_NET_IF_DL_H 93 | # include 94 | #endif 95 | 96 | /* For the benefit of stupid platforms (Linux), include all the sockaddr 97 | definitions we can lay our hands on. It can also be useful for the benefit 98 | of another stupid platform (FreeBSD, see PR 152036). */ 99 | #include 100 | # if HAVE_NETASH_ASH_H 101 | # include 102 | # endif 103 | # if HAVE_NETATALK_AT_H 104 | # include 105 | # endif 106 | # if HAVE_NETAX25_AX25_H 107 | # include 108 | # endif 109 | # if HAVE_NETECONET_EC_H 110 | # include 111 | # endif 112 | # if HAVE_NETIPX_IPX_H 113 | # include 114 | # endif 115 | # if HAVE_NETPACKET_PACKET_H 116 | # include 117 | # endif 118 | # if HAVE_NETROSE_ROSE_H 119 | # include 120 | # endif 121 | # if HAVE_LINUX_IRDA_H 122 | # include 123 | # endif 124 | # if HAVE_LINUX_ATM_H 125 | # include 126 | # endif 127 | # if HAVE_LINUX_LLC_H 128 | # include 129 | # endif 130 | # if HAVE_LINUX_TIPC_H 131 | # include 132 | # endif 133 | # if HAVE_LINUX_DN_H 134 | # include 135 | # endif 136 | 137 | /* Map address families to sizes of sockaddr structs */ 138 | static int af_to_len(int af) 139 | { 140 | switch (af) { 141 | case AF_INET: return sizeof (struct sockaddr_in); 142 | #if defined(AF_INET6) && HAVE_SOCKADDR_IN6 143 | case AF_INET6: return sizeof (struct sockaddr_in6); 144 | #endif 145 | #if defined(AF_AX25) && HAVE_SOCKADDR_AX25 146 | # if defined(AF_NETROM) 147 | case AF_NETROM: /* I'm assuming this is carried over x25 */ 148 | # endif 149 | case AF_AX25: return sizeof (struct sockaddr_ax25); 150 | #endif 151 | #if defined(AF_IPX) && HAVE_SOCKADDR_IPX 152 | case AF_IPX: return sizeof (struct sockaddr_ipx); 153 | #endif 154 | #if defined(AF_APPLETALK) && HAVE_SOCKADDR_AT 155 | case AF_APPLETALK: return sizeof (struct sockaddr_at); 156 | #endif 157 | #if defined(AF_ATMPVC) && HAVE_SOCKADDR_ATMPVC 158 | case AF_ATMPVC: return sizeof (struct sockaddr_atmpvc); 159 | #endif 160 | #if defined(AF_ATMSVC) && HAVE_SOCKADDR_ATMSVC 161 | case AF_ATMSVC: return sizeof (struct sockaddr_atmsvc); 162 | #endif 163 | #if defined(AF_X25) && HAVE_SOCKADDR_X25 164 | case AF_X25: return sizeof (struct sockaddr_x25); 165 | #endif 166 | #if defined(AF_ROSE) && HAVE_SOCKADDR_ROSE 167 | case AF_ROSE: return sizeof (struct sockaddr_rose); 168 | #endif 169 | #if defined(AF_DECnet) && HAVE_SOCKADDR_DN 170 | case AF_DECnet: return sizeof (struct sockaddr_dn); 171 | #endif 172 | #if defined(AF_PACKET) && HAVE_SOCKADDR_LL 173 | case AF_PACKET: return sizeof (struct sockaddr_ll); 174 | #endif 175 | #if defined(AF_ASH) && HAVE_SOCKADDR_ASH 176 | case AF_ASH: return sizeof (struct sockaddr_ash); 177 | #endif 178 | #if defined(AF_ECONET) && HAVE_SOCKADDR_EC 179 | case AF_ECONET: return sizeof (struct sockaddr_ec); 180 | #endif 181 | #if defined(AF_IRDA) && HAVE_SOCKADDR_IRDA 182 | case AF_IRDA: return sizeof (struct sockaddr_irda); 183 | #endif 184 | #if defined(AF_LINK) && HAVE_SOCKADDR_DL 185 | case AF_LINK: return sizeof (struct sockaddr_dl); 186 | #endif 187 | } 188 | return sizeof (struct sockaddr); 189 | } 190 | 191 | #if !HAVE_SOCKADDR_SA_LEN 192 | #define SA_LEN(sa) af_to_len(sa->sa_family) 193 | #if HAVE_SIOCGLIFNUM 194 | #define SS_LEN(sa) af_to_len(sa->ss_family) 195 | #else 196 | #define SS_LEN(sa) SA_LEN(sa) 197 | #endif 198 | #else 199 | #define SA_LEN(sa) sa->sa_len 200 | #endif /* !HAVE_SOCKADDR_SA_LEN */ 201 | 202 | # if HAVE_GETIFADDRS 203 | # include 204 | # endif /* HAVE_GETIFADDRS */ 205 | 206 | # if !HAVE_GETIFADDRS && (!HAVE_SOCKET_IOCTLS || !HAVE_SIOCGIFCONF) 207 | /* If the platform doesn't define, what we need, barf. If you're seeing this, 208 | it means you need to write suitable code to retrieve interface information 209 | on your system. */ 210 | # error You need to add code for your platform. 211 | # endif 212 | 213 | #else /* defined(WIN32) */ 214 | 215 | #define _WIN32_WINNT 0x0501 216 | 217 | # include 218 | # include 219 | # include 220 | # include 221 | 222 | #endif /* defined(WIN32) */ 223 | 224 | #ifndef TRUE 225 | #define TRUE 1 226 | #endif 227 | 228 | #ifndef FALSE 229 | #define FALSE 0 230 | #endif 231 | 232 | /* On systems without AF_LINK (Windows, for instance), define it anyway, but 233 | give it a crazy value. On Linux, which has AF_PACKET but not AF_LINK, 234 | define AF_LINK as the latter instead. */ 235 | #ifndef AF_LINK 236 | # ifdef AF_PACKET 237 | # define AF_LINK AF_PACKET 238 | # else 239 | # define AF_LINK -1000 240 | # endif 241 | # define HAVE_AF_LINK 0 242 | #else 243 | # define HAVE_AF_LINK 1 244 | #endif 245 | 246 | /* -- Utility Functions ----------------------------------------------------- */ 247 | 248 | #if !defined(WIN32) 249 | #if !HAVE_GETNAMEINFO 250 | #undef getnameinfo 251 | #undef NI_NUMERICHOST 252 | 253 | #define getnameinfo our_getnameinfo 254 | #define NI_NUMERICHOST 1 255 | 256 | /* A very simple getnameinfo() for platforms without */ 257 | static int 258 | getnameinfo (const struct sockaddr *addr, int addr_len, 259 | char *buffer, int buflen, 260 | char *buf2, int buf2len, 261 | int flags) 262 | { 263 | switch (addr->sa_family) { 264 | case AF_INET: 265 | { 266 | const struct sockaddr_in *sin = (struct sockaddr_in *)addr; 267 | const unsigned char *bytes = (unsigned char *)&sin->sin_addr.s_addr; 268 | char tmpbuf[20]; 269 | 270 | sprintf (tmpbuf, "%d.%d.%d.%d", 271 | bytes[0], bytes[1], bytes[2], bytes[3]); 272 | 273 | strncpy (buffer, tmpbuf, buflen); 274 | } 275 | break; 276 | #ifdef AF_INET6 277 | case AF_INET6: 278 | { 279 | const struct sockaddr_in6 *sin = (const struct sockaddr_in6 *)addr; 280 | const unsigned char *bytes = sin->sin6_addr.s6_addr; 281 | int n; 282 | char tmpbuf[80], *ptr = tmpbuf; 283 | int done_double_colon = FALSE; 284 | int colon_mode = FALSE; 285 | 286 | for (n = 0; n < 8; ++n) { 287 | unsigned char b1 = bytes[2 * n]; 288 | unsigned char b2 = bytes[2 * n + 1]; 289 | 290 | if (b1) { 291 | if (colon_mode) { 292 | colon_mode = FALSE; 293 | *ptr++ = ':'; 294 | } 295 | sprintf (ptr, "%x%02x", b1, b2); 296 | ptr += strlen (ptr); 297 | *ptr++ = ':'; 298 | } else if (b2) { 299 | if (colon_mode) { 300 | colon_mode = FALSE; 301 | *ptr++ = ':'; 302 | } 303 | sprintf (ptr, "%x", b2); 304 | ptr += strlen (ptr); 305 | *ptr++ = ':'; 306 | } else { 307 | if (!colon_mode) { 308 | if (done_double_colon) { 309 | *ptr++ = '0'; 310 | *ptr++ = ':'; 311 | } else { 312 | if (n == 0) 313 | *ptr++ = ':'; 314 | colon_mode = TRUE; 315 | done_double_colon = TRUE; 316 | } 317 | } 318 | } 319 | } 320 | if (colon_mode) { 321 | colon_mode = FALSE; 322 | *ptr++ = ':'; 323 | *ptr++ = '\0'; 324 | } else { 325 | *--ptr = '\0'; 326 | } 327 | 328 | strncpy (buffer, tmpbuf, buflen); 329 | } 330 | break; 331 | #endif /* AF_INET6 */ 332 | default: 333 | return -1; 334 | } 335 | 336 | return 0; 337 | } 338 | #endif 339 | 340 | static int 341 | string_from_sockaddr (struct sockaddr *addr, 342 | char *buffer, 343 | size_t buflen) 344 | { 345 | struct sockaddr* bigaddr = 0; 346 | int failure; 347 | struct sockaddr* gniaddr; 348 | socklen_t gnilen; 349 | 350 | if (!addr || addr->sa_family == AF_UNSPEC) 351 | return -1; 352 | 353 | if (SA_LEN(addr) < af_to_len(addr->sa_family)) { 354 | /* Sometimes ifa_netmask can be truncated. So let's detruncate it. FreeBSD 355 | PR: kern/152036: getifaddrs(3) returns truncated sockaddrs for netmasks 356 | -- http://www.freebsd.org/cgi/query-pr.cgi?pr=152036 */ 357 | gnilen = af_to_len(addr->sa_family); 358 | bigaddr = calloc(1, gnilen); 359 | if (!bigaddr) 360 | return -1; 361 | memcpy(bigaddr, addr, SA_LEN(addr)); 362 | #if HAVE_SOCKADDR_SA_LEN 363 | bigaddr->sa_len = gnilen; 364 | #endif 365 | gniaddr = bigaddr; 366 | } else { 367 | gnilen = SA_LEN(addr); 368 | gniaddr = addr; 369 | } 370 | 371 | failure = getnameinfo (gniaddr, gnilen, 372 | buffer, buflen, 373 | NULL, 0, 374 | NI_NUMERICHOST); 375 | 376 | if (bigaddr) { 377 | free(bigaddr); 378 | bigaddr = 0; 379 | } 380 | 381 | if (failure) { 382 | size_t n, len; 383 | char *ptr; 384 | const char *data; 385 | 386 | len = SA_LEN(addr); 387 | 388 | #if HAVE_AF_LINK 389 | /* BSD-like systems have AF_LINK */ 390 | if (addr->sa_family == AF_LINK) { 391 | struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr; 392 | len = dladdr->sdl_alen; 393 | data = LLADDR(dladdr); 394 | } else { 395 | #endif 396 | #if defined(AF_PACKET) 397 | /* Linux has AF_PACKET instead */ 398 | if (addr->sa_family == AF_PACKET) { 399 | struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr; 400 | len = lladdr->sll_halen; 401 | data = (const char *)lladdr->sll_addr; 402 | } else { 403 | #endif 404 | /* We don't know anything about this sockaddr, so just display 405 | the entire data area in binary. */ 406 | len -= (sizeof (struct sockaddr) - sizeof (addr->sa_data)); 407 | data = addr->sa_data; 408 | #if defined(AF_PACKET) 409 | } 410 | #endif 411 | #if HAVE_AF_LINK 412 | } 413 | #endif 414 | 415 | if (buflen < 3 * len) 416 | return -1; 417 | 418 | ptr = buffer; 419 | buffer[0] = '\0'; 420 | 421 | for (n = 0; n < len; ++n) { 422 | sprintf (ptr, "%02x:", data[n] & 0xff); 423 | ptr += 3; 424 | } 425 | if (len) 426 | *--ptr = '\0'; 427 | } 428 | 429 | if (!buffer[0]) 430 | return -1; 431 | 432 | return 0; 433 | } 434 | 435 | /* Tries to format in CIDR form where possible; falls back to using 436 | string_from_sockaddr(). */ 437 | static int 438 | string_from_netmask (struct sockaddr *addr, 439 | char *buffer, 440 | size_t buflen) 441 | { 442 | #ifdef AF_INET6 443 | if (addr && addr->sa_family == AF_INET6) { 444 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 445 | unsigned n = 16; 446 | unsigned zeroes = 0; 447 | unsigned prefix; 448 | unsigned bytes; 449 | char *bufptr = buffer; 450 | char *bufend = buffer + buflen; 451 | char pfxbuf[16]; 452 | 453 | while (n--) { 454 | unsigned char byte = sin6->sin6_addr.s6_addr[n]; 455 | 456 | /* We need to count the rightmost zeroes */ 457 | unsigned char x = byte; 458 | unsigned zx = 8; 459 | 460 | x &= -x; 461 | if (x) 462 | --zx; 463 | if (x & 0x0f) 464 | zx -= 4; 465 | if (x & 0x33) 466 | zx -= 2; 467 | if (x & 0x55) 468 | zx -= 1; 469 | 470 | zeroes += zx; 471 | 472 | if (byte) 473 | break; 474 | } 475 | 476 | prefix = 128 - zeroes; 477 | bytes = 2 * ((prefix + 15) / 16); 478 | 479 | for (n = 0; n < bytes; ++n) { 480 | unsigned char byte = sin6->sin6_addr.s6_addr[n]; 481 | char ch1, ch2; 482 | 483 | if (n && !(n & 1)) { 484 | if (bufptr < bufend) 485 | *bufptr++ = ':'; 486 | } 487 | 488 | ch1 = '0' + (byte >> 4); 489 | if (ch1 > '9') 490 | ch1 += 'a' - '0' - 10; 491 | ch2 = '0' + (byte & 0xf); 492 | if (ch2 > '9') 493 | ch2 += 'a' - '0' - 10; 494 | 495 | if (bufptr < bufend) 496 | *bufptr++ = ch1; 497 | if (bufptr < bufend) 498 | *bufptr++ = ch2; 499 | } 500 | 501 | if (bytes < 16) { 502 | if (bufend - bufptr > 2) { 503 | *bufptr++ = ':'; 504 | *bufptr++ = ':'; 505 | } 506 | } 507 | 508 | sprintf (pfxbuf, "/%u", prefix); 509 | 510 | if (bufend - bufptr > (int)strlen(pfxbuf)) 511 | strcpy (bufptr, pfxbuf); 512 | 513 | if (buflen) 514 | buffer[buflen - 1] = '\0'; 515 | 516 | return 0; 517 | } 518 | #endif 519 | 520 | return string_from_sockaddr(addr, buffer, buflen); 521 | } 522 | #endif /* !defined(WIN32) */ 523 | 524 | #if defined(WIN32) 525 | static int 526 | compare_bits (const void *pva, 527 | const void *pvb, 528 | unsigned bits) 529 | { 530 | const unsigned char *pa = (const unsigned char *)pva; 531 | const unsigned char *pb = (const unsigned char *)pvb; 532 | unsigned char a, b; 533 | static unsigned char masks[] = { 534 | 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 535 | }; 536 | while (bits >= 8) { 537 | a = *pa++; 538 | b = *pb++; 539 | if (a < b) 540 | return -1; 541 | else if (a > b) 542 | return +1; 543 | bits -= 8; 544 | } 545 | 546 | if (bits) { 547 | a = *pa++ & masks[bits]; 548 | b = *pb++ & masks[bits]; 549 | if (a < b) 550 | return -1; 551 | else if (a > b) 552 | return +1; 553 | } 554 | 555 | return 0; 556 | } 557 | 558 | static PyObject * 559 | netmask_from_prefix (unsigned prefix) 560 | { 561 | char buffer[256]; 562 | char *bufptr = buffer; 563 | char *bufend = buffer + sizeof(buffer); 564 | unsigned bytes = 2 * ((prefix + 15) / 16); 565 | static const unsigned char masks[] = { 566 | 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 567 | }; 568 | unsigned n; 569 | unsigned left = prefix; 570 | char pfxbuf[16]; 571 | 572 | for (n = 0; n < bytes; ++n) { 573 | unsigned char byte; 574 | char ch1, ch2; 575 | 576 | if (left >= 8) { 577 | byte = 0xff; 578 | left -= 8; 579 | } else { 580 | byte = masks[left]; 581 | left = 0; 582 | } 583 | 584 | if (n && !(n & 1)) { 585 | if (bufptr < bufend) 586 | *bufptr++ = ':'; 587 | } 588 | 589 | ch1 = '0' + (byte >> 4); 590 | if (ch1 > '9') 591 | ch1 += 'a' - '0' - 10; 592 | ch2 = '0' + (byte & 0xf); 593 | if (ch2 > '9') 594 | ch2 += 'a' - '0' - 10; 595 | 596 | if (bufptr < bufend) 597 | *bufptr++ = ch1; 598 | if (bufptr < bufend) 599 | *bufptr++ = ch2; 600 | } 601 | 602 | if (bytes < 16) { 603 | if (bufend - bufptr > 2) { 604 | *bufptr++ = ':'; 605 | *bufptr++ = ':'; 606 | } 607 | } 608 | 609 | sprintf (pfxbuf, "/%u", prefix); 610 | 611 | if ((size_t)(bufend - bufptr) > strlen(pfxbuf)) 612 | strcpy (bufptr, pfxbuf); 613 | 614 | buffer[sizeof(buffer) - 1] = '\0'; 615 | 616 | return PyUnicode_FromString(buffer); 617 | } 618 | 619 | /* We dynamically bind to WSAAddressToStringW or WSAAddressToStringA 620 | depending on which is available, as the latter is deprecated and 621 | the former doesn't exist on all Windows versions on which this code 622 | might run. */ 623 | typedef INT (WSAAPI *WSAAddressToStringWPtr)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOW, LPWSTR, LPDWORD); 624 | typedef INT (WSAAPI *WSAAddressToStringAPtr)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); 625 | 626 | static WSAAddressToStringWPtr 627 | get_address_to_string_w(void) { 628 | static int ptr_is_set; 629 | static WSAAddressToStringWPtr ptr; 630 | 631 | if (!ptr_is_set) { 632 | HMODULE hmod = LoadLibrary ("ws2_32.dll"); 633 | ptr = (WSAAddressToStringWPtr)GetProcAddress (hmod, "WSAAddressToStringW"); 634 | if (!ptr) 635 | FreeLibrary (hmod); 636 | ptr_is_set = 1; 637 | } 638 | 639 | return ptr; 640 | } 641 | 642 | static WSAAddressToStringAPtr 643 | get_address_to_string_a(void) { 644 | static int ptr_is_set; 645 | static WSAAddressToStringAPtr ptr; 646 | 647 | if (!ptr_is_set) { 648 | HMODULE hmod = LoadLibrary ("ws2_32.dll"); 649 | ptr = (WSAAddressToStringAPtr)GetProcAddress (hmod, "WSAAddressToStringA"); 650 | if (!ptr) 651 | FreeLibrary (hmod); 652 | ptr_is_set = 1; 653 | } 654 | 655 | return ptr; 656 | } 657 | 658 | static PyObject * 659 | string_from_address(SOCKADDR *addr, DWORD addrlen) 660 | { 661 | WSAAddressToStringWPtr AddressToStringW = get_address_to_string_w(); 662 | 663 | if (AddressToStringW) { 664 | wchar_t buffer[256]; 665 | DWORD dwLen = sizeof(buffer) / sizeof(wchar_t); 666 | INT iRet; 667 | 668 | iRet = AddressToStringW (addr, addrlen, NULL, buffer, &dwLen); 669 | 670 | if (iRet == 0) 671 | return PyUnicode_FromWideChar (buffer, dwLen - 1); 672 | } else { 673 | char buffer[256]; 674 | DWORD dwLen = sizeof(buffer); 675 | WSAAddressToStringAPtr AddressToStringA = get_address_to_string_a(); 676 | INT iRet; 677 | 678 | iRet = AddressToStringA (addr, addrlen, NULL, buffer, &dwLen); 679 | 680 | if (iRet == 0) 681 | return PyUnicode_FromString (buffer); 682 | } 683 | 684 | return NULL; 685 | } 686 | #endif 687 | 688 | static int 689 | add_to_family (PyObject *result, int family, PyObject *obj) 690 | { 691 | PyObject *py_family; 692 | PyObject *list; 693 | 694 | if (!PyObject_Size (obj)) 695 | return TRUE; 696 | 697 | py_family = PyInt_FromLong (family); 698 | list = PyDict_GetItem (result, py_family); 699 | 700 | if (!py_family) { 701 | Py_DECREF (obj); 702 | Py_XDECREF (list); 703 | return FALSE; 704 | } 705 | 706 | if (!list) { 707 | list = PyList_New (1); 708 | if (!list) { 709 | Py_DECREF (obj); 710 | Py_DECREF (py_family); 711 | return FALSE; 712 | } 713 | 714 | PyList_SET_ITEM (list, 0, obj); 715 | PyDict_SetItem (result, py_family, list); 716 | Py_DECREF (list); 717 | } else { 718 | PyList_Append (list, obj); 719 | Py_DECREF (obj); 720 | } 721 | 722 | return TRUE; 723 | } 724 | 725 | #if HAVE_GETIFADDRS 726 | static PyObject* getifaddrsinfo(struct ifaddrs *addr) 727 | { 728 | /* Sometimes there are records without addresses (e.g. in the case of a 729 | dial-up connection via ppp, which on Linux can have a link address 730 | record with no actual address). We skip these as they aren't useful. 731 | Thanks to Christian Kauhaus for reporting this issue. */ 732 | if (!addr->ifa_addr) 733 | return NULL; 734 | 735 | char buffer[256]; 736 | PyObject *pyaddr = NULL, *netmask = NULL, *braddr = NULL, *flags = NULL; 737 | 738 | #if HAVE_IPV6_SOCKET_IOCTLS 739 | /* For IPv6 addresses we try to get the flags. */ 740 | if (addr->ifa_addr->sa_family == AF_INET6) { 741 | struct sockaddr_in6 *sin; 742 | struct in6_ifreq ifr6; 743 | 744 | int sock6 = socket (AF_INET6, SOCK_DGRAM, 0); 745 | 746 | if (sock6 < 0) { 747 | PyErr_SetFromErrno (PyExc_OSError); 748 | return NULL; 749 | } 750 | 751 | sin = (struct sockaddr_in6 *)addr->ifa_addr; 752 | strncpy (ifr6.ifr_name, addr->ifa_name, IFNAMSIZ); 753 | ifr6.ifr_addr = *sin; 754 | 755 | if (ioctl (sock6, SIOCGIFAFLAG_IN6, &ifr6) >= 0) { 756 | flags = PyLong_FromUnsignedLong (ifr6.ifr_ifru.ifru_flags6); 757 | } 758 | 759 | close (sock6); 760 | } 761 | #endif /* HAVE_IPV6_SOCKET_IOCTLS */ 762 | 763 | if (string_from_sockaddr (addr->ifa_addr, buffer, sizeof (buffer)) == 0) 764 | pyaddr = PyUnicode_FromString (buffer); 765 | 766 | if (string_from_netmask (addr->ifa_netmask, buffer, sizeof (buffer)) == 0) 767 | netmask = PyUnicode_FromString (buffer); 768 | 769 | if (string_from_sockaddr (addr->ifa_broadaddr, buffer, sizeof (buffer)) == 0) 770 | braddr = PyUnicode_FromString (buffer); 771 | 772 | /* Cygwin's implementation of getaddrinfo() is buggy and returns broadcast 773 | addresses for 169.254.0.0/16. Nix them here. */ 774 | if (addr->ifa_addr->sa_family == AF_INET) { 775 | struct sockaddr_in *sin = (struct sockaddr_in *)addr->ifa_addr; 776 | 777 | if ((ntohl(sin->sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000) { 778 | Py_XDECREF (braddr); 779 | braddr = NULL; 780 | } 781 | } 782 | 783 | { 784 | PyObject *dict = PyDict_New(); 785 | 786 | if (!dict) { 787 | Py_XDECREF (pyaddr); 788 | Py_XDECREF (netmask); 789 | Py_XDECREF (braddr); 790 | Py_XDECREF (flags); 791 | return NULL; 792 | } 793 | 794 | if (pyaddr) 795 | PyDict_SetItemString (dict, "addr", pyaddr); 796 | if (netmask) 797 | PyDict_SetItemString (dict, "netmask", netmask); 798 | 799 | if (braddr) { 800 | if (addr->ifa_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) 801 | PyDict_SetItemString (dict, "peer", braddr); 802 | else 803 | PyDict_SetItemString (dict, "broadcast", braddr); 804 | } 805 | 806 | if (flags) 807 | PyDict_SetItemString (dict, "flags", flags); 808 | 809 | Py_XDECREF (pyaddr); 810 | Py_XDECREF (netmask); 811 | Py_XDECREF (braddr); 812 | Py_XDECREF (flags); 813 | 814 | return dict; 815 | } 816 | } 817 | #endif 818 | 819 | #if HAVE_SOCKET_IOCTLS 820 | static PyObject* socket_ioctls_info(const char* ifname, int sock) 821 | { 822 | PyObject* result = PyDict_New (); 823 | if (!result) 824 | return NULL; 825 | 826 | struct CNAME(ifreq) ifr; 827 | PyObject *addr = NULL, *netmask = NULL, *braddr = NULL, *dstaddr = NULL; 828 | int is_p2p = FALSE; 829 | char buffer[256]; 830 | 831 | strncpy (ifr.CNAME(ifr_name), ifname, IFNAMSIZ); 832 | 833 | #if HAVE_SIOCGIFHWADDR 834 | if (ioctl (sock, SIOCGIFHWADDR, &ifr) == 0) { 835 | 836 | if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) { 837 | PyObject *hwaddr = PyUnicode_FromString (buffer); 838 | PyObject *dict = PyDict_New (); 839 | 840 | if (!hwaddr || !dict) { 841 | Py_XDECREF (hwaddr); 842 | Py_XDECREF (dict); 843 | Py_XDECREF (result); 844 | return NULL; 845 | } 846 | 847 | PyDict_SetItemString (dict, "addr", hwaddr); 848 | Py_DECREF (hwaddr); 849 | 850 | if (!add_to_family (result, AF_LINK, dict)) { 851 | Py_DECREF (result); 852 | return NULL; 853 | } 854 | } 855 | } 856 | #endif 857 | 858 | #if HAVE_SIOCGIFADDR 859 | #if HAVE_SIOCGLIFNUM 860 | if (ioctl (sock, SIOCGLIFADDR, &ifr) == 0) { 861 | #else 862 | if (ioctl (sock, SIOCGIFADDR, &ifr) == 0) { 863 | #endif 864 | if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) 865 | addr = PyUnicode_FromString (buffer); 866 | } 867 | #endif 868 | 869 | #if HAVE_SIOCGIFNETMASK 870 | #if HAVE_SIOCGLIFNUM 871 | if (ioctl (sock, SIOCGLIFNETMASK, &ifr) == 0) { 872 | #else 873 | if (ioctl (sock, SIOCGIFNETMASK, &ifr) == 0) { 874 | #endif 875 | if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) 876 | netmask = PyUnicode_FromString (buffer); 877 | } 878 | #endif 879 | 880 | #if HAVE_SIOCGIFFLAGS 881 | #if HAVE_SIOCGLIFNUM 882 | if (ioctl (sock, SIOCGLIFFLAGS, &ifr) == 0) { 883 | #else 884 | if (ioctl (sock, SIOCGIFFLAGS, &ifr) == 0) { 885 | #endif 886 | if (ifr.CNAME(ifr_flags) & IFF_POINTOPOINT) 887 | is_p2p = TRUE; 888 | } 889 | #endif 890 | 891 | #if HAVE_SIOCGIFBRDADDR 892 | #if HAVE_SIOCGLIFNUM 893 | if (!is_p2p && ioctl (sock, SIOCGLIFBRDADDR, &ifr) == 0) { 894 | #else 895 | if (!is_p2p && ioctl (sock, SIOCGIFBRDADDR, &ifr) == 0) { 896 | #endif 897 | if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) 898 | braddr = PyUnicode_FromString (buffer); 899 | } 900 | #endif 901 | 902 | #if HAVE_SIOCGIFDSTADDR 903 | #if HAVE_SIOCGLIFNUM 904 | if (is_p2p && ioctl (sock, SIOCGLIFBRDADDR, &ifr) == 0) { 905 | #else 906 | if (is_p2p && ioctl (sock, SIOCGIFBRDADDR, &ifr) == 0) { 907 | #endif 908 | if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) 909 | dstaddr = PyUnicode_FromString (buffer); 910 | } 911 | #endif 912 | PyObject *dict = PyDict_New(); 913 | 914 | if (!dict) { 915 | Py_XDECREF (addr); 916 | Py_XDECREF (netmask); 917 | Py_XDECREF (braddr); 918 | Py_XDECREF (dstaddr); 919 | Py_DECREF (result); 920 | return NULL; 921 | } 922 | 923 | if (addr) 924 | PyDict_SetItemString (dict, "addr", addr); 925 | if (netmask) 926 | PyDict_SetItemString (dict, "netmask", netmask); 927 | if (braddr) 928 | PyDict_SetItemString (dict, "broadcast", braddr); 929 | if (dstaddr) 930 | PyDict_SetItemString (dict, "peer", dstaddr); 931 | 932 | Py_XDECREF (addr); 933 | Py_XDECREF (netmask); 934 | Py_XDECREF (braddr); 935 | Py_XDECREF (dstaddr); 936 | 937 | if (!add_to_family (result, AF_INET, dict)) { 938 | Py_DECREF (result); 939 | return NULL; 940 | } 941 | 942 | return result; 943 | } 944 | #endif 945 | 946 | #if defined(WIN32) 947 | static PyObject* winifaddrinfo(PIP_ADAPTER_ADDRESSES pInfo) 948 | { 949 | PIP_ADAPTER_UNICAST_ADDRESS pUniAddr; 950 | PyObject* result = PyDict_New(); 951 | if(!result) 952 | return NULL; 953 | 954 | char buffer[256]; 955 | 956 | /* Do the physical address */ 957 | if (256 >= 3 * pInfo->PhysicalAddressLength) { 958 | PyObject *hwaddr, *dict; 959 | char *ptr = buffer; 960 | unsigned n; 961 | 962 | *ptr = '\0'; 963 | for (n = 0; n < pInfo->PhysicalAddressLength; ++n) { 964 | sprintf (ptr, "%02x:", pInfo->PhysicalAddress[n] & 0xff); 965 | ptr += 3; 966 | } 967 | *--ptr = '\0'; 968 | 969 | hwaddr = PyUnicode_FromString (buffer); 970 | dict = PyDict_New (); 971 | 972 | if (!dict) { 973 | Py_XDECREF (hwaddr); 974 | Py_DECREF (result); 975 | return NULL; 976 | } 977 | 978 | PyDict_SetItemString (dict, "addr", hwaddr); 979 | Py_DECREF (hwaddr); 980 | 981 | if (!add_to_family (result, AF_LINK, dict)) { 982 | Py_DECREF (result); 983 | return NULL; 984 | } 985 | } 986 | 987 | for (pUniAddr = pInfo->FirstUnicastAddress; 988 | pUniAddr; 989 | pUniAddr = pUniAddr->Next) { 990 | PyObject *addr; 991 | PyObject *mask = NULL; 992 | PyObject *bcast = NULL; 993 | PIP_ADAPTER_PREFIX pPrefix; 994 | short family = pUniAddr->Address.lpSockaddr->sa_family; 995 | 996 | addr = string_from_address (pUniAddr->Address.lpSockaddr, 997 | pUniAddr->Address.iSockaddrLength); 998 | 999 | if (!addr) 1000 | continue; 1001 | 1002 | /* Find the netmask, where possible */ 1003 | if (family == AF_INET) { 1004 | struct sockaddr_in *pAddr 1005 | = (struct sockaddr_in *)pUniAddr->Address.lpSockaddr; 1006 | int prefix_len = -1; 1007 | struct sockaddr_in maskAddr, bcastAddr; 1008 | unsigned toDo; 1009 | unsigned wholeBytes, remainingBits; 1010 | unsigned char *pMaskBits, *pBcastBits; 1011 | PIP_ADAPTER_PREFIX pBest = NULL; 1012 | 1013 | for (pPrefix = pInfo->FirstPrefix; 1014 | pPrefix; 1015 | pPrefix = pPrefix->Next) { 1016 | struct sockaddr_in *pPrefixAddr 1017 | = (struct sockaddr_in *)pPrefix->Address.lpSockaddr; 1018 | 1019 | if (pPrefixAddr->sin_family != AF_INET 1020 | || (prefix_len >= 0 1021 | && pPrefix->PrefixLength < (unsigned)prefix_len) 1022 | || (prefix_len >= 0 && pPrefix->PrefixLength == 32)) 1023 | continue; 1024 | 1025 | if (compare_bits (&pPrefixAddr->sin_addr, 1026 | &pAddr->sin_addr, 1027 | pPrefix->PrefixLength) == 0) { 1028 | prefix_len = pPrefix->PrefixLength; 1029 | pBest = pPrefix; 1030 | } 1031 | } 1032 | 1033 | if (!pBest) 1034 | continue; 1035 | 1036 | if (prefix_len < 0) 1037 | prefix_len = 32; 1038 | 1039 | memcpy (&maskAddr, 1040 | pBest->Address.lpSockaddr, 1041 | sizeof (maskAddr)); 1042 | memcpy (&bcastAddr, 1043 | pBest->Address.lpSockaddr, 1044 | sizeof (bcastAddr)); 1045 | 1046 | wholeBytes = prefix_len >> 3; 1047 | remainingBits = prefix_len & 7; 1048 | 1049 | toDo = wholeBytes; 1050 | pMaskBits = (unsigned char *)&maskAddr.sin_addr; 1051 | 1052 | while (toDo--) 1053 | *pMaskBits++ = 0xff; 1054 | 1055 | toDo = 4 - wholeBytes; 1056 | 1057 | pBcastBits = (unsigned char *)&bcastAddr.sin_addr + wholeBytes; 1058 | 1059 | if (remainingBits) { 1060 | static const unsigned char masks[] = { 1061 | 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 1062 | }; 1063 | *pMaskBits++ = masks[remainingBits]; 1064 | *pBcastBits &= masks[remainingBits]; 1065 | *pBcastBits++ |= ~masks[remainingBits]; 1066 | --toDo; 1067 | } 1068 | 1069 | while (toDo--) { 1070 | *pMaskBits++ = 0; 1071 | *pBcastBits++ = 0xff; 1072 | } 1073 | 1074 | mask = string_from_address ((SOCKADDR *)&maskAddr, 1075 | sizeof (maskAddr)); 1076 | bcast = string_from_address ((SOCKADDR *)&bcastAddr, 1077 | sizeof (bcastAddr)); 1078 | } else if (family == AF_INET6) { 1079 | struct sockaddr_in6 *pAddr 1080 | = (struct sockaddr_in6 *)pUniAddr->Address.lpSockaddr; 1081 | int prefix_len = -1; 1082 | struct sockaddr_in6 bcastAddr; 1083 | unsigned toDo; 1084 | unsigned wholeBytes, remainingBits; 1085 | unsigned char *pBcastBits; 1086 | PIP_ADAPTER_PREFIX pBest = NULL; 1087 | 1088 | for (pPrefix = pInfo->FirstPrefix; 1089 | pPrefix; 1090 | pPrefix = pPrefix->Next) { 1091 | struct sockaddr_in6 *pPrefixAddr 1092 | = (struct sockaddr_in6 *)pPrefix->Address.lpSockaddr; 1093 | 1094 | if (pPrefixAddr->sin6_family != AF_INET6 1095 | || (prefix_len >= 0 1096 | && pPrefix->PrefixLength < (unsigned)prefix_len) 1097 | || (prefix_len >= 0 && pPrefix->PrefixLength == 128)) 1098 | continue; 1099 | 1100 | if (compare_bits (&pPrefixAddr->sin6_addr, 1101 | &pAddr->sin6_addr, 1102 | pPrefix->PrefixLength) == 0) { 1103 | prefix_len = pPrefix->PrefixLength; 1104 | pBest = pPrefix; 1105 | } 1106 | } 1107 | 1108 | if (!pBest) 1109 | continue; 1110 | 1111 | if (prefix_len < 0) 1112 | prefix_len = 128; 1113 | 1114 | memcpy (&bcastAddr, 1115 | pBest->Address.lpSockaddr, 1116 | sizeof (bcastAddr)); 1117 | 1118 | wholeBytes = prefix_len >> 3; 1119 | remainingBits = prefix_len & 7; 1120 | 1121 | toDo = 16 - wholeBytes; 1122 | 1123 | pBcastBits = (unsigned char *)&bcastAddr.sin6_addr + wholeBytes; 1124 | 1125 | if (remainingBits) { 1126 | static const unsigned char masks[] = { 1127 | 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 1128 | }; 1129 | *pBcastBits &= masks[remainingBits]; 1130 | *pBcastBits++ |= ~masks[remainingBits]; 1131 | --toDo; 1132 | } 1133 | 1134 | while (toDo--) 1135 | *pBcastBits++ = 0xff; 1136 | 1137 | mask = netmask_from_prefix (prefix_len); 1138 | bcast = string_from_address ((SOCKADDR *)&bcastAddr, sizeof(bcastAddr)); 1139 | } 1140 | 1141 | { 1142 | PyObject *dict; 1143 | 1144 | dict = PyDict_New (); 1145 | 1146 | if (!dict) { 1147 | Py_XDECREF (addr); 1148 | Py_XDECREF (mask); 1149 | Py_XDECREF (bcast); 1150 | Py_DECREF (result); 1151 | return NULL; 1152 | } 1153 | 1154 | if (addr) 1155 | PyDict_SetItemString (dict, "addr", addr); 1156 | if (mask) 1157 | PyDict_SetItemString (dict, "netmask", mask); 1158 | if (bcast) 1159 | PyDict_SetItemString (dict, "broadcast", bcast); 1160 | 1161 | Py_XDECREF (addr); 1162 | Py_XDECREF (mask); 1163 | Py_XDECREF (bcast); 1164 | 1165 | if (!add_to_family (result, family, dict)) { 1166 | Py_DECREF (result); 1167 | return NULL; 1168 | } 1169 | } 1170 | } 1171 | return result; 1172 | } 1173 | #endif 1174 | 1175 | /* -- ifaddresses() --------------------------------------------------------- */ 1176 | 1177 | static PyObject * 1178 | ifaddrs (PyObject *self, PyObject *args) 1179 | { 1180 | const char *ifname; 1181 | PyObject *result; 1182 | int found = FALSE; 1183 | #if defined(WIN32) 1184 | PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, pInfo = NULL; 1185 | ULONG ulBufferLength = 0; 1186 | DWORD dwRet; 1187 | #elif HAVE_GETIFADDRS 1188 | struct ifaddrs *addrs = NULL; 1189 | struct ifaddrs *addr = NULL; 1190 | #endif 1191 | 1192 | if (!PyArg_ParseTuple (args, "s", &ifname)) 1193 | return NULL; 1194 | 1195 | result = PyDict_New (); 1196 | 1197 | if (!result) 1198 | return NULL; 1199 | 1200 | #if defined(WIN32) 1201 | /* .. Win32 ............................................................... */ 1202 | 1203 | /* First, retrieve the adapter information. We do this in a loop, in 1204 | case someone adds or removes adapters in the meantime. */ 1205 | do { 1206 | dwRet = GetAdaptersAddresses (AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, 1207 | pAdapterAddresses, &ulBufferLength); 1208 | 1209 | if (dwRet == ERROR_BUFFER_OVERFLOW) { 1210 | if (pAdapterAddresses) 1211 | free (pAdapterAddresses); 1212 | pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc (ulBufferLength); 1213 | 1214 | if (!pAdapterAddresses) { 1215 | Py_DECREF (result); 1216 | PyErr_SetString (PyExc_MemoryError, "Not enough memory"); 1217 | return NULL; 1218 | } 1219 | } 1220 | } while (dwRet == ERROR_BUFFER_OVERFLOW); 1221 | 1222 | /* If we failed, then fail in Python too */ 1223 | if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) { 1224 | Py_DECREF (result); 1225 | if (pAdapterAddresses) 1226 | free (pAdapterAddresses); 1227 | 1228 | PyErr_SetString (PyExc_OSError, 1229 | "Unable to obtain adapter information."); 1230 | return NULL; 1231 | } 1232 | 1233 | for (pInfo = pAdapterAddresses; pInfo; pInfo = pInfo->Next) { 1234 | if (strcmp (pInfo->AdapterName, ifname) != 0) 1235 | continue; 1236 | 1237 | result = winifaddrinfo(pInfo); 1238 | if(!result) 1239 | continue; 1240 | 1241 | found = TRUE; 1242 | break; 1243 | } 1244 | 1245 | free ((void *)pAdapterAddresses); 1246 | #elif HAVE_GETIFADDRS 1247 | /* .. UNIX, with getifaddrs() ............................................. */ 1248 | 1249 | if (getifaddrs (&addrs) < 0) { 1250 | Py_DECREF (result); 1251 | PyErr_SetFromErrno (PyExc_OSError); 1252 | return NULL; 1253 | } 1254 | 1255 | for (addr = addrs; addr; addr = addr->ifa_next) { 1256 | if (!addr->ifa_addr) 1257 | continue; 1258 | 1259 | if (addr->ifa_name == NULL || strcmp (addr->ifa_name, ifname) != 0) 1260 | continue; 1261 | 1262 | PyObject* ifinfo = getifaddrsinfo(addr); 1263 | if (ifinfo != NULL) 1264 | { 1265 | found = TRUE; 1266 | } 1267 | 1268 | if (!add_to_family (result, addr->ifa_addr->sa_family, ifinfo)) { 1269 | Py_DECREF (result); 1270 | freeifaddrs (addrs); 1271 | return NULL; 1272 | } 1273 | } 1274 | 1275 | freeifaddrs (addrs); 1276 | #elif HAVE_SOCKET_IOCTLS 1277 | /* .. UNIX, with SIOC ioctls() ............................................ */ 1278 | 1279 | int sock = socket(AF_INET, SOCK_DGRAM, 0); 1280 | 1281 | if (sock < 0) { 1282 | Py_DECREF (result); 1283 | PyErr_SetFromErrno (PyExc_OSError); 1284 | return NULL; 1285 | } 1286 | 1287 | result = socket_ioctls_info(ifname, sock); 1288 | if(result != NULL) 1289 | { 1290 | found = TRUE; 1291 | } 1292 | close (sock); 1293 | #endif /* HAVE_SOCKET_IOCTLS */ 1294 | 1295 | if (found) 1296 | return result; 1297 | else { 1298 | Py_DECREF (result); 1299 | PyErr_SetString (PyExc_ValueError, 1300 | "You must specify a valid interface name."); 1301 | return NULL; 1302 | } 1303 | } 1304 | 1305 | /* -- allifaddresses() --------------------------------------------------------- */ 1306 | static PyObject * 1307 | allifaddrs (PyObject *self) 1308 | { 1309 | PyObject *result; 1310 | #if defined(WIN32) 1311 | PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, pInfo = NULL; 1312 | ULONG ulBufferLength = 0; 1313 | DWORD dwRet; 1314 | #elif HAVE_GETIFADDRS 1315 | struct ifaddrs *addrs = NULL; 1316 | struct ifaddrs *addr = NULL; 1317 | #endif 1318 | 1319 | result = PyDict_New (); 1320 | 1321 | if (!result) 1322 | return NULL; 1323 | #if defined(WIN32) 1324 | /* .. Win32 ............................................................... */ 1325 | 1326 | /* First, retrieve the adapter information. We do this in a loop, in 1327 | case someone adds or removes adapters in the meantime. */ 1328 | do { 1329 | dwRet = GetAdaptersAddresses (AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, 1330 | pAdapterAddresses, &ulBufferLength); 1331 | 1332 | if (dwRet == ERROR_BUFFER_OVERFLOW) { 1333 | if (pAdapterAddresses) 1334 | free (pAdapterAddresses); 1335 | pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc (ulBufferLength); 1336 | 1337 | if (!pAdapterAddresses) { 1338 | Py_DECREF (result); 1339 | PyErr_SetString (PyExc_MemoryError, "Not enough memory"); 1340 | return NULL; 1341 | } 1342 | } 1343 | } while (dwRet == ERROR_BUFFER_OVERFLOW); 1344 | 1345 | /* If we failed, then fail in Python too */ 1346 | if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) { 1347 | Py_DECREF (result); 1348 | if (pAdapterAddresses) 1349 | free (pAdapterAddresses); 1350 | 1351 | PyErr_SetString (PyExc_OSError, "Unable to obtain adapter information."); 1352 | return NULL; 1353 | } 1354 | 1355 | for (pInfo = pAdapterAddresses; pInfo; pInfo = pInfo->Next) { 1356 | PyObject* dict = winifaddrinfo(pInfo); 1357 | 1358 | if (!dict) 1359 | continue; 1360 | 1361 | PyObject *ifname = PyUnicode_FromString (pInfo->AdapterName); 1362 | PyDict_SetItem(result, ifname, dict); 1363 | Py_XDECREF(ifname); 1364 | } 1365 | 1366 | free ((void *)pAdapterAddresses); 1367 | #elif HAVE_GETIFADDRS 1368 | /* .. UNIX, with getifaddrs() ............................................. */ 1369 | 1370 | if (getifaddrs (&addrs) < 0) { 1371 | Py_DECREF (result); 1372 | PyErr_SetFromErrno (PyExc_OSError); 1373 | return NULL; 1374 | } 1375 | 1376 | for (addr = addrs; addr; addr = addr->ifa_next) { 1377 | if (!addr->ifa_addr) 1378 | continue; 1379 | 1380 | PyObject *ifinfo = getifaddrsinfo(addr); 1381 | if (!ifinfo) 1382 | continue; 1383 | 1384 | PyObject *ifname = PyUnicode_FromString (addr->ifa_name); 1385 | PyObject* dict; 1386 | if (PyDict_Contains(result, ifname)) { 1387 | dict = PyDict_GetItem(result, ifname); 1388 | } else { 1389 | dict = PyDict_New (); 1390 | PyDict_SetItem(result, ifname, dict); 1391 | } 1392 | 1393 | Py_XDECREF(ifname); 1394 | 1395 | if (!add_to_family (dict, addr->ifa_addr->sa_family, ifinfo)) { 1396 | Py_DECREF (dict); 1397 | freeifaddrs (addrs); 1398 | return NULL; 1399 | } 1400 | } 1401 | 1402 | freeifaddrs (addrs); 1403 | #elif HAVE_SOCKET_IOCTLS && HAVE_SIOCGIFCONF 1404 | /* .. UNIX, with SIOC ioctls() ............................................ */ 1405 | int sock = socket(AF_INET, SOCK_DGRAM, 0); 1406 | 1407 | if (sock < 0) { 1408 | Py_DECREF (result); 1409 | PyErr_SetFromErrno (PyExc_OSError); 1410 | return NULL; 1411 | } 1412 | int fd = socket (AF_INET, SOCK_DGRAM, 0); 1413 | struct CNAME(ifconf) ifc; 1414 | int len = -1; 1415 | 1416 | if (fd < 0) { 1417 | PyErr_SetFromErrno (PyExc_OSError); 1418 | return NULL; 1419 | } 1420 | 1421 | // Try to find out how much space we need 1422 | #if HAVE_SIOCGSIZIFCONF 1423 | if (ioctl (fd, SIOCGSIZIFCONF, &len) < 0) 1424 | len = -1; 1425 | #elif HAVE_SIOCGLIFNUM 1426 | { struct lifnum lifn; 1427 | lifn.lifn_family = AF_UNSPEC; 1428 | lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 1429 | ifc.lifc_family = AF_UNSPEC; 1430 | ifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 1431 | if (ioctl (fd, SIOCGLIFNUM, (char *)&lifn) < 0) 1432 | len = -1; 1433 | else 1434 | len = lifn.lifn_count; 1435 | } 1436 | #endif 1437 | 1438 | // As a last resort, guess 1439 | if (len < 0) 1440 | len = 64; 1441 | 1442 | ifc.CNAME(ifc_len) = (int)(len * sizeof (struct CNAME(ifreq))); 1443 | ifc.CNAME(ifc_buf) = malloc (ifc.CNAME(ifc_len)); 1444 | 1445 | if (!ifc.CNAME(ifc_buf)) { 1446 | PyErr_SetString (PyExc_MemoryError, "Not enough memory"); 1447 | close (fd); 1448 | return NULL; 1449 | } 1450 | 1451 | #if HAVE_SIOCGLIFNUM 1452 | if (ioctl (fd, SIOCGLIFCONF, &ifc) < 0) { 1453 | #else 1454 | if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) { 1455 | #endif 1456 | free (ifc.CNAME(ifc_req)); 1457 | PyErr_SetFromErrno (PyExc_OSError); 1458 | close (fd); 1459 | return NULL; 1460 | } 1461 | struct CNAME(ifreq) *pfreq = ifc.CNAME(ifc_req); 1462 | struct CNAME(ifreq) *pfreqend = (struct CNAME(ifreq) *)((char *)pfreq 1463 | + ifc.CNAME(ifc_len)); 1464 | while (pfreq < pfreqend) { 1465 | char* if_name = pfreq->CNAME(ifr_name); 1466 | PyObject *name = PyUnicode_FromString (if_name); 1467 | if (!PyDict_Contains(result, name)) { 1468 | PyObject* dict = socket_ioctls_info(if_name, sock); 1469 | PyDict_SetItem(result, name, dict); 1470 | Py_XDECREF(dict); 1471 | } 1472 | 1473 | #if !HAVE_SOCKADDR_SA_LEN 1474 | ++pfreq; 1475 | #else 1476 | /* On some platforms, the ifreq struct can *grow*(!) if the socket address 1477 | is very long. Mac OS X is such a platform. */ 1478 | { 1479 | size_t len = sizeof (struct CNAME(ifreq)); 1480 | if (pfreq->ifr_addr.sa_len > sizeof (struct sockaddr)) 1481 | len = len - sizeof (struct sockaddr) + pfreq->ifr_addr.sa_len; 1482 | pfreq = (struct CNAME(ifreq) *)((char *)pfreq + len); 1483 | } 1484 | #endif 1485 | } 1486 | 1487 | free (ifc.CNAME(ifc_buf)); 1488 | close (fd); 1489 | #endif /* HAVE_SOCKET_IOCTLS */ 1490 | return result; 1491 | } 1492 | 1493 | /* -- interfaces() ---------------------------------------------------------- */ 1494 | 1495 | static PyObject * 1496 | interfaces (PyObject *self) 1497 | { 1498 | PyObject *result; 1499 | 1500 | #if defined(WIN32) 1501 | /* .. Win32 ............................................................... */ 1502 | 1503 | PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, pInfo = NULL; 1504 | ULONG ulBufferLength = 0; 1505 | DWORD dwRet; 1506 | 1507 | /* First, retrieve the adapter information */ 1508 | do { 1509 | dwRet = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, 1510 | pAdapterAddresses, &ulBufferLength); 1511 | 1512 | if (dwRet == ERROR_BUFFER_OVERFLOW) { 1513 | if (pAdapterAddresses) 1514 | free (pAdapterAddresses); 1515 | pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc (ulBufferLength); 1516 | 1517 | if (!pAdapterAddresses) { 1518 | PyErr_SetString (PyExc_MemoryError, "Not enough memory"); 1519 | return NULL; 1520 | } 1521 | } 1522 | } while (dwRet == ERROR_BUFFER_OVERFLOW); 1523 | 1524 | /* If we failed, then fail in Python too */ 1525 | if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) { 1526 | if (pAdapterAddresses) 1527 | free (pAdapterAddresses); 1528 | 1529 | PyErr_SetString (PyExc_OSError, 1530 | "Unable to obtain adapter information."); 1531 | return NULL; 1532 | } 1533 | 1534 | result = PyList_New(0); 1535 | 1536 | if (dwRet == ERROR_NO_DATA) { 1537 | free (pAdapterAddresses); 1538 | return result; 1539 | } 1540 | 1541 | for (pInfo = pAdapterAddresses; pInfo; pInfo = pInfo->Next) { 1542 | PyObject *ifname = (PyObject *)PyUnicode_FromString (pInfo->AdapterName); 1543 | 1544 | PyList_Append (result, ifname); 1545 | Py_DECREF (ifname); 1546 | } 1547 | 1548 | free (pAdapterAddresses); 1549 | #elif HAVE_GETIFADDRS 1550 | /* .. UNIX, with getifaddrs() ............................................. */ 1551 | 1552 | struct ifaddrs *addrs = NULL; 1553 | struct ifaddrs *addr = NULL; 1554 | 1555 | PyObject *dictionary = PyDict_New(); 1556 | 1557 | if (getifaddrs (&addrs) < 0) { 1558 | PyErr_SetFromErrno (PyExc_OSError); 1559 | return NULL; 1560 | } 1561 | 1562 | for (addr = addrs; addr; addr = addr->ifa_next) { 1563 | if (addr->ifa_name == NULL) 1564 | continue; 1565 | 1566 | PyDict_SetItemString(dictionary, addr->ifa_name, Py_None); 1567 | } 1568 | 1569 | result = PyMapping_Keys(dictionary); 1570 | 1571 | freeifaddrs (addrs); 1572 | #elif HAVE_SIOCGIFCONF 1573 | /* .. UNIX, with SIOC ioctl()s ............................................ */ 1574 | 1575 | const char *prev_name = NULL; 1576 | int fd = socket (AF_INET, SOCK_DGRAM, 0); 1577 | struct CNAME(ifconf) ifc; 1578 | int len = -1; 1579 | 1580 | if (fd < 0) { 1581 | PyErr_SetFromErrno (PyExc_OSError); 1582 | return NULL; 1583 | } 1584 | 1585 | // Try to find out how much space we need 1586 | #if HAVE_SIOCGSIZIFCONF 1587 | if (ioctl (fd, SIOCGSIZIFCONF, &len) < 0) 1588 | len = -1; 1589 | #elif HAVE_SIOCGLIFNUM 1590 | { struct lifnum lifn; 1591 | lifn.lifn_family = AF_UNSPEC; 1592 | lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 1593 | ifc.lifc_family = AF_UNSPEC; 1594 | ifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 1595 | if (ioctl (fd, SIOCGLIFNUM, (char *)&lifn) < 0) 1596 | len = -1; 1597 | else 1598 | len = lifn.lifn_count; 1599 | } 1600 | #endif 1601 | 1602 | // As a last resort, guess 1603 | if (len < 0) 1604 | len = 64; 1605 | 1606 | ifc.CNAME(ifc_len) = (int)(len * sizeof (struct CNAME(ifreq))); 1607 | ifc.CNAME(ifc_buf) = malloc (ifc.CNAME(ifc_len)); 1608 | 1609 | if (!ifc.CNAME(ifc_buf)) { 1610 | PyErr_SetString (PyExc_MemoryError, "Not enough memory"); 1611 | close (fd); 1612 | return NULL; 1613 | } 1614 | 1615 | #if HAVE_SIOCGLIFNUM 1616 | if (ioctl (fd, SIOCGLIFCONF, &ifc) < 0) { 1617 | #else 1618 | if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) { 1619 | #endif 1620 | free (ifc.CNAME(ifc_req)); 1621 | PyErr_SetFromErrno (PyExc_OSError); 1622 | close (fd); 1623 | return NULL; 1624 | } 1625 | 1626 | result = PyList_New (0); 1627 | struct CNAME(ifreq) *pfreq = ifc.CNAME(ifc_req); 1628 | struct CNAME(ifreq) *pfreqend = (struct CNAME(ifreq) *)((char *)pfreq 1629 | + ifc.CNAME(ifc_len)); 1630 | while (pfreq < pfreqend) { 1631 | if (!prev_name || strncmp (prev_name, pfreq->CNAME(ifr_name), IFNAMSIZ) != 0) { 1632 | PyObject *name = PyUnicode_FromString (pfreq->CNAME(ifr_name)); 1633 | 1634 | if (!PySequence_Contains (result, name)) 1635 | PyList_Append (result, name); 1636 | Py_XDECREF (name); 1637 | 1638 | prev_name = pfreq->CNAME(ifr_name); 1639 | } 1640 | 1641 | #if !HAVE_SOCKADDR_SA_LEN 1642 | ++pfreq; 1643 | #else 1644 | /* On some platforms, the ifreq struct can *grow*(!) if the socket address 1645 | is very long. Mac OS X is such a platform. */ 1646 | { 1647 | size_t len = sizeof (struct CNAME(ifreq)); 1648 | if (pfreq->ifr_addr.sa_len > sizeof (struct sockaddr)) 1649 | len = len - sizeof (struct sockaddr) + pfreq->ifr_addr.sa_len; 1650 | pfreq = (struct CNAME(ifreq) *)((char *)pfreq + len); 1651 | } 1652 | #endif 1653 | } 1654 | 1655 | free (ifc.CNAME(ifc_buf)); 1656 | close (fd); 1657 | #endif /* HAVE_SIOCGIFCONF */ 1658 | 1659 | return result; 1660 | } 1661 | 1662 | /* -- gateways() ------------------------------------------------------------ */ 1663 | 1664 | static PyObject * 1665 | gateways (PyObject *self) 1666 | { 1667 | PyObject *result, *defaults; 1668 | 1669 | #if defined(WIN32) 1670 | /* .. Win32 ............................................................... */ 1671 | 1672 | /* We try to access GetIPForwardTable2() and FreeMibTable() through 1673 | function pointers so that this code will still run on machines 1674 | running Windows versions prior to Vista. On those systems, we 1675 | fall back to the older GetIPForwardTable() API (and can only find 1676 | IPv4 gateways as a result). 1677 | 1678 | We also fall back to the older API if the newer code fails for 1679 | some reason. */ 1680 | 1681 | HANDLE hIpHelper; 1682 | typedef NTSTATUS (WINAPI *PGETIPFORWARDTABLE2)(ADDRESS_FAMILY Family, 1683 | PMIB_IPFORWARD_TABLE2 *pTable); 1684 | typedef VOID (WINAPI *PFREEMIBTABLE)(PVOID Memory); 1685 | 1686 | PGETIPFORWARDTABLE2 pGetIpForwardTable2; 1687 | PFREEMIBTABLE pFreeMibTable; 1688 | 1689 | hIpHelper = GetModuleHandle (TEXT("iphlpapi.dll")); 1690 | 1691 | result = NULL; 1692 | pGetIpForwardTable2 = (PGETIPFORWARDTABLE2) 1693 | GetProcAddress (hIpHelper, "GetIpForwardTable2"); 1694 | pFreeMibTable = (PFREEMIBTABLE) 1695 | GetProcAddress (hIpHelper, "FreeMibTable"); 1696 | 1697 | if (pGetIpForwardTable2) { 1698 | PMIB_IPFORWARD_TABLE2 table; 1699 | DWORD dwErr = pGetIpForwardTable2 (AF_UNSPEC, &table); 1700 | 1701 | if (dwErr == NO_ERROR) { 1702 | DWORD n; 1703 | ULONG lBestInetMetric = ~(ULONG)0, lBestInet6Metric = ~(ULONG)0; 1704 | 1705 | result = PyDict_New(); 1706 | defaults = PyDict_New(); 1707 | PyDict_SetItemString (result, "default", defaults); 1708 | Py_DECREF(defaults); 1709 | 1710 | /* This prevents a crash on PyPy */ 1711 | defaults = PyDict_GetItemString (result, "default"); 1712 | 1713 | for (n = 0; n < table->NumEntries; ++n) { 1714 | MIB_IFROW ifRow; 1715 | PyObject *ifname; 1716 | PyObject *gateway; 1717 | PyObject *isdefault; 1718 | PyObject *tuple, *deftuple = NULL; 1719 | WCHAR *pwcsName; 1720 | DWORD dwFamily = table->Table[n].NextHop.si_family; 1721 | BOOL bBest = FALSE; 1722 | 1723 | if (table->Table[n].DestinationPrefix.PrefixLength) 1724 | continue; 1725 | 1726 | switch (dwFamily) { 1727 | case AF_INET: 1728 | if (!table->Table[n].NextHop.Ipv4.sin_addr.s_addr) 1729 | continue; 1730 | break; 1731 | case AF_INET6: 1732 | if (memcmp (&table->Table[n].NextHop.Ipv6.sin6_addr, 1733 | &in6addr_any, 1734 | sizeof (struct in6_addr)) == 0) 1735 | continue; 1736 | break; 1737 | default: 1738 | continue; 1739 | } 1740 | 1741 | memset (&ifRow, 0, sizeof (ifRow)); 1742 | ifRow.dwIndex = table->Table[n].InterfaceIndex; 1743 | if (GetIfEntry (&ifRow) != NO_ERROR) 1744 | continue; 1745 | 1746 | gateway = string_from_address ((SOCKADDR *)&table->Table[n].NextHop, 1747 | sizeof (table->Table[n].NextHop)); 1748 | 1749 | if (!gateway) 1750 | continue; 1751 | 1752 | /* Strip the prefix from the interface name */ 1753 | pwcsName = ifRow.wszName; 1754 | if (_wcsnicmp (L"\\DEVICE\\TCPIP_", pwcsName, 14) == 0) 1755 | pwcsName += 14; 1756 | 1757 | switch (dwFamily) { 1758 | case AF_INET: 1759 | bBest = table->Table[n].Metric < lBestInetMetric; 1760 | lBestInetMetric = table->Table[n].Metric; 1761 | break; 1762 | case AF_INET6: 1763 | bBest = table->Table[n].Metric < lBestInet6Metric; 1764 | lBestInet6Metric = table->Table[n].Metric; 1765 | break; 1766 | } 1767 | 1768 | ifname = PyUnicode_FromWideChar (pwcsName, wcslen (pwcsName)); 1769 | isdefault = bBest ? Py_True : Py_False; 1770 | 1771 | tuple = PyTuple_Pack (3, gateway, ifname, isdefault); 1772 | 1773 | if (PyObject_IsTrue (isdefault)) 1774 | deftuple = PyTuple_Pack (2, gateway, ifname); 1775 | 1776 | Py_DECREF (gateway); 1777 | Py_DECREF (ifname); 1778 | 1779 | if (tuple && !add_to_family (result, dwFamily, tuple)) { 1780 | Py_DECREF (deftuple); 1781 | Py_DECREF (result); 1782 | free (table); 1783 | return NULL; 1784 | } 1785 | 1786 | if (deftuple) { 1787 | PyObject *pyfamily = PyInt_FromLong (dwFamily); 1788 | 1789 | PyDict_SetItem (defaults, pyfamily, deftuple); 1790 | 1791 | Py_DECREF (pyfamily); 1792 | Py_DECREF (deftuple); 1793 | } 1794 | } 1795 | 1796 | pFreeMibTable (table); 1797 | } 1798 | } 1799 | 1800 | if (!result) { 1801 | PMIB_IPFORWARDTABLE table = NULL; 1802 | DWORD dwRet; 1803 | DWORD dwSize = 0; 1804 | DWORD n; 1805 | DWORD dwBestMetric = ~(DWORD)0; 1806 | 1807 | do { 1808 | dwRet = GetIpForwardTable (table, &dwSize, FALSE); 1809 | 1810 | if (dwRet == ERROR_INSUFFICIENT_BUFFER) { 1811 | PMIB_IPFORWARDTABLE tbl = (PMIB_IPFORWARDTABLE)realloc (table, dwSize); 1812 | 1813 | if (!tbl) { 1814 | free (table); 1815 | PyErr_NoMemory(); 1816 | return NULL; 1817 | } 1818 | 1819 | table = tbl; 1820 | } 1821 | } while (dwRet == ERROR_INSUFFICIENT_BUFFER); 1822 | 1823 | if (dwRet != NO_ERROR) { 1824 | free (table); 1825 | PyErr_SetFromWindowsErr (dwRet); 1826 | return NULL; 1827 | } 1828 | 1829 | result = PyDict_New(); 1830 | defaults = PyDict_New(); 1831 | PyDict_SetItemString (result, "default", defaults); 1832 | Py_DECREF(defaults); 1833 | 1834 | /* This prevents a crash on PyPy */ 1835 | defaults = PyDict_GetItemString (result, "default"); 1836 | 1837 | for (n = 0; n < table->dwNumEntries; ++n) { 1838 | MIB_IFROW ifRow; 1839 | PyObject *ifname; 1840 | PyObject *gateway; 1841 | PyObject *isdefault; 1842 | PyObject *tuple, *deftuple = NULL; 1843 | DWORD dwGateway; 1844 | char gwbuf[16]; 1845 | WCHAR *pwcsName; 1846 | BOOL bBest; 1847 | 1848 | if (table->table[n].dwForwardDest 1849 | || !table->table[n].dwForwardNextHop 1850 | || table->table[n].dwForwardType != MIB_IPROUTE_TYPE_INDIRECT) 1851 | continue; 1852 | 1853 | memset (&ifRow, 0, sizeof (ifRow)); 1854 | ifRow.dwIndex = table->table[n].dwForwardIfIndex; 1855 | if (GetIfEntry (&ifRow) != NO_ERROR) 1856 | continue; 1857 | 1858 | dwGateway = ntohl (table->table[n].dwForwardNextHop); 1859 | 1860 | sprintf (gwbuf, "%u.%u.%u.%u", 1861 | (dwGateway >> 24) & 0xff, 1862 | (dwGateway >> 16) & 0xff, 1863 | (dwGateway >> 8) & 0xff, 1864 | dwGateway & 0xff); 1865 | 1866 | /* Strip the prefix from the interface name */ 1867 | pwcsName = ifRow.wszName; 1868 | if (_wcsnicmp (L"\\DEVICE\\TCPIP_", pwcsName, 14) == 0) 1869 | pwcsName += 14; 1870 | 1871 | bBest = table->table[n].dwForwardMetric1 < dwBestMetric; 1872 | if (bBest) 1873 | dwBestMetric = table->table[n].dwForwardMetric1; 1874 | 1875 | ifname = PyUnicode_FromWideChar (pwcsName, wcslen (pwcsName)); 1876 | gateway = PyUnicode_FromString (gwbuf); 1877 | isdefault = bBest ? Py_True : Py_False; 1878 | 1879 | tuple = PyTuple_Pack (3, gateway, ifname, isdefault); 1880 | 1881 | if (PyObject_IsTrue (isdefault)) 1882 | deftuple = PyTuple_Pack (2, gateway, ifname); 1883 | 1884 | Py_DECREF (gateway); 1885 | Py_DECREF (ifname); 1886 | 1887 | if (tuple && !add_to_family (result, AF_INET, tuple)) { 1888 | Py_DECREF (deftuple); 1889 | Py_DECREF (result); 1890 | free (table); 1891 | return NULL; 1892 | } 1893 | 1894 | if (deftuple) { 1895 | PyObject *pyfamily = PyInt_FromLong (AF_INET); 1896 | 1897 | PyDict_SetItem (defaults, pyfamily, deftuple); 1898 | 1899 | Py_DECREF (pyfamily); 1900 | Py_DECREF (deftuple); 1901 | } 1902 | } 1903 | } 1904 | #elif defined(HAVE_PF_NETLINK) 1905 | /* .. Linux (PF_NETLINK socket) ........................................... */ 1906 | 1907 | /* PF_NETLINK is pretty poorly documented and it looks to be quite easy to 1908 | get wrong. This *appears* to be the right way to do it, even though a 1909 | lot of the code out there on the 'Net is very different! */ 1910 | 1911 | struct routing_msg { 1912 | struct nlmsghdr hdr; 1913 | struct rtmsg rt; 1914 | char data[0]; 1915 | } *pmsg, *msgbuf; 1916 | int s; 1917 | int seq = 0; 1918 | ssize_t ret; 1919 | struct sockaddr_nl sanl; 1920 | static const struct sockaddr_nl sanl_kernel = { .nl_family = AF_NETLINK }; 1921 | socklen_t sanl_len; 1922 | int pagesize = getpagesize(); 1923 | int bufsize = pagesize < 8192 ? pagesize : 8192; 1924 | int is_multi = 0; 1925 | int interrupted = 0; 1926 | int def_priorities[RTNL_FAMILY_MAX]; 1927 | 1928 | memset(def_priorities, 0xff, sizeof(def_priorities)); 1929 | 1930 | result = PyDict_New(); 1931 | defaults = PyDict_New(); 1932 | PyDict_SetItemString (result, "default", defaults); 1933 | Py_DECREF (defaults); 1934 | 1935 | /* This prevents a crash on PyPy */ 1936 | defaults = PyDict_GetItemString (result, "default"); 1937 | 1938 | msgbuf = (struct routing_msg *)malloc (bufsize); 1939 | 1940 | if (!msgbuf) { 1941 | PyErr_NoMemory (); 1942 | Py_DECREF (result); 1943 | return NULL; 1944 | } 1945 | 1946 | s = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 1947 | 1948 | if (s < 0) { 1949 | PyErr_SetFromErrno (PyExc_OSError); 1950 | Py_DECREF (result); 1951 | free (msgbuf); 1952 | return NULL; 1953 | } 1954 | 1955 | sanl.nl_family = AF_NETLINK; 1956 | sanl.nl_groups = 0; 1957 | sanl.nl_pid = 0; 1958 | 1959 | if (bind (s, (struct sockaddr *)&sanl, sizeof (sanl)) < 0) { 1960 | PyErr_SetFromErrno (PyExc_OSError); 1961 | Py_DECREF (result); 1962 | free (msgbuf); 1963 | close (s); 1964 | return NULL; 1965 | } 1966 | 1967 | sanl_len = sizeof (sanl); 1968 | if (getsockname (s, (struct sockaddr *)&sanl, &sanl_len) < 0) { 1969 | PyErr_SetFromErrno (PyExc_OSError); 1970 | Py_DECREF (result); 1971 | free (msgbuf); 1972 | close (s); 1973 | return NULL; 1974 | } 1975 | 1976 | do { 1977 | interrupted = 0; 1978 | 1979 | pmsg = msgbuf; 1980 | memset (pmsg, 0, sizeof (struct routing_msg)); 1981 | pmsg->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1982 | pmsg->hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; 1983 | pmsg->hdr.nlmsg_seq = ++seq; 1984 | pmsg->hdr.nlmsg_type = RTM_GETROUTE; 1985 | pmsg->hdr.nlmsg_pid = 0; 1986 | 1987 | pmsg->rt.rtm_family = 0; 1988 | 1989 | if (sendto (s, pmsg, pmsg->hdr.nlmsg_len, 0, 1990 | (struct sockaddr *)&sanl_kernel, sizeof(sanl_kernel)) < 0) { 1991 | PyErr_SetFromErrno (PyExc_OSError); 1992 | Py_DECREF (result); 1993 | free (msgbuf); 1994 | close (s); 1995 | return NULL; 1996 | } 1997 | 1998 | do { 1999 | struct sockaddr_nl sanl_from; 2000 | struct iovec iov = { msgbuf, bufsize }; 2001 | struct msghdr msghdr = { 2002 | &sanl_from, 2003 | sizeof(sanl_from), 2004 | &iov, 2005 | 1, 2006 | 0, 2007 | 0, 2008 | 0 2009 | }; 2010 | int nllen; 2011 | 2012 | ret = recvmsg (s, &msghdr, 0); 2013 | 2014 | if (msghdr.msg_flags & MSG_TRUNC) { 2015 | PyErr_SetString (PyExc_OSError, "netlink message truncated"); 2016 | Py_DECREF (result); 2017 | free (msgbuf); 2018 | close (s); 2019 | return NULL; 2020 | } 2021 | 2022 | if (ret < 0) { 2023 | PyErr_SetFromErrno (PyExc_OSError); 2024 | Py_DECREF (result); 2025 | free (msgbuf); 2026 | close (s); 2027 | return NULL; 2028 | } 2029 | 2030 | nllen = ret; 2031 | pmsg = msgbuf; 2032 | while (NLMSG_OK (&pmsg->hdr, nllen)) { 2033 | void *dst = NULL; 2034 | void *gw = NULL; 2035 | int ifndx = -1; 2036 | struct rtattr *attrs, *attr; 2037 | int len; 2038 | int priority; 2039 | 2040 | /* Ignore messages not for us */ 2041 | if (pmsg->hdr.nlmsg_seq != seq || pmsg->hdr.nlmsg_pid != sanl.nl_pid) 2042 | goto next; 2043 | 2044 | /* This is only defined on Linux kernel versions 3.1 and higher */ 2045 | #ifdef NLM_F_DUMP_INTR 2046 | if (pmsg->hdr.nlmsg_flags & NLM_F_DUMP_INTR) { 2047 | /* The dump was interrupted by a signal; we need to go round again */ 2048 | interrupted = 1; 2049 | is_multi = 0; 2050 | break; 2051 | } 2052 | #endif 2053 | 2054 | is_multi = pmsg->hdr.nlmsg_flags & NLM_F_MULTI; 2055 | 2056 | if (pmsg->hdr.nlmsg_type == NLMSG_DONE) { 2057 | is_multi = interrupted = 0; 2058 | break; 2059 | } 2060 | 2061 | if (pmsg->hdr.nlmsg_type == NLMSG_ERROR) { 2062 | struct nlmsgerr *perr = (struct nlmsgerr *)&pmsg->rt; 2063 | errno = -perr->error; 2064 | PyErr_SetFromErrno (PyExc_OSError); 2065 | Py_DECREF (result); 2066 | free (msgbuf); 2067 | close (s); 2068 | return NULL; 2069 | } 2070 | 2071 | attr = attrs = RTM_RTA(&pmsg->rt); 2072 | len = RTM_PAYLOAD(&pmsg->hdr); 2073 | priority = -1; 2074 | while (RTA_OK(attr, len)) { 2075 | switch (attr->rta_type) { 2076 | case RTA_GATEWAY: 2077 | gw = RTA_DATA(attr); 2078 | break; 2079 | case RTA_DST: 2080 | dst = RTA_DATA(attr); 2081 | break; 2082 | case RTA_OIF: 2083 | ifndx = *(int *)RTA_DATA(attr); 2084 | break; 2085 | case RTA_PRIORITY: 2086 | priority = *(int *)RTA_DATA(attr); 2087 | break; 2088 | default: 2089 | break; 2090 | } 2091 | 2092 | attr = RTA_NEXT(attr, len); 2093 | } 2094 | 2095 | static const unsigned char ipv4_default[4] = {}; 2096 | static const unsigned char ipv6_default[16] = {}; 2097 | 2098 | /* We're looking for gateways with no destination */ 2099 | if ((!dst 2100 | || (pmsg->rt.rtm_family == AF_INET && !memcmp(dst, ipv4_default, sizeof(ipv4_default))) 2101 | || (pmsg->rt.rtm_family == AF_INET6 && !memcmp(dst, ipv6_default, sizeof(ipv6_default))) 2102 | ) && gw && ifndx >= 0) { 2103 | char buffer[256]; 2104 | char ifnamebuf[IF_NAMESIZE]; 2105 | char *ifname; 2106 | const char *addr; 2107 | PyObject *pyifname; 2108 | PyObject *pyaddr; 2109 | PyObject *isdefault; 2110 | PyObject *tuple = NULL, *deftuple = NULL; 2111 | 2112 | ifname = if_indextoname (ifndx, ifnamebuf); 2113 | 2114 | if (!ifname) 2115 | goto next; 2116 | 2117 | addr = inet_ntop (pmsg->rt.rtm_family, gw, buffer, sizeof (buffer)); 2118 | 2119 | if (!addr) 2120 | goto next; 2121 | 2122 | /* We set isdefault to True if this route came from the main table; 2123 | this should correspond with the way most people set up alternate 2124 | routing tables on Linux. */ 2125 | 2126 | isdefault = pmsg->rt.rtm_table == RT_TABLE_MAIN ? Py_True : Py_False; 2127 | 2128 | /* Priority starts at 0, having none means we use kernel default (0) */ 2129 | if (priority < 0) { 2130 | priority = 0; 2131 | } 2132 | 2133 | /* Try to pick the active default route based on priority (which 2134 | is displayed in the UI as "metric", confusingly) */ 2135 | if (pmsg->rt.rtm_family < RTNL_FAMILY_MAX) { 2136 | /* If no active default route found, or metric is lower */ 2137 | if (def_priorities[pmsg->rt.rtm_family] == -1 2138 | || priority < def_priorities[pmsg->rt.rtm_family]) 2139 | /* Set new default */ 2140 | def_priorities[pmsg->rt.rtm_family] = priority; 2141 | else 2142 | /* Leave default, but unset isdefault for iface tuple */ 2143 | isdefault = Py_False; 2144 | } 2145 | 2146 | pyifname = PyUnicode_FromString (ifname); 2147 | pyaddr = PyUnicode_FromString (buffer); 2148 | 2149 | tuple = PyTuple_Pack (3, pyaddr, pyifname, isdefault); 2150 | 2151 | if (PyObject_IsTrue (isdefault)) 2152 | deftuple = PyTuple_Pack (2, pyaddr, pyifname); 2153 | 2154 | Py_DECREF (pyaddr); 2155 | Py_DECREF (pyifname); 2156 | 2157 | if (tuple && !add_to_family (result, pmsg->rt.rtm_family, tuple)) { 2158 | Py_XDECREF (deftuple); 2159 | Py_DECREF (result); 2160 | free (msgbuf); 2161 | close (s); 2162 | return NULL; 2163 | } 2164 | 2165 | if (deftuple) { 2166 | PyObject *pyfamily = PyInt_FromLong (pmsg->rt.rtm_family); 2167 | 2168 | PyDict_SetItem (defaults, pyfamily, deftuple); 2169 | 2170 | Py_DECREF (pyfamily); 2171 | Py_DECREF (deftuple); 2172 | } 2173 | } 2174 | 2175 | next: 2176 | pmsg = (struct routing_msg *)NLMSG_NEXT(&pmsg->hdr, nllen); 2177 | } 2178 | } while (is_multi); 2179 | } while (interrupted); 2180 | 2181 | free (msgbuf); 2182 | close (s); 2183 | #elif defined(HAVE_SYSCTL_CTL_NET) 2184 | /* .. UNIX, via sysctl() .................................................. */ 2185 | 2186 | int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_FLAGS, 2187 | RTF_UP | RTF_GATEWAY }; 2188 | size_t len; 2189 | char *buffer = NULL, *ptr, *end; 2190 | int ret; 2191 | char ifnamebuf[IF_NAMESIZE]; 2192 | char *ifname; 2193 | 2194 | result = PyDict_New(); 2195 | defaults = PyDict_New(); 2196 | PyDict_SetItemString (result, "default", defaults); 2197 | Py_DECREF (defaults); 2198 | 2199 | /* This prevents a crash on PyPy */ 2200 | defaults = PyDict_GetItemString (result, "default"); 2201 | 2202 | /* Remembering that the routing table may change while we're reading it, 2203 | we need to do this in a loop until we succeed. */ 2204 | do { 2205 | if (sysctl (mib, 6, 0, &len, 0, 0) < 0) { 2206 | PyErr_SetFromErrno (PyExc_OSError); 2207 | free (buffer); 2208 | Py_DECREF (result); 2209 | return NULL; 2210 | } 2211 | 2212 | ptr = realloc(buffer, len); 2213 | if (!ptr) { 2214 | PyErr_NoMemory(); 2215 | free (buffer); 2216 | Py_DECREF (result); 2217 | return NULL; 2218 | } 2219 | 2220 | buffer = ptr; 2221 | 2222 | ret = sysctl (mib, 6, buffer, &len, 0, 0); 2223 | } while (ret != 0 && (errno == ENOMEM || errno == EINTR)); 2224 | 2225 | if (ret < 0) { 2226 | PyErr_SetFromErrno (PyExc_OSError); 2227 | free (buffer); 2228 | Py_DECREF (result); 2229 | return NULL; 2230 | } 2231 | 2232 | ptr = buffer; 2233 | end = buffer + len; 2234 | 2235 | while (ptr + sizeof (struct rt_msghdr) <= end) { 2236 | struct rt_msghdr *msg = (struct rt_msghdr *)ptr; 2237 | char *msgend = (char *)msg + msg->rtm_msglen; 2238 | int addrs = msg->rtm_addrs; 2239 | int addr = RTA_DST; 2240 | PyObject *pyifname; 2241 | 2242 | if (msgend > end) 2243 | break; 2244 | 2245 | ifname = if_indextoname (msg->rtm_index, ifnamebuf); 2246 | 2247 | if (!ifname) { 2248 | ptr = msgend; 2249 | continue; 2250 | } 2251 | 2252 | pyifname = PyUnicode_FromString (ifname); 2253 | 2254 | ptr = (char *)(msg + 1); 2255 | while (ptr + sizeof (struct sockaddr) <= msgend && addrs) { 2256 | struct sockaddr *sa = (struct sockaddr *)ptr; 2257 | int len = SA_LEN(sa); 2258 | 2259 | if (!len) 2260 | len = 4; 2261 | else 2262 | len = (len + 3) & ~3; 2263 | 2264 | if (ptr + len > msgend) 2265 | break; 2266 | 2267 | while (!(addrs & addr)) 2268 | addr <<= 1; 2269 | 2270 | addrs &= ~addr; 2271 | 2272 | if (addr == RTA_DST) { 2273 | if (sa->sa_family == AF_INET) { 2274 | struct sockaddr_in *sin = (struct sockaddr_in *)sa; 2275 | if (sin->sin_addr.s_addr != INADDR_ANY) 2276 | break; 2277 | #ifdef AF_INET6 2278 | } else if (sa->sa_family == AF_INET6) { 2279 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 2280 | if (memcmp (&sin6->sin6_addr, &in6addr_any, sizeof (in6addr_any)) != 0) 2281 | break; 2282 | #endif 2283 | } else { 2284 | break; 2285 | } 2286 | } 2287 | 2288 | if (addr == RTA_GATEWAY) { 2289 | char strbuf[256]; 2290 | PyObject *tuple = NULL; 2291 | PyObject *deftuple = NULL; 2292 | 2293 | if (string_from_sockaddr (sa, strbuf, sizeof(strbuf)) == 0) { 2294 | PyObject *pyaddr = PyUnicode_FromString (strbuf); 2295 | #ifdef RTF_IFSCOPE 2296 | PyObject *isdefault = PyBool_FromLong (!(msg->rtm_flags & RTF_IFSCOPE)); 2297 | #else 2298 | Py_INCREF(Py_True); 2299 | PyObject *isdefault = Py_True; 2300 | #endif 2301 | tuple = PyTuple_Pack (3, pyaddr, pyifname, isdefault); 2302 | 2303 | if (PyObject_IsTrue (isdefault)) 2304 | deftuple = PyTuple_Pack (2, pyaddr, pyifname); 2305 | 2306 | Py_DECREF (pyaddr); 2307 | Py_DECREF (isdefault); 2308 | } 2309 | 2310 | if (tuple && !add_to_family (result, sa->sa_family, tuple)) { 2311 | Py_DECREF (deftuple); 2312 | Py_DECREF (result); 2313 | Py_DECREF (pyifname); 2314 | free (buffer); 2315 | return NULL; 2316 | } 2317 | 2318 | if (deftuple) { 2319 | PyObject *pyfamily = PyInt_FromLong (sa->sa_family); 2320 | 2321 | PyDict_SetItem (defaults, pyfamily, deftuple); 2322 | 2323 | Py_DECREF (pyfamily); 2324 | Py_DECREF (deftuple); 2325 | } 2326 | } 2327 | 2328 | /* These are aligned on a 4-byte boundary */ 2329 | ptr += len; 2330 | } 2331 | 2332 | Py_DECREF (pyifname); 2333 | ptr = msgend; 2334 | } 2335 | 2336 | free (buffer); 2337 | #elif defined(HAVE_PF_ROUTE) 2338 | /* .. UNIX, via PF_ROUTE socket ........................................... */ 2339 | 2340 | /* The PF_ROUTE code will only retrieve gateway information for AF_INET and 2341 | AF_INET6. This is because it would need to loop through all possible 2342 | values, and the messages it needs to send in each case are potentially 2343 | different. It is also very likely to return a maximum of one gateway 2344 | in each case (since we can't read the entire routing table this way, we 2345 | can only ask about routes). */ 2346 | 2347 | int pagesize = getpagesize(); 2348 | int bufsize = pagesize < 8192 ? 8192 : pagesize; 2349 | struct rt_msghdr *pmsg; 2350 | int s; 2351 | int seq = 0; 2352 | int pid = getpid(); 2353 | ssize_t ret; 2354 | struct sockaddr_in *sin_dst, *sin_netmask; 2355 | struct sockaddr_dl *sdl_ifp; 2356 | struct sockaddr_in6 *sin6_dst; 2357 | size_t msglen; 2358 | char ifnamebuf[IF_NAMESIZE]; 2359 | char *ifname; 2360 | int skip; 2361 | 2362 | result = PyDict_New(); 2363 | defaults = PyDict_New(); 2364 | PyDict_SetItemString (result, "default", defaults); 2365 | Py_DECREF(defaults); 2366 | 2367 | pmsg = (struct rt_msghdr *)malloc (bufsize); 2368 | 2369 | if (!pmsg) { 2370 | PyErr_NoMemory(); 2371 | return NULL; 2372 | } 2373 | 2374 | s = socket (PF_ROUTE, SOCK_RAW, 0); 2375 | 2376 | if (s < 0) { 2377 | PyErr_SetFromErrno (PyExc_OSError); 2378 | free (pmsg); 2379 | return NULL; 2380 | } 2381 | 2382 | msglen = (sizeof (struct rt_msghdr) 2383 | + 2 * sizeof (struct sockaddr_in) 2384 | + sizeof (struct sockaddr_dl)); 2385 | memset (pmsg, 0, msglen); 2386 | 2387 | /* AF_INET first */ 2388 | pmsg->rtm_msglen = msglen; 2389 | pmsg->rtm_type = RTM_GET; 2390 | pmsg->rtm_index = 0; 2391 | pmsg->rtm_flags = RTF_UP | RTF_GATEWAY; 2392 | pmsg->rtm_version = RTM_VERSION; 2393 | pmsg->rtm_seq = ++seq; 2394 | pmsg->rtm_pid = 0; 2395 | pmsg->rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP; 2396 | 2397 | sin_dst = (struct sockaddr_in *)(pmsg + 1); 2398 | sin_netmask = (struct sockaddr_in *)(sin_dst + 1); 2399 | sdl_ifp = (struct sockaddr_dl *)(sin_netmask + 1); 2400 | 2401 | sin_dst->sin_family = AF_INET; 2402 | sin_netmask->sin_family = AF_INET; 2403 | sdl_ifp->sdl_family = AF_LINK; 2404 | 2405 | #if HAVE_SOCKADDR_SA_LEN 2406 | sin_dst->sin_len = sizeof (struct sockaddr_in); 2407 | sin_netmask->sin_len = sizeof (struct sockaddr_in); 2408 | sdl_ifp->sdl_len = sizeof (struct sockaddr_dl); 2409 | #endif 2410 | 2411 | skip = 0; 2412 | if (send (s, pmsg, msglen, 0) < 0) { 2413 | if (errno == ESRCH) 2414 | skip = 1; 2415 | else { 2416 | PyErr_SetFromErrno (PyExc_OSError); 2417 | close (s); 2418 | free (pmsg); 2419 | return NULL; 2420 | } 2421 | } 2422 | 2423 | while (!skip && !(pmsg->rtm_flags & RTF_DONE)) { 2424 | char *ptr; 2425 | char *msgend; 2426 | int addrs; 2427 | int addr; 2428 | struct sockaddr_in *dst = NULL; 2429 | struct sockaddr_in *gw = NULL; 2430 | struct sockaddr_dl *ifp = NULL; 2431 | PyObject *tuple = NULL; 2432 | PyObject *deftuple = NULL; 2433 | 2434 | do { 2435 | ret = recv (s, pmsg, bufsize, 0); 2436 | } while ((ret < 0 && errno == EINTR) 2437 | || (ret > 0 && (pmsg->rtm_seq != seq || pmsg->rtm_pid != pid))); 2438 | 2439 | if (ret < 0) { 2440 | PyErr_SetFromErrno (PyExc_OSError); 2441 | close (s); 2442 | free (pmsg); 2443 | return NULL; 2444 | } 2445 | 2446 | if (pmsg->rtm_errno != 0) { 2447 | if (pmsg->rtm_errno == ESRCH) 2448 | skip = 1; 2449 | else { 2450 | errno = pmsg->rtm_errno; 2451 | PyErr_SetFromErrno (PyExc_OSError); 2452 | close (s); 2453 | free (pmsg); 2454 | return NULL; 2455 | } 2456 | } 2457 | 2458 | if (skip) 2459 | break; 2460 | 2461 | ptr = (char *)(pmsg + 1); 2462 | msgend = (char *)pmsg + pmsg->rtm_msglen; 2463 | addrs = pmsg->rtm_addrs; 2464 | addr = RTA_DST; 2465 | while (ptr + sizeof (struct sockaddr) <= msgend && addrs) { 2466 | struct sockaddr *sa = (struct sockaddr *)ptr; 2467 | int len = SA_LEN(sa); 2468 | 2469 | if (!len) 2470 | len = 4; 2471 | else 2472 | len = (len + 3) & ~3; 2473 | 2474 | if (ptr + len > msgend) 2475 | break; 2476 | 2477 | while (!(addrs & addr)) 2478 | addr <<= 1; 2479 | 2480 | addrs &= ~addr; 2481 | 2482 | switch (addr) { 2483 | case RTA_DST: 2484 | dst = (struct sockaddr_in *)sa; 2485 | break; 2486 | case RTA_GATEWAY: 2487 | gw = (struct sockaddr_in *)sa; 2488 | break; 2489 | case RTA_IFP: 2490 | ifp = (struct sockaddr_dl *)sa; 2491 | break; 2492 | } 2493 | 2494 | ptr += len; 2495 | } 2496 | 2497 | if ((dst && dst->sin_family != AF_INET) 2498 | || (gw && gw->sin_family != AF_INET) 2499 | || (ifp && ifp->sdl_family != AF_LINK)) { 2500 | dst = gw = NULL; 2501 | ifp = NULL; 2502 | } 2503 | 2504 | if (dst && dst->sin_addr.s_addr == INADDR_ANY) 2505 | dst = NULL; 2506 | 2507 | if (!dst && gw && ifp) { 2508 | char buffer[256]; 2509 | 2510 | if (ifp->sdl_index) 2511 | ifname = if_indextoname (ifp->sdl_index, ifnamebuf); 2512 | else { 2513 | memcpy (ifnamebuf, ifp->sdl_data, ifp->sdl_nlen); 2514 | ifnamebuf[ifp->sdl_nlen] = '\0'; 2515 | ifname = ifnamebuf; 2516 | } 2517 | 2518 | if (string_from_sockaddr ((struct sockaddr *)gw, 2519 | buffer, sizeof(buffer)) == 0) { 2520 | PyObject *pyifname = PyUnicode_FromString (ifname); 2521 | PyObject *pyaddr = PyUnicode_FromString (buffer); 2522 | #ifdef RTF_IFSCOPE 2523 | PyObject *isdefault = PyBool_FromLong (!(pmsg->rtm_flags & RTF_IFSCOPE)); 2524 | #else 2525 | PyObject *isdefault = Py_True; 2526 | Py_INCREF(isdefault); 2527 | #endif 2528 | 2529 | tuple = PyTuple_Pack (3, pyaddr, pyifname, isdefault); 2530 | 2531 | if (PyObject_IsTrue (isdefault)) 2532 | deftuple = PyTuple_Pack (2, pyaddr, pyifname); 2533 | 2534 | Py_DECREF (pyaddr); 2535 | Py_DECREF (pyifname); 2536 | Py_DECREF (isdefault); 2537 | } 2538 | 2539 | if (tuple && !add_to_family (result, AF_INET, tuple)) { 2540 | Py_DECREF (deftuple); 2541 | Py_DECREF (result); 2542 | free (pmsg); 2543 | return NULL; 2544 | } 2545 | 2546 | if (deftuple) { 2547 | PyObject *pyfamily = PyInt_FromLong (AF_INET); 2548 | 2549 | PyDict_SetItem (defaults, pyfamily, deftuple); 2550 | 2551 | Py_DECREF (pyfamily); 2552 | Py_DECREF (deftuple); 2553 | } 2554 | } 2555 | } 2556 | 2557 | /* The code below is very similar to, but not identical to, the code above. 2558 | We could probably refactor some of it, but take care---there are subtle 2559 | differences! */ 2560 | 2561 | #ifdef AF_INET6 2562 | /* AF_INET6 now */ 2563 | msglen = (sizeof (struct rt_msghdr) 2564 | + sizeof (struct sockaddr_in6) 2565 | + sizeof (struct sockaddr_dl)); 2566 | memset (pmsg, 0, msglen); 2567 | 2568 | pmsg->rtm_msglen = msglen; 2569 | pmsg->rtm_type = RTM_GET; 2570 | pmsg->rtm_index = 0; 2571 | pmsg->rtm_flags = RTF_UP | RTF_GATEWAY; 2572 | pmsg->rtm_version = RTM_VERSION; 2573 | pmsg->rtm_seq = ++seq; 2574 | pmsg->rtm_pid = 0; 2575 | pmsg->rtm_addrs = RTA_DST | RTA_IFP; 2576 | 2577 | sin6_dst = (struct sockaddr_in6 *)(pmsg + 1); 2578 | sdl_ifp = (struct sockaddr_dl *)(sin6_dst + 1); 2579 | 2580 | sin6_dst->sin6_family = AF_INET6; 2581 | sin6_dst->sin6_addr = in6addr_any; 2582 | sdl_ifp->sdl_family = AF_LINK; 2583 | 2584 | #if HAVE_SOCKADDR_SA_LEN 2585 | sin6_dst->sin6_len = sizeof (struct sockaddr_in6); 2586 | sdl_ifp->sdl_len = sizeof (struct sockaddr_dl); 2587 | #endif 2588 | 2589 | skip = 0; 2590 | if (send (s, pmsg, msglen, 0) < 0) { 2591 | if (errno == ESRCH) 2592 | skip = 1; 2593 | else { 2594 | PyErr_SetFromErrno (PyExc_OSError); 2595 | close (s); 2596 | free (pmsg); 2597 | return NULL; 2598 | } 2599 | } 2600 | 2601 | while (!skip && !(pmsg->rtm_flags & RTF_DONE)) { 2602 | char *ptr; 2603 | char *msgend; 2604 | int addrs; 2605 | int addr; 2606 | struct sockaddr_in6 *dst = NULL; 2607 | struct sockaddr_in6 *gw = NULL; 2608 | struct sockaddr_dl *ifp = NULL; 2609 | PyObject *tuple = NULL; 2610 | PyObject *deftuple = NULL; 2611 | 2612 | do { 2613 | ret = recv (s, pmsg, bufsize, 0); 2614 | } while ((ret < 0 && errno == EINTR) 2615 | || (ret > 0 && (pmsg->rtm_seq != seq || pmsg->rtm_pid != pid))); 2616 | 2617 | if (ret < 0) { 2618 | PyErr_SetFromErrno (PyExc_OSError); 2619 | close (s); 2620 | free (pmsg); 2621 | return NULL; 2622 | } 2623 | 2624 | if (pmsg->rtm_errno != 0) { 2625 | if (pmsg->rtm_errno == ESRCH) 2626 | skip = 1; 2627 | else { 2628 | errno = pmsg->rtm_errno; 2629 | PyErr_SetFromErrno (PyExc_OSError); 2630 | close (s); 2631 | free (pmsg); 2632 | return NULL; 2633 | } 2634 | } 2635 | 2636 | if (skip) 2637 | break; 2638 | 2639 | ptr = (char *)(pmsg + 1); 2640 | msgend = (char *)pmsg + pmsg->rtm_msglen; 2641 | addrs = pmsg->rtm_addrs; 2642 | addr = RTA_DST; 2643 | while (ptr + sizeof (struct sockaddr) <= msgend && addrs) { 2644 | struct sockaddr *sa = (struct sockaddr *)ptr; 2645 | int len = SA_LEN(sa); 2646 | 2647 | if (!len) 2648 | len = 4; 2649 | else 2650 | len = (len + 3) & ~3; 2651 | 2652 | if (ptr + len > msgend) 2653 | break; 2654 | 2655 | while (!(addrs & addr)) 2656 | addr <<= 1; 2657 | 2658 | addrs &= ~addr; 2659 | 2660 | switch (addr) { 2661 | case RTA_DST: 2662 | dst = (struct sockaddr_in6 *)sa; 2663 | break; 2664 | case RTA_GATEWAY: 2665 | gw = (struct sockaddr_in6 *)sa; 2666 | break; 2667 | case RTA_IFP: 2668 | ifp = (struct sockaddr_dl *)sa; 2669 | break; 2670 | } 2671 | 2672 | ptr += len; 2673 | } 2674 | 2675 | if ((dst && dst->sin6_family != AF_INET6) 2676 | || (gw && gw->sin6_family != AF_INET6) 2677 | || (ifp && ifp->sdl_family != AF_LINK)) { 2678 | dst = gw = NULL; 2679 | ifp = NULL; 2680 | } 2681 | 2682 | if (dst && memcmp (&dst->sin6_addr, &in6addr_any, 2683 | sizeof(struct in6_addr)) == 0) 2684 | dst = NULL; 2685 | 2686 | if (!dst && gw && ifp) { 2687 | char buffer[256]; 2688 | 2689 | if (ifp->sdl_index) 2690 | ifname = if_indextoname (ifp->sdl_index, ifnamebuf); 2691 | else { 2692 | memcpy (ifnamebuf, ifp->sdl_data, ifp->sdl_nlen); 2693 | ifnamebuf[ifp->sdl_nlen] = '\0'; 2694 | ifname = ifnamebuf; 2695 | } 2696 | 2697 | if (string_from_sockaddr ((struct sockaddr *)gw, 2698 | buffer, sizeof(buffer)) == 0) { 2699 | PyObject *pyifname = PyUnicode_FromString (ifname); 2700 | PyObject *pyaddr = PyUnicode_FromString (buffer); 2701 | #ifdef RTF_IFSCOPE 2702 | PyObject *isdefault = PyBool_FromLong (!(pmsg->rtm_flags & RTF_IFSCOPE)); 2703 | #else 2704 | PyObject *isdefault = Py_True; 2705 | Py_INCREF (isdefault); 2706 | #endif 2707 | 2708 | tuple = PyTuple_Pack (3, pyaddr, pyifname, isdefault); 2709 | 2710 | if (PyObject_IsTrue (isdefault)) 2711 | deftuple = PyTuple_Pack (2, pyaddr, pyifname); 2712 | 2713 | Py_DECREF (pyaddr); 2714 | Py_DECREF (pyifname); 2715 | Py_DECREF (isdefault); 2716 | } 2717 | 2718 | if (tuple && !add_to_family (result, AF_INET6, tuple)) { 2719 | Py_DECREF (deftuple); 2720 | Py_DECREF (result); 2721 | free (pmsg); 2722 | return NULL; 2723 | } 2724 | 2725 | if (deftuple) { 2726 | PyObject *pyfamily = PyInt_FromLong (AF_INET6); 2727 | 2728 | PyDict_SetItem (defaults, pyfamily, deftuple); 2729 | 2730 | Py_DECREF (pyfamily); 2731 | Py_DECREF (deftuple); 2732 | } 2733 | } 2734 | } 2735 | #endif /* AF_INET6 */ 2736 | 2737 | free (pmsg); 2738 | #else 2739 | /* If we don't know how to implement this on your platform, we raise an 2740 | exception. */ 2741 | PyErr_SetString (PyExc_OSError, 2742 | "Unable to obtain gateway information on your platform."); 2743 | #endif 2744 | 2745 | return result; 2746 | } 2747 | 2748 | /* -- Python Module --------------------------------------------------------- */ 2749 | 2750 | // On Python >= 3.4, the function signature shown by help() can be customized if the 2751 | // function signature is followed by --\n\n 2752 | // https://stackoverflow.com/a/41245451 2753 | #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4 2754 | #define SIGNATURE_SEPARATOR "--\n" 2755 | #else 2756 | #define SIGNATURE_SEPARATOR "" 2757 | #endif 2758 | 2759 | static PyMethodDef methods[] = { 2760 | { "ifaddresses", (PyCFunction)ifaddrs, METH_VARARGS, 2761 | "ifaddresses(ifaddress, /)\n" 2762 | SIGNATURE_SEPARATOR 2763 | "\n" 2764 | "Obtain information about the specified network interface.\n" 2765 | "\n" 2766 | "Returns a dict whose keys are equal to the address family constants,\n" 2767 | "e.g. netifaces.AF_INET, and whose values are a list of addresses in\n" 2768 | "that family that are attached to the network interface." }, 2769 | { "allifaddresses", (PyCFunction)allifaddrs, METH_NOARGS, 2770 | "Obtain information about all network interfaces.\n" 2771 | "\n" 2772 | "Returns a dict whose keys are equal to the network interface name,\n" 2773 | "e.g. 'eth0', and whose value is dict of (key: family_address, value: network_interface_info) " }, 2774 | { "interfaces", (PyCFunction)interfaces, METH_NOARGS, 2775 | "interfaces()\n" 2776 | SIGNATURE_SEPARATOR 2777 | "\n" 2778 | "Obtain a list of the interfaces available on this machine." }, 2779 | { "gateways", (PyCFunction)gateways, METH_NOARGS, 2780 | "gateways()\n" 2781 | SIGNATURE_SEPARATOR 2782 | "\n" 2783 | "Obtain a list of the gateways on this machine.\n" 2784 | "\n" 2785 | "Returns a dict whose keys are equal to the address family constants,\n" 2786 | "e.g. netifaces.AF_INET, and whose values are a list of tuples of the\n" 2787 | "format (
, , ).\n" 2788 | "\n" 2789 | "There is also a special entry with the key 'default', which you can use\n" 2790 | "to quickly obtain the default gateway for a particular address family.\n" 2791 | "\n" 2792 | "There may in general be multiple gateways; different address\n" 2793 | "families may have different gateway settings (e.g. AF_INET vs AF_INET6)\n" 2794 | "and on some systems it's also possible to have interface-specific\n" 2795 | "default gateways.\n" }, 2796 | { NULL, NULL, 0, NULL } 2797 | }; 2798 | 2799 | MODULE_DEF("_netifaces", NULL, methods); 2800 | 2801 | MODULE_INIT(_netifaces) 2802 | { 2803 | PyObject *address_family_dict; 2804 | PyObject *m; 2805 | 2806 | #ifdef WIN32 2807 | WSADATA wsad; 2808 | 2809 | WSAStartup(MAKEWORD (2, 2), &wsad); 2810 | #endif 2811 | 2812 | MODULE_CREATE(m, "_netifaces", NULL, methods); 2813 | if (!m) 2814 | return MODULE_ERROR; 2815 | 2816 | /* Address families (auto-detect using #ifdef) */ 2817 | address_family_dict = PyDict_New(); 2818 | #ifdef AF_UNSPEC 2819 | PyModule_AddIntConstant (m, "AF_UNSPEC", AF_UNSPEC); 2820 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNSPEC), 2821 | PyUnicode_FromString("AF_UNSPEC")); 2822 | #endif 2823 | #ifdef AF_UNIX 2824 | PyModule_AddIntConstant (m, "AF_UNIX", AF_UNIX); 2825 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNIX), 2826 | PyUnicode_FromString("AF_UNIX")); 2827 | #endif 2828 | #ifdef AF_FILE 2829 | PyModule_AddIntConstant (m, "AF_FILE", AF_FILE); 2830 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_FILE), 2831 | PyUnicode_FromString("AF_FILE")); 2832 | #endif 2833 | #ifdef AF_INET 2834 | PyModule_AddIntConstant (m, "AF_INET", AF_INET); 2835 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_INET), 2836 | PyUnicode_FromString("AF_INET")); 2837 | #endif 2838 | #ifdef AF_AX25 2839 | PyModule_AddIntConstant (m, "AF_AX25", AF_AX25); 2840 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_AX25), 2841 | PyUnicode_FromString("AF_AX25")); 2842 | #endif 2843 | #ifdef AF_IMPLINK 2844 | PyModule_AddIntConstant (m, "AF_IMPLINK", AF_IMPLINK); 2845 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IMPLINK), 2846 | PyUnicode_FromString("AF_IMPLINK")); 2847 | #endif 2848 | #ifdef AF_PUP 2849 | PyModule_AddIntConstant (m, "AF_PUP", AF_PUP); 2850 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PUP), 2851 | PyUnicode_FromString("AF_PUP")); 2852 | #endif 2853 | #ifdef AF_CHAOS 2854 | PyModule_AddIntConstant (m, "AF_CHAOS", AF_CHAOS); 2855 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CHAOS), 2856 | PyUnicode_FromString("AF_CHAOS")); 2857 | #endif 2858 | #ifdef AF_NS 2859 | PyModule_AddIntConstant (m, "AF_NS", AF_NS); 2860 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NS), 2861 | PyUnicode_FromString("AF_NS")); 2862 | #endif 2863 | #ifdef AF_ISO 2864 | PyModule_AddIntConstant (m, "AF_ISO", AF_ISO); 2865 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ISO), 2866 | PyUnicode_FromString("AF_ISO")); 2867 | #endif 2868 | #ifdef AF_ECMA 2869 | PyModule_AddIntConstant (m, "AF_ECMA", AF_ECMA); 2870 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ECMA), 2871 | PyUnicode_FromString("AF_ECMA")); 2872 | #endif 2873 | #ifdef AF_DATAKIT 2874 | PyModule_AddIntConstant (m, "AF_DATAKIT", AF_DATAKIT); 2875 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DATAKIT), 2876 | PyUnicode_FromString("AF_DATAKIT")); 2877 | #endif 2878 | #ifdef AF_CCITT 2879 | PyModule_AddIntConstant (m, "AF_CCITT", AF_CCITT); 2880 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CCITT), 2881 | PyUnicode_FromString("AF_CCITT")); 2882 | #endif 2883 | #ifdef AF_SNA 2884 | PyModule_AddIntConstant (m, "AF_SNA", AF_SNA); 2885 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SNA), 2886 | PyUnicode_FromString("AF_SNA")); 2887 | #endif 2888 | #ifdef AF_DECnet 2889 | PyModule_AddIntConstant (m, "AF_DECnet", AF_DECnet); 2890 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DECnet), 2891 | PyUnicode_FromString("AF_DECnet")); 2892 | #endif 2893 | #ifdef AF_DLI 2894 | PyModule_AddIntConstant (m, "AF_DLI", AF_DLI); 2895 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DLI), 2896 | PyUnicode_FromString("AF_DLI")); 2897 | #endif 2898 | #ifdef AF_LAT 2899 | PyModule_AddIntConstant (m, "AF_LAT", AF_LAT); 2900 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_LAT), 2901 | PyUnicode_FromString("AF_LAT")); 2902 | #endif 2903 | #ifdef AF_HYLINK 2904 | PyModule_AddIntConstant (m, "AF_HYLINK", AF_HYLINK); 2905 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_HYLINK), 2906 | PyUnicode_FromString("AF_HYLINK")); 2907 | #endif 2908 | #ifdef AF_APPLETALK 2909 | PyModule_AddIntConstant (m, "AF_APPLETALK", AF_APPLETALK); 2910 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_APPLETALK), 2911 | PyUnicode_FromString("AF_APPLETALK")); 2912 | #endif 2913 | #ifdef AF_ROUTE 2914 | PyModule_AddIntConstant (m, "AF_ROUTE", AF_ROUTE); 2915 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ROUTE), 2916 | PyUnicode_FromString("AF_ROUTE")); 2917 | #endif 2918 | #ifdef AF_LINK 2919 | PyModule_AddIntConstant (m, "AF_LINK", AF_LINK); 2920 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_LINK), 2921 | PyUnicode_FromString("AF_LINK")); 2922 | #endif 2923 | #ifdef AF_PACKET 2924 | PyModule_AddIntConstant (m, "AF_PACKET", AF_PACKET); 2925 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PACKET), 2926 | PyUnicode_FromString("AF_PACKET")); 2927 | #endif 2928 | #ifdef AF_COIP 2929 | PyModule_AddIntConstant (m, "AF_COIP", AF_COIP); 2930 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_COIP), 2931 | PyUnicode_FromString("AF_COIP")); 2932 | #endif 2933 | #ifdef AF_CNT 2934 | PyModule_AddIntConstant (m, "AF_CNT", AF_CNT); 2935 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CNT), 2936 | PyUnicode_FromString("AF_CNT")); 2937 | #endif 2938 | #ifdef AF_IPX 2939 | PyModule_AddIntConstant (m, "AF_IPX", AF_IPX); 2940 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IPX), 2941 | PyUnicode_FromString("AF_IPX")); 2942 | #endif 2943 | #ifdef AF_SIP 2944 | PyModule_AddIntConstant (m, "AF_SIP", AF_SIP); 2945 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SIP), 2946 | PyUnicode_FromString("AF_SIP")); 2947 | #endif 2948 | #ifdef AF_NDRV 2949 | PyModule_AddIntConstant (m, "AF_NDRV", AF_NDRV); 2950 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NDRV), 2951 | PyUnicode_FromString("AF_NDRV")); 2952 | #endif 2953 | #ifdef AF_ISDN 2954 | PyModule_AddIntConstant (m, "AF_ISDN", AF_ISDN); 2955 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ISDN), 2956 | PyUnicode_FromString("AF_ISDN")); 2957 | #endif 2958 | #ifdef AF_INET6 2959 | PyModule_AddIntConstant (m, "AF_INET6", AF_INET6); 2960 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_INET6), 2961 | PyUnicode_FromString("AF_INET6")); 2962 | #endif 2963 | #ifdef AF_NATM 2964 | PyModule_AddIntConstant (m, "AF_NATM", AF_NATM); 2965 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NATM), 2966 | PyUnicode_FromString("AF_NATM")); 2967 | #endif 2968 | #ifdef AF_SYSTEM 2969 | PyModule_AddIntConstant (m, "AF_SYSTEM", AF_SYSTEM); 2970 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SYSTEM), 2971 | PyUnicode_FromString("AF_SYSTEM")); 2972 | #endif 2973 | #ifdef AF_NETBIOS 2974 | PyModule_AddIntConstant (m, "AF_NETBIOS", AF_NETBIOS); 2975 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETBIOS), 2976 | PyUnicode_FromString("AF_NETBIOS")); 2977 | #endif 2978 | #ifdef AF_NETBEUI 2979 | PyModule_AddIntConstant (m, "AF_NETBEUI", AF_NETBEUI); 2980 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETBEUI), 2981 | PyUnicode_FromString("AF_NETBEUI")); 2982 | #endif 2983 | #ifdef AF_PPP 2984 | PyModule_AddIntConstant (m, "AF_PPP", AF_PPP); 2985 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PPP), 2986 | PyUnicode_FromString("AF_PPP")); 2987 | #endif 2988 | #ifdef AF_ATM 2989 | PyModule_AddIntConstant (m, "AF_ATM", AF_ATM); 2990 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATM), 2991 | PyUnicode_FromString("AF_ATM")); 2992 | #endif 2993 | #ifdef AF_ATMPVC 2994 | PyModule_AddIntConstant (m, "AF_ATMPVC", AF_ATMPVC); 2995 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATMPVC), 2996 | PyUnicode_FromString("AF_ATMPVC")); 2997 | #endif 2998 | #ifdef AF_ATMSVC 2999 | PyModule_AddIntConstant (m, "AF_ATMSVC", AF_ATMSVC); 3000 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATMSVC), 3001 | PyUnicode_FromString("AF_ATMSVC")); 3002 | #endif 3003 | #ifdef AF_NETGRAPH 3004 | PyModule_AddIntConstant (m, "AF_NETGRAPH", AF_NETGRAPH); 3005 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETGRAPH), 3006 | PyUnicode_FromString("AF_NETGRAPH")); 3007 | #endif 3008 | #ifdef AF_VOICEVIEW 3009 | PyModule_AddIntConstant (m, "AF_VOICEVIEW", AF_VOICEVIEW); 3010 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_VOICEVIEW), 3011 | PyUnicode_FromString("AF_VOICEVIEW")); 3012 | #endif 3013 | #ifdef AF_FIREFOX 3014 | PyModule_AddIntConstant (m, "AF_FIREFOX", AF_FIREFOX); 3015 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_FIREFOX), 3016 | PyUnicode_FromString("AF_FIREFOX")); 3017 | #endif 3018 | #ifdef AF_UNKNOWN1 3019 | PyModule_AddIntConstant (m, "AF_UNKNOWN1", AF_UNKNOWN1); 3020 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNKNOWN1), 3021 | PyUnicode_FromString("AF_UNKNOWN1")); 3022 | #endif 3023 | #ifdef AF_BAN 3024 | PyModule_AddIntConstant (m, "AF_BAN", AF_BAN); 3025 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BAN), 3026 | PyUnicode_FromString("AF_BAN")); 3027 | #endif 3028 | #ifdef AF_CLUSTER 3029 | PyModule_AddIntConstant (m, "AF_CLUSTER", AF_CLUSTER); 3030 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CLUSTER), 3031 | PyUnicode_FromString("AF_CLUSTER")); 3032 | #endif 3033 | #ifdef AF_12844 3034 | PyModule_AddIntConstant (m, "AF_12844", AF_12844); 3035 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_12844), 3036 | PyUnicode_FromString("AF_12844")); 3037 | #endif 3038 | #ifdef AF_IRDA 3039 | PyModule_AddIntConstant (m, "AF_IRDA", AF_IRDA); 3040 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IRDA), 3041 | PyUnicode_FromString("AF_IRDA")); 3042 | #endif 3043 | #ifdef AF_NETDES 3044 | PyModule_AddIntConstant (m, "AF_NETDES", AF_NETDES); 3045 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETDES), 3046 | PyUnicode_FromString("AF_NETDES")); 3047 | #endif 3048 | #ifdef AF_NETROM 3049 | PyModule_AddIntConstant (m, "AF_NETROM", AF_NETROM); 3050 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETROM), 3051 | PyUnicode_FromString("AF_NETROM")); 3052 | #endif 3053 | #ifdef AF_BRIDGE 3054 | PyModule_AddIntConstant (m, "AF_BRIDGE", AF_BRIDGE); 3055 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BRIDGE), 3056 | PyUnicode_FromString("AF_BRIDGE")); 3057 | #endif 3058 | #ifdef AF_X25 3059 | PyModule_AddIntConstant (m, "AF_X25", AF_X25); 3060 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_X25), 3061 | PyUnicode_FromString("AF_X25")); 3062 | #endif 3063 | #ifdef AF_ROSE 3064 | PyModule_AddIntConstant (m, "AF_ROSE", AF_ROSE); 3065 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ROSE), 3066 | PyUnicode_FromString("AF_ROSE")); 3067 | #endif 3068 | #ifdef AF_SECURITY 3069 | PyModule_AddIntConstant (m, "AF_SECURITY", AF_SECURITY); 3070 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SECURITY), 3071 | PyUnicode_FromString("AF_SECURITY")); 3072 | #endif 3073 | #ifdef AF_KEY 3074 | PyModule_AddIntConstant (m, "AF_KEY", AF_KEY); 3075 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_KEY), 3076 | PyUnicode_FromString("AF_KEY")); 3077 | #endif 3078 | #ifdef AF_NETLINK 3079 | PyModule_AddIntConstant (m, "AF_NETLINK", AF_NETLINK); 3080 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETLINK), 3081 | PyUnicode_FromString("AF_NETLINK")); 3082 | #endif 3083 | #ifdef AF_ASH 3084 | PyModule_AddIntConstant (m, "AF_ASH", AF_ASH); 3085 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ASH), 3086 | PyUnicode_FromString("AF_ASH")); 3087 | #endif 3088 | #ifdef AF_ECONET 3089 | PyModule_AddIntConstant (m, "AF_ECONET", AF_ECONET); 3090 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ECONET), 3091 | PyUnicode_FromString("AF_ECONET")); 3092 | #endif 3093 | #ifdef AF_SNA 3094 | PyModule_AddIntConstant (m, "AF_SNA", AF_SNA); 3095 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SNA), 3096 | PyUnicode_FromString("AF_SNA")); 3097 | #endif 3098 | #ifdef AF_PPPOX 3099 | PyModule_AddIntConstant (m, "AF_PPPOX", AF_PPPOX); 3100 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PPPOX), 3101 | PyUnicode_FromString("AF_PPPOX")); 3102 | #endif 3103 | #ifdef AF_WANPIPE 3104 | PyModule_AddIntConstant (m, "AF_WANPIPE", AF_WANPIPE); 3105 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_WANPIPE), 3106 | PyUnicode_FromString("AF_WANPIPE")); 3107 | #endif 3108 | #ifdef AF_BLUETOOTH 3109 | PyModule_AddIntConstant (m, "AF_BLUETOOTH", AF_BLUETOOTH); 3110 | PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BLUETOOTH), 3111 | PyUnicode_FromString("AF_BLUETOOTH")); 3112 | #endif 3113 | #ifdef IN6_IFF_AUTOCONF 3114 | PyModule_AddIntConstant (m, "IN6_IFF_AUTOCONF", IN6_IFF_AUTOCONF); 3115 | #endif 3116 | #ifdef IN6_IFF_TEMPORARY 3117 | PyModule_AddIntConstant (m, "IN6_IFF_TEMPORARY", IN6_IFF_TEMPORARY); 3118 | #endif 3119 | #ifdef IN6_IFF_DYNAMIC 3120 | PyModule_AddIntConstant (m, "IN6_IFF_DYNAMIC", IN6_IFF_DYNAMIC); 3121 | #endif 3122 | #ifdef IN6_IFF_OPTIMISTIC 3123 | PyModule_AddIntConstant (m, "IN6_IFF_OPTIMISTIC", IN6_IFF_OPTIMISTIC); 3124 | #endif 3125 | #ifdef IN6_IFF_SECURED 3126 | PyModule_AddIntConstant (m, "IN6_IFF_SECURED", IN6_IFF_SECURED); 3127 | #endif 3128 | PyModule_AddObject(m, "address_families", address_family_dict); 3129 | 3130 | // Add-in the version number from setup.py 3131 | #undef STR 3132 | #undef _STR 3133 | #define _STR(x) #x 3134 | #define STR(x) _STR(x) 3135 | 3136 | PyModule_AddStringConstant(m, "version", STR(NETIFACES_VERSION)); 3137 | 3138 | MODULE_RETURN(m); 3139 | } 3140 | --------------------------------------------------------------------------------