PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/FNET/fnet_stack/services/llmnr/fnet_llmnr.c

https://gitlab.com/fuggles/ucos
C | 562 lines | 281 code | 75 blank | 206 comment | 67 complexity | f317931048e081b27b991c98be3d8c03 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /**************************************************************************
  2. *
  3. * Copyright 2014 by Andrey Butok. FNET Community.
  4. *
  5. ***************************************************************************
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License Version 3
  8. * or later (the "LGPL").
  9. *
  10. * As a special exception, the copyright holders of the FNET project give you
  11. * permission to link the FNET sources with independent modules to produce an
  12. * executable, regardless of the license terms of these independent modules,
  13. * and to copy and distribute the resulting executable under terms of your
  14. * choice, provided that you also meet, for each linked independent module,
  15. * the terms and conditions of the license of that module.
  16. * An independent module is a module which is not derived from or based
  17. * on this library.
  18. * If you modify the FNET sources, you may extend this exception
  19. * to your version of the FNET sources, but you are not obligated
  20. * to do so. If you do not wish to do so, delete this
  21. * exception statement from your version.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * and the GNU Lesser General Public License along with this program.
  29. * If not, see <http://www.gnu.org/licenses/>.
  30. *
  31. **********************************************************************/ /*!
  32. *
  33. * @file fnet_llmnr.c
  34. *
  35. * @author Andrey Butok
  36. *
  37. * @brief LLMNR Server/Responder implementation (RFC4795).
  38. *
  39. ***************************************************************************/
  40. #include "fnet.h"
  41. #if FNET_CFG_LLMNR
  42. #include "fnet_llmnr.h"
  43. #include "services/dns/fnet_dns_prv.h"
  44. #if FNET_CFG_DEBUG_LLMNR
  45. #define FNET_DEBUG_LLMNR FNET_DEBUG
  46. #else
  47. #define FNET_DEBUG_LLMNR(...)
  48. #endif
  49. /************************************************************************
  50. * Definitions
  51. *************************************************************************/
  52. /* LLMNR-server states. */
  53. typedef enum
  54. {
  55. FNET_LLMNR_STATE_DISABLED = 0, /**< @brief The LLMNR server is not
  56. * initialized or released. */
  57. FNET_LLMNR_STATE_WAITING_REQUEST, /**< @brief LLMNR server is waiting
  58. * for a request from a LLMNR client. */
  59. } fnet_llmnr_state_t;
  60. /* RFC 4795: The IPv4 link-scope multicast address a given responder listens to, and to which a
  61. * sender sends queries, is 224.0.0.252.*/
  62. #define FNET_LLMNR_IP4_LINK_LOCAL_MULTICAST_ADDR FNET_IP4_ADDR_INIT(224, 0, 0, 252)
  63. /* RFC 4795: The IPv6 link-scope multicast address a given responder listens to,
  64. * and to which a sender sends all queries, is FF02:0:0:0:0:0:1:3.*/
  65. const fnet_ip6_addr_t fnet_llmnr_ip6_link_local_multicast_addr = FNET_IP6_ADDR_INIT(0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x00, 0x03);
  66. /* Error strings.*/
  67. #define FNET_LLMNR_ERR_PARAMS "LLMNR: Wrong input parameters."
  68. #define FNET_LLMNR_ERR_SOCKET_CREATION "LLMNR: Socket creation error."
  69. #define FNET_LLMNR_ERR_SOCKET_BIND "LLMNR: Socket Error during bind."
  70. #define FNET_LLMNR_ERR_SERVICE "LLMNR: Service registration is failed."
  71. #define FNET_LLMNR_ERR_IS_INITIALIZED "LLMNR: DNS is already initialized."
  72. #define FNET_LLMNR_ERR_JOIN_MULTICAST "LLMNR: Joining to multicast group is failed."
  73. #define FNET_LLMNR_MESSAGE_SIZE (FNET_DNS_MESSAGE_SIZE) /* Messages carried by UDP are restricted to 512 bytes (not counting the IP
  74. * or UDP headers).
  75. * Longer messages (not supported) are truncated and the TC bit is set in
  76. * the header.*/
  77. /* For UDP queries and responses, the Hop Limit field in the IPv6 header
  78. * and the TTL field in the IPV4 header MAY be set to any value.
  79. * However, it is RECOMMENDED that the value 255 be used for
  80. * compatibility with early implementations of [RFC3927]. */
  81. #define FNET_LLMNR_TTL (255)
  82. /************************************************************************
  83. * [RFC 4795 2.1.1.] LLMNR Header Format
  84. *************************************************************************
  85. LLMNR queries and responses utilize the DNS header format defined in
  86. [RFC1035] with exceptions noted below:
  87. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  88. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  89. | ID |
  90. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  91. |QR| Opcode | C|TC| T| Z| Z| Z| Z| RCODE |
  92. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  93. | QDCOUNT |
  94. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  95. | ANCOUNT |
  96. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  97. | NSCOUNT |
  98. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  99. | ARCOUNT |
  100. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  101. */
  102. FNET_COMP_PACKED_BEGIN
  103. typedef struct
  104. {
  105. unsigned short id FNET_COMP_PACKED; /* A 16-bit identifier assigned by the program that generates
  106. * any kind of query. This identifier is copied from the query
  107. * to the response and can be used by the sender to match
  108. * responses to outstanding queries. The ID field in a query
  109. * SHOULD be set to a pseudo-random value. */
  110. unsigned short flags FNET_COMP_PACKED; /* Flags.*/
  111. unsigned short qdcount FNET_COMP_PACKED; /* An unsigned 16-bit integer specifying the number of entries
  112. * in the question section. A sender MUST place only one
  113. * question into the question section of an LLMNR query. LLMNR
  114. * responders MUST silently discard LLMNR queries with QDCOUNT
  115. * not equal to one. LLMNR senders MUST silently discard LLMNR
  116. * responses with QDCOUNT not equal to one.*/
  117. unsigned short ancount FNET_COMP_PACKED; /* An unsigned 16-bit integer specifying the number of resource
  118. * records in the answer section. LLMNR responders MUST
  119. * silently discard LLMNR queries with ANCOUNT not equal to
  120. * zero.*/
  121. unsigned short nscount FNET_COMP_PACKED; /* An unsigned 16-bit integer specifying the number of name
  122. * server resource records in the authority records section.
  123. * Authority record section processing is described in Section
  124. * 2.9. LLMNR responders MUST silently discard LLMNR queries
  125. * with NSCOUNT not equal to zero.*/
  126. unsigned short arcount FNET_COMP_PACKED; /* An unsigned 16-bit integer specifying the number of resource
  127. * records in the additional records section.*/
  128. } fnet_llmnr_header_t;
  129. FNET_COMP_PACKED_END
  130. /* LLMNR Header Flags.*/
  131. #define FNET_LLMNR_HEADER_FLAGS_QR (0x8000) /* Query/Response. A 1-bit field, which, if set, indicates that
  132. * the message is an LLMNR response; if clear, then the message
  133. * is an LLMNR query.*/
  134. #define FNET_LLMNR_HEADER_FLAGS_OPCODE (0x7800) /* A 4-bit field that specifies the kind of query in this
  135. * message. This value is set by the originator of a query and
  136. * copied into the response. This specification defines the
  137. * behavior of standard queries and responses (opcode value of
  138. * zero). Future specifications may define the use of other
  139. * opcodes with LLMNR. LLMNR senders and responders MUST
  140. * support standard queries (opcode value of zero). LLMNR
  141. * queries with unsupported OPCODE values MUST be silently
  142. * discarded by responders.*/
  143. #define FNET_LLMNR_HEADER_FLAGS_C (0x0400) /* Conflict. When set within a query, the 'C'onflict bit
  144. * indicates that a sender has received multiple LLMNR responses
  145. * to this query. In an LLMNR response, if the name is
  146. * considered UNIQUE, then the 'C' bit is clear; otherwise, it
  147. * is set. LLMNR senders do not retransmit queries with the 'C'
  148. * bit set. Responders MUST NOT respond to LLMNR queries with
  149. * the 'C' bit set, but may start the uniqueness verification
  150. * process, as described in Section 4.2. */
  151. #define FNET_LLMNR_HEADER_FLAGS_TC (0x0200) /* TrunCation. The 'TC' bit specifies that this message was
  152. * truncated due to length greater than that permitted on the
  153. * transmission channel. The 'TC' bit MUST NOT be set in an
  154. * LLMNR query and, if set, is ignored by an LLMNR responder.
  155. * If the 'TC' bit is set in an LLMNR response, then the sender
  156. * SHOULD resend the LLMNR query over TCP using the unicast
  157. * address of the responder as the destination address. */
  158. #define FNET_LLMNR_HEADER_FLAGS_T (0x0100) /* The 'T'entative bit is set in a response if the
  159. * responder is authoritative for the name, but has not yet
  160. * verified the uniqueness of the name. A responder MUST ignore
  161. * the 'T' bit in a query, if set. A response with the 'T' bit
  162. * set is silently discarded by the sender, except if it is a
  163. * uniqueness query, in which case, a conflict has been detected
  164. * and a responder MUST resolve the conflict as described in
  165. * Section 4.1.*/
  166. #define FNET_LLMNR_HEADER_FLAGS_RCODE (0x000F) /* Response code. This 4-bit field is set as part of LLMNR
  167. * responses. In an LLMNR query, the sender MUST set RCODE to
  168. * zero; the responder ignores the RCODE and assumes it to be
  169. * zero. The response to a multicast LLMNR query MUST have
  170. * RCODE set to zero. A sender MUST silently discard an LLMNR
  171. * response with a non-zero RCODE sent in response to a
  172. * multicast query. */
  173. static void fnet_llmnr_state_machine(void *);
  174. static int fnet_llmnr_hostname_cmp(const unsigned char *req_hostname, const unsigned char *hostname);
  175. /************************************************************************
  176. * LLMNR server interface structure
  177. *************************************************************************/
  178. struct fnet_llmnr_if
  179. {
  180. fnet_llmnr_state_t state; /* Current state.*/
  181. SOCKET socket_listen; /* Listening socket.*/
  182. fnet_poll_desc_t service_descriptor; /* Network interface descriptor. */
  183. fnet_netif_desc_t netif; /* Service descriptor. */
  184. const char *host_name; /* Link-local host name. */
  185. fnet_uint32 host_name_ttl; /* TTL value that indicates for how many seconds link-local host name
  186. * is valid for LLMNR querier, in seconds (it is optional).@n
  187. * Default value is defined by @ref FNET_CFG_LLMNR_HOSTNAME_TTL. */
  188. char message[FNET_LLMNR_MESSAGE_SIZE]; /* Message buffer.*/
  189. };
  190. /* The LLMNR Server interface */
  191. static struct fnet_llmnr_if llmnr_if_list[FNET_CFG_LLMNR_MAX];
  192. /************************************************************************
  193. * NAME: fnet_llmnr_is_host_name
  194. *
  195. * DESCRIPTION: Checks if this our host name.
  196. ************************************************************************/
  197. static int fnet_llmnr_hostname_cmp(const unsigned char *req_hostname, const unsigned char *hostname)
  198. {
  199. int req_hostname_index=0;
  200. int hostname_index=0;
  201. int i;
  202. unsigned char req_hostname_len;
  203. unsigned char hostname_c;
  204. req_hostname_len = req_hostname[req_hostname_index++];
  205. hostname_c = hostname[hostname_index];
  206. while(req_hostname_len
  207. && ((req_hostname_len & FNET_DNS_NAME_COMPRESSED_MASK) == 0) /* No compression is allowed in query.*/
  208. && hostname_c )
  209. {
  210. for (i=0; i<req_hostname_len; i++)
  211. {
  212. if (fnet_tolower(hostname[hostname_index++]) != fnet_tolower(req_hostname[req_hostname_index++]))
  213. {
  214. return FNET_FALSE;
  215. }
  216. }
  217. req_hostname_len = req_hostname[req_hostname_index++];
  218. hostname_c = hostname[hostname_index++];
  219. if(hostname_c != '.')
  220. {
  221. break;
  222. }
  223. }
  224. return (req_hostname_len == 0) && (hostname_c == 0);
  225. }
  226. /************************************************************************
  227. * NAME: fnet_llmnr_init
  228. *
  229. * DESCRIPTION: Initializes Link-Local Multicast Name Resolution (LLMNR)
  230. * server/responder service.
  231. ************************************************************************/
  232. fnet_llmnr_desc_t fnet_llmnr_init( struct fnet_llmnr_params *params )
  233. {
  234. struct fnet_llmnr_if *llmnr_if = 0;
  235. int i;
  236. struct sockaddr local_addr;
  237. int option = FNET_LLMNR_TTL;
  238. unsigned long host_name_length;
  239. /* Check input paramters. */
  240. if((params == 0) || (params->netif_desc == 0) || (params->host_name == 0)
  241. || ((host_name_length = fnet_strlen(params->host_name)) == 0) || (host_name_length >= FNET_DNS_MAME_SIZE))
  242. {
  243. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_PARAMS);
  244. goto ERROR_1;
  245. }
  246. /* Try to find free LLMNR server descriptor. */
  247. for(i=0; i < FNET_CFG_LLMNR_MAX; i++)
  248. {
  249. if(llmnr_if_list[i].state == FNET_LLMNR_STATE_DISABLED)
  250. {
  251. llmnr_if = &llmnr_if_list[i];
  252. }
  253. }
  254. if(llmnr_if == 0)
  255. {
  256. /* No free LLMNR descriptor. */
  257. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_IS_INITIALIZED);
  258. goto ERROR_1;
  259. }
  260. /* Reset interface structure. */
  261. fnet_memset_zero(llmnr_if, sizeof(struct fnet_llmnr_if));
  262. /* Set parameters.*/
  263. llmnr_if->netif = params->netif_desc;
  264. llmnr_if->host_name = params->host_name;
  265. if(params->host_name_ttl == 0)
  266. {
  267. llmnr_if->host_name_ttl = FNET_CFG_LLMNR_HOSTNAME_TTL;
  268. }
  269. else
  270. {
  271. llmnr_if->host_name_ttl = params->host_name_ttl;
  272. }
  273. /* Init local socket address.*/
  274. fnet_memset_zero(&local_addr, sizeof(local_addr));
  275. local_addr.sa_family = params->addr_family;
  276. if(local_addr.sa_family == 0)
  277. {
  278. local_addr.sa_family = AF_SUPPORTED;
  279. }
  280. local_addr.sa_port = FNET_CFG_LLMNR_PORT;
  281. /* Create listen socket */
  282. if((llmnr_if->socket_listen = socket(local_addr.sa_family, SOCK_DGRAM, 0)) == SOCKET_INVALID)
  283. {
  284. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_SOCKET_CREATION);
  285. goto ERROR_1;
  286. }
  287. /* Bind socket. */
  288. if(bind(llmnr_if->socket_listen, &local_addr, sizeof(local_addr)) == SOCKET_ERROR)
  289. {
  290. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_SOCKET_BIND);
  291. goto ERROR_2;
  292. }
  293. /* Join Multicast Group.*/
  294. #if FNET_CFG_IP4
  295. if(local_addr.sa_family & AF_INET)
  296. {
  297. struct ip_mreq mreq; /* Multicast group information.*/
  298. mreq.imr_multiaddr.s_addr = FNET_LLMNR_IP4_LINK_LOCAL_MULTICAST_ADDR;
  299. mreq.imr_interface.s_addr = fnet_netif_get_ip4_addr( params->netif_desc );
  300. /* Join multicast group. */
  301. if(setsockopt(llmnr_if->socket_listen, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR)
  302. {
  303. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_JOIN_MULTICAST);
  304. goto ERROR_2;
  305. }
  306. /*
  307. * For UDP queries and responses, the Hop Limit field in the IPv6 header
  308. * and the TTL field in the IPV4 header MAY be set to any value.
  309. * However, it is RECOMMENDED that the value 255 be used for
  310. * compatibility with early implementations of [RFC3927]. */
  311. setsockopt(llmnr_if->socket_listen, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof(option));
  312. }
  313. #endif
  314. #if FNET_CFG_IP6
  315. if(local_addr.sa_family & AF_INET6)
  316. {
  317. struct ipv6_mreq mreq6; /* Multicast group information.*/
  318. FNET_IP6_ADDR_COPY(&fnet_llmnr_ip6_link_local_multicast_addr, &mreq6.ipv6imr_multiaddr.s6_addr);
  319. mreq6.ipv6imr_interface = fnet_netif_get_scope_id(params->netif_desc);
  320. /* Join multicast group. */
  321. if(setsockopt(llmnr_if->socket_listen, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq6, sizeof(mreq6)) == SOCKET_ERROR)
  322. {
  323. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_JOIN_MULTICAST);
  324. goto ERROR_2;
  325. }
  326. /* For UDP queries and responses, the Hop Limit field in the IPv6 header
  327. * and the TTL field in the IPV4 header MAY be set to any value.
  328. * However, it is RECOMMENDED that the value 255 be used for
  329. * compatibility with early implementations of [RFC3927]. */
  330. setsockopt(llmnr_if->socket_listen, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof(option));
  331. }
  332. #endif
  333. /* Register service. */
  334. llmnr_if->service_descriptor = fnet_poll_service_register(fnet_llmnr_state_machine, (void *) llmnr_if);
  335. if(llmnr_if->service_descriptor == (fnet_poll_desc_t)FNET_ERR)
  336. {
  337. FNET_DEBUG_LLMNR(FNET_LLMNR_ERR_SERVICE);
  338. goto ERROR_2;
  339. }
  340. llmnr_if->state = FNET_LLMNR_STATE_WAITING_REQUEST;
  341. return (fnet_llmnr_desc_t)llmnr_if;
  342. ERROR_2:
  343. closesocket(llmnr_if->socket_listen);
  344. ERROR_1:
  345. return FNET_ERR;
  346. }
  347. /************************************************************************
  348. * NAME: fnet_llmnr_state_machine
  349. *
  350. * DESCRIPTION: LLMNR server state machine.
  351. ************************************************************************/
  352. static void fnet_llmnr_state_machine( void *fnet_llmnr_if_p )
  353. {
  354. struct sockaddr addr;
  355. unsigned int addr_len;
  356. int received;
  357. struct fnet_llmnr_if *llmnr_if = (struct fnet_llmnr_if *)fnet_llmnr_if_p;
  358. fnet_llmnr_header_t *llmnr_header;
  359. switch(llmnr_if->state)
  360. {
  361. /*---- WAITING_REQUEST --------------------------------------------*/
  362. case FNET_LLMNR_STATE_WAITING_REQUEST:
  363. addr_len = sizeof(addr);
  364. received = recvfrom(llmnr_if->socket_listen, llmnr_if->message, sizeof(llmnr_if->message), 0, &addr, &addr_len );
  365. if(received >= sizeof(fnet_llmnr_header_t) )
  366. {
  367. llmnr_header = (fnet_llmnr_header_t *)llmnr_if->message;
  368. if( ((llmnr_header->flags & FNET_HTONS(FNET_LLMNR_HEADER_FLAGS_QR)) == 0) /* Request.*/
  369. /* LLMNR senders and responders MUST
  370. * support standard queries (opcode value of zero). LLMNR
  371. * queries with unsupported OPCODE values MUST be silently
  372. * discarded by responders.*/
  373. && ((llmnr_header->flags & FNET_HTONS(FNET_LLMNR_HEADER_FLAGS_OPCODE)) == 0)
  374. /* LLMNR responders MUST silently discard LLMNR queries with QDCOUNT
  375. * not equal to one.*/
  376. && (llmnr_header->qdcount == FNET_HTONS(1))
  377. /* LLMNR responders MUST
  378. * silently discard LLMNR queries with ANCOUNT not equal to zero.*/
  379. && (llmnr_header->ancount == 0)
  380. /* LLMNR responders MUST silently discard LLMNR queries
  381. * with NSCOUNT not equal to zero.*/
  382. && (llmnr_header->nscount == 0)
  383. )
  384. {
  385. const char *req_hostname = &llmnr_if->message[sizeof(fnet_llmnr_header_t)];
  386. fnet_dns_q_tail_t *q_tail;
  387. unsigned long req_hostname_len = fnet_strlen(req_hostname);
  388. /* Check size */
  389. if(received >= (sizeof(fnet_llmnr_header_t) + sizeof(fnet_dns_q_tail_t) + req_hostname_len))
  390. {
  391. FNET_DEBUG_LLMNR("LLMNR: Req name = %s", req_hostname);
  392. /* Responders MUST NOT respond to LLMNR queries for names for which
  393. they are not authoritative.*/
  394. if(fnet_llmnr_hostname_cmp((const unsigned char *)req_hostname, (const unsigned char *)llmnr_if->host_name))
  395. {
  396. q_tail = (fnet_dns_q_tail_t *)(req_hostname + req_hostname_len);
  397. /* Check Question Class. */
  398. if (q_tail->qclass == FNET_HTONS(FNET_DNS_HEADER_CLASS_IN) )
  399. {
  400. fnet_dns_rr_header_t *rr_header = (fnet_dns_rr_header_t*)(q_tail+1);
  401. int send_size = (char*)rr_header - (char *)llmnr_header;
  402. /* Prepare query response.*/
  403. #if FNET_CFG_IP4
  404. if(q_tail->qtype == FNET_HTONS(FNET_DNS_TYPE_A))
  405. {
  406. FNET_DEBUG_LLMNR("LLMNR: IPv4");
  407. *((fnet_ip4_addr_t*)(&rr_header->rdata)) = fnet_netif_get_ip4_addr(llmnr_if->netif);
  408. rr_header->rdlength = fnet_htons(sizeof(fnet_ip4_addr_t));
  409. rr_header->type = FNET_HTONS(FNET_DNS_TYPE_A);
  410. send_size += sizeof(fnet_dns_rr_header_t);
  411. }else
  412. #endif
  413. #if FNET_CFG_IP6
  414. if(q_tail->qtype == FNET_HTONS(FNET_DNS_TYPE_AAAA))
  415. {
  416. fnet_netif_ip6_addr_info_t addr_info;
  417. FNET_DEBUG_LLMNR("LLMNR: IPv6");
  418. if(fnet_netif_get_ip6_addr (llmnr_if->netif, 0, &addr_info) == FNET_TRUE)
  419. {
  420. FNET_IP6_ADDR_COPY( &addr_info.address, (fnet_ip6_addr_t*)(&rr_header->rdata));
  421. rr_header->rdlength = fnet_htons(sizeof(fnet_ip6_addr_t));
  422. rr_header->type = FNET_HTONS(FNET_DNS_TYPE_AAAA);
  423. send_size += sizeof(fnet_dns_rr_header_t) - sizeof(unsigned long) + sizeof(fnet_ip6_addr_t);
  424. }
  425. else
  426. {
  427. break; /* No IPv6 address.*/
  428. }
  429. }else
  430. #endif
  431. {
  432. break; /* Not supported query type.*/
  433. }
  434. /* Init the rest of answer parameters.*/
  435. rr_header->ttl = fnet_htonl(llmnr_if->host_name_ttl);
  436. rr_header->rr_class = FNET_HTONS(FNET_DNS_HEADER_CLASS_IN);
  437. rr_header->name_ptr = fnet_htons((FNET_DNS_NAME_COMPRESSED_MASK<<8) | (FNET_DNS_NAME_COMPRESSED_INDEX_MASK & sizeof(fnet_llmnr_header_t)));
  438. /* Updtae LLMNR header response.*/
  439. llmnr_header->ancount = FNET_HTONS(1); /* One answer.*/
  440. llmnr_header->flags |= FNET_HTONS(FNET_LLMNR_HEADER_FLAGS_QR /* Query response.*/
  441. |FNET_LLMNR_HEADER_FLAGS_C); /* The name is not considered unique.*/
  442. /* A responder responds to a multicast query by sending a unicast UDP response to the sender.*/
  443. sendto(llmnr_if->socket_listen, llmnr_if->message, send_size, 0, &addr, addr_len);
  444. }
  445. }
  446. }
  447. }
  448. /* else = wrong message.*/
  449. }
  450. break;
  451. default:
  452. break;
  453. }
  454. }
  455. /************************************************************************
  456. * NAME: fnet_llmnr_release
  457. *
  458. * DESCRIPTION: eleases the Link-Local Multicast Name Resolution (LLMNR)
  459. * server/responder service.
  460. ************************************************************************/
  461. void fnet_llmnr_release(fnet_llmnr_desc_t desc)
  462. {
  463. struct fnet_llmnr_if *llmnr_if = (struct fnet_llmnr_if *)desc;
  464. if(llmnr_if && (llmnr_if->state != FNET_LLMNR_STATE_DISABLED))
  465. {
  466. closesocket(llmnr_if->socket_listen);
  467. fnet_poll_service_unregister(llmnr_if->service_descriptor); /* Delete service.*/
  468. llmnr_if->state = FNET_LLMNR_STATE_DISABLED;
  469. }
  470. }
  471. /************************************************************************
  472. * NAME: fnet_llmnr_enabled
  473. *
  474. * DESCRIPTION: This function returns FNET_TRUE if the LLMNR server
  475. * is enabled/initialised.
  476. ************************************************************************/
  477. int fnet_llmnr_enabled(fnet_llmnr_desc_t desc)
  478. {
  479. struct fnet_llmnr_if *llmnr_if = (struct fnet_llmnr_if *) desc;
  480. int result;
  481. if(llmnr_if)
  482. result = (llmnr_if->state == FNET_LLMNR_STATE_DISABLED) ? FNET_FALSE : FNET_TRUE;
  483. else
  484. result = FNET_FALSE;
  485. return result;
  486. }
  487. #endif /* FNET_CFG_LLMNR*/