Investigating DHCP on YellowJacket WiServer —
What is DHCP?https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol explains: “The Dynamic Host Configuration Protocol (DHCP) is a standardized network protocol used on Internet Protocol (IP) networks for dynamically distributing network configuration parameters, such as IP addresses for interfaces and services.… Most residential network routers receive a globally unique IP address within the provider network. Within a local network, DHCP assigns a local IP address to each device connected to the local network.… When a computer or other networked device connects to a network, the DHCP client software sends a broadcast query requesting necessary information. The DHCP server manages a pool of IP addresses and information about client configuration parameters such as default gateway, domain name, the name servers, and time servers. On receiving a request, the server may respond with specific information for each client, as previously configured by an administrator, or with a specific address and any other information valid for the entire network and for the time period for which the allocation (lease) is valid.”
WiShield V1.4 includes code and an example sketch for DHCP. The Examples:SocketAppDHCP.ino sketch was modified to communicate over wifi with a Mac on the local network. The sketch requires APP_SOCKAPP, APP_UDPAPP, and UIP_DHCP to be selected in apps-conf.h as noted in the sketch comments. Initially, the sketch did not connect with the Mac. As noted in comments in the YJ57 sketch code, Wireshark was used to figure out the ip/port issues. Changing the destination port, “uint16_t dest_Port = 80;”, from 6000 to 80 in the YJ57 sketch, allowed the two devices to communicate using TCP.
To use the python script below, copy the code to a file “SocketAppDHCP_V14_02.py”, and execute that file in Terminal:
Mac: me$ python SocketAppDHCP_V14_02.py
In the SocketAppDHCP_V14_02.ino sketch, change the destination port to “uint16_t dest_Port = 3333;” which is the port being used by the python script. As the SocketAppDHCP_V14_02 sketch executes, the Mac Terminal app will display the messages sent from YJ57 to python, which include the YJ57 ip/port and “char packet[] = “SocketAppDHCP”;”:
Mac: me$ python SocketAppDHCP_V14_02.py Connected by ('10.0.1.57', 1026) SocketAppDHCP
Following is the SocketAppDHCP_V14_02 sketch modified for use with python script port 3333:
/* * SocketAppDHCP_V14_02 sketch * 2016-04-22 * 84Park * * A simple socket application / DHCP example sketch for the WiShield * Sample python server script for this sketch to connect with at bottom of sketch * * To begin, the sketch will run as written without the python script and * will connect to a Mac on the local network. * * Compiled with WiShield_V14 library (ref: github.com/hamityanik/WiShield_user_contrib) and Arduino 1.6.5 * This code works 2016-04-22 with YJ57 board with/without SD Card Shield * Pre-calculated security_data[] inits in 6 seconds * * Example Output to Serial Monitor * === Initializing WiShield as Client to display DHCP Query on Serial Monitor === WiFi Init OK; Start the DHCP query... DHCP IP : 10.0.1.57 // YJ57 Arduino IP rather than local_ip[] DHCP GATEWAY: 10.0.1.1 DHCP NETMASK: 255.255.255.0 DHCP DNS : 10.0.1.1 SA: connected / send SA: newdata SA: acked SA: closed / timedout * */ // Requires APP_SOCKAPP, APP_UDPAPP and UIP_DHCP to be defined in apps-conf.h // APP_SOCKAPP - for the TCP sockets components of the sketch // APP_UDPAPP - for the UDP/DNS components of the sketch // UIP_DHCP - for the DHCP components of the sketch #include <WiShield.h> extern "C" { #include "uip.h" } // Wireless configuration parameters ---------------------------------------- unsigned char local_ip[] = {10, 0, 1, 57}; // IP address of WiShield unsigned char gateway_ip[] = {10, 0, 1, 1}; // router or gateway IP address unsigned char subnet_mask[] = {255, 255, 255, 0}; // subnet mask for the local network char ssid[] = {"Network"}; // max 32 bytes uint16_t localPort = 1026; // local port to listen on // The resolved DNS address uint16_t dns_ip[] = {10, 0, 1, 1}; // DNS server addr // typedef uint16_t u16_t; //uint16_t dnsAddr[] = {0, 0, 0, 0}; // witypes.h typedef unsigned char uint16; unsigned char == uint16_t; 16 bits //char dest_URL[] = {"w1.weather.gov"}; uint16_t dest_ip[] = {10, 0, 1, 64}; // IP address of Mac on local network // uint16_t dest_Port = 80; // destination port uint16_t dest_Port = 3333; // destination port for use with python script below unsigned char security_type = 5; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2; 4 - WPA Precalc; 5 - WPA2 Precalc // Depending on your security_type, uncomment the appropriate type of security_data // 0 - None (open) // const char security_data[] PROGMEM = {}; // 1 - WEP // UIP_WEP_KEY_LEN. 5 bytes for 64-bit key, 13 bytes for 128-bit key // Only supply the appropriate key, do not specify 4 keys and then try to specify which to use //const char security_data[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, }; // 2, 3 - WPA/WPA2 Passphrase // 8 to 63 characters which will be used to generate the 32 byte calculated key // Expect the g2100 to take 30 seconds to calculate the key from a passphrase // const char security_data[] PROGMEM = {"Network_Passcode"}; // 4, 5 - WPA/WPA2 Precalc // The 32 byte precalculate WPA/WPA2 key. This can be calculated in advance to save boot time //const prog_char security_data[] PROGMEM = { // 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x1f, //}; // Calc the Precalc: // http://jorisvr.nl/wpapsk.html // The derived key will appear in the form as a sequence of 64 hexadecimal digits. /*0599967ce21000026c2cf439ea561c3d37abbf48085738cbe9b9a9ca093a6adb*/ const char security_data[] PROGMEM = { 0x05, 0x99, 0x96, 0x7c, 0xe2, 0x10, 0x00, 0x02, 0x6c, 0x2c, 0xf4, 0x39, 0xea, 0x56, 0x1c, 0x3d, 0x37, 0xab, 0xbf, 0x48, 0x08, 0x57, 0x38, 0xcb, 0xe9, 0xb9, 0xa9, 0xca, 0x09, 0x3a, 0x6a, 0xdb, }; // setup the wireless mode; infrastructure - connect to AP; adhoc - connect to another WiFi device //#define WIRELESS_MODE_INFRA 1 //#define WIRELESS_MODE_ADHOC 2 unsigned char wireless_mode = WIRELESS_MODE_INFRA; // End of wireless configuration parameters ---------------------------------------- /* * uint16_t localPort = 1026; // local port to listen on * fails SA: aborted * uint16_t dest_Port = 6000; // local port to listen on * fails SA: aborted * Wireshark: 143 18.779493 10.0.1.57 10.0.1.64 TCP 58 1026 → 6000 [SYN] Seq=0 Win=429 Len=0 MSS=429 * Wireshark: 144 18.779572 10.0.1.64 10.0.1.57 TCP 54 6000 → 1026 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0 * Wireshark: 465 33.282291 10.0.1.64 10.0.1.57 UDP 47 6000 → 1026 Len=5 * uint16_t dest_Port = 80; // local port to listen on * passes SA: connected * === Initializing WiShield as Client to display DHCP Query on Serial Monitor === * Local port:1026 * Destination port:80 * Destination ip:10,0,1,64 * * WiFi Init OK; Start the DHCP query... * DHCP IP : 10.0.1.57 * DHCP GATEWAY: 10.0.1.1 * DHCP NETMASK: 255.255.255.0 * DHCP DNS : 10.0.1.1 * SA: connected / send * SA: newdata * SA: acked * SA: closed / timedout * * Wireshark: 20 8.294431 Microchi_0a:a0:c7 Broadcast LLC 20 S P, func=RNR, N(R)=64; DSAP NULL LSAP Individual, SSAP NULL LSAP Command * Wireshark: 29 9.830348 Microchi_0a:a0:c7 Broadcast ARP 42 Who has 10.0.1.64? Tell 10.0.1.57 * Wireshark: 30 9.830402 Apple_00:f9:7e Microchi_0a:a0:c7 ARP 42 10.0.1.64 is at 00:26:bb:00:f9:7e * * Wireshark: 38 11.791007 10.0.1.57 10.0.1.64 TCP 58 1026 → 80 [SYN] Seq=0 Win=429 Len=0 MSS=429 * Wireshark: 39 11.791154 10.0.1.64 10.0.1.57 TCP 58 80 → 1026 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 * Wireshark: 41 11.798863 10.0.1.57 10.0.1.64 TCP 67 [TCP segment of a reassembled PDU] * Wireshark: 42 11.798946 10.0.1.64 10.0.1.57 TCP 54 80 → 1026 [ACK] Seq=1 Ack=14 Win=65535 Len=0 * Wireshark: 43 11.804133 10.0.1.57 10.0.1.64 TCP 54 1026 → 80 [FIN, ACK] Seq=14 Ack=1 Win=429 Len=0 * Wireshark: 44 11.804246 10.0.1.64 10.0.1.57 TCP 54 80 → 1026 [ACK] Seq=1 Ack=15 Win=65535 Len=0 * Wireshark: 45 11.805637 10.0.1.64 10.0.1.57 TCP 54 80 → 1026 [FIN, ACK] Seq=1 Ack=15 Win=65535 Len=0 * Wireshark: 46 11.810786 10.0.1.57 10.0.1.64 TCP 54 1026 → 80 [ACK] Seq=15 Ack=2 Win=429 Len=0 * * Wireshark: 51 11.950227 10.0.1.64 10.0.1.57 UDP 47 6000 → 1026 Len=5 * (UDP message from Processing sketch port 6000 that was broadcasting on Mac ip 10.0.1.64) */ char packetBuffer[255]; //buffer to hold incoming packet char ReplyBuffer[] = "acknowledged"; // a string to send back // global data boolean connectAndSendTCP = false; uip_ipaddr_t srvaddr; void setup() { // Enable Serial output Serial.begin(115200); Serial.println ("\n=== Initializing WiShield as Client to display DHCP Query on Serial Monitor ==="); Serial.print("Local port:"); Serial.print(localPort); Serial.print("\nDestination port:"); Serial.print(dest_Port); Serial.print("\nDestination ip:"); Serial.print(dest_ip[0]); Serial.print(","); Serial.print (dest_ip[1]); Serial.print(","); Serial.print (dest_ip[2]); Serial.print(","); Serial.println (dest_ip[3]); Serial.println(); WiFi.init(); Serial.println("\nWiFi Init OK; Start the DHCP query..."); uip_dhcp_request(); } void loop() { if (true == connectAndSendTCP) { connectAndSendTCP = false; // Address of server to connect to //uip_ipaddr(&srvaddr, 10,0,1,64); uip_ipaddr(&srvaddr, (dest_ip[0]), (dest_ip[1]), (dest_ip[2]), (dest_ip[3])); uip_connect(&srvaddr, HTONS(dest_Port)); } WiFi.run(); } extern "C" { // Process UDP UIP_APPCALL events void udpapp_appcall(void) { uip_dhcp_run(); } // DHCP query complete callback void uip_dhcp_callback(const struct dhcp_state *s) { if (NULL != s) { // Set the received IP addr data into the uIP stack uip_sethostaddr(s->ipaddr); // DHCP assigned Arduino Wifi ip address uip_setdraddr(s->default_router); // code assigned gateway_ip[] uip_setnetmask(s->netmask); // code assigned subnet_mask[] // code assigned dnsaddr -> dns_ip[] // Print the received data - its quick and dirty but informative Serial.print("DHCP IP : "); Serial.print(uip_ipaddr1(s->ipaddr), DEC); Serial.print("."); Serial.print(uip_ipaddr2(s->ipaddr), DEC); Serial.print("."); Serial.print(uip_ipaddr3(s->ipaddr), DEC); Serial.print("."); Serial.println(uip_ipaddr4(s->ipaddr), DEC); Serial.print("DHCP GATEWAY: "); Serial.print(uip_ipaddr1(s->default_router), DEC); Serial.print("."); Serial.print(uip_ipaddr2(s->default_router), DEC); Serial.print("."); Serial.print(uip_ipaddr3(s->default_router), DEC); Serial.print("."); Serial.println(uip_ipaddr4(s->default_router), DEC); Serial.print("DHCP NETMASK: "); Serial.print(uip_ipaddr1(s->netmask), DEC); Serial.print("."); Serial.print(uip_ipaddr2(s->netmask), DEC); Serial.print("."); Serial.print(uip_ipaddr3(s->netmask), DEC); Serial.print("."); Serial.println(uip_ipaddr4(s->netmask), DEC); Serial.print("DHCP DNS : "); Serial.print(uip_ipaddr1(s->dnsaddr), DEC); Serial.print("."); Serial.print(uip_ipaddr2(s->dnsaddr), DEC); Serial.print("."); Serial.print(uip_ipaddr3(s->dnsaddr), DEC); Serial.print("."); Serial.println(uip_ipaddr4(s->dnsaddr), DEC); } else { Serial.println("DHCP NULL FALLBACK"); } // Shut down DHCP uip_dhcp_shutdown(); connectAndSendTCP = true; } char packet[] = "SocketAppDHCP"; void socket_app_appcall(void) { if (uip_closed() || uip_timedout()) { Serial.println("SA: closed / timedout"); uip_close(); return; } if (uip_poll()) { Serial.println("SA: poll"); } if (uip_aborted()) { Serial.println("SA: aborted"); } if (uip_connected()) { Serial.println("SA: connected / send"); uip_send(packet, strlen(packet)); } if (uip_acked()) { Serial.println("SA: acked"); uip_close(); } if (uip_newdata()) { Serial.println("SA: newdata"); } if (uip_rexmit()) { Serial.println("SA: rexmit"); uip_send(packet, strlen(packet)); } } // These uIP callbacks are unused for the purposes of this simple DHCP example // but they must exist. void socket_app_init(void) { } void udpapp_init(void) { } void dummy_app_appcall(void) { } } /* # -- Beginning of python server script import socket HOST = '' # Symbolic name meaning all available interfaces PORT = 3333 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) try: while 1: conn, addr = s.accept() print 'Connected by', addr data = conn.recv(1024) if not data: continue print data conn.close() except: conn.close() # -- End of python script */(Apr 28, 2016)
No comments:
Post a Comment