An access controller for man doors at our facility. It receives Wiegand signals from a keypad/card reader and activates a relay to open the door. Access codes are stored in EEPROM. The active code list is updated from TFTP on a local server.

Dependencies:   24LCxx_I2C CardReader USBHOST

Revision:
0:a56239ae90c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DHCPOptions.cpp	Mon Sep 25 19:02:40 2017 +0000
@@ -0,0 +1,142 @@
+
+#include "DHCPOptions.h"
+
+int DHCPOptions::getOptions(char* tftp_server, const char* mac_address, const uint32_t timeout)
+{
+    char mac_bin[DHCP_CHADDR_SIZE + 1] = {0}; // Initialize the hardware address array to zeros.
+    int bind_result;
+    DHCPPacket pkt, rec_pkt;
+    
+    // Generate binary version of the MAC string.
+    macStrToBin(mac_bin, mac_address);
+    
+    SocketAddress dhcp_addr(DHCP_BROADCAST_ADDRESS, DHCP_SERVER_PORT);
+    m_sock.open(m_eth);
+    m_sock.set_timeout(timeout);
+    bind_result = m_sock.bind(DHCP_CLIENT_PORT);
+    
+    if (bind_result < 0)
+    {
+        printf("DHCP Port Binding Failed: %d\n", bind_result);
+        return -1; // DHCP port bind failed.
+    }
+    
+    // Construct a DHCP DISCOVER packet
+    pkt.op = DHCP_OP_REQUEST;
+    pkt.htype = DHCP_HTYPE;
+    pkt.hlen = DHCP_HLEN;
+    pkt.hops = DHCP_HOPS;
+    pkt.xid = htonl(rand());
+    pkt.secs = htons(DHCP_SECS);
+    pkt.flags = htons(DHCP_FLAGS);
+    pkt.ciaddr = htonl(DHCP_CIADDR);
+    pkt.yiaddr = htonl(DHCP_YIADDR);
+    pkt.siaddr = htonl(DHCP_SIADDR);
+    pkt.giaddr = htonl(DHCP_GIADDR);
+    // MAC address with padding - 16 bytes total
+    memcpy(pkt.chaddr, mac_bin, DHCP_CHADDR_SIZE);
+    memset(pkt.sname, 0, DHCP_SNAME_SIZE);
+    memset(pkt.file, 0, DHCP_FILE_SIZE);
+    // Options List
+    pkt.magic = htonl(DHCP_MAGIC_COOKIE);
+    pkt.op_mtype = 53;
+    pkt.mtype_len = 1;
+    pkt.mtype = 1;
+    char discover_options[] = {DHCP_PREQLIST, 1, DHCP_OPTION_TFTPSERVER, DHCP_OPTION_STOP};
+    memcpy(pkt.options, discover_options, sizeof(discover_options));
+    
+    // Send read request
+    int bytes_sent = m_sock.sendto(dhcp_addr, (char*)&pkt, sizeof(DHCPPacket));
+    if (bytes_sent < 0)
+    {
+        printf("DHCP Discover Failed: %d\n", bytes_sent);
+        return -2; // DHCP Discover send failed.
+    }
+    else
+    {
+        //printf("Sent: %d\n", bytes_sent);
+    }
+    
+    // Get data packet from the DHCP server
+    int bytes_received = m_sock.recvfrom(&dhcp_addr, (char*)&rec_pkt, sizeof(DHCPPacket));
+    if (bytes_received < 0)
+    {
+        printf("DHCP Offer Failed: %d\n", bytes_received);
+        return -3; // UDP packet recevie failed.
+    }
+    else
+    {
+        //printf("Received: %d\n", bytes_received);
+    }
+    
+    if (decodeOptions(tftp_server, rec_pkt) < 0)
+    {
+        printf("Failed to find the TFTP server option.\n");
+        return -4; // Failed to find the TFTP server name option from the DHCP offer response packet.
+    }
+    
+    m_sock.close();
+    return 0;
+}
+
+int DHCPOptions::decodeOptions(char* tftp_server, DHCPPacket& pkt)
+{
+    char* dhcp_options = pkt.options;
+    int optionIndex = 0;
+    int optionLength = 0;
+    
+    while (optionIndex < DHCP_OPTIONS_SIZE && dhcp_options[optionIndex] != DHCP_OPTION_STOP)
+    {
+        // Get the length of the current DHCP option field.
+        optionLength = dhcp_options[optionIndex + 1];
+        
+        // Check for the TFTP server option code.
+        if (dhcp_options[optionIndex] == DHCP_OPTION_TFTPSERVER)
+        {
+            // Copy the TFTP server string to the output string.
+            memcpy(tftp_server, dhcp_options + optionIndex + 2, optionLength);
+            return 0;
+        }
+        
+        // Move to the next option.
+        optionIndex += 2 + optionLength;
+    }
+    
+    return -1; // Failed to find the DHCP option.
+}
+
+int DHCPOptions::macStrToBin(char* macBin, const char* macStr)
+{
+    if (strlen(macStr) != MAC_STRING_LENGTH)
+    {
+        return -1; // Invalid MAC string
+    }
+    else
+    {
+        for (int byteIndex = 0; byteIndex < 6; byteIndex++)
+        {
+            macBin[byteIndex] = (charToNum(macStr[byteIndex * 3]) * 16) + charToNum(macStr[(byteIndex * 3) + 1]);
+        }
+    }
+    
+    return 0;
+}
+
+unsigned char DHCPOptions::charToNum(const char input)
+{
+    if(input >= '0' && input <= '9')
+    {
+        return input - '0';
+    }
+    if(input >= 'A' && input <= 'F')
+    {
+        return input - 'A' + 10;
+    }
+    if(input >= 'a' && input <= 'f')
+    {
+        return input - 'a' + 10;
+    }
+
+    return 0;
+}
+    
\ No newline at end of file