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