/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2016-06-03 18:28:39 UTC
  • Revision ID: teddy@recompile.se-20160603182839-064dp506ht0ylzrt
mandos: Bug fix for Python 2.7 and the "--interface" option

* mandos: Try harder at program start to find correct value of
          SO_BINDTODEVICE, even if it is missing from the Python
          standard libraries.
  (IPv6_TCPServer.server_bind): If SO_BINDTODEVICE was not found, fall
                                back to a hard-coded value (and emit
                                warning).

Reported-by: Valerio Bellizzomi <valerio@selnet.org>

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
import xml.dom.minidom
87
87
import inspect
88
88
 
 
89
# Try to find the value of SO_BINDTODEVICE:
89
90
try:
 
91
    # This is where SO_BINDTODEVICE is in Python 3.3 (or 3.4?) and
 
92
    # newer, and it is also the most natural place for it:
90
93
    SO_BINDTODEVICE = socket.SO_BINDTODEVICE
91
94
except AttributeError:
92
95
    try:
 
96
        # This is where SO_BINDTODEVICE was up to and including Python
 
97
        # 2.6, and also 3.2:
93
98
        from IN import SO_BINDTODEVICE
94
99
    except ImportError:
95
 
        SO_BINDTODEVICE = None
 
100
        # In Python 2.7 it seems to have been removed entirely.
 
101
        # Try running the C preprocessor:
 
102
        try:
 
103
            cc = subprocess.Popen(["cc", "--language=c", "-E",
 
104
                                   "/dev/stdin"],
 
105
                                  stdin=subprocess.PIPE,
 
106
                                  stdout=subprocess.PIPE)
 
107
            stdout = cc.communicate(
 
108
                "#include <sys/socket.h>\nSO_BINDTODEVICE\n")[0]
 
109
            SO_BINDTODEVICE = int(stdout.splitlines()[-1])
 
110
        except (OSError, ValueError, IndexError):
 
111
            # No value found
 
112
            SO_BINDTODEVICE = None
96
113
 
97
114
if sys.version_info.major == 2:
98
115
    str = unicode
2438
2455
        bind to an address or port if they were not specified."""
2439
2456
        if self.interface is not None:
2440
2457
            if SO_BINDTODEVICE is None:
2441
 
                logger.error("SO_BINDTODEVICE does not exist;"
2442
 
                             " cannot bind to interface %s",
2443
 
                             self.interface)
2444
 
            else:
2445
 
                try:
2446
 
                    self.socket.setsockopt(
2447
 
                        socket.SOL_SOCKET, SO_BINDTODEVICE,
2448
 
                        (self.interface + "\0").encode("utf-8"))
2449
 
                except socket.error as error:
2450
 
                    if error.errno == errno.EPERM:
2451
 
                        logger.error("No permission to bind to"
2452
 
                                     " interface %s", self.interface)
2453
 
                    elif error.errno == errno.ENOPROTOOPT:
2454
 
                        logger.error("SO_BINDTODEVICE not available;"
2455
 
                                     " cannot bind to interface %s",
2456
 
                                     self.interface)
2457
 
                    elif error.errno == errno.ENODEV:
2458
 
                        logger.error("Interface %s does not exist,"
2459
 
                                     " cannot bind", self.interface)
2460
 
                    else:
2461
 
                        raise
 
2458
                # Fall back to a hard-coded value which seems to be
 
2459
                # common enough.
 
2460
                logger.warning("SO_BINDTODEVICE not found, trying 25")
 
2461
                SO_BINDTODEVICE = 25
 
2462
            try:
 
2463
                self.socket.setsockopt(
 
2464
                    socket.SOL_SOCKET, SO_BINDTODEVICE,
 
2465
                    (self.interface + "\0").encode("utf-8"))
 
2466
            except socket.error as error:
 
2467
                if error.errno == errno.EPERM:
 
2468
                    logger.error("No permission to bind to"
 
2469
                                 " interface %s", self.interface)
 
2470
                elif error.errno == errno.ENOPROTOOPT:
 
2471
                    logger.error("SO_BINDTODEVICE not available;"
 
2472
                                 " cannot bind to interface %s",
 
2473
                                 self.interface)
 
2474
                elif error.errno == errno.ENODEV:
 
2475
                    logger.error("Interface %s does not exist,"
 
2476
                                 " cannot bind", self.interface)
 
2477
                else:
 
2478
                    raise
2462
2479
        # Only bind(2) the socket if we really need to.
2463
2480
        if self.server_address[0] or self.server_address[1]:
2464
2481
            if not self.server_address[0]: