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
DHCPOptions.cpp@0:a56239ae90c2, 2017-09-25 (annotated)
- Committer:
- acesrobertm
- Date:
- Mon Sep 25 19:02:40 2017 +0000
- Revision:
- 0:a56239ae90c2
in process of moving networking code to non-blocking format
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
acesrobertm | 0:a56239ae90c2 | 1 | |
acesrobertm | 0:a56239ae90c2 | 2 | #include "DHCPOptions.h" |
acesrobertm | 0:a56239ae90c2 | 3 | |
acesrobertm | 0:a56239ae90c2 | 4 | int DHCPOptions::getOptions(char* tftp_server, const char* mac_address, const uint32_t timeout) |
acesrobertm | 0:a56239ae90c2 | 5 | { |
acesrobertm | 0:a56239ae90c2 | 6 | char mac_bin[DHCP_CHADDR_SIZE + 1] = {0}; // Initialize the hardware address array to zeros. |
acesrobertm | 0:a56239ae90c2 | 7 | int bind_result; |
acesrobertm | 0:a56239ae90c2 | 8 | DHCPPacket pkt, rec_pkt; |
acesrobertm | 0:a56239ae90c2 | 9 | |
acesrobertm | 0:a56239ae90c2 | 10 | // Generate binary version of the MAC string. |
acesrobertm | 0:a56239ae90c2 | 11 | macStrToBin(mac_bin, mac_address); |
acesrobertm | 0:a56239ae90c2 | 12 | |
acesrobertm | 0:a56239ae90c2 | 13 | SocketAddress dhcp_addr(DHCP_BROADCAST_ADDRESS, DHCP_SERVER_PORT); |
acesrobertm | 0:a56239ae90c2 | 14 | m_sock.open(m_eth); |
acesrobertm | 0:a56239ae90c2 | 15 | m_sock.set_timeout(timeout); |
acesrobertm | 0:a56239ae90c2 | 16 | bind_result = m_sock.bind(DHCP_CLIENT_PORT); |
acesrobertm | 0:a56239ae90c2 | 17 | |
acesrobertm | 0:a56239ae90c2 | 18 | if (bind_result < 0) |
acesrobertm | 0:a56239ae90c2 | 19 | { |
acesrobertm | 0:a56239ae90c2 | 20 | printf("DHCP Port Binding Failed: %d\n", bind_result); |
acesrobertm | 0:a56239ae90c2 | 21 | return -1; // DHCP port bind failed. |
acesrobertm | 0:a56239ae90c2 | 22 | } |
acesrobertm | 0:a56239ae90c2 | 23 | |
acesrobertm | 0:a56239ae90c2 | 24 | // Construct a DHCP DISCOVER packet |
acesrobertm | 0:a56239ae90c2 | 25 | pkt.op = DHCP_OP_REQUEST; |
acesrobertm | 0:a56239ae90c2 | 26 | pkt.htype = DHCP_HTYPE; |
acesrobertm | 0:a56239ae90c2 | 27 | pkt.hlen = DHCP_HLEN; |
acesrobertm | 0:a56239ae90c2 | 28 | pkt.hops = DHCP_HOPS; |
acesrobertm | 0:a56239ae90c2 | 29 | pkt.xid = htonl(rand()); |
acesrobertm | 0:a56239ae90c2 | 30 | pkt.secs = htons(DHCP_SECS); |
acesrobertm | 0:a56239ae90c2 | 31 | pkt.flags = htons(DHCP_FLAGS); |
acesrobertm | 0:a56239ae90c2 | 32 | pkt.ciaddr = htonl(DHCP_CIADDR); |
acesrobertm | 0:a56239ae90c2 | 33 | pkt.yiaddr = htonl(DHCP_YIADDR); |
acesrobertm | 0:a56239ae90c2 | 34 | pkt.siaddr = htonl(DHCP_SIADDR); |
acesrobertm | 0:a56239ae90c2 | 35 | pkt.giaddr = htonl(DHCP_GIADDR); |
acesrobertm | 0:a56239ae90c2 | 36 | // MAC address with padding - 16 bytes total |
acesrobertm | 0:a56239ae90c2 | 37 | memcpy(pkt.chaddr, mac_bin, DHCP_CHADDR_SIZE); |
acesrobertm | 0:a56239ae90c2 | 38 | memset(pkt.sname, 0, DHCP_SNAME_SIZE); |
acesrobertm | 0:a56239ae90c2 | 39 | memset(pkt.file, 0, DHCP_FILE_SIZE); |
acesrobertm | 0:a56239ae90c2 | 40 | // Options List |
acesrobertm | 0:a56239ae90c2 | 41 | pkt.magic = htonl(DHCP_MAGIC_COOKIE); |
acesrobertm | 0:a56239ae90c2 | 42 | pkt.op_mtype = 53; |
acesrobertm | 0:a56239ae90c2 | 43 | pkt.mtype_len = 1; |
acesrobertm | 0:a56239ae90c2 | 44 | pkt.mtype = 1; |
acesrobertm | 0:a56239ae90c2 | 45 | char discover_options[] = {DHCP_PREQLIST, 1, DHCP_OPTION_TFTPSERVER, DHCP_OPTION_STOP}; |
acesrobertm | 0:a56239ae90c2 | 46 | memcpy(pkt.options, discover_options, sizeof(discover_options)); |
acesrobertm | 0:a56239ae90c2 | 47 | |
acesrobertm | 0:a56239ae90c2 | 48 | // Send read request |
acesrobertm | 0:a56239ae90c2 | 49 | int bytes_sent = m_sock.sendto(dhcp_addr, (char*)&pkt, sizeof(DHCPPacket)); |
acesrobertm | 0:a56239ae90c2 | 50 | if (bytes_sent < 0) |
acesrobertm | 0:a56239ae90c2 | 51 | { |
acesrobertm | 0:a56239ae90c2 | 52 | printf("DHCP Discover Failed: %d\n", bytes_sent); |
acesrobertm | 0:a56239ae90c2 | 53 | return -2; // DHCP Discover send failed. |
acesrobertm | 0:a56239ae90c2 | 54 | } |
acesrobertm | 0:a56239ae90c2 | 55 | else |
acesrobertm | 0:a56239ae90c2 | 56 | { |
acesrobertm | 0:a56239ae90c2 | 57 | //printf("Sent: %d\n", bytes_sent); |
acesrobertm | 0:a56239ae90c2 | 58 | } |
acesrobertm | 0:a56239ae90c2 | 59 | |
acesrobertm | 0:a56239ae90c2 | 60 | // Get data packet from the DHCP server |
acesrobertm | 0:a56239ae90c2 | 61 | int bytes_received = m_sock.recvfrom(&dhcp_addr, (char*)&rec_pkt, sizeof(DHCPPacket)); |
acesrobertm | 0:a56239ae90c2 | 62 | if (bytes_received < 0) |
acesrobertm | 0:a56239ae90c2 | 63 | { |
acesrobertm | 0:a56239ae90c2 | 64 | printf("DHCP Offer Failed: %d\n", bytes_received); |
acesrobertm | 0:a56239ae90c2 | 65 | return -3; // UDP packet recevie failed. |
acesrobertm | 0:a56239ae90c2 | 66 | } |
acesrobertm | 0:a56239ae90c2 | 67 | else |
acesrobertm | 0:a56239ae90c2 | 68 | { |
acesrobertm | 0:a56239ae90c2 | 69 | //printf("Received: %d\n", bytes_received); |
acesrobertm | 0:a56239ae90c2 | 70 | } |
acesrobertm | 0:a56239ae90c2 | 71 | |
acesrobertm | 0:a56239ae90c2 | 72 | if (decodeOptions(tftp_server, rec_pkt) < 0) |
acesrobertm | 0:a56239ae90c2 | 73 | { |
acesrobertm | 0:a56239ae90c2 | 74 | printf("Failed to find the TFTP server option.\n"); |
acesrobertm | 0:a56239ae90c2 | 75 | return -4; // Failed to find the TFTP server name option from the DHCP offer response packet. |
acesrobertm | 0:a56239ae90c2 | 76 | } |
acesrobertm | 0:a56239ae90c2 | 77 | |
acesrobertm | 0:a56239ae90c2 | 78 | m_sock.close(); |
acesrobertm | 0:a56239ae90c2 | 79 | return 0; |
acesrobertm | 0:a56239ae90c2 | 80 | } |
acesrobertm | 0:a56239ae90c2 | 81 | |
acesrobertm | 0:a56239ae90c2 | 82 | int DHCPOptions::decodeOptions(char* tftp_server, DHCPPacket& pkt) |
acesrobertm | 0:a56239ae90c2 | 83 | { |
acesrobertm | 0:a56239ae90c2 | 84 | char* dhcp_options = pkt.options; |
acesrobertm | 0:a56239ae90c2 | 85 | int optionIndex = 0; |
acesrobertm | 0:a56239ae90c2 | 86 | int optionLength = 0; |
acesrobertm | 0:a56239ae90c2 | 87 | |
acesrobertm | 0:a56239ae90c2 | 88 | while (optionIndex < DHCP_OPTIONS_SIZE && dhcp_options[optionIndex] != DHCP_OPTION_STOP) |
acesrobertm | 0:a56239ae90c2 | 89 | { |
acesrobertm | 0:a56239ae90c2 | 90 | // Get the length of the current DHCP option field. |
acesrobertm | 0:a56239ae90c2 | 91 | optionLength = dhcp_options[optionIndex + 1]; |
acesrobertm | 0:a56239ae90c2 | 92 | |
acesrobertm | 0:a56239ae90c2 | 93 | // Check for the TFTP server option code. |
acesrobertm | 0:a56239ae90c2 | 94 | if (dhcp_options[optionIndex] == DHCP_OPTION_TFTPSERVER) |
acesrobertm | 0:a56239ae90c2 | 95 | { |
acesrobertm | 0:a56239ae90c2 | 96 | // Copy the TFTP server string to the output string. |
acesrobertm | 0:a56239ae90c2 | 97 | memcpy(tftp_server, dhcp_options + optionIndex + 2, optionLength); |
acesrobertm | 0:a56239ae90c2 | 98 | return 0; |
acesrobertm | 0:a56239ae90c2 | 99 | } |
acesrobertm | 0:a56239ae90c2 | 100 | |
acesrobertm | 0:a56239ae90c2 | 101 | // Move to the next option. |
acesrobertm | 0:a56239ae90c2 | 102 | optionIndex += 2 + optionLength; |
acesrobertm | 0:a56239ae90c2 | 103 | } |
acesrobertm | 0:a56239ae90c2 | 104 | |
acesrobertm | 0:a56239ae90c2 | 105 | return -1; // Failed to find the DHCP option. |
acesrobertm | 0:a56239ae90c2 | 106 | } |
acesrobertm | 0:a56239ae90c2 | 107 | |
acesrobertm | 0:a56239ae90c2 | 108 | int DHCPOptions::macStrToBin(char* macBin, const char* macStr) |
acesrobertm | 0:a56239ae90c2 | 109 | { |
acesrobertm | 0:a56239ae90c2 | 110 | if (strlen(macStr) != MAC_STRING_LENGTH) |
acesrobertm | 0:a56239ae90c2 | 111 | { |
acesrobertm | 0:a56239ae90c2 | 112 | return -1; // Invalid MAC string |
acesrobertm | 0:a56239ae90c2 | 113 | } |
acesrobertm | 0:a56239ae90c2 | 114 | else |
acesrobertm | 0:a56239ae90c2 | 115 | { |
acesrobertm | 0:a56239ae90c2 | 116 | for (int byteIndex = 0; byteIndex < 6; byteIndex++) |
acesrobertm | 0:a56239ae90c2 | 117 | { |
acesrobertm | 0:a56239ae90c2 | 118 | macBin[byteIndex] = (charToNum(macStr[byteIndex * 3]) * 16) + charToNum(macStr[(byteIndex * 3) + 1]); |
acesrobertm | 0:a56239ae90c2 | 119 | } |
acesrobertm | 0:a56239ae90c2 | 120 | } |
acesrobertm | 0:a56239ae90c2 | 121 | |
acesrobertm | 0:a56239ae90c2 | 122 | return 0; |
acesrobertm | 0:a56239ae90c2 | 123 | } |
acesrobertm | 0:a56239ae90c2 | 124 | |
acesrobertm | 0:a56239ae90c2 | 125 | unsigned char DHCPOptions::charToNum(const char input) |
acesrobertm | 0:a56239ae90c2 | 126 | { |
acesrobertm | 0:a56239ae90c2 | 127 | if(input >= '0' && input <= '9') |
acesrobertm | 0:a56239ae90c2 | 128 | { |
acesrobertm | 0:a56239ae90c2 | 129 | return input - '0'; |
acesrobertm | 0:a56239ae90c2 | 130 | } |
acesrobertm | 0:a56239ae90c2 | 131 | if(input >= 'A' && input <= 'F') |
acesrobertm | 0:a56239ae90c2 | 132 | { |
acesrobertm | 0:a56239ae90c2 | 133 | return input - 'A' + 10; |
acesrobertm | 0:a56239ae90c2 | 134 | } |
acesrobertm | 0:a56239ae90c2 | 135 | if(input >= 'a' && input <= 'f') |
acesrobertm | 0:a56239ae90c2 | 136 | { |
acesrobertm | 0:a56239ae90c2 | 137 | return input - 'a' + 10; |
acesrobertm | 0:a56239ae90c2 | 138 | } |
acesrobertm | 0:a56239ae90c2 | 139 | |
acesrobertm | 0:a56239ae90c2 | 140 | return 0; |
acesrobertm | 0:a56239ae90c2 | 141 | } |
acesrobertm | 0:a56239ae90c2 | 142 |