普通文本  |  98行  |  3.65 KB

# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging, socket
from collections import namedtuple

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error

PROTO_FILE = '/proc/net/protocols'

# Defines that python's socket lacks.
IPPROTO_UDPLITE = 193
AF_BLUETOOTH = 31
BTPROTO_L2CAP = 0
BTPROTO_HCI = 1
BTPROTO_SCO = 2
BTPROTO_RFCOMM = 3

# Contains information needed to create a socket using a particular
# protocol.
Protocol = namedtuple('Protocol', ['name', 'domain', 'socket_type',
                                   'proto_num'])
REQUIRED = set([
        Protocol('RFCOMM', AF_BLUETOOTH, socket.SOCK_STREAM, BTPROTO_RFCOMM),
        Protocol('RFCOMM', AF_BLUETOOTH, socket.SOCK_SEQPACKET, BTPROTO_SCO),
        Protocol('L2CAP', AF_BLUETOOTH, socket.SOCK_STREAM, BTPROTO_L2CAP),
        Protocol('HCI', AF_BLUETOOTH, socket.SOCK_RAW, BTPROTO_HCI),
        Protocol('PACKET', socket.AF_PACKET, socket.SOCK_DGRAM, 0),
        Protocol('RAWv6', socket.AF_INET6, socket.SOCK_RAW, 0),
        Protocol('UDPLITEv6', socket.AF_INET6, socket.SOCK_DGRAM,
                 IPPROTO_UDPLITE),
        Protocol('UDPv6', socket.AF_INET6, socket.SOCK_DGRAM, 0),
        Protocol('TCPv6', socket.AF_INET6, socket.SOCK_STREAM, 0),
        Protocol('UNIX', socket.AF_UNIX, socket.SOCK_STREAM, 0),
        Protocol('UDP-Lite', socket.AF_INET, socket.SOCK_DGRAM,
                 IPPROTO_UDPLITE),
        Protocol('PING', socket.AF_INET, socket.SOCK_DGRAM,
                 socket.IPPROTO_ICMP),
        Protocol('RAW', socket.AF_INET, socket.SOCK_RAW, 0),
        Protocol('UDP', socket.AF_INET, socket.SOCK_DGRAM, 0),
        Protocol('TCP', socket.AF_INET, socket.SOCK_STREAM, 0),
        Protocol('NETLINK', socket.AF_NETLINK, socket.SOCK_DGRAM, 0),
        ])

class kernel_ProtocolCheck(test.test):
    version = 1

    def _try_protocol(self, proto):
        """
        Try to create a socket with the specified protocol.

        @param proto Protocol to use to create a socket.
        """
        try:
            sock = socket.socket(proto.domain, proto.socket_type,
                                 proto.proto_num)
            sock.close()
            logging.info('created socket with protocol %s' % (proto.name))
        except socket.error:
            # We don't really care if it fails, any required module should've
            # been loaded anyways.
            logging.info('failed to create socket with protocol %s' %
                         (proto.name))

    def _get_supported_protocols(self):
        """
        Returns the set of supported protocols from /proc/net/protocols.
        """
        f = open(PROTO_FILE)
        if not f:
            raise error.TestError('failed to open %s' % (PROTO_FILE))
        lines = f.readlines()[1:]
        supported = set(line.split()[0] for line in lines)
        f.close()
        return supported

    def run_once(self):
        """
        Check that the kernel supports all required network protocols.
        """
        for proto in REQUIRED:
            # Opening a socket with a protocol should ensure that all necessary
            # modules get loaded.
            self._try_protocol(proto)

        supported = self._get_supported_protocols()

        # Check that each required protocol is supported.
        required = set(proto.name for proto in REQUIRED)
        failures = required - supported

        # Fail if any protocols were unsupported.
        if failures:
            raise error.TestFail('required protocols are unsupported: %s' %
                                 (", ".join(failures)))