Home | History | Annotate | Download | only in kernel_ProtocolCheck
      1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging, socket
      6 from collections import namedtuple
      7 
      8 from autotest_lib.client.bin import test
      9 from autotest_lib.client.common_lib import error
     10 
     11 PROTO_FILE = '/proc/net/protocols'
     12 
     13 # Defines that python's socket lacks.
     14 IPPROTO_UDPLITE = 193
     15 AF_BLUETOOTH = 31
     16 BTPROTO_L2CAP = 0
     17 BTPROTO_HCI = 1
     18 BTPROTO_SCO = 2
     19 BTPROTO_RFCOMM = 3
     20 
     21 # Contains information needed to create a socket using a particular
     22 # protocol.
     23 Protocol = namedtuple('Protocol', ['name', 'domain', 'socket_type',
     24                                    'proto_num'])
     25 REQUIRED = set([
     26         Protocol('RFCOMM', AF_BLUETOOTH, socket.SOCK_STREAM, BTPROTO_RFCOMM),
     27         Protocol('RFCOMM', AF_BLUETOOTH, socket.SOCK_SEQPACKET, BTPROTO_SCO),
     28         Protocol('L2CAP', AF_BLUETOOTH, socket.SOCK_STREAM, BTPROTO_L2CAP),
     29         Protocol('HCI', AF_BLUETOOTH, socket.SOCK_RAW, BTPROTO_HCI),
     30         Protocol('PACKET', socket.AF_PACKET, socket.SOCK_DGRAM, 0),
     31         Protocol('RAWv6', socket.AF_INET6, socket.SOCK_RAW, 0),
     32         Protocol('UDPLITEv6', socket.AF_INET6, socket.SOCK_DGRAM,
     33                  IPPROTO_UDPLITE),
     34         Protocol('UDPv6', socket.AF_INET6, socket.SOCK_DGRAM, 0),
     35         Protocol('TCPv6', socket.AF_INET6, socket.SOCK_STREAM, 0),
     36         Protocol('UNIX', socket.AF_UNIX, socket.SOCK_STREAM, 0),
     37         Protocol('UDP-Lite', socket.AF_INET, socket.SOCK_DGRAM,
     38                  IPPROTO_UDPLITE),
     39         Protocol('PING', socket.AF_INET, socket.SOCK_DGRAM,
     40                  socket.IPPROTO_ICMP),
     41         Protocol('RAW', socket.AF_INET, socket.SOCK_RAW, 0),
     42         Protocol('UDP', socket.AF_INET, socket.SOCK_DGRAM, 0),
     43         Protocol('TCP', socket.AF_INET, socket.SOCK_STREAM, 0),
     44         Protocol('NETLINK', socket.AF_NETLINK, socket.SOCK_DGRAM, 0),
     45         ])
     46 
     47 class kernel_ProtocolCheck(test.test):
     48     version = 1
     49 
     50     def _try_protocol(self, proto):
     51         """
     52         Try to create a socket with the specified protocol.
     53 
     54         @param proto Protocol to use to create a socket.
     55         """
     56         try:
     57             sock = socket.socket(proto.domain, proto.socket_type,
     58                                  proto.proto_num)
     59             sock.close()
     60             logging.info('created socket with protocol %s' % (proto.name))
     61         except socket.error:
     62             # We don't really care if it fails, any required module should've
     63             # been loaded anyways.
     64             logging.info('failed to create socket with protocol %s' %
     65                          (proto.name))
     66 
     67     def _get_supported_protocols(self):
     68         """
     69         Returns the set of supported protocols from /proc/net/protocols.
     70         """
     71         f = open(PROTO_FILE)
     72         if not f:
     73             raise error.TestError('failed to open %s' % (PROTO_FILE))
     74         lines = f.readlines()[1:]
     75         supported = set(line.split()[0] for line in lines)
     76         f.close()
     77         return supported
     78 
     79     def run_once(self):
     80         """
     81         Check that the kernel supports all required network protocols.
     82         """
     83         for proto in REQUIRED:
     84             # Opening a socket with a protocol should ensure that all necessary
     85             # modules get loaded.
     86             self._try_protocol(proto)
     87 
     88         supported = self._get_supported_protocols()
     89 
     90         # Check that each required protocol is supported.
     91         required = set(proto.name for proto in REQUIRED)
     92         failures = required - supported
     93 
     94         # Fail if any protocols were unsupported.
     95         if failures:
     96             raise error.TestFail('required protocols are unsupported: %s' %
     97                                  (", ".join(failures)))
     98