2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 * Copyright (C) 2020 embedd.ch
16 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
17 * Copyright (C) 2020 John Crispin <john@phrozen.org>
20 #include <libubox/blobmsg.h>
27 static struct blob_buf b
;
28 static LIST_HEAD(stations
);
29 static struct usteer_timeout_queue tq
;
31 static struct ubus_object bss_obj
;
32 static struct ubus_context
*ubus_ctx
;
33 static int freq
= 2412;
43 struct list_head list
;
44 struct usteer_timeout probe_t
;
50 static void gen_val(struct var
*val
)
52 int delta
= val
->max
- val
->min
;
59 if (fread(&v
, sizeof(v
), 1, r_fd
) != sizeof(v
))
60 fprintf(stderr
, "short read\n");
61 val
->cur
+= (((unsigned int) v
) * delta
) / 0xff;
65 blobmsg_add_macaddr(struct blob_buf
*buf
, const char *name
, const uint8_t *addr
)
67 char *s
= blobmsg_alloc_string_buffer(buf
, name
, 20);
68 sprintf(s
, MAC_ADDR_FMT
, MAC_ADDR_DATA(addr
));
69 blobmsg_add_string_buffer(buf
);
72 static void sta_send_probe(struct sta_data
*sta
)
74 const char *type
= "probe";
76 int sig
= -95 + sta
->signal
.cur
;
79 blobmsg_add_macaddr(&b
, "address", sta
->addr
);
80 blobmsg_add_u32(&b
, "freq", freq
);
81 blobmsg_add_u32(&b
, "signal", sig
);
82 ret
= ubus_notify(ubus_ctx
, &bss_obj
, type
, b
.head
, 100);
84 fprintf(stderr
, "STA "MAC_ADDR_FMT
" probe: %d (%d ms, signal: %d)\n",
85 MAC_ADDR_DATA(sta
->addr
), ret
, sta
->probe
.cur
, sig
);
88 static void sta_schedule_probe(struct sta_data
*sta
)
91 gen_val(&sta
->signal
);
92 usteer_timeout_set(&tq
, &sta
->probe_t
, sta
->probe
.cur
);
95 static void sta_probe(struct usteer_timeout_queue
*q
, struct usteer_timeout
*t
)
97 struct sta_data
*sta
= container_of(t
, struct sta_data
, probe_t
);
100 sta_schedule_probe(sta
);
103 static void init_station(struct sta_data
*sta
)
105 list_add_tail(&sta
->list
, &stations
);
106 if (fread(&sta
->addr
, sizeof(sta
->addr
), 1, r_fd
) != sizeof(sta
->addr
))
107 fprintf(stderr
, "short read\n");
110 sta_schedule_probe(sta
);
113 static void create_stations(struct sta_data
*ref
, int n
)
115 struct sta_data
*sta
;
119 sta
= calloc(n
, sizeof(*sta
));
120 for (i
= 0; i
< n
; i
++) {
121 memcpy(sta
, ref
, sizeof(*sta
));
127 static int usage(const char *prog
)
129 fprintf(stderr
, "Usage: %s <options>\n"
131 " -p <msec>[-<msec>]: probing interval (fixed or min-max)\n"
132 " -s <rssi>[-<rssi>]: rssi (signal strength) (fixed or min-max)\n"
133 " -n <n>: create <n> stations\n"
134 " -f <freq>: set operating frequency\n"
135 " uses parameters set before this option\n"
141 static bool parse_var(struct var
*var
, const char *str
)
145 var
->min
= strtoul(str
, &err
, 0);
153 var
->max
= strtoul(err
+ 1, &err
, 0);
161 hostapd_bss_get_clients(struct ubus_context
*ctx
, struct ubus_object
*obj
,
162 struct ubus_request_data
*req
, const char *method
,
163 struct blob_attr
*msg
)
165 blob_buf_init(&b
, 0);
166 ubus_send_reply(ctx
, req
, b
.head
);
170 static const struct ubus_method bss_methods
[] = {
171 UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients
),
174 static struct ubus_object_type bss_object_type
=
175 UBUS_OBJECT_TYPE("hostapd_bss", bss_methods
);
177 static struct ubus_object bss_obj
= {
178 .name
= "hostapd.wlan0",
179 .type
= &bss_object_type
,
180 .methods
= bss_methods
,
181 .n_methods
= ARRAY_SIZE(bss_methods
),
184 int main(int argc
, char **argv
)
186 struct sta_data sdata
= {
187 .signal
= { 0, -30, -30 },
188 .probe
= { 0, 1000, 30000 },
194 r_fd
= fopen("/dev/urandom", "r");
200 usteer_timeout_init(&tq
);
202 while ((ch
= getopt(argc
, argv
, "p:s:f:n:v")) != -1) {
205 if (!parse_var(&sdata
.probe
, optarg
))
209 if (!parse_var(&sdata
.signal
, optarg
))
216 create_stations(&sdata
, atoi(optarg
));
226 ubus_ctx
= ubus_connect(NULL
);
228 fprintf(stderr
, "Failed to connect to ubus\n");
232 ubus_add_uloop(ubus_ctx
);
234 if (ubus_add_object(ubus_ctx
, &bss_obj
)) {
235 fprintf(stderr
, "Failed to register AP ubus object\n");
243 return usage(argv
[0]);