jablonka.czprosek.czf

discover

Subversion Repositories:
[/] [trunk/] [discover.c] - Blame information for rev 5

 

Line No. Rev Author Line
11simandl#include <arpa/inet.h>
2#include <netinet/in.h>
3#include <stdio.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <unistd.h>
7#include <stdlib.h>
8#include <string.h>
9#include <ctype.h>
10#include <netdb.h>
11#include <sys/select.h>
12#include <sys/time.h>
13#include <ifaddrs.h>
14#include <net/if.h>
15 
16#define BUFLEN 1024
17#define UBNT_PORT 10001
18 
19#define SNDLEN 4
20 
21 
22struct udisc_msg_hdr {
23 uint8_t vh;
24 uint8_t vl;
25 uint16_t length;
26} __attribute__((packed));
27 
28struct udisc_rec_hdr {
29 uint8_t type;
30 uint16_t length;
31} __attribute__((packed));
32 
335jikosstruct cache_entry {
34 unsigned long s_addr;
35 unsigned short s_port;
36};
37 
38#define MAXENTRIES 1024
39struct cache_entry cache[MAXENTRIES];
40size_t cachep;
41 
42int add_cache(unsigned long s_addr, unsigned short s_port)
43{
44 if (cachep == 1024)
45 return 0;
46 
47 cache[cachep].s_addr = s_addr;
48 cache[cachep].s_port = s_port;
49 cachep++;
50 
51 return 1;
52}
53 
54int lookup_cache(unsigned long s_addr, unsigned short s_port)
55{
56 int i;
57 
58 for (i = 0; i <= cachep; i++)
59 if (cache[i].s_addr == s_addr && cache[i].s_port == s_port)
60 return 1;
61 return 0;
62}
63 
641simandlint main(int argc, char *argv[])
65{
66 
67 struct sockaddr_in si_srv;
68 struct sockaddr_in si_clnt;
69 int sock;
70 socklen_t soutlen = sizeof(si_srv);
71 socklen_t sinlen = sizeof(si_srv);
72 char rcvbuf[BUFLEN];
73 char sendbuf[BUFLEN];
74 ssize_t rlen;
75 
76 struct udisc_msg_hdr *umh;
77 struct udisc_rec_hdr *urh;
78 char *p;
79 char *dest;
80 
81 struct addrinfo hints;
82 struct addrinfo *ai_res;
83 int result;
84 int i, t;
85 
86 fd_set socks;
87 struct timeval tv;
88 
89 int multicast;
90 
91 int responses = 0;
92 
93 struct ifaddrs *ifa;
94 
953simandl memset(&hints, 0, sizeof(hints));
961simandl hints.ai_protocol = IPPROTO_UDP;
97 hints.ai_socktype = SOCK_DGRAM;
98 hints.ai_flags = AI_CANONNAME;
99 hints.ai_family = PF_UNSPEC;
100 
101 if (argc < 2) {
102 dest = "233.89.188.1";
103 multicast = 1;
104 } else {
105 dest = argv[1];
106 multicast = 0;
107 }
108 
109 if ((result = getaddrinfo(dest, NULL, &hints, &ai_res))) {
110 printf("getaddrinfo-failed: %s\n", gai_strerror(result));
111 exit(1);
112 }
113 
114 if ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
115 perror("socket");
116 exit(1);
117 }
118 
119 memset((char *) &si_clnt, 0, sizeof(si_clnt));
120 si_clnt.sin_family = AF_INET;
121 si_clnt.sin_port = htons(UBNT_PORT);
122 si_clnt.sin_addr = ((struct sockaddr_in *)ai_res->ai_addr)->sin_addr;
123 
124 sendbuf[0] = 1;
125 sendbuf[1] = 0;
126 sendbuf[2] = 0;
127 sendbuf[3] = 0;
128 
129 if (multicast) {
130 
131 char loop = 0;
132 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(char));
133 
134 if (getifaddrs(&ifa)) {
135 perror("getifaddrs");
136 exit(1);
137 }
138 
139 for (; ifa; ifa = ifa->ifa_next) {
140 
141 if (!(ifa->ifa_flags & IFF_UP))
142 continue;
143 if (!ifa->ifa_addr)
144 continue;
145 if (ifa->ifa_addr->sa_family != AF_INET)
146 continue;
147 if (!strcmp(ifa->ifa_name, "lo"))
148 continue;
149 if (!strncmp(ifa->ifa_name, "dummy", 5))
150 continue;
151 
152 printf("Probing %s:%d", inet_ntoa(si_clnt.sin_addr), UBNT_PORT);
153 printf(" via %s (%s).\n", ifa->ifa_name, inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr));
154 
155 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), sizeof(struct in_addr))) {
156 perror("setsockopt");
157 exit(1);
158 }
159 
160 if (sendto(sock, sendbuf, SNDLEN, 0, (struct sockaddr *)&si_clnt, soutlen) == -1) {
161 perror("socket");
162 exit(1);
163 }
164 }
165 
166 } else {
167 
168 printf("Probing %s:%d.\n", inet_ntoa(si_clnt.sin_addr), UBNT_PORT);
169 
170 if (sendto(sock, sendbuf, SNDLEN, 0, (struct sockaddr *)&si_clnt, soutlen) == -1) {
171 perror("socket");
172 exit(1);
173 }
174 }
175 
176 
177 FD_ZERO(&socks);
178 FD_SET(sock, &socks);
179 tv.tv_sec = 0;
180 tv.tv_usec = 200000;
181 
182 while (select(sock + 1, &socks, NULL, NULL, &tv)) {
183 
184 if ((rlen = recvfrom(sock, rcvbuf, BUFLEN, 0, (struct sockaddr *)&si_srv, &sinlen)) == -1) {
185 perror("recvfrom");
186 exit(1);
187 }
188 
189 if (ntohs(si_srv.sin_port) != UBNT_PORT)
190 continue;
191 
192 responses++;
193 
1945jikos if (!lookup_cache(si_srv.sin_addr.s_addr, si_srv.sin_port)) {
195 if (!add_cache(si_srv.sin_addr.s_addr, si_srv.sin_port)) {
196 fprintf(stderr, "too many unique responses\n");
197 exit(1);
198 }
199 } else {
200 continue;
201 }
202 
2031simandl printf("\n");
204 printf("Response : %s:%d\n", inet_ntoa(si_srv.sin_addr), ntohs(si_srv.sin_port));
205 
206 p = rcvbuf;
207 
208 umh = (void*)p;
209 p += sizeof(struct udisc_msg_hdr);
210 rlen -= sizeof(struct udisc_msg_hdr);
211 
212 printf("Discovery: v%d.%02d\n", umh->vh, umh->vl);
213 
214 if (umh->vh != 1 && umh->vl != 0 && ntohs(umh->length) != rlen) {
215 fprintf(stderr, "protocol invalid\n");
216 exit(1);
217 }
218 
219 while (rlen > 0) {
220 
221 urh = (void*)p;
222 p += sizeof(struct udisc_rec_hdr);
223 rlen -= sizeof(struct udisc_rec_hdr);
224 
225 
226 
227 
228 switch (urh->type) {
229 
230 
231 
232 case 2:
233 printf("IP Address: ");
234 for (i = 0; i < 4; i++) {
235 printf("%d", (unsigned char) p[i + 6]);
236 if (i < 3)
237 printf(".");
238 }
239 
240 printf(" (");
241 for (i = 0; i < 6; i++) {
242 printf("%02x", (unsigned char) p[i]);
243 if (i < 5)
244 printf(":");
245 }
246 
247 printf(")\n");
248 break;
249 
250 
251 case 1:
252 printf("MAC Address: ");
253 for (i = 0; i < 6; i++) {
254 printf("%02x", (unsigned char) p[i]);
255 if (i < 5)
256 printf(":");
257 }
258 
259 printf("\n");
260 break;
261 
262 
263 case 3:
264 case 11:
265 case 12:
266 case 13:
267 
268 switch(urh->type) {
269 
270 case 3:
271 printf("FW Version: ");
272 break;
273 case 11:
274 printf("Hostname: ");
275 break;
276 case 12:
277 printf("Model: ");
278 break;
279 case 13:
280 printf("ESSID: ");
281 break;
282 }
283 
284 for (i = 0; i < ntohs(urh->length); i++)
285 printf("%c", isprint(p[i]) ? p[i] : '.');
286 printf("\n");
287 
288 break;
289 
290 case 14:
291 
292 printf("Mode: %s (%d)\n", *p == 2 ? "Station" : (*p == 3 ? "AP" : "?"), *p);
293 break;
294 
295 case 10:
296 t = ntohl(*(uint32_t *)p);
297 printf("Uptime: %dd, %d:%02d:%02d\n", t / 60 / 60 / 24, t / 60 / 60 % 24, t / 60 % 60, t % 60);
298 break;
299 
3004simandl case 16:
301 printf("System ID: 0x%02hhX%02hhX\n", p[0], p[1]);
302 break;
303 
3041simandl default:
305 
306 printf("Entry %3d: ", urh->type);
307 
308 for (i = 0; i < ntohs(urh->length); i++)
309 printf("%02x ", (unsigned char) p[i]);
310 
311 printf(" >");
312 
313 for (i = 0; i < ntohs(urh->length); i++)
314 printf("%c", isprint(p[i]) ? p[i] : '.');
315 printf("<\n");
316 
317 
318 }
319 
320 p += ntohs(urh->length);
321 rlen -= ntohs(urh->length);
322 }
323 
324 
325 }
326 
327 
328 close(sock);
329 
330 if (!responses) {
331 printf("No UBNT routers found.\n");
332 return 1;
333 }
334 
335 printf("\n");
336 
337 return 0;
338 
339}
340 

Powered by WebSVN 2.2.1