]> git.karo-electronics.de Git - mdnsd.git/blob - mquery.c
Added netwatch to the Makefile
[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 "xht.h"
15 #include "sdtxt.h"
16
17 void txt_printer (xht h, const char *key, void *val, void *arg)
18 {
19   printf ("   %s=%s\n", key, (char *) val);
20 }
21
22
23 // print an answer
24 int ans(mdnsda a, void *arg)
25 {
26     int now;
27     xht h;
28     struct in_addr ip_addr;
29     if(a->ttl == 0) now = 0;
30     else now = a->ttl - time(0);
31     switch(a->type)
32     {
33     case QTYPE_A:
34         ip_addr.s_addr = a->ip;
35         printf("A %s for %d seconds to ip %s\n",a->name,now,inet_ntoa(ip_addr));
36         break;
37     case QTYPE_PTR:
38         printf("PTR %s for %d seconds to %s\n",a->name,now,a->rdname);
39         break;
40     case QTYPE_SRV:
41         printf("SRV %s for %d seconds to %s:%d\n",a->name,now,a->rdname,a->srv.port);
42         break;
43     case QTYPE_TXT:
44         printf("TXT %s for %d seconds:\n",a->name,now);
45         h = txt2sd (a->rdata, a->rdlen);
46         xht_walk (h, txt_printer, NULL);
47         xht_free (h);
48         break;
49     default:
50         printf("%d %s for %d seconds with %d data\n",a->type,a->name,now,a->rdlen);
51     }
52
53     return 0;
54 }
55
56 // create multicast 224.0.0.251:5353 socket
57 int msock()
58 {
59     int s, flag = 1, ittl = 255;
60     struct sockaddr_in in;
61     struct ip_mreq mc;
62     char ttl = 255;
63
64     bzero(&in, sizeof(in));
65     in.sin_family = AF_INET;
66     in.sin_port = htons(5353);
67     in.sin_addr.s_addr = 0;
68
69     if((s = socket(AF_INET,SOCK_DGRAM,0)) < 0) return 0;
70 #ifdef SO_REUSEPORT
71     setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&flag, sizeof(flag));
72 #endif
73     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag));
74     if(bind(s,(struct sockaddr*)&in,sizeof(in))) { close(s); return 0; }
75
76     mc.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
77     mc.imr_interface.s_addr = htonl(INADDR_ANY);
78     setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc));
79     setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
80     setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ittl, sizeof(ittl));
81
82     flag =  fcntl(s, F_GETFL, 0);
83     flag |= O_NONBLOCK;
84     fcntl(s, F_SETFL, flag);
85
86     return s;
87 }
88
89 int main(int argc, char *argv[])
90 {
91     mdnsd d;
92     struct message m;
93     unsigned long int ip;
94     unsigned short int port;
95     struct timeval *tv;
96     int bsize, ssize = sizeof(struct sockaddr_in);
97     unsigned char buf[MAX_PACKET_LEN];
98     struct sockaddr_in from, to;
99     fd_set fds;
100     int s;
101
102     if(argc != 3) { printf("usage: mquery 12 _http._tcp.local.\n"); return -1; }
103
104     d = mdnsd_new(1,1000);
105     if((s = msock()) == 0) { printf("can't create socket: %s\n",strerror(errno)); return 1; }
106
107     mdnsd_query(d,argv[2],atoi(argv[1]),ans,0);
108
109     while(1)
110     {
111         tv = mdnsd_sleep(d);
112         FD_ZERO(&fds);
113         FD_SET(s,&fds);
114         select(s+1,&fds,0,0,tv);
115
116         if(FD_ISSET(s,&fds))
117         {
118             while((bsize = recvfrom(s,buf,MAX_PACKET_LEN,0,(struct sockaddr*)&from,&ssize)) > 0)
119             {
120                 bzero(&m,sizeof(struct message));
121                 message_parse(&m,buf);
122                 mdnsd_in(d,&m,(unsigned long int)from.sin_addr.s_addr,from.sin_port);
123             }
124             if(bsize < 0 && errno != EAGAIN) { printf("can't read from socket %d: %s\n",errno,strerror(errno)); return 1; }
125         }
126         while(mdnsd_out(d,&m,&ip,&port))
127         {
128             bzero(&to, sizeof(to));
129             to.sin_family = AF_INET;
130             to.sin_port = port;
131             to.sin_addr.s_addr = ip;
132             if(sendto(s,message_packet(&m),message_packet_len(&m),0,(struct sockaddr *)&to,sizeof(struct sockaddr_in)) != message_packet_len(&m))  { printf("can't write to socket: %s\n",strerror(errno)); return 1; }
133         }
134     }
135
136     mdnsd_shutdown(d);
137     mdnsd_free(d);
138     return 0;
139 }
140