]> git.karo-electronics.de Git - mdnsd.git/blob - mquery.c
Add futher files to .gitignore
[mdnsd.git] / mquery.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <arpa/inet.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12
13 #include "mdnsd.h"
14 #include "shash.h"
15 #include "rfc1035.h"
16 #include "dns_sd_txt.h"
17
18 void txt_printer (SHASH UNUSED(hash), const char *key, void *val, void *UNUSED(arg))
19 {
20     printf ("   %s=%s\n", key, (char *) val);
21 }
22
23
24 // print an answer
25 int ans(TMdnsdAnswer *answer, void *UNUSED(arg))
26 {
27     int now;
28     SHASH hash;
29     struct in_addr ip_addr;
30     if(answer->ttl == 0) now = 0;
31     else now = answer->ttl - time(0);
32     switch(answer->type)
33     {
34         case QTYPE_A:
35             ip_addr = answer->ip;
36             printf("A %s for %d seconds to ip %s\n",answer->name,now,inet_ntoa(ip_addr));
37             break;
38         case QTYPE_PTR:
39             printf("PTR %s for %d seconds to %s\n",answer->name,now,answer->rdname);
40             break;
41         case QTYPE_SRV:
42             printf("SRV %s for %d seconds to %s:%d\n",answer->name,now,answer->rdname,answer->srv.port);
43             break;
44         case QTYPE_TXT:
45             printf("TXT %s for %d seconds:\n",answer->name,now);
46             hash = DnsTxt2Sd (answer->rdata, answer->rdlen);
47             SHashForEach(hash, txt_printer, NULL);
48             SHashFree (hash);
49             break;
50         default:
51             printf("%d %s for %d seconds with %d data\n",answer->type,answer->name,now,answer->rdlen);
52     }
53
54     return 0;
55 }
56
57 // create multicast 224.0.0.251:5353 socket
58 int msock()
59 {
60     int s, flag = 1, ittl = 255;
61     struct sockaddr_in in;
62     struct ip_mreq mc;
63     char ttl = 255;
64
65     bzero(&in, sizeof(in));
66     in.sin_family = AF_INET;
67     in.sin_port = htons(MDNS_PORT);
68     in.sin_addr.s_addr = 0;
69
70     if((s = socket(AF_INET,SOCK_DGRAM,0)) < 0) return 0;
71 #ifdef SO_REUSEPORT
72     setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&flag, sizeof(flag));
73 #endif
74     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag));
75     if(bind(s,(struct sockaddr*)&in,sizeof(in))) { close(s); return 0; }
76
77     mc.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
78     mc.imr_interface.s_addr = htonl(INADDR_ANY);
79     setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc));
80     setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
81     setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ittl, sizeof(ittl));
82
83     flag =  fcntl(s, F_GETFL, 0);
84     flag |= O_NONBLOCK;
85     fcntl(s, F_SETFL, flag);
86
87     return s;
88 }
89
90 int main(int argc, char *argv[])
91 {
92     TMdnsd *d;
93     DNSMESSAGE m;
94     struct in_addr ip;
95     uint16_t port;
96     struct timeval *tv;
97     int bsize, ssize = sizeof(struct sockaddr_in);
98     uint8_t buf[MAX_PACKET_LEN];
99     struct sockaddr_in from, to;
100     fd_set fds;
101     int s;
102
103     if(argc != 3) { printf("usage: mquery 12 _http._tcp.local.\n"); return -1; }
104
105     d = MdnsdNew(1, 1000);
106     if((s = msock()) == 0) { printf("can't create socket: %s\n",strerror(errno)); return 1; }
107
108     MdnsdQuery(d,argv[2],atoi(argv[1]),ans,0);
109
110     while(1)
111     {
112         tv = MdnsdGetMaxSleepTime(d);
113         FD_ZERO(&fds);
114         FD_SET(s,&fds);
115         select(s+1,&fds,0,0,tv);
116
117         if(FD_ISSET(s,&fds))
118         {
119             while((bsize = recvfrom(s,buf,MAX_PACKET_LEN,0,(struct sockaddr*)&from,&ssize)) > 0)
120             {
121                 bzero(&m,sizeof(DNSMESSAGE));
122                 DnsParseMsg(&m,buf);
123                 MdnsdInput(d, &m, from.sin_addr, from.sin_port);
124             }
125             if(bsize < 0 && errno != EAGAIN) { printf("can't read from socket %d: %s\n",errno,strerror(errno)); return 1; }
126         }
127
128         while(MdnsdOutput(d,&m,&ip,&port))
129         {
130             bzero(&to, sizeof(to));
131             to.sin_family = AF_INET;
132             to.sin_port = port;
133             to.sin_addr = ip;
134             if(sendto(s,DnsMsg2Pkt(&m),DnsMsgLen(&m),0,(struct sockaddr *)&to,sizeof(struct sockaddr_in)) != DnsMsgLen(&m))  { printf("can't write to socket: %s\n",strerror(errno)); return 1; }
135         }
136     }
137
138     MdnsdShutdown(d);
139     MdnsdFree(d);
140     return 0;
141 }
142