// // Created by jedi on 25.06.21. // #include "wifi.h" #include "log.h" #include #include #include #include #include extern "C" { #include #include #include } #include #include #include #include const char *wificfg_default_ssid = "fiatlux_%02X%02X%02X"; const char *wificfg_default_password = "fiatlux02"; const char *wificfg_default_hostname = "fiatlux-%02x%02x%02x"; char *wifi_sta_ssid = nullptr; char *wifi_sta_password = nullptr; char *wifi_ap_ssid = nullptr; char *wifi_ap_password = nullptr; SemaphoreHandle_t wifi_available_semaphore = nullptr; [[noreturn]] static void dns_task(void *pvParameters) { char *wifi_ap_ip_addr = nullptr; sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); if(!wifi_ap_ip_addr) { syslog("dns: no ip address\n"); vTaskDelete(nullptr); } ip4_addr_t server_addr; server_addr.addr = ipaddr_addr(wifi_ap_ip_addr); #if LWIP_IPV6 int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); sockaddr_in6 serv_addr; memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin6_family = AF_INET6; serv_addr.sin6_port = htons(53); serv_addr.sin6_flowinfo = 0; serv_addr.sin6_addr = in6addr_any; serv_addr.sin6_scope_id = IP6_NO_ZONE; #else int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sockaddr_in serv_addr; memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(53); #endif bind(fd, (sockaddr *) &serv_addr, sizeof(serv_addr)); const ifreq ifreq0 = {"en0"}; const ifreq ifreq1 = {"en1"}; setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, sdk_wifi_get_opmode() == STATIONAP_MODE ? &ifreq1 : &ifreq0, sizeof(ifreq0)); for (;;) { uint8_t buffer[96]; sockaddr_storage src_addr; socklen_t src_addr_len = sizeof(src_addr); ssize_t count = recvfrom(fd, buffer, sizeof(buffer), 0, (sockaddr *) &src_addr, &src_addr_len); /* Drop messages that are too large to send a response in the buffer */ if(count > 0 && count + 16 <= (ssize_t) sizeof(buffer)) { size_t qname_len = strlen((const char *) (buffer + 12)) + 1; uint32_t reply_len = 2 + 10 + qname_len + 16 + 4; uint8_t *head = buffer + 2; *head++ = 0x80; // Flags *head++ = 0x00; *head++ = 0x00; // Q count *head++ = 0x01; *head++ = 0x00; // A count *head++ = 0x01; *head++ = 0x00; // Auth count *head++ = 0x00; *head++ = 0x00; // Add count *head++ = 0x00; head += qname_len; *head++ = 0x00; // Q type *head++ = 0x01; *head++ = 0x00; // Q class *head++ = 0x01; *head++ = 0xC0; // LBL offs *head++ = 0x0C; *head++ = 0x00; // Type *head++ = 0x01; *head++ = 0x00; // Class *head++ = 0x01; *head++ = 0x00; // TTL *head++ = 0x00; *head++ = 0x00; *head++ = 0x78; *head++ = 0x00; // RD len *head++ = 0x04; *head++ = ip4_addr1(&server_addr); *head++ = ip4_addr2(&server_addr); *head++ = ip4_addr3(&server_addr); *head++ = ip4_addr4(&server_addr); sendto(fd, buffer, reply_len, 0, (sockaddr *) &src_addr, src_addr_len); } } } extern "C" void wifi_task(void *pvParameters) { (void) pvParameters; /* Default a hostname. */ char *hostname = nullptr; sysparam_get_string("hostname", &hostname); if(!hostname && wificfg_default_hostname) { uint8_t macaddr[6]; char name[32]; sdk_wifi_get_macaddr(1, macaddr); snprintf(name, sizeof(name), wificfg_default_hostname, macaddr[3], macaddr[4], macaddr[5]); sysparam_set_string("hostname", name); } if(hostname) { free(hostname); } sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid); sysparam_get_string("wifi_ap_password", &wifi_ap_password); sysparam_get_string("wifi_sta_ssid", &wifi_sta_ssid); sysparam_get_string("wifi_sta_password", &wifi_sta_password); int8_t wifi_sta_enable = 1; int8_t wifi_ap_enable = 1; sysparam_get_int8("wifi_sta_enable", &wifi_sta_enable); sysparam_get_int8("wifi_ap_enable", &wifi_ap_enable); if(!wifi_sta_enable) wifi_ap_enable = 1; int8_t wifi_sta_disabled_restarts = 0; sysparam_get_int8("wifi_sta_disabled_restarts", &wifi_sta_disabled_restarts); if(wifi_sta_disabled_restarts > 0) { wifi_sta_enable = 0; wifi_sta_disabled_restarts--; sysparam_set_int8("wifi_sta_disabled_restarts", wifi_sta_disabled_restarts); } int8_t wifi_ap_disabled_restarts = 0; sysparam_get_int8("wifi_ap_disabled_restarts", &wifi_ap_disabled_restarts); if(wifi_ap_disabled_restarts > 0) { wifi_ap_enable = 0; wifi_ap_disabled_restarts--; sysparam_set_int8("wifi_ap_disabled_restarts", wifi_ap_disabled_restarts); } /* Validate the configuration. */ if(wifi_sta_enable && (!wifi_sta_ssid || !wifi_sta_password || strlen(wifi_sta_ssid) < 1 || strlen(wifi_sta_ssid) > 32 || !wifi_sta_password || strlen(wifi_sta_password) < 8 || strlen(wifi_sta_password) >= 64)) { wifi_sta_enable = 0; } if(wifi_ap_enable) { /* Default AP ssid and password. */ if(!wifi_ap_ssid && wificfg_default_ssid) { uint8_t macaddr[6]; char ssid[32]; sdk_wifi_get_macaddr(1, macaddr); snprintf(ssid, sizeof(ssid), wificfg_default_ssid, macaddr[3], macaddr[4], macaddr[5]); sysparam_set_string("wifi_ap_ssid", ssid); sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid); if(!wifi_ap_password && wificfg_default_password) { sysparam_set_string("wifi_ap_password", wificfg_default_password); sysparam_get_string("wifi_ap_password", &wifi_ap_password); } } printf("ssid: %s\n", wifi_ap_ssid); /* If the ssid and password are not valid then disable the AP interface. */ if(!wifi_ap_ssid || strlen(wifi_ap_ssid) < 1 || strlen(wifi_ap_ssid) >= 32 || !wifi_ap_password || strlen(wifi_ap_password) < 8 || strlen(wifi_ap_password) >= 64) { syslog("len err\n"); wifi_ap_enable = 0; } } int8_t wifi_mode = NULL_MODE; if(wifi_sta_enable && wifi_ap_enable) wifi_mode = STATIONAP_MODE; else if(wifi_sta_enable) wifi_mode = STATION_MODE; else if(wifi_ap_enable) wifi_mode = SOFTAP_MODE; sdk_wifi_set_opmode(wifi_mode); if(wifi_sta_enable) { printf("try STA Mode: %s %s\n", wifi_sta_ssid, wifi_sta_password); sdk_station_config config; strcpy((char *) config.ssid, wifi_sta_ssid); strcpy((char *) config.password, wifi_sta_password); config.bssid_set = 0; int8_t wifi_sta_dhcp = 1; sysparam_get_int8("wifi_sta_dhcp", &wifi_sta_dhcp); if(!wifi_sta_dhcp) { char *wifi_sta_ip_addr = nullptr; char *wifi_sta_netmask = nullptr; char *wifi_sta_gateway = nullptr; sysparam_get_string("wifi_sta_ip_addr", &wifi_sta_ip_addr); sysparam_get_string("wifi_sta_netmask", &wifi_sta_netmask); sysparam_get_string("wifi_sta_gateway", &wifi_sta_gateway); if(wifi_sta_ip_addr && strlen(wifi_sta_ip_addr) > 4 && wifi_sta_netmask && strlen(wifi_sta_netmask) > 4 && wifi_sta_gateway && strlen(wifi_sta_gateway) > 4) { sdk_wifi_station_dhcpc_stop(); ip_info info; memset(&info, 0x0, sizeof(info)); info.ip.addr = ipaddr_addr(wifi_sta_ip_addr); info.netmask.addr = ipaddr_addr(wifi_sta_netmask); info.gw.addr = ipaddr_addr(wifi_sta_gateway); sdk_wifi_set_ip_info(STATION_IF, &info); } if(wifi_sta_ip_addr) free(wifi_sta_ip_addr); if(wifi_sta_netmask) free(wifi_sta_netmask); if(wifi_sta_gateway) free(wifi_sta_gateway); } sdk_wifi_station_set_config(&config); } if(wifi_ap_enable) { printf("try AP Mode: %s %s\n", wifi_ap_ssid, wifi_ap_password); /* Read and validate paramenters. */ int8_t wifi_ap_ssid_hidden = 0; sysparam_get_int8("wifi_ap_ssid_hidden", &wifi_ap_ssid_hidden); if(wifi_ap_ssid_hidden < 0 || wifi_ap_ssid_hidden > 1) { wifi_ap_ssid_hidden = 1; } int8_t wifi_ap_channel = 6; sysparam_get_int8("wifi_ap_channel", &wifi_ap_channel); #if 0 /* AU does not allow channels above 13, although 14 works. */ if(wifi_ap_channel > 13) { wifi_ap_channel = 13; } /* US does not allow channels above 11, although they work. */ if (wifi_ap_channel > 11) { wifi_ap_channel = 11; } #endif if(wifi_ap_channel < 1 || wifi_ap_channel > 14) { wifi_ap_channel = 6; } int8_t wifi_ap_authmode = AUTH_WPA_WPA2_PSK; sysparam_get_int8("wifi_ap_authmode", &wifi_ap_authmode); if(wifi_ap_authmode != AUTH_OPEN && wifi_ap_authmode != AUTH_WPA_PSK && wifi_ap_authmode != AUTH_WPA2_PSK && wifi_ap_authmode != AUTH_WPA_WPA2_PSK) { wifi_ap_authmode = AUTH_WPA_WPA2_PSK; } int8_t wifi_ap_max_conn = 3; sysparam_get_int8("wifi_ap_max_conn", &wifi_ap_max_conn); if(wifi_ap_max_conn < 1 || wifi_ap_max_conn > 8) { wifi_ap_max_conn = 3; } int32_t wifi_ap_beacon_interval = 100; sysparam_get_int32("wifi_ap_beacon_interval", &wifi_ap_beacon_interval); if(wifi_ap_beacon_interval < 0 || wifi_ap_beacon_interval > 1000) { wifi_ap_beacon_interval = 100; } /* Default AP IP address and netmask. */ char *wifi_ap_ip_addr = nullptr; sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); if(!wifi_ap_ip_addr) { sysparam_set_string("wifi_ap_ip_addr", "172.16.0.1"); sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); } char *wifi_ap_netmask = nullptr; sysparam_get_string("wifi_ap_netmask", &wifi_ap_netmask); if(!wifi_ap_netmask) { sysparam_set_string("wifi_ap_netmask", "255.255.0.0"); sysparam_get_string("wifi_ap_netmask", &wifi_ap_netmask); } if(strlen(wifi_ap_ip_addr) >= 7 && strlen(wifi_ap_netmask) >= 7) { ip_info ap_ip; ap_ip.ip.addr = ipaddr_addr(wifi_ap_ip_addr); ap_ip.netmask.addr = ipaddr_addr(wifi_ap_netmask); IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0); sdk_wifi_set_ip_info(1, &ap_ip); sdk_softap_config ap_config; strcpy((char *) ap_config.ssid, wifi_ap_ssid); ap_config.ssid_len = strlen(wifi_ap_ssid); strcpy((char *) ap_config.password, wifi_ap_password); ap_config.channel = static_cast(wifi_ap_channel); ap_config.authmode = static_cast(wifi_ap_authmode); ap_config.ssid_hidden = static_cast(wifi_ap_ssid_hidden); ap_config.max_connection = static_cast(wifi_ap_max_conn); ap_config.beacon_interval = static_cast(wifi_ap_beacon_interval); sdk_wifi_softap_set_config(&ap_config); int8_t wifi_ap_dhcp_leases = 4; sysparam_get_int8("wifi_ap_dhcp_leases", &wifi_ap_dhcp_leases); if(wifi_ap_dhcp_leases) { ip4_addr_t first_client_ip; first_client_ip.addr = ap_ip.ip.addr + htonl(1); int8_t wifi_ap_dns = 1; sysparam_get_int8("wifi_ap_dns", &wifi_ap_dns); if(wifi_ap_dns < 0 || wifi_ap_dns > 1) wifi_ap_dns = 1; dhcpserver_start(&first_client_ip, wifi_ap_dhcp_leases); dhcpserver_set_router(&ap_ip.ip); if(wifi_ap_dns) { dhcpserver_set_dns(&ap_ip.ip); xTaskCreate(dns_task, "dns_task", 384, nullptr, 2, nullptr); } } } free(wifi_ap_ip_addr); free(wifi_ap_netmask); } if(wifi_sta_ssid) free(wifi_sta_ssid); if(wifi_sta_password) free(wifi_sta_password); if(wifi_ap_ssid) free(wifi_ap_ssid); if(wifi_ap_password) free(wifi_ap_password); xSemaphoreGive(wifi_available_semaphore); //monitor loop connection here vTaskDelete(nullptr); }