1#include <stdlib.h> 2#include <avahi-common/malloc.h> 3#include <avahi-core/log.h> 4 5#include "llmnr-response.h" 6 7AvahiLLMNRResponseScheduler *avahi_llmnr_response_scheduler_new(AvahiInterface *i) { 8 AvahiLLMNRResponseScheduler *s; 9 10 assert(i); 11 12 if (!(s = avahi_new(AvahiLLMNRResponseScheduler, 1))) 13 return NULL; 14 15 s->interface = i; 16 s->time_event_queue = i->monitor->server->time_event_queue; 17 18 AVAHI_LLIST_HEAD_INIT(AvahiLLMNRResponseJob, s->jobs); 19 20 return s; 21} 22 23static AvahiLLMNRResponseJob *job_new( 24 AvahiLLMNRResponseScheduler *s, 25 AvahiDnsPacket *p, 26 const AvahiAddress *a, 27 uint16_t port) { 28 AvahiLLMNRResponseJob *rj; 29 30 assert(a->proto == s->interface->protocol); 31 32 if (!(rj = avahi_new(AvahiLLMNRResponseJob, 1))) 33 return NULL; 34 35 rj->s = s; 36 rj->reply = p; 37 rj->address = *a; 38 rj->port = port; 39 rj->time_event = NULL; 40 41 AVAHI_LLIST_PREPEND(AvahiLLMNRResponseJob, jobs, s->jobs , rj); 42 43 return rj; 44} 45 46void avahi_llmnr_response_job_free(AvahiLLMNRResponseScheduler *s, AvahiLLMNRResponseJob *rj) { 47 assert(s); 48 assert(rj); 49 50 if (rj->time_event) 51 avahi_time_event_free(rj->time_event); 52 53 if (rj->reply) 54 avahi_dns_packet_free(rj->reply); 55 56 AVAHI_LLIST_REMOVE(AvahiLLMNRResponseJob, jobs, s->jobs, rj); 57 58 avahi_free(rj); 59} 60 61 62void avahi_llmnr_response_scheduler_clear(AvahiLLMNRResponseScheduler *s) { 63 assert(s); 64 65 while (s->jobs) 66 avahi_llmnr_response_job_free(s, s->jobs); 67} 68 69void avahi_llmnr_response_scheduler_free(AvahiLLMNRResponseScheduler *s) { 70 assert(s); 71 72 avahi_llmnr_response_scheduler_clear(s); 73 avahi_free(s); 74} 75 76static void elapse_response_callback(AVAHI_GCC_UNUSED AvahiTimeEvent *e, void *userdata) { 77 AvahiLLMNRResponseJob *rj = userdata; 78 79 assert(rj); 80 81 /* Send Packet */ 82 avahi_interface_send_packet_unicast(rj->s->interface, rj->reply, &rj->address, rj->port, AVAHI_LLMNR); 83 avahi_llmnr_response_job_free(rj->s, rj); 84} 85 86int avahi_post_llmnr_response(AvahiLLMNRResponseScheduler *s, AvahiDnsPacket *p, const AvahiAddress *a, uint16_t port) { 87 AvahiLLMNRResponseJob *rj; 88 struct timeval tv; 89 90 assert(s); 91 assert(p); 92 assert(a); 93 assert(port); 94 95 assert(a->proto == s->interface->protocol); 96 97 if (!s->interface->llmnr.verifying) 98 return 0; 99 100 if (!(rj = job_new(s, p, a, port))) 101 return 0; 102 103 avahi_elapse_time(&tv, 0, AVAHI_LLMNR_JITTER); 104 rj->time_event = avahi_time_event_new(s->time_event_queue, &tv, elapse_response_callback, rj); 105 106 return 1; 107} 108 109 110