1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25 #define LWS_WIFI_MAX_SCAN_TRACK 16 26 #define LWS_ETH_ALEN 6 27 28 typedef uint8_t lws_wifi_ch_t; 29 typedef int8_t lws_wifi_rssi_t; 30 struct lws_netdev_instance; 31 32 typedef enum { 33 LWSNDTYP_UNKNOWN, 34 LWSNDTYP_WIFI, 35 LWSNDTYP_ETH, 36 } lws_netdev_type_t; 37 38 /* 39 * Base class for netdev configuration 40 */ 41 42 typedef struct lws_netdev_config { 43 void *plat_config; 44 } lws_netdev_config_t; 45 46 /* 47 * Const Logical generic network interface ops 48 */ 49 50 typedef struct lws_netdev_ops { 51 struct lws_netdev_instance * (*create)(struct lws_context *ctx, 52 const struct lws_netdev_ops *ops, 53 const char *name, void *platinfo); 54 int (*configure)(struct lws_netdev_instance *nd, 55 lws_netdev_config_t *config); 56 int (*up)(struct lws_netdev_instance *nd); 57 int (*down)(struct lws_netdev_instance *nd); 58 int (*event)(struct lws_netdev_instance *nd, lws_usec_t timestamp, 59 void *buf, size_t len); 60 /**< these are SMD events coming from lws event loop thread context */ 61 void (*destroy)(struct lws_netdev_instance **pnd); 62 int (*connect)(struct lws_netdev_instance *wnd, const char *ssid, 63 const char *passphrase, uint8_t *bssid); 64 void (*scan)(struct lws_netdev_instance *nd); 65 } lws_netdev_ops_t; 66 67 /* 68 * Network devices on this platform 69 * 70 * We also hold a list of all known network credentials (when they are needed 71 * because there is a network interface without anything to connect to) and 72 * the lws_settings instance they are stored in 73 */ 74 75 typedef struct lws_netdevs { 76 lws_dll2_owner_t owner; 77 /**< list of netdevs / lws_netdev_instance_t -based objects */ 78 79 lws_dll2_owner_t owner_creds; 80 /**< list of known credentials */ 81 struct lwsac *ac_creds; 82 /**< lwsac holding retreived credentials settings, or NULL */ 83 lws_settings_instance_t *si; 84 85 lws_sockaddr46 sa46_dns_resolver; 86 87 uint8_t refcount_creds; 88 /**< when there are multiple netdevs, must refcount creds in mem */ 89 } lws_netdevs_t; 90 91 /* 92 * Base class for an allocated instantiated derived object using lws_netdev_ops, 93 * ie, a specific ethernet device 94 */ 95 96 typedef struct lws_netdev_instance { 97 const char *name; 98 const lws_netdev_ops_t *ops; 99 void *platinfo; 100 lws_dll2_t list; 101 uint8_t mac[LWS_ETH_ALEN]; 102 uint8_t type; /* lws_netdev_type_t */ 103 } lws_netdev_instance_t; 104 105 enum { 106 LNDIW_ALG_OPEN, 107 LNDIW_ALG_WPA2, 108 109 LNDIW_MODE_STA = (1 << 0), 110 LNDIW_MODE_AP = (1 << 1), 111 LNDIW_UP = (1 << 7), 112 113 LNDIW_ACQ_IPv4 = (1 << 0), 114 LNDIW_ACQ_IPv6 = (1 << 1), 115 }; 116 117 /* 118 * Group AP / Station State 119 */ 120 121 typedef enum { 122 LWSNDVWIFI_STATE_INITIAL, 123 /* 124 * We should gratuitously try whatever last worked for us, then 125 * if that fails, worry about the rest of the logic 126 */ 127 LWSNDVWIFI_STATE_SCAN, 128 /* 129 * Unconnected, scanning: AP known in one of the config slots -> 130 * configure it, start timeout + LWSNDVWIFI_STATE_STAT, if no AP 131 * already up in same group with lower MAC, after a random 132 * period start up our AP (LWSNDVWIFI_STATE_AP) 133 */ 134 LWSNDVWIFI_STATE_AP, 135 /* Trying to be the group AP... periodically do a scan 136 * LWSNDVWIFI_STATE_AP_SCAN, faster and then slower 137 */ 138 LWSNDVWIFI_STATE_AP_SCAN, 139 /* 140 * doing a scan while trying to be the group AP... if we see a 141 * lower MAC being the AP for the same group AP, abandon being 142 * an AP and join that AP as a station 143 */ 144 LWSNDVWIFI_STATE_STAT_GRP_AP, 145 /* 146 * We have decided to join another group member who is being the 147 * AP, as its MAC is lower than ours. This is a stable state, 148 * but we still do periodic scans 149 * LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN and will always prefer an 150 * AP configured in a slot. 151 */ 152 LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN, 153 /* 154 * We have joined a group member who is doing the AP job... we 155 * want to check every now and then if a configured AP has 156 * appeared that we should better use instead. Otherwise stay 157 * in LWSNDVWIFI_STATE_STAT_GRP_AP 158 */ 159 LWSNDVWIFI_STATE_STAT, 160 /* 161 * trying to connect to another non-group AP. If we don't get an 162 * IP within a timeout and retries, mark it as unusable it and go back 163 */ 164 LWSNDVWIFI_STATE_STAT_HAPPY, 165 } lws_netdev_wifi_state_t; 166 167 /* 168 * Generic WIFI credentials 169 */ 170 171 typedef struct lws_wifi_creds { 172 lws_dll2_t list; 173 174 uint8_t bssid[LWS_ETH_ALEN]; 175 char passphrase[64]; 176 char ssid[33]; 177 uint8_t alg; 178 } lws_wifi_creds_t; 179 180 /* 181 * Generic WIFI Network Device Instance 182 */ 183 184 typedef struct lws_netdev_instance_wifi { 185 lws_netdev_instance_t inst; 186 lws_dll2_owner_t scan; /* sorted scan results */ 187 lws_sorted_usec_list_t sul_scan; 188 189 lws_wifi_creds_t *ap_cred; 190 const char *ap_ip; 191 192 const char *sta_ads; 193 194 char current_attempt_ssid[33]; 195 uint8_t current_attempt_bssid[LWS_ETH_ALEN]; 196 197 uint8_t flags; 198 uint8_t state; /* lws_netdev_wifi_state_t */ 199 } lws_netdev_instance_wifi_t; 200 201 /* 202 * Logical scan results sorted list item 203 */ 204 205 typedef struct lws_wifi_sta { 206 lws_dll2_t list; 207 208 uint32_t last_seen; /* unix time */ 209 uint32_t last_tried; /* unix time */ 210 211 uint8_t bssid[LWS_ETH_ALEN]; 212 char *ssid; /* points to overallocation */ 213 uint8_t ssid_len; 214 lws_wifi_ch_t ch; 215 lws_wifi_rssi_t rssi[8]; 216 int16_t rssi_avg; 217 uint8_t authmode; 218 219 uint8_t rssi_count; 220 uint8_t rssi_next; 221 222 /* ssid overallocated afterwards */ 223 } lws_wifi_sta_t; 224 225 #define rssi_averaged(_x) (_x->rssi_count ? \ 226 ((int)_x->rssi_avg / (int)_x->rssi_count) : \ 227 -200) 228 229 LWS_VISIBLE LWS_EXTERN lws_netdevs_t * 230 lws_netdevs_from_ctx(struct lws_context *ctx); 231 232 LWS_VISIBLE LWS_EXTERN int 233 lws_netdev_credentials_settings_set(lws_netdevs_t *nds); 234 235 LWS_VISIBLE LWS_EXTERN int 236 lws_netdev_credentials_settings_get(lws_netdevs_t *nds); 237 238 LWS_VISIBLE LWS_EXTERN struct lws_netdev_instance * 239 lws_netdev_wifi_create_plat(struct lws_context *ctx, 240 const lws_netdev_ops_t *ops, const char *name, 241 void *platinfo); 242 LWS_VISIBLE LWS_EXTERN int 243 lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, 244 lws_netdev_config_t *config); 245 LWS_VISIBLE LWS_EXTERN int 246 lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, 247 void *buf, size_t len); 248 LWS_VISIBLE LWS_EXTERN int 249 lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd); 250 LWS_VISIBLE LWS_EXTERN int 251 lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd); 252 LWS_VISIBLE LWS_EXTERN void 253 lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd); 254 LWS_VISIBLE LWS_EXTERN void 255 lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd); 256 257 LWS_VISIBLE LWS_EXTERN int 258 lws_netdev_wifi_connect_plat(lws_netdev_instance_t *wnd, const char *ssid, 259 const char *passphrase, uint8_t *bssid); 260 261 LWS_VISIBLE LWS_EXTERN lws_netdev_instance_t * 262 lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname); 263 264 #define lws_netdev_wifi_plat_ops \ 265 .create = lws_netdev_wifi_create_plat, \ 266 .configure = lws_netdev_wifi_configure_plat, \ 267 .event = lws_netdev_wifi_event_plat, \ 268 .up = lws_netdev_wifi_up_plat, \ 269 .down = lws_netdev_wifi_down_plat, \ 270 .connect = lws_netdev_wifi_connect_plat, \ 271 .scan = lws_netdev_wifi_scan_plat, \ 272 .destroy = lws_netdev_wifi_destroy_plat 273 274 /* 275 * This is for plat / OS level init that is necessary to be able to use 276 * networking or wifi at all, without mentioning any specific device 277 */ 278 279 LWS_VISIBLE LWS_EXTERN int 280 lws_netdev_plat_init(void); 281 282 LWS_VISIBLE LWS_EXTERN int 283 lws_netdev_plat_wifi_init(void); 284