lwip-1.4.1 (partial)

Dependents:   IGLOO_board

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?

UserRevisionLine numberNew 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 /*
ua1arn 1:119c4f7144c8 26 * version: 1.0 demo (7.02.2015)
ua1arn 1:119c4f7144c8 27 * brief: tiny dns ipv4 server using lwip (pcb)
ua1arn 1:119c4f7144c8 28 */
ua1arn 1:119c4f7144c8 29
ua1arn 1:119c4f7144c8 30 #include "dnserver.h"
ua1arn 1:119c4f7144c8 31
ua1arn 1:119c4f7144c8 32 #define DNS_MAX_HOST_NAME_LEN 128
ua1arn 1:119c4f7144c8 33
ua1arn 1:119c4f7144c8 34 static struct udp_pcb *pcb = NULL;
ua1arn 1:119c4f7144c8 35 dns_query_proc_t query_proc = NULL;
ua1arn 1:119c4f7144c8 36
ua1arn 1:119c4f7144c8 37 #pragma pack(push, 1)
ua1arn 1:119c4f7144c8 38 typedef struct
ua1arn 1:119c4f7144c8 39 {
ua1arn 1:119c4f7144c8 40 #if BYTE_ORDER == LITTLE_ENDIAN
ua1arn 1:119c4f7144c8 41 uint8_t rd: 1, /* Recursion Desired */
ua1arn 1:119c4f7144c8 42 tc: 1, /* Truncation Flag */
ua1arn 1:119c4f7144c8 43 aa: 1, /* Authoritative Answer Flag */
ua1arn 1:119c4f7144c8 44 opcode: 4, /* Operation code */
ua1arn 1:119c4f7144c8 45 qr: 1; /* Query/Response Flag */
ua1arn 1:119c4f7144c8 46 uint8_t rcode: 4, /* Response Code */
ua1arn 1:119c4f7144c8 47 z: 3, /* Zero */
ua1arn 1:119c4f7144c8 48 ra: 1; /* Recursion Available */
ua1arn 1:119c4f7144c8 49 #else
ua1arn 1:119c4f7144c8 50 uint8_t qr: 1, /* Query/Response Flag */
ua1arn 1:119c4f7144c8 51 opcode: 4, /* Operation code */
ua1arn 1:119c4f7144c8 52 aa: 1, /* Authoritative Answer Flag */
ua1arn 1:119c4f7144c8 53 tc: 1, /* Truncation Flag */
ua1arn 1:119c4f7144c8 54 rd: 1; /* Recursion Desired */
ua1arn 1:119c4f7144c8 55 uint8_t ra: 1, /* Recursion Available */
ua1arn 1:119c4f7144c8 56 z: 3, /* Zero */
ua1arn 1:119c4f7144c8 57 rcode: 4; /* Response Code */
ua1arn 1:119c4f7144c8 58 #endif
ua1arn 1:119c4f7144c8 59 } dns_header_flags_t;
ua1arn 1:119c4f7144c8 60
ua1arn 1:119c4f7144c8 61 typedef struct
ua1arn 1:119c4f7144c8 62 {
ua1arn 1:119c4f7144c8 63 uint16_t id;
ua1arn 1:119c4f7144c8 64 dns_header_flags_t flags;
ua1arn 1:119c4f7144c8 65 uint16_t n_record[4];
ua1arn 1:119c4f7144c8 66 } dns_header_t;
ua1arn 1:119c4f7144c8 67
ua1arn 1:119c4f7144c8 68 typedef struct dns_answer
ua1arn 1:119c4f7144c8 69 {
ua1arn 1:119c4f7144c8 70 uint16_t name;
ua1arn 1:119c4f7144c8 71 uint16_t type;
ua1arn 1:119c4f7144c8 72 uint16_t Class;
ua1arn 1:119c4f7144c8 73 uint32_t ttl;
ua1arn 1:119c4f7144c8 74 uint16_t len;
ua1arn 1:119c4f7144c8 75 uint32_t addr;
ua1arn 1:119c4f7144c8 76 } dns_answer_t;
ua1arn 1:119c4f7144c8 77 #pragma pack(pop)
ua1arn 1:119c4f7144c8 78
ua1arn 1:119c4f7144c8 79 typedef struct dns_query
ua1arn 1:119c4f7144c8 80 {
ua1arn 1:119c4f7144c8 81 char name[DNS_MAX_HOST_NAME_LEN];
ua1arn 1:119c4f7144c8 82 uint16_t type;
ua1arn 1:119c4f7144c8 83 uint16_t Class;
ua1arn 1:119c4f7144c8 84 } dns_query_t;
ua1arn 1:119c4f7144c8 85
ua1arn 1:119c4f7144c8 86 static int parse_next_query(void *data, int size, dns_query_t *query)
ua1arn 1:119c4f7144c8 87 {
ua1arn 1:119c4f7144c8 88 int len;
ua1arn 1:119c4f7144c8 89 int lables;
ua1arn 1:119c4f7144c8 90 uint8_t *ptr;
ua1arn 1:119c4f7144c8 91
ua1arn 1:119c4f7144c8 92 len = 0;
ua1arn 1:119c4f7144c8 93 lables = 0;
ua1arn 1:119c4f7144c8 94 ptr = (uint8_t *)data;
ua1arn 1:119c4f7144c8 95
ua1arn 1:119c4f7144c8 96 while (true)
ua1arn 1:119c4f7144c8 97 {
ua1arn 1:119c4f7144c8 98 uint8_t lable_len;
ua1arn 1:119c4f7144c8 99 if (size <= 0) return -1;
ua1arn 1:119c4f7144c8 100 lable_len = *ptr++;
ua1arn 1:119c4f7144c8 101 size--;
ua1arn 1:119c4f7144c8 102 if (lable_len == 0) break;
ua1arn 1:119c4f7144c8 103 if (lables > 0)
ua1arn 1:119c4f7144c8 104 {
ua1arn 1:119c4f7144c8 105 if (len == DNS_MAX_HOST_NAME_LEN) return -2;
ua1arn 1:119c4f7144c8 106 query->name[len++] = '.';
ua1arn 1:119c4f7144c8 107 }
ua1arn 1:119c4f7144c8 108 if (lable_len > size) return -1;
ua1arn 1:119c4f7144c8 109 if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2;
ua1arn 1:119c4f7144c8 110 memcpy(&query->name[len], ptr, lable_len);
ua1arn 1:119c4f7144c8 111 len += lable_len;
ua1arn 1:119c4f7144c8 112 ptr += lable_len;
ua1arn 1:119c4f7144c8 113 size -= lable_len;
ua1arn 1:119c4f7144c8 114 lables++;
ua1arn 1:119c4f7144c8 115 }
ua1arn 1:119c4f7144c8 116
ua1arn 1:119c4f7144c8 117 if (size < 4) return -1;
ua1arn 1:119c4f7144c8 118 query->name[len] = 0;
ua1arn 1:119c4f7144c8 119 query->type = *(uint16_t *)ptr;
ua1arn 1:119c4f7144c8 120 ptr += 2;
ua1arn 1:119c4f7144c8 121 query->Class = *(uint16_t *)ptr;
ua1arn 1:119c4f7144c8 122 ptr += 2;
ua1arn 1:119c4f7144c8 123 return ptr - (uint8_t *)data;
ua1arn 1:119c4f7144c8 124 }
ua1arn 1:119c4f7144c8 125
ua1arn 1:119c4f7144c8 126 static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
ua1arn 1:119c4f7144c8 127 {
ua1arn 1:119c4f7144c8 128 int len;
ua1arn 1:119c4f7144c8 129 dns_header_t *header;
ua1arn 1:119c4f7144c8 130 static dns_query_t query;
ua1arn 1:119c4f7144c8 131 struct pbuf *out;
ua1arn 1:119c4f7144c8 132 ip_addr_t host_addr;
ua1arn 1:119c4f7144c8 133 dns_answer_t *answer;
ua1arn 1:119c4f7144c8 134
ua1arn 1:119c4f7144c8 135 if (p->len <= sizeof(dns_header_t)) goto error;
ua1arn 1:119c4f7144c8 136 header = (dns_header_t *)p->payload;
ua1arn 1:119c4f7144c8 137 if (header->flags.qr != 0) goto error;
ua1arn 1:119c4f7144c8 138 if (ntohs(header->n_record[0]) != 1) goto error;
ua1arn 1:119c4f7144c8 139
ua1arn 1:119c4f7144c8 140 len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query);
ua1arn 1:119c4f7144c8 141 if (len < 0) goto error;
ua1arn 1:119c4f7144c8 142 if (!query_proc(query.name, &host_addr)) goto refuse;
ua1arn 1:119c4f7144c8 143
ua1arn 1:119c4f7144c8 144 len += sizeof(dns_header_t);
ua1arn 1:119c4f7144c8 145 out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL);
ua1arn 1:119c4f7144c8 146 if (out == NULL) goto error;
ua1arn 1:119c4f7144c8 147
ua1arn 1:119c4f7144c8 148 memcpy(out->payload, p->payload, len);
ua1arn 1:119c4f7144c8 149 header = (dns_header_t *)out->payload;
ua1arn 1:119c4f7144c8 150 header->flags.qr = 1;
ua1arn 1:119c4f7144c8 151 header->n_record[1] = htons(1);
ua1arn 1:119c4f7144c8 152 answer = (struct dns_answer *)((uint8_t *)out->payload + len);
ua1arn 1:119c4f7144c8 153 answer->name = htons(0xC00C);
ua1arn 1:119c4f7144c8 154 answer->type = htons(1);
ua1arn 1:119c4f7144c8 155 answer->Class = htons(1);
ua1arn 1:119c4f7144c8 156 answer->ttl = htonl(32);
ua1arn 1:119c4f7144c8 157 answer->len = htons(4);
ua1arn 1:119c4f7144c8 158 answer->addr = host_addr.addr;
ua1arn 1:119c4f7144c8 159
ua1arn 1:119c4f7144c8 160 udp_sendto(upcb, out, addr, port);
ua1arn 1:119c4f7144c8 161 pbuf_free(out);
ua1arn 1:119c4f7144c8 162 pbuf_free(p);
ua1arn 1:119c4f7144c8 163 return;
ua1arn 1:119c4f7144c8 164
ua1arn 1:119c4f7144c8 165 refuse:
ua1arn 1:119c4f7144c8 166 header->flags.qr = 1;
ua1arn 1:119c4f7144c8 167 header->flags.rcode = 5;
ua1arn 1:119c4f7144c8 168 udp_sendto(upcb, p, addr, port);
ua1arn 1:119c4f7144c8 169 pbuf_free(p);
ua1arn 1:119c4f7144c8 170 return;
ua1arn 1:119c4f7144c8 171
ua1arn 1:119c4f7144c8 172 error:
ua1arn 1:119c4f7144c8 173 pbuf_free(p);
ua1arn 1:119c4f7144c8 174 }
ua1arn 1:119c4f7144c8 175
ua1arn 1:119c4f7144c8 176 err_t dnserv_init(ip_addr_t *bind, uint16_t port, dns_query_proc_t qp)
ua1arn 1:119c4f7144c8 177 {
ua1arn 1:119c4f7144c8 178 err_t err;
ua1arn 1:119c4f7144c8 179 udp_init();
ua1arn 1:119c4f7144c8 180 dnserv_free();
ua1arn 1:119c4f7144c8 181 pcb = udp_new();
ua1arn 1:119c4f7144c8 182 if (pcb == NULL)
ua1arn 1:119c4f7144c8 183 return ERR_MEM;
ua1arn 1:119c4f7144c8 184 err = udp_bind(pcb, bind, port);
ua1arn 1:119c4f7144c8 185 if (err != ERR_OK)
ua1arn 1:119c4f7144c8 186 {
ua1arn 1:119c4f7144c8 187 dnserv_free();
ua1arn 1:119c4f7144c8 188 return err;
ua1arn 1:119c4f7144c8 189 }
ua1arn 1:119c4f7144c8 190 udp_recv(pcb, udp_recv_proc, NULL);
ua1arn 1:119c4f7144c8 191 query_proc = qp;
ua1arn 1:119c4f7144c8 192 return ERR_OK;
ua1arn 1:119c4f7144c8 193 }
ua1arn 1:119c4f7144c8 194
ua1arn 1:119c4f7144c8 195 void dnserv_free()
ua1arn 1:119c4f7144c8 196 {
ua1arn 1:119c4f7144c8 197 if (pcb == NULL) return;
ua1arn 1:119c4f7144c8 198 udp_remove(pcb);
ua1arn 1:119c4f7144c8 199 pcb = NULL;
ua1arn 1:119c4f7144c8 200 }