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