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