Support responding to unicast queries: initially just legacy queries and multicast responses.
This commit is contained in:
parent
2ce1bb8ae4
commit
0aa116dbce
115
mdnsd.c
115
mdnsd.c
@ -554,6 +554,32 @@ static int create_recv_sock(int domain)
|
||||
return sd;
|
||||
}
|
||||
|
||||
static ssize_t send_packet_to(int fd, const void *data, size_t len, struct sockaddr_in *toaddr) {
|
||||
|
||||
return sendto(fd, data, len, 0, (struct sockaddr *) toaddr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
// populate the specified list which matches the RR name and type
|
||||
static int populate_query(struct mdnsd *svr, struct rr_list **rr_head)
|
||||
{
|
||||
int num_qns = 0;
|
||||
|
||||
// check if we have the records
|
||||
pthread_mutex_lock(&svr->data_lock);
|
||||
|
||||
while (svr->query) {
|
||||
struct rr_entry *qn_e = rr_list_remove(&svr->query, svr->query->e);
|
||||
if (qn_e == NULL) {
|
||||
break;
|
||||
}
|
||||
num_qns += rr_list_append(rr_head, qn_e);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&svr->data_lock);
|
||||
|
||||
return num_qns;
|
||||
}
|
||||
|
||||
static ssize_t send_packet(int fd, const void *data, size_t len, int domain) {
|
||||
static struct sockaddr_in toaddr;
|
||||
char *addr;
|
||||
@ -578,28 +604,7 @@ static ssize_t send_packet(int fd, const void *data, size_t len, int domain) {
|
||||
toaddr.sin_port = htons(port);
|
||||
toaddr.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
return sendto(fd, data, len, 0, (struct sockaddr *) &toaddr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
// populate the specified list which matches the RR name and type
|
||||
static int populate_query(struct mdnsd *svr, struct rr_list **rr_head)
|
||||
{
|
||||
int num_qns = 0;
|
||||
|
||||
// check if we have the records
|
||||
pthread_mutex_lock(&svr->data_lock);
|
||||
|
||||
while (svr->query) {
|
||||
struct rr_entry *qn_e = rr_list_remove(&svr->query, svr->query->e);
|
||||
if (qn_e == NULL) {
|
||||
break;
|
||||
}
|
||||
num_qns += rr_list_append(rr_head, qn_e);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&svr->data_lock);
|
||||
|
||||
return num_qns;
|
||||
return send_packet_to( fd, data, len, &toaddr);
|
||||
}
|
||||
|
||||
#ifndef MDNS_NO_RESPONDER_SUPPORT
|
||||
@ -902,7 +907,7 @@ out_with_mutex:
|
||||
|
||||
// processes the incoming MDNS packet
|
||||
// returns >0 if processed, 0 otherwise
|
||||
static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns_pkt *reply) {
|
||||
static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct sockaddr_in *fromtoaddr, struct mdns_pkt *reply) {
|
||||
int result;
|
||||
|
||||
assert(pkt != NULL);
|
||||
@ -919,6 +924,15 @@ static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns
|
||||
pkt->num_ans_rr,
|
||||
pkt->num_add_rr);
|
||||
|
||||
int unicast = 0; /* 0, 1, 2, 4 = no, direct unicast, legacy, unicast-response */
|
||||
if (fromtoaddr->sin_port != htons(MDNS_PORT)) {
|
||||
/* legacy query */
|
||||
unicast |= 2;
|
||||
} else if (fromtoaddr->sin_addr.s_addr != inet_addr(MDNS_ADDR)) {
|
||||
/* direct unicast - send back to same addr:port */
|
||||
unicast |= 1;
|
||||
}
|
||||
|
||||
// loop through questions
|
||||
struct rr_list *qnl = pkt->rr_qn;
|
||||
for (int i = 0; i < pkt->num_qn; i++, qnl = qnl->next) {
|
||||
@ -929,10 +943,10 @@ static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns
|
||||
DEBUG_PRINTF("qn #%d: type %s (%02x) %s - ", i, rr_get_type_name(qn->type), qn->type, namestr);
|
||||
MDNS_FREE(namestr);
|
||||
|
||||
// check if it's a unicast query - we ignore those
|
||||
// check if it's a unicast query - we don't treat those differently
|
||||
if (qn->unicast_query) {
|
||||
DEBUG_PRINTF("skipping unicast query\n");
|
||||
continue;
|
||||
DEBUG_PRINTF("treating unicast query as multicast\n");
|
||||
unicast |= 4;
|
||||
}
|
||||
|
||||
num_ans_added = populate_answers(svr, &reply->rr_ans, qn->name, qn->type);
|
||||
@ -943,7 +957,7 @@ static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns
|
||||
|
||||
// remove our replies if they were already in their answers
|
||||
struct rr_list *prev_ans = NULL;
|
||||
for (struct rr_list *ans = reply->rr_ans; ans; ) {
|
||||
for (struct rr_list *ans = reply->rr_ans; ans;) {
|
||||
struct rr_list *next_ans = ans->next;
|
||||
struct rr_entry *known_ans = rr_entry_match(pkt->rr_ans, ans->e);
|
||||
|
||||
@ -965,12 +979,11 @@ static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns
|
||||
// adjust answer count
|
||||
reply->num_ans_rr--;
|
||||
}
|
||||
|
||||
|
||||
prev_ans = ans;
|
||||
ans = next_ans;
|
||||
}
|
||||
|
||||
|
||||
// see if we can match additional records for answers
|
||||
add_related_rr(svr, reply->rr_ans, reply);
|
||||
|
||||
@ -979,6 +992,29 @@ static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns
|
||||
|
||||
DEBUG_PRINTF("\n");
|
||||
|
||||
/* specific processing for unicast, ... or not */
|
||||
if (unicast & 2) {
|
||||
/* legacy: (rfc6762#section-5.4) send back to same addr:port, no cache flush, TTL -> 10s */
|
||||
struct rr_list *rr_grps[] = { reply->rr_ans, reply->rr_add, NULL };
|
||||
for (struct rr_list **rrl = rr_grps; *rrl; ++rrl) {
|
||||
for (struct rr_list *ans = *rrl; ans; ans = ans->next) {
|
||||
ans->e->cache_flush = 0;
|
||||
ans->e->ttl = DEFAULT_TTL_LEGACY;
|
||||
}
|
||||
}
|
||||
} else if (unicast & 1) {
|
||||
/* direct: (rfc6762#section-5.5) should be sending answers to same addr:5353 if on LAN, then multicast */
|
||||
/* let's pretend the first reply got lost ... */
|
||||
fromtoaddr->sin_port = 0;
|
||||
} else if (unicast & 4) {
|
||||
/* unicast-response: (rfc6762#section-5.4) should be sending answers to QUs to same addr:5353 if on LAN, then multicast */
|
||||
/* let's pretend the first reply got lost ... */
|
||||
fromtoaddr->sin_port = 0;
|
||||
} else {
|
||||
/* send usual multicast response */
|
||||
fromtoaddr->sin_port = 0;
|
||||
}
|
||||
|
||||
return reply->num_ans_rr;
|
||||
} else {
|
||||
result = 0;
|
||||
@ -1162,6 +1198,9 @@ static void main_loop(struct mdnsd *svr) {
|
||||
max_fd = svr->notify_pipe[0];
|
||||
|
||||
while (1) {
|
||||
struct sockaddr_in fromaddr;
|
||||
socklen_t sockaddr_size = sizeof(struct sockaddr_in);
|
||||
|
||||
svr->sendmsg_requested = 0;
|
||||
|
||||
FD_ZERO(&sockfd_set);
|
||||
@ -1176,9 +1215,6 @@ static void main_loop(struct mdnsd *svr) {
|
||||
if (read_pipe(svr->notify_pipe[0], (char *)¬ify_buf, 1) == -1)
|
||||
log_message(LOG_ERR, "read_pipe() failed; %s\n", strerror(errno));
|
||||
} else if (FD_ISSET(svr->sockfd, &sockfd_set)) {
|
||||
struct sockaddr_in fromaddr;
|
||||
socklen_t sockaddr_size = sizeof(struct sockaddr_in);
|
||||
|
||||
ssize_t recvsize = recvfrom(svr->sockfd, pkt_buffer, PACKET_SIZE, 0,
|
||||
(struct sockaddr *) &fromaddr, &sockaddr_size);
|
||||
if (recvsize < 0) {
|
||||
@ -1198,7 +1234,7 @@ static void main_loop(struct mdnsd *svr) {
|
||||
if (svr->sockfd != -1) {
|
||||
/* succeed to create recv socket */
|
||||
break;
|
||||
}
|
||||
}
|
||||
remaining_cnt--;
|
||||
}
|
||||
if (svr->sockfd == -1) {
|
||||
@ -1216,13 +1252,20 @@ static void main_loop(struct mdnsd *svr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("data from=%s size=%ld\n", inet_ntoa(fromaddr.sin_addr), (long) recvsize);
|
||||
DEBUG_PRINTF("data from=%s:%d size=%ld\n", inet_ntoa(fromaddr.sin_addr), (long) recvsize);
|
||||
struct mdns_pkt *mdns = mdns_parse_pkt(pkt_buffer, recvsize);
|
||||
if (mdns != NULL) {
|
||||
if (process_mdns_pkt(svr, mdns, mdns_packet)) {
|
||||
struct sockaddr_in toaddr = fromaddr;
|
||||
if (process_mdns_pkt(svr, mdns, &toaddr, mdns_packet)) {
|
||||
#ifndef MDNS_NO_RESPONDER_SUPPORT
|
||||
size_t replylen = mdns_encode_pkt(mdns_packet, pkt_buffer, PACKET_SIZE);
|
||||
if (send_packet(svr->sockfd, pkt_buffer, replylen, svr->domain) == -1)
|
||||
ssize_t ret = -1;
|
||||
if (toaddr.sin_port != 0) {
|
||||
ret = send_packet_to(svr->sockfd, pkt_buffer, replylen, &toaddr);
|
||||
} else {
|
||||
ret = send_packet(svr->sockfd, pkt_buffer, replylen, svr->domain);
|
||||
}
|
||||
if (ret == -1)
|
||||
log_message(LOG_ERR, "send_packet() failed; %s\n", strerror(errno));
|
||||
#endif
|
||||
} else if (mdns->num_qn == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user