xref: /aosp_15_r20/external/iw/ap.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
1 #include <errno.h>
2 #include <netlink/genl/genl.h>
3 #include <netlink/genl/family.h>
4 #include <netlink/genl/ctrl.h>
5 #include <netlink/msg.h>
6 #include <netlink/attr.h>
7 #include "nl80211.h"
8 #include "iw.h"
9 
10 SECTION(ap);
11 
handle_start_ap(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)12 static int handle_start_ap(struct nl80211_state *state,
13 			   struct nl_msg *msg, int argc, char **argv,
14 			   enum id_input id)
15 {
16 	struct chandef chandef;
17 	int res, parsed;
18 	char *end;
19 	int val, len;
20 	char buf[2304];
21 
22 	if (argc < 6)
23 		return 1;
24 
25 	/* SSID */
26 	NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]);
27 	argv++;
28 	argc--;
29 
30 	/* chandef */
31 	res = parse_freqchan(&chandef, false, argc, argv, &parsed);
32 	if (res)
33 		return res;
34 	argc -= parsed;
35 	argv += parsed;
36 	res = put_chandef(msg, &chandef);
37 	if (res)
38 		return res;
39 
40 	/* beacon interval */
41 	val = strtoul(argv[0], &end, 10);
42 	if (*end != '\0')
43 		return -EINVAL;
44 
45 	NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, val);
46 	argv++;
47 	argc--;
48 
49 	/* dtim */
50 	val = strtoul(argv[0], &end, 10);
51 	if (*end != '\0')
52 		return -EINVAL;
53 
54 	NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, val);
55 	argv++;
56 	argc--;
57 
58 	if (strcmp(argv[0], "hidden-ssid") == 0) {
59 		argc--;
60 		argv++;
61 		NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
62 			    NL80211_HIDDEN_SSID_ZERO_LEN);
63 	} else if (strcmp(argv[0], "zeroed-ssid") == 0) {
64 		argc--;
65 		argv++;
66 		NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
67 			    NL80211_HIDDEN_SSID_ZERO_CONTENTS);
68 	}
69 
70 	/* beacon head must be provided */
71 	if (strcmp(argv[0], "head") != 0)
72 		return 1;
73 	argv++;
74 	argc--;
75 
76 	len = strlen(argv[0]);
77 	if (!len || (len % 2))
78 		return -EINVAL;
79 
80 	if (!hex2bin(&argv[0][0], buf))
81 		return -EINVAL;
82 
83 	NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, (len / 2), &buf);
84 	argv++;
85 	argc--;
86 
87 	if (!argc)
88 		return 0;
89 
90 	/* tail is optional */
91 	if (strcmp(argv[0], "tail") == 0) {
92 		argv++;
93 		argc--;
94 
95 		if (!argc)
96 			return -EINVAL;
97 
98 		len = strlen(argv[0]);
99 		if (!len || (len % 2))
100 			return -EINVAL;
101 
102 		if (!hex2bin(&argv[0][0], buf))
103 			return -EINVAL;
104 
105 		NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, (len / 2), &buf);
106 		argv++;
107 		argc--;
108 	}
109 
110 	if (!argc)
111 		return 0;
112 
113 	/* inactivity time (optional) */
114 	if (strcmp(argv[0], "inactivity-time") == 0) {
115 		argv++;
116 		argc--;
117 
118 		if (!argc)
119 			return -EINVAL;
120 		len = strlen(argv[0]);
121 		if (!len)
122 			return -EINVAL;
123 
124 		val = strtoul(argv[0], &end, 10);
125 		if (*end != '\0')
126 			return -EINVAL;
127 
128 		NLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT, val);
129 		argv++;
130 		argc--;
131 	}
132 
133 	if (!argc) {
134 		return 0;
135 	}
136 
137 	if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
138 		return 1;
139 
140 	argv++;
141 	argc--;
142 
143 	return parse_keys(msg, &argv, &argc);
144  nla_put_failure:
145 	return -ENOSPC;
146 }
147 COMMAND(ap, start, "",
148 	NL80211_CMD_NEW_BEACON, 0, CIB_NETDEV, handle_start_ap,
149 	"<SSID> <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]"
150 	" <beacon interval in TU> <DTIM period> [hidden-ssid|zeroed-ssid] head"
151 	" <beacon head in hexadecimal> [tail <beacon tail in hexadecimal>]"
152 	" [inactivity-time <inactivity time in seconds>] [key0:abcde d:1:6162636465]\n");
153 
handle_stop_ap(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)154 static int handle_stop_ap(struct nl80211_state *state,
155 			  struct nl_msg *msg,
156 			  int argc, char **argv,
157 			  enum id_input id)
158 {
159 	return 0;
160 }
161 COMMAND(ap, stop, "",
162 	NL80211_CMD_DEL_BEACON, 0, CIB_NETDEV, handle_stop_ap,
163 	"Stop AP functionality\n");
164