mirror of
https://github.com/Hopiu/linkchecker.git
synced 2026-04-30 02:54:42 +00:00
Improved network interface detection on POSIX systems
git-svn-id: https://linkchecker.svn.sourceforge.net/svnroot/linkchecker/trunk/linkchecker@3792 e7d03fd6-7b0d-0410-9947-9c21f3af8025
This commit is contained in:
parent
7cb6900a9c
commit
83bd7ce4ac
8 changed files with 129 additions and 34 deletions
|
|
@ -26,6 +26,10 @@
|
|||
Changed: linkchecker, linkcheck/checker/urlbase.py
|
||||
Added: linkcheck/clamav.py
|
||||
|
||||
* Improved network interface detection on POSIX systems.
|
||||
Type: bugfix
|
||||
Added: linkcheck/network/*
|
||||
|
||||
4.9 "Michael Clayton" (released 25.4.2008)
|
||||
|
||||
* Parse Shockwave Flash (SWF) for URLs to check
|
||||
|
|
|
|||
1
Makefile
1
Makefile
|
|
@ -59,6 +59,7 @@ localbuild: MANIFEST
|
|||
$(PYTHON) setup.py build
|
||||
cp -f build/lib.linux-$(MACHINE)-$(PYVER)/linkcheck/HtmlParser/htmlsax.so linkcheck/HtmlParser
|
||||
cp -f build/lib.linux-$(MACHINE)-$(PYVER)/linkcheck/ftpparse/_ftpparse.so linkcheck/ftpparse
|
||||
cp -f build/lib.linux-$(MACHINE)-$(PYVER)/linkcheck/network/_network.so linkcheck/network
|
||||
|
||||
.PHONY: deb_orig
|
||||
deb_orig:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ __all__ = [
|
|||
'dnssec',
|
||||
'exception',
|
||||
'flags',
|
||||
'ifconfig',
|
||||
'inet',
|
||||
'ipv4',
|
||||
'ipv6',
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
import socket
|
||||
import sets
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import encodings.idna
|
||||
|
||||
|
|
@ -377,11 +378,11 @@ class Resolver(object):
|
|||
@return: list of IP addresses
|
||||
@rtype: list of strings
|
||||
"""
|
||||
if not sys.platform.startswith('linux'):
|
||||
# only Linux is supported right now
|
||||
if os.name != 'posix':
|
||||
# only POSIX is supported right now
|
||||
return []
|
||||
import linkcheck.dns.ifconfig
|
||||
ifc = linkcheck.dns.ifconfig.IfConfig()
|
||||
from linkcheck.network import IfConfig
|
||||
ifc = IfConfig()
|
||||
return [ifc.getAddr(iface) for iface in ifc.getInterfaceList() \
|
||||
if ifc.isUp(iface)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
"""from http://twistedmatrix.com/wiki/python/IfConfig
|
||||
"""
|
||||
|
||||
import socket
|
||||
import errno
|
||||
import array
|
||||
import fcntl
|
||||
import struct
|
||||
from _network import ifreq_size
|
||||
from .. import log, LOG_DNS
|
||||
|
||||
|
||||
|
|
@ -40,14 +40,20 @@ class IfConfig (object):
|
|||
def __init__ (self):
|
||||
# create a socket so we have a handle to query
|
||||
self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
# Note that sizeof(struct ifreq) is not always 32
|
||||
# (eg. on *BSD, x86_64 Linux) Thus the function call.
|
||||
self.ifr_size = ifreq_size()
|
||||
|
||||
def _ioctl (self, func, args):
|
||||
return fcntl.ioctl(self.sockfd.fileno(), func, args)
|
||||
|
||||
def _getifreq (self, ifname):
|
||||
"""Return ifreq buffer for given interface name."""
|
||||
return struct.pack("%ds" % self.ifr_size, ifname)
|
||||
|
||||
def _getaddr (self, ifname, func):
|
||||
ifreq = struct.pack("32s", ifname)
|
||||
try:
|
||||
result = self._ioctl(func, ifreq)
|
||||
result = self._ioctl(func, self._getifreq(ifname))
|
||||
except IOError, msg:
|
||||
log.warn(LOG_DNS,
|
||||
"error getting addr for interface %r: %s", ifname, msg)
|
||||
|
|
@ -55,9 +61,7 @@ class IfConfig (object):
|
|||
return socket.inet_ntoa(result[20:24])
|
||||
|
||||
def getInterfaceList (self):
|
||||
"""
|
||||
Get all interface names in a list.
|
||||
"""
|
||||
"""Get all interface names in a list."""
|
||||
# initial 8kB buffer to hold interface data
|
||||
bufsize = 8192
|
||||
# 80kB buffer should be enough for most boxen
|
||||
|
|
@ -80,22 +84,18 @@ class IfConfig (object):
|
|||
size, ptr = struct.unpack("iP", result)
|
||||
i = 0
|
||||
while i < size:
|
||||
# XXX on *BSD, struct ifreq is not hardcoded 32, but dynamic.
|
||||
ifreq_size = 32
|
||||
ifconf = data[i:i+ifreq_size]
|
||||
name, dummy = struct.unpack("16s16s", ifconf)
|
||||
name, dummy = name.split('\0', 1)
|
||||
iflist.append(name)
|
||||
i += ifreq_size
|
||||
ifconf = data[i:i+self.ifr_size]
|
||||
name = struct.unpack("16s%ds" % (self.ifr_size-16), ifconf)[0]
|
||||
name = name.split('\0', 1)[0]
|
||||
if name:
|
||||
iflist.append(name)
|
||||
i += self.ifr_size
|
||||
return iflist
|
||||
|
||||
def getFlags (self, ifname):
|
||||
"""
|
||||
Get the flags for an interface
|
||||
"""
|
||||
ifreq = struct.pack("32s", ifname)
|
||||
"""Get the flags for an interface"""
|
||||
try:
|
||||
result = self._ioctl(self.SIOCGIFFLAGS, ifreq)
|
||||
result = self._ioctl(self.SIOCGIFFLAGS, self._getifreq(ifname))
|
||||
except IOError, msg:
|
||||
log.warn(LOG_DNS,
|
||||
"error getting flags for interface %r: %s", ifname, msg)
|
||||
|
|
@ -106,40 +106,35 @@ class IfConfig (object):
|
|||
return flags
|
||||
|
||||
def getAddr (self, ifname):
|
||||
"""
|
||||
Get the inet addr for an interface.
|
||||
"""Get the inet addr for an interface.
|
||||
@param ifname: interface name
|
||||
@type ifname: string
|
||||
"""
|
||||
return self._getaddr(ifname, self.SIOCGIFADDR)
|
||||
|
||||
def getMask (self, ifname):
|
||||
"""
|
||||
Get the netmask for an interface.
|
||||
"""Get the netmask for an interface.
|
||||
@param ifname: interface name
|
||||
@type ifname: string
|
||||
"""
|
||||
return self._getaddr(ifname, self.SIOCGIFNETMASK)
|
||||
|
||||
def getBroadcast (self, ifname):
|
||||
"""
|
||||
Get the broadcast addr for an interface.
|
||||
"""Get the broadcast addr for an interface.
|
||||
@param ifname: interface name
|
||||
@type ifname: string
|
||||
"""
|
||||
return self._getaddr(ifname, self.SIOCGIFBRDADDR)
|
||||
|
||||
def isUp (self, ifname):
|
||||
"""
|
||||
Check whether interface is UP.
|
||||
"""Check whether interface is UP.
|
||||
@param ifname: interface name
|
||||
@type ifname: string
|
||||
"""
|
||||
return (self.getFlags(ifname) & self.IFF_UP) != 0
|
||||
|
||||
def isLoopback (self, ifname):
|
||||
"""
|
||||
Check whether interface is a loopback device.
|
||||
"""Check whether interface is a loopback device.
|
||||
@param ifname: interface name
|
||||
@type ifname: string
|
||||
"""
|
||||
44
linkcheck/network/_network.c
Normal file
44
linkcheck/network/_network.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (C) 2000-2008 Bastian Kleineidam
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
/* The struct ifreq size varies on different platforms, so we need
|
||||
this helper function to determine the size of it.
|
||||
*/
|
||||
static PyObject* network_ifreq_size (PyObject* self, PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
return Py_BuildValue("i", sizeof(struct ifreq));
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef _functions[] = {
|
||||
{"ifreq_size", network_ifreq_size, METH_VARARGS,
|
||||
"Return sizeof(struct ifreq)."},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
PyMODINIT_FUNC init_network(void)
|
||||
{
|
||||
(void) Py_InitModule("_network", _functions);
|
||||
}
|
||||
11
setup.py
11
setup.py
|
|
@ -507,7 +507,8 @@ o a (Fast)CGI web interface (requires HTTP server)
|
|||
'linkcheck.cache', 'linkcheck.htmlutil',
|
||||
'linkcheck.dns', 'linkcheck.dns.rdtypes',
|
||||
'linkcheck.dns.rdtypes.ANY', 'linkcheck.dns.rdtypes.IN',
|
||||
'linkcheck.HtmlParser', 'linkcheck.ftpparse', ],
|
||||
'linkcheck.HtmlParser', 'linkcheck.ftpparse',
|
||||
'linkcheck.network', ],
|
||||
ext_modules = [Extension('linkcheck.HtmlParser.htmlsax',
|
||||
sources = ['linkcheck/HtmlParser/htmllex.c',
|
||||
'linkcheck/HtmlParser/htmlparse.c',
|
||||
|
|
@ -520,6 +521,14 @@ o a (Fast)CGI web interface (requires HTTP server)
|
|||
include_dirs = include_dirs + \
|
||||
[normpath("linkcheck/HtmlParser")],
|
||||
),
|
||||
Extension("linkcheck.network._network",
|
||||
["linkcheck/network/_network.c",],
|
||||
extra_compile_args = extra_compile_args,
|
||||
library_dirs = library_dirs,
|
||||
libraries = libraries,
|
||||
define_macros = define_macros,
|
||||
include_dirs = include_dirs,
|
||||
),
|
||||
Extension("linkcheck.ftpparse._ftpparse",
|
||||
["linkcheck/ftpparse/_ftpparse.c",
|
||||
"linkcheck/ftpparse/ftpparse.c"],
|
||||
|
|
|
|||
42
tests/test_network.py
Normal file
42
tests/test_network.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2008 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
"""
|
||||
Test network functions.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import linkcheck.network
|
||||
|
||||
|
||||
class TestNetwork (unittest.TestCase):
|
||||
"""Test network functions."""
|
||||
|
||||
def test_ifreq_size (self):
|
||||
self.assertTrue(linkcheck.network.ifreq_size() > 0)
|
||||
|
||||
def test_interfaces (self):
|
||||
ifc = linkcheck.network.IfConfig()
|
||||
ifc.getInterfaceList()
|
||||
|
||||
|
||||
def test_suite ():
|
||||
"""Build and return a TestSuite."""
|
||||
return unittest.makeSuite(TestNetwork)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
Reference in a new issue