1#!/usr/bin/env python3

2# Copyright 2015-2020 Canonical Ltd.

3# All rights reserved.

4#

5# Written by:

6# Jonathan Cave <jonathan.cave@canonical.com>

7# Po-Hsu Lin <po-hsu.lin@canonical.com>

8

9 import argparse

10 import logging

11 import os

12 import sys

13 import subprocess

14 import tempfile

15

16

17 class WifiMasterMode:

18 """Make system to act as an 802.11 Wi-Fi Access Point."""

19

20 def main(self):

21 parser = argparse.ArgumentParser()

22 parser.add_argument(

23 "--protocol",

24 default="g",

25 choices=["a", "b", "g", "ad"],

26 help="802.11 protocol, possible value: a/b/g/ad",

27 )

28 parser.add_argument(

29 "--auto", action="store_true", help="Run in the automated mode"

30 )

31 args = parser.parse_args()

32

33 data_dir = ""

34 try:

35 data_dir = os.environ["PLAINBOX_PROVIDER_DATA"]

36 except KeyError:

37 logging.error("PLAINBOX_PROVIDER_DATA variable not set")

38 return 1

39 logging.info("Provider data dir: {}".format(data_dir))

40

41 wifi_dev = "wlan0"

42 try:

43 wifi_dev = os.environ["WIFI_AP_DEV"]

44 except KeyError:

45 logging.info("WIFI_AP_DEV variable not set, defaulting to wlan0")

46 logging.info("Wi-Fi adapter: {}".format(wifi_dev))

47

48 conf_in = os.path.join(data_dir, "hostapd.conf.in")

49 if not os.path.isfile(conf_in):

50 logging.error("Couldn't find {}".format(conf_in))

51 return 1

52

53 with tempfile.NamedTemporaryFile(mode="w+t") as conf_file_out:

54 with open(conf_in, "r") as conf_file_in:

55 data_in = conf_file_in.read()

56 data_out = data_in.replace("$PROTOCOL", args.protocol)

57 data_out = data_out.replace("$WIFI-DEV-NAME", wifi_dev)

58 conf_file_out.write(data_out)

59 conf_file_out.flush()

60

61 if args.auto:

62 child = subprocess.Popen(

63 ["hostapd", "-d", conf_file_out.name],

64 stdout=subprocess.PIPE,

65 universal_newlines=True,

66 )

67 log = ""

68 while child.poll() is None:

69 output = child.stdout.readline()

70 log += output

71 if "AP-ENABLED" in output:

72 logging.info(output)

73 logging.info("AP successfully established.")

74 child.terminate()

75 if child.poll() != 0:

76 output = child.stdout.read()

77 logging.error(log + output)

78 logging.error("AP failed to start")

79 return child.poll()

80 else:

81 # Print and flush this or it will get buffered during test

82 print(

83 "Hit any key to start the Access Point, a second key "

84 + "press will stop the Access Point:"

85 )

86 sys.stdout.flush()

87 input()

88

89 try:

90 child = subprocess.Popen(["hostapd", conf_file_out.name])

91

92 # kill the process on input

93 input()

94 finally:

95 child.terminate()

96

97

98 if __name__ == "__main__":

99 WifiMasterMode().main()