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