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 5import logging, socket 6from collections import namedtuple 7 8from autotest_lib.client.bin import test 9from autotest_lib.client.common_lib import error 10 11PROTO_FILE = '/proc/net/protocols' 12 13# Defines that python's socket lacks. 14IPPROTO_UDPLITE = 193 15AF_BLUETOOTH = 31 16BTPROTO_L2CAP = 0 17BTPROTO_HCI = 1 18BTPROTO_SCO = 2 19BTPROTO_RFCOMM = 3 20 21# Contains information needed to create a socket using a particular 22# protocol. 23Protocol = namedtuple('Protocol', ['name', 'domain', 'socket_type', 24 'proto_num']) 25REQUIRED = 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 47class 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