lwip-1.4.1 (partial)
dhcp-server/dhserver.c@1:119c4f7144c8, 2018-07-24 (annotated)
- Committer:
- ua1arn
- Date:
- Tue Jul 24 17:36:01 2018 +0000
- Revision:
- 1:119c4f7144c8
lwip 1.4.1 with necessary servers
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ua1arn | 1:119c4f7144c8 | 1 | /* |
ua1arn | 1:119c4f7144c8 | 2 | * The MIT License (MIT) |
ua1arn | 1:119c4f7144c8 | 3 | * |
ua1arn | 1:119c4f7144c8 | 4 | * Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com> |
ua1arn | 1:119c4f7144c8 | 5 | * |
ua1arn | 1:119c4f7144c8 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
ua1arn | 1:119c4f7144c8 | 7 | * of this software and associated documentation files (the "Software"), to deal |
ua1arn | 1:119c4f7144c8 | 8 | * in the Software without restriction, including without limitation the rights |
ua1arn | 1:119c4f7144c8 | 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
ua1arn | 1:119c4f7144c8 | 10 | * copies of the Software, and to permit persons to whom the Software is |
ua1arn | 1:119c4f7144c8 | 11 | * furnished to do so, subject to the following conditions: |
ua1arn | 1:119c4f7144c8 | 12 | * |
ua1arn | 1:119c4f7144c8 | 13 | * The above copyright notice and this permission notice shall be included in all |
ua1arn | 1:119c4f7144c8 | 14 | * copies or substantial portions of the Software. |
ua1arn | 1:119c4f7144c8 | 15 | * |
ua1arn | 1:119c4f7144c8 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
ua1arn | 1:119c4f7144c8 | 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
ua1arn | 1:119c4f7144c8 | 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
ua1arn | 1:119c4f7144c8 | 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
ua1arn | 1:119c4f7144c8 | 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
ua1arn | 1:119c4f7144c8 | 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
ua1arn | 1:119c4f7144c8 | 22 | * SOFTWARE. |
ua1arn | 1:119c4f7144c8 | 23 | */ |
ua1arn | 1:119c4f7144c8 | 24 | |
ua1arn | 1:119c4f7144c8 | 25 | #include "dhserver.h" |
ua1arn | 1:119c4f7144c8 | 26 | |
ua1arn | 1:119c4f7144c8 | 27 | /* DHCP message type */ |
ua1arn | 1:119c4f7144c8 | 28 | #define DHCP_DISCOVER 1 |
ua1arn | 1:119c4f7144c8 | 29 | #define DHCP_OFFER 2 |
ua1arn | 1:119c4f7144c8 | 30 | #define DHCP_REQUEST 3 |
ua1arn | 1:119c4f7144c8 | 31 | #define DHCP_DECLINE 4 |
ua1arn | 1:119c4f7144c8 | 32 | #define DHCP_ACK 5 |
ua1arn | 1:119c4f7144c8 | 33 | #define DHCP_NAK 6 |
ua1arn | 1:119c4f7144c8 | 34 | #define DHCP_RELEASE 7 |
ua1arn | 1:119c4f7144c8 | 35 | #define DHCP_INFORM 8 |
ua1arn | 1:119c4f7144c8 | 36 | |
ua1arn | 1:119c4f7144c8 | 37 | /* DHCP options */ |
ua1arn | 1:119c4f7144c8 | 38 | enum DHCP_OPTIONS |
ua1arn | 1:119c4f7144c8 | 39 | { |
ua1arn | 1:119c4f7144c8 | 40 | DHCP_PAD = 0, |
ua1arn | 1:119c4f7144c8 | 41 | DHCP_SUBNETMASK = 1, |
ua1arn | 1:119c4f7144c8 | 42 | DHCP_ROUTER = 3, |
ua1arn | 1:119c4f7144c8 | 43 | DHCP_DNSSERVER = 6, |
ua1arn | 1:119c4f7144c8 | 44 | DHCP_HOSTNAME = 12, |
ua1arn | 1:119c4f7144c8 | 45 | DHCP_DNSDOMAIN = 15, |
ua1arn | 1:119c4f7144c8 | 46 | DHCP_MTU = 26, |
ua1arn | 1:119c4f7144c8 | 47 | DHCP_BROADCAST = 28, |
ua1arn | 1:119c4f7144c8 | 48 | DHCP_PERFORMROUTERDISC = 31, |
ua1arn | 1:119c4f7144c8 | 49 | DHCP_STATICROUTE = 33, |
ua1arn | 1:119c4f7144c8 | 50 | DHCP_NISDOMAIN = 40, |
ua1arn | 1:119c4f7144c8 | 51 | DHCP_NISSERVER = 41, |
ua1arn | 1:119c4f7144c8 | 52 | DHCP_NTPSERVER = 42, |
ua1arn | 1:119c4f7144c8 | 53 | DHCP_VENDOR = 43, |
ua1arn | 1:119c4f7144c8 | 54 | DHCP_IPADDRESS = 50, |
ua1arn | 1:119c4f7144c8 | 55 | DHCP_LEASETIME = 51, |
ua1arn | 1:119c4f7144c8 | 56 | DHCP_OPTIONSOVERLOADED = 52, |
ua1arn | 1:119c4f7144c8 | 57 | DHCP_MESSAGETYPE = 53, |
ua1arn | 1:119c4f7144c8 | 58 | DHCP_SERVERID = 54, |
ua1arn | 1:119c4f7144c8 | 59 | DHCP_PARAMETERREQUESTLIST = 55, |
ua1arn | 1:119c4f7144c8 | 60 | DHCP_MESSAGE = 56, |
ua1arn | 1:119c4f7144c8 | 61 | DHCP_MAXMESSAGESIZE = 57, |
ua1arn | 1:119c4f7144c8 | 62 | DHCP_RENEWALTIME = 58, |
ua1arn | 1:119c4f7144c8 | 63 | DHCP_REBINDTIME = 59, |
ua1arn | 1:119c4f7144c8 | 64 | DHCP_CLASSID = 60, |
ua1arn | 1:119c4f7144c8 | 65 | DHCP_CLIENTID = 61, |
ua1arn | 1:119c4f7144c8 | 66 | DHCP_USERCLASS = 77, /* RFC 3004 */ |
ua1arn | 1:119c4f7144c8 | 67 | DHCP_FQDN = 81, |
ua1arn | 1:119c4f7144c8 | 68 | DHCP_DNSSEARCH = 119, /* RFC 3397 */ |
ua1arn | 1:119c4f7144c8 | 69 | DHCP_CSR = 121, /* RFC 3442 */ |
ua1arn | 1:119c4f7144c8 | 70 | DHCP_MSCSR = 249, /* MS code for RFC 3442 */ |
ua1arn | 1:119c4f7144c8 | 71 | DHCP_END = 255 |
ua1arn | 1:119c4f7144c8 | 72 | }; |
ua1arn | 1:119c4f7144c8 | 73 | |
ua1arn | 1:119c4f7144c8 | 74 | typedef struct |
ua1arn | 1:119c4f7144c8 | 75 | { |
ua1arn | 1:119c4f7144c8 | 76 | uint8_t dp_op; /* packet opcode type */ |
ua1arn | 1:119c4f7144c8 | 77 | uint8_t dp_htype; /* hardware addr type */ |
ua1arn | 1:119c4f7144c8 | 78 | uint8_t dp_hlen; /* hardware addr length */ |
ua1arn | 1:119c4f7144c8 | 79 | uint8_t dp_hops; /* gateway hops */ |
ua1arn | 1:119c4f7144c8 | 80 | uint32_t dp_xid; /* transaction ID */ |
ua1arn | 1:119c4f7144c8 | 81 | uint16_t dp_secs; /* seconds since boot began */ |
ua1arn | 1:119c4f7144c8 | 82 | uint16_t dp_flags; |
ua1arn | 1:119c4f7144c8 | 83 | uint8_t dp_ciaddr[4]; /* client IP address */ |
ua1arn | 1:119c4f7144c8 | 84 | uint8_t dp_yiaddr[4]; /* 'your' IP address */ |
ua1arn | 1:119c4f7144c8 | 85 | uint8_t dp_siaddr[4]; /* server IP address */ |
ua1arn | 1:119c4f7144c8 | 86 | uint8_t dp_giaddr[4]; /* gateway IP address */ |
ua1arn | 1:119c4f7144c8 | 87 | uint8_t dp_chaddr[16]; /* client hardware address */ |
ua1arn | 1:119c4f7144c8 | 88 | uint8_t dp_legacy[192]; |
ua1arn | 1:119c4f7144c8 | 89 | uint8_t dp_magic[4]; |
ua1arn | 1:119c4f7144c8 | 90 | uint8_t dp_options[275]; /* options area */ |
ua1arn | 1:119c4f7144c8 | 91 | } DHCP_TYPE; |
ua1arn | 1:119c4f7144c8 | 92 | |
ua1arn | 1:119c4f7144c8 | 93 | DHCP_TYPE dhcp_data; |
ua1arn | 1:119c4f7144c8 | 94 | static struct udp_pcb *pcb = NULL; |
ua1arn | 1:119c4f7144c8 | 95 | static dhcp_config_t *config = NULL; |
ua1arn | 1:119c4f7144c8 | 96 | |
ua1arn | 1:119c4f7144c8 | 97 | char magic_cookie[] = {0x63,0x82,0x53,0x63}; |
ua1arn | 1:119c4f7144c8 | 98 | |
ua1arn | 1:119c4f7144c8 | 99 | static dhcp_entry_t *entry_by_ip(uint32_t ip) |
ua1arn | 1:119c4f7144c8 | 100 | { |
ua1arn | 1:119c4f7144c8 | 101 | int i; |
ua1arn | 1:119c4f7144c8 | 102 | for (i = 0; i < config->num_entry; i++) |
ua1arn | 1:119c4f7144c8 | 103 | if (*(uint32_t *)config->entries[i].addr == ip) |
ua1arn | 1:119c4f7144c8 | 104 | return &config->entries[i]; |
ua1arn | 1:119c4f7144c8 | 105 | return NULL; |
ua1arn | 1:119c4f7144c8 | 106 | } |
ua1arn | 1:119c4f7144c8 | 107 | |
ua1arn | 1:119c4f7144c8 | 108 | static dhcp_entry_t *entry_by_mac(uint8_t *mac) |
ua1arn | 1:119c4f7144c8 | 109 | { |
ua1arn | 1:119c4f7144c8 | 110 | int i; |
ua1arn | 1:119c4f7144c8 | 111 | for (i = 0; i < config->num_entry; i++) |
ua1arn | 1:119c4f7144c8 | 112 | if (memcmp(config->entries[i].mac, mac, 6) == 0) |
ua1arn | 1:119c4f7144c8 | 113 | return &config->entries[i]; |
ua1arn | 1:119c4f7144c8 | 114 | return NULL; |
ua1arn | 1:119c4f7144c8 | 115 | } |
ua1arn | 1:119c4f7144c8 | 116 | |
ua1arn | 1:119c4f7144c8 | 117 | static __inline bool is_vacant(dhcp_entry_t *entry) |
ua1arn | 1:119c4f7144c8 | 118 | { |
ua1arn | 1:119c4f7144c8 | 119 | return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; |
ua1arn | 1:119c4f7144c8 | 120 | } |
ua1arn | 1:119c4f7144c8 | 121 | |
ua1arn | 1:119c4f7144c8 | 122 | static dhcp_entry_t *vacant_address() |
ua1arn | 1:119c4f7144c8 | 123 | { |
ua1arn | 1:119c4f7144c8 | 124 | int i; |
ua1arn | 1:119c4f7144c8 | 125 | for (i = 0; i < config->num_entry; i++) |
ua1arn | 1:119c4f7144c8 | 126 | if (is_vacant(config->entries + i)) |
ua1arn | 1:119c4f7144c8 | 127 | return config->entries + 1; |
ua1arn | 1:119c4f7144c8 | 128 | return NULL; |
ua1arn | 1:119c4f7144c8 | 129 | } |
ua1arn | 1:119c4f7144c8 | 130 | |
ua1arn | 1:119c4f7144c8 | 131 | static __inline void free_entry(dhcp_entry_t *entry) |
ua1arn | 1:119c4f7144c8 | 132 | { |
ua1arn | 1:119c4f7144c8 | 133 | memset(entry->mac, 0, 6); |
ua1arn | 1:119c4f7144c8 | 134 | } |
ua1arn | 1:119c4f7144c8 | 135 | |
ua1arn | 1:119c4f7144c8 | 136 | uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) |
ua1arn | 1:119c4f7144c8 | 137 | { |
ua1arn | 1:119c4f7144c8 | 138 | int i = 0; |
ua1arn | 1:119c4f7144c8 | 139 | while ((i + 1) < size) |
ua1arn | 1:119c4f7144c8 | 140 | { |
ua1arn | 1:119c4f7144c8 | 141 | int next = i + attrs[i + 1] + 2; |
ua1arn | 1:119c4f7144c8 | 142 | if (next > size) return NULL; |
ua1arn | 1:119c4f7144c8 | 143 | if (attrs[i] == attr) |
ua1arn | 1:119c4f7144c8 | 144 | return attrs + i; |
ua1arn | 1:119c4f7144c8 | 145 | i = next; |
ua1arn | 1:119c4f7144c8 | 146 | } |
ua1arn | 1:119c4f7144c8 | 147 | return NULL; |
ua1arn | 1:119c4f7144c8 | 148 | } |
ua1arn | 1:119c4f7144c8 | 149 | |
ua1arn | 1:119c4f7144c8 | 150 | int fill_options(void *dest, |
ua1arn | 1:119c4f7144c8 | 151 | uint8_t msg_type, |
ua1arn | 1:119c4f7144c8 | 152 | const char *domain, |
ua1arn | 1:119c4f7144c8 | 153 | uint32_t dns, |
ua1arn | 1:119c4f7144c8 | 154 | int lease_time, |
ua1arn | 1:119c4f7144c8 | 155 | uint32_t serverid, |
ua1arn | 1:119c4f7144c8 | 156 | uint32_t router, |
ua1arn | 1:119c4f7144c8 | 157 | uint32_t subnet) |
ua1arn | 1:119c4f7144c8 | 158 | { |
ua1arn | 1:119c4f7144c8 | 159 | uint8_t *ptr = (uint8_t *)dest; |
ua1arn | 1:119c4f7144c8 | 160 | /* ACK message type */ |
ua1arn | 1:119c4f7144c8 | 161 | *ptr++ = 53; |
ua1arn | 1:119c4f7144c8 | 162 | *ptr++ = 1; |
ua1arn | 1:119c4f7144c8 | 163 | *ptr++ = msg_type; |
ua1arn | 1:119c4f7144c8 | 164 | |
ua1arn | 1:119c4f7144c8 | 165 | /* dhcp server identifier */ |
ua1arn | 1:119c4f7144c8 | 166 | *ptr++ = DHCP_SERVERID; |
ua1arn | 1:119c4f7144c8 | 167 | *ptr++ = 4; |
ua1arn | 1:119c4f7144c8 | 168 | *(uint32_t *)ptr = serverid; |
ua1arn | 1:119c4f7144c8 | 169 | ptr += 4; |
ua1arn | 1:119c4f7144c8 | 170 | |
ua1arn | 1:119c4f7144c8 | 171 | /* lease time */ |
ua1arn | 1:119c4f7144c8 | 172 | *ptr++ = DHCP_LEASETIME; |
ua1arn | 1:119c4f7144c8 | 173 | *ptr++ = 4; |
ua1arn | 1:119c4f7144c8 | 174 | *ptr++ = (lease_time >> 24) & 0xFF; |
ua1arn | 1:119c4f7144c8 | 175 | *ptr++ = (lease_time >> 16) & 0xFF; |
ua1arn | 1:119c4f7144c8 | 176 | *ptr++ = (lease_time >> 8) & 0xFF; |
ua1arn | 1:119c4f7144c8 | 177 | *ptr++ = (lease_time >> 0) & 0xFF; |
ua1arn | 1:119c4f7144c8 | 178 | |
ua1arn | 1:119c4f7144c8 | 179 | /* subnet mask */ |
ua1arn | 1:119c4f7144c8 | 180 | *ptr++ = DHCP_SUBNETMASK; |
ua1arn | 1:119c4f7144c8 | 181 | *ptr++ = 4; |
ua1arn | 1:119c4f7144c8 | 182 | *(uint32_t *)ptr = subnet; |
ua1arn | 1:119c4f7144c8 | 183 | ptr += 4; |
ua1arn | 1:119c4f7144c8 | 184 | |
ua1arn | 1:119c4f7144c8 | 185 | /* router */ |
ua1arn | 1:119c4f7144c8 | 186 | if (router != 0) |
ua1arn | 1:119c4f7144c8 | 187 | { |
ua1arn | 1:119c4f7144c8 | 188 | *ptr++ = DHCP_ROUTER; |
ua1arn | 1:119c4f7144c8 | 189 | *ptr++ = 4; |
ua1arn | 1:119c4f7144c8 | 190 | *(uint32_t *)ptr = router; |
ua1arn | 1:119c4f7144c8 | 191 | ptr += 4; |
ua1arn | 1:119c4f7144c8 | 192 | } |
ua1arn | 1:119c4f7144c8 | 193 | |
ua1arn | 1:119c4f7144c8 | 194 | /* domain name */ |
ua1arn | 1:119c4f7144c8 | 195 | if (domain != NULL) |
ua1arn | 1:119c4f7144c8 | 196 | { |
ua1arn | 1:119c4f7144c8 | 197 | int len = strlen(domain); |
ua1arn | 1:119c4f7144c8 | 198 | *ptr++ = DHCP_DNSDOMAIN; |
ua1arn | 1:119c4f7144c8 | 199 | *ptr++ = len; |
ua1arn | 1:119c4f7144c8 | 200 | memcpy(ptr, domain, len); |
ua1arn | 1:119c4f7144c8 | 201 | ptr += len; |
ua1arn | 1:119c4f7144c8 | 202 | } |
ua1arn | 1:119c4f7144c8 | 203 | |
ua1arn | 1:119c4f7144c8 | 204 | /* domain name server (DNS) */ |
ua1arn | 1:119c4f7144c8 | 205 | if (dns != 0) |
ua1arn | 1:119c4f7144c8 | 206 | { |
ua1arn | 1:119c4f7144c8 | 207 | *ptr++ = DHCP_DNSSERVER; |
ua1arn | 1:119c4f7144c8 | 208 | *ptr++ = 4; |
ua1arn | 1:119c4f7144c8 | 209 | *(uint32_t *)ptr = dns; |
ua1arn | 1:119c4f7144c8 | 210 | ptr += 4; |
ua1arn | 1:119c4f7144c8 | 211 | } |
ua1arn | 1:119c4f7144c8 | 212 | |
ua1arn | 1:119c4f7144c8 | 213 | /* end */ |
ua1arn | 1:119c4f7144c8 | 214 | *ptr++ = DHCP_END; |
ua1arn | 1:119c4f7144c8 | 215 | return ptr - (uint8_t *)dest; |
ua1arn | 1:119c4f7144c8 | 216 | } |
ua1arn | 1:119c4f7144c8 | 217 | |
ua1arn | 1:119c4f7144c8 | 218 | static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port) |
ua1arn | 1:119c4f7144c8 | 219 | { |
ua1arn | 1:119c4f7144c8 | 220 | uint8_t *ptr; |
ua1arn | 1:119c4f7144c8 | 221 | dhcp_entry_t *entry; |
ua1arn | 1:119c4f7144c8 | 222 | struct pbuf *pp; |
ua1arn | 1:119c4f7144c8 | 223 | |
ua1arn | 1:119c4f7144c8 | 224 | int n = p->len; |
ua1arn | 1:119c4f7144c8 | 225 | if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); |
ua1arn | 1:119c4f7144c8 | 226 | memcpy(&dhcp_data, p->payload, n); |
ua1arn | 1:119c4f7144c8 | 227 | switch (dhcp_data.dp_options[2]) |
ua1arn | 1:119c4f7144c8 | 228 | { |
ua1arn | 1:119c4f7144c8 | 229 | case DHCP_DISCOVER: |
ua1arn | 1:119c4f7144c8 | 230 | entry = entry_by_mac(dhcp_data.dp_chaddr); |
ua1arn | 1:119c4f7144c8 | 231 | if (entry == NULL) entry = vacant_address(); |
ua1arn | 1:119c4f7144c8 | 232 | if (entry == NULL) break; |
ua1arn | 1:119c4f7144c8 | 233 | |
ua1arn | 1:119c4f7144c8 | 234 | dhcp_data.dp_op = 2; /* reply */ |
ua1arn | 1:119c4f7144c8 | 235 | dhcp_data.dp_secs = 0; |
ua1arn | 1:119c4f7144c8 | 236 | dhcp_data.dp_flags = 0; |
ua1arn | 1:119c4f7144c8 | 237 | *(uint32_t *)dhcp_data.dp_yiaddr = *(uint32_t *)entry->addr; |
ua1arn | 1:119c4f7144c8 | 238 | memcpy(dhcp_data.dp_magic, magic_cookie, 4); |
ua1arn | 1:119c4f7144c8 | 239 | |
ua1arn | 1:119c4f7144c8 | 240 | memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); |
ua1arn | 1:119c4f7144c8 | 241 | |
ua1arn | 1:119c4f7144c8 | 242 | fill_options(dhcp_data.dp_options, |
ua1arn | 1:119c4f7144c8 | 243 | DHCP_OFFER, |
ua1arn | 1:119c4f7144c8 | 244 | config->domain, |
ua1arn | 1:119c4f7144c8 | 245 | *(uint32_t *)config->dns, |
ua1arn | 1:119c4f7144c8 | 246 | entry->lease, |
ua1arn | 1:119c4f7144c8 | 247 | *(uint32_t *)config->addr, |
ua1arn | 1:119c4f7144c8 | 248 | 0, |
ua1arn | 1:119c4f7144c8 | 249 | *(uint32_t *)entry->subnet); |
ua1arn | 1:119c4f7144c8 | 250 | |
ua1arn | 1:119c4f7144c8 | 251 | pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); |
ua1arn | 1:119c4f7144c8 | 252 | if (pp == NULL) break; |
ua1arn | 1:119c4f7144c8 | 253 | memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); |
ua1arn | 1:119c4f7144c8 | 254 | udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); |
ua1arn | 1:119c4f7144c8 | 255 | pbuf_free(pp); |
ua1arn | 1:119c4f7144c8 | 256 | break; |
ua1arn | 1:119c4f7144c8 | 257 | |
ua1arn | 1:119c4f7144c8 | 258 | case DHCP_REQUEST: |
ua1arn | 1:119c4f7144c8 | 259 | /* 1. find requested ipaddr in option list */ |
ua1arn | 1:119c4f7144c8 | 260 | ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); |
ua1arn | 1:119c4f7144c8 | 261 | if (ptr == NULL) break; |
ua1arn | 1:119c4f7144c8 | 262 | if (ptr[1] != 4) break; |
ua1arn | 1:119c4f7144c8 | 263 | ptr += 2; |
ua1arn | 1:119c4f7144c8 | 264 | |
ua1arn | 1:119c4f7144c8 | 265 | /* 2. does hw-address registered? */ |
ua1arn | 1:119c4f7144c8 | 266 | entry = entry_by_mac(dhcp_data.dp_chaddr); |
ua1arn | 1:119c4f7144c8 | 267 | if (entry != NULL) free_entry(entry); |
ua1arn | 1:119c4f7144c8 | 268 | |
ua1arn | 1:119c4f7144c8 | 269 | /* 3. find requested ipaddr */ |
ua1arn | 1:119c4f7144c8 | 270 | entry = entry_by_ip(*(uint32_t *)ptr); |
ua1arn | 1:119c4f7144c8 | 271 | if (entry == NULL) break; |
ua1arn | 1:119c4f7144c8 | 272 | if (!is_vacant(entry)) break; |
ua1arn | 1:119c4f7144c8 | 273 | |
ua1arn | 1:119c4f7144c8 | 274 | /* 4. fill struct fields */ |
ua1arn | 1:119c4f7144c8 | 275 | memcpy(dhcp_data.dp_yiaddr, ptr, 4); |
ua1arn | 1:119c4f7144c8 | 276 | dhcp_data.dp_op = 2; /* reply */ |
ua1arn | 1:119c4f7144c8 | 277 | dhcp_data.dp_secs = 0; |
ua1arn | 1:119c4f7144c8 | 278 | dhcp_data.dp_flags = 0; |
ua1arn | 1:119c4f7144c8 | 279 | memcpy(dhcp_data.dp_magic, magic_cookie, 4); |
ua1arn | 1:119c4f7144c8 | 280 | |
ua1arn | 1:119c4f7144c8 | 281 | /* 5. fill options */ |
ua1arn | 1:119c4f7144c8 | 282 | memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); |
ua1arn | 1:119c4f7144c8 | 283 | |
ua1arn | 1:119c4f7144c8 | 284 | fill_options(dhcp_data.dp_options, |
ua1arn | 1:119c4f7144c8 | 285 | DHCP_ACK, |
ua1arn | 1:119c4f7144c8 | 286 | config->domain, |
ua1arn | 1:119c4f7144c8 | 287 | *(uint32_t *)config->dns, |
ua1arn | 1:119c4f7144c8 | 288 | entry->lease, |
ua1arn | 1:119c4f7144c8 | 289 | *(uint32_t *)config->addr, |
ua1arn | 1:119c4f7144c8 | 290 | 0, |
ua1arn | 1:119c4f7144c8 | 291 | *(uint32_t *)entry->subnet); |
ua1arn | 1:119c4f7144c8 | 292 | |
ua1arn | 1:119c4f7144c8 | 293 | /* 6. send ACK */ |
ua1arn | 1:119c4f7144c8 | 294 | pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); |
ua1arn | 1:119c4f7144c8 | 295 | if (pp == NULL) break; |
ua1arn | 1:119c4f7144c8 | 296 | memcpy(entry->mac, dhcp_data.dp_chaddr, 6); |
ua1arn | 1:119c4f7144c8 | 297 | memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); |
ua1arn | 1:119c4f7144c8 | 298 | udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); |
ua1arn | 1:119c4f7144c8 | 299 | pbuf_free(pp); |
ua1arn | 1:119c4f7144c8 | 300 | break; |
ua1arn | 1:119c4f7144c8 | 301 | |
ua1arn | 1:119c4f7144c8 | 302 | default: |
ua1arn | 1:119c4f7144c8 | 303 | break; |
ua1arn | 1:119c4f7144c8 | 304 | } |
ua1arn | 1:119c4f7144c8 | 305 | pbuf_free(p); |
ua1arn | 1:119c4f7144c8 | 306 | } |
ua1arn | 1:119c4f7144c8 | 307 | |
ua1arn | 1:119c4f7144c8 | 308 | err_t dhserv_init(dhcp_config_t *c) |
ua1arn | 1:119c4f7144c8 | 309 | { |
ua1arn | 1:119c4f7144c8 | 310 | err_t err; |
ua1arn | 1:119c4f7144c8 | 311 | udp_init(); |
ua1arn | 1:119c4f7144c8 | 312 | dhserv_free(); |
ua1arn | 1:119c4f7144c8 | 313 | pcb = udp_new(); |
ua1arn | 1:119c4f7144c8 | 314 | if (pcb == NULL) |
ua1arn | 1:119c4f7144c8 | 315 | return ERR_MEM; |
ua1arn | 1:119c4f7144c8 | 316 | err = udp_bind(pcb, IP_ADDR_ANY, c->port); |
ua1arn | 1:119c4f7144c8 | 317 | if (err != ERR_OK) |
ua1arn | 1:119c4f7144c8 | 318 | { |
ua1arn | 1:119c4f7144c8 | 319 | dhserv_free(); |
ua1arn | 1:119c4f7144c8 | 320 | return err; |
ua1arn | 1:119c4f7144c8 | 321 | } |
ua1arn | 1:119c4f7144c8 | 322 | udp_recv(pcb, udp_recv_proc, NULL); |
ua1arn | 1:119c4f7144c8 | 323 | config = c; |
ua1arn | 1:119c4f7144c8 | 324 | return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 325 | } |
ua1arn | 1:119c4f7144c8 | 326 | |
ua1arn | 1:119c4f7144c8 | 327 | void dhserv_free(void) |
ua1arn | 1:119c4f7144c8 | 328 | { |
ua1arn | 1:119c4f7144c8 | 329 | if (pcb == NULL) return; |
ua1arn | 1:119c4f7144c8 | 330 | udp_remove(pcb); |
ua1arn | 1:119c4f7144c8 | 331 | pcb = NULL; |
ua1arn | 1:119c4f7144c8 | 332 | } |