]> git.sur5r.net Git - ngadmin/blob - spy/src/spy.c
7c842cc3ddddab2c84c1f0f86ff25315c62f405c
[ngadmin] / spy / src / spy.c
1
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <poll.h>
5 #include <ctype.h>
6 #include <signal.h>
7 #include <arpa/inet.h>
8
9 #include <ngadmin.h> /* FIXME */
10 #include <nsdp/protocol.h>
11 #include <nsdp/attr.h>
12 #include <nsdp/net.h>
13 #include <nsdp/str.h>
14
15
16 static void print_password (const char *pass, unsigned int len)
17 {
18         unsigned int i;
19         char *s;
20         
21         
22         if (isStringPrintable(pass, len)) {
23                 /* all characters are printable, cleartext password assumed */
24                 printf("(clear) \"%s\"", pass);
25                 return;
26         }
27         
28         s = malloc(len + 1);
29         if (s == NULL)
30                 return;
31         memcpy(s, pass, len);
32         s[len] = '\0';
33         
34         passwordEndecode(s, len);
35         
36         if (isStringPrintable(s, len)) {
37                 /* all characters are printable, encrypted password assumed */
38                 printf("(encrypted) \"%s\"", s);
39                 free(s);
40                 return;
41         }
42         
43         free(s);
44         
45         /* unknown encoding, fallback to hex display */
46         printf("(hex) ");
47         for (i = 0; i < len; i++)
48                 printf("%02x ", (unsigned char)pass[i]);
49 }
50
51
52 static void print_attr (const struct attr *at)
53 {
54         unsigned char p, ports, *byte = at->data;
55         unsigned short *word = at->data;
56         char *s = at->data;
57         struct ether_addr *eth = at->data;
58         struct in_addr *ip = at->data;
59         struct attr_port_status *apsu = at->data;
60         struct attr_port_stat *apsi = at->data;
61         struct attr_cabletest_do *acd = at->data;
62         struct attr_cabletest_result *acr = at->data;
63         struct attr_vlan_conf *avc = at->data;
64         struct attr_pvid *ap = at->data;
65         struct attr_qos *aq = at->data;
66         struct attr_bitrate *ab = at->data;
67         struct attr_mirror *am = at->data;
68         struct attr_igmp_vlan *aiv = at->data;
69         
70         
71         printf("code = %04X, length = %d\n", at->attr, at->size);
72         
73         if (at->size == 0) {
74                 printf("\tempty\n\n");
75                 return;
76         }
77         
78         switch (at->attr) {
79         
80         case ATTR_PRODUCT:
81                 trim(s, at->size);
82                 printf("\tproduct = %s\n", s);
83                 break;
84         
85         case ATTR_NAME:
86                 trim(s, at->size);
87                 printf("\tname = %s\n", s);
88                 break;
89         
90         case ATTR_MAC:
91                 printf("\tMAC = %s\n", ether_ntoa(eth));
92                 break;
93         
94         case ATTR_IP:
95                 printf("\tIP = %s\n", inet_ntoa(*ip));
96                 break;
97         
98         case ATTR_NETMASK:
99                 printf("\tnetmask = %s\n", inet_ntoa(*ip));
100                 break;
101         
102         case ATTR_GATEWAY:
103                 printf("\tgateway = %s\n", inet_ntoa(*ip));
104                 break;
105         
106         case ATTR_NEW_PASSWORD:
107                 printf("\tnew password = ");
108                 print_password(s, at->size);
109                 printf("\n");
110                 break;
111         
112         case ATTR_PASSWORD:
113                 printf("\tpassword = ");
114                 print_password(s, at->size);
115                 printf("\n");
116                 break;
117         
118         case ATTR_DHCP:
119                 printf("\tDHCP = %s\n", (at->size == 1 ? *byte : *word) ? "yes" : "no");
120                 break;
121         
122         case ATTR_FIRM_VER:
123                 trim(s, at->size);
124                 printf("\tfirmware = %s\n", s);
125                 break;
126         
127         case ATTR_FIRM_UPGRADE:
128                 printf("\tfirmware upgrade requested\n");
129                 break;
130         
131         case ATTR_RESTART:
132                 printf("\trestart requested\n");
133                 break;
134         
135         case ATTR_ENCPASS:
136                 printf("\tpassword must be encrypted\n");
137                 break;
138         
139         case ATTR_DEFAULTS:
140                 printf("\treset parameters requested\n");
141                 break;
142         
143         case ATTR_PORT_STATUS:
144                 printf("\tport status\n");
145                 printf("\tport = %u\n", apsu->port);
146                 printf("\tstate = %s\n", safeStr(getSpeedStr(apsu->status)));
147                 break;
148         
149         case ATTR_PORT_STATISTICS:
150                 printf("\tport statistics\n");
151                 printf("\tport = %u\n", apsi->port);
152                 printf("\treceived = %llu\n", apsi->recv);
153                 printf("\tsend = %llu\n", apsi->sent);
154                 printf("\tCRC = %llu\n", apsi->crc);
155                 break;
156         
157         case ATTR_STATS_RESET:
158                 printf("\tport statistics reset requested\n");
159                 break;
160         
161         
162         case ATTR_CABLETEST_DO:
163                 printf("\tstart cabletest\n");
164                 printf("\tport = %u\n", acd->port);
165                 printf("\taction = %u\n", acd->action);
166                 break;
167         
168         case ATTR_CABLETEST_RESULT:
169                 printf("\tcabletest result\n");
170                 printf("\tport = %u\n", acr->port);
171                 if (at->size > 1) {
172                         printf("\tv1 = %u\n", acr->v1);
173                         printf("\tv2 = %u\n", acr->v2);
174                 }
175                 break;
176         
177         case ATTR_VLAN_TYPE:
178                 printf("\tVLAN type = %s\n", safeStr(getVlanTypeStr(*byte)));
179                 break;
180         
181         case ATTR_VLAN_PORT_CONF:
182                 printf("\tport based VLAN configuration\n");
183                 printf("\tVLAN = %u\n", avc->vlan);
184                 ports = at->size - sizeof(struct attr_vlan_conf);
185                 for (p = 0; p < ports; p++)
186                         printf("\tport %d = %s\n", p + 1, safeStr(getVlanCodeStr(avc->ports[p])));
187                 break;
188         
189         case ATTR_VLAN_DOT_CONF:
190                 printf("\t802.1Q based VLAN configuration\n");
191                 printf("\tVLAN = %u\n", avc->vlan);
192                 ports = at->size - sizeof(struct attr_vlan_conf);
193                 for (p = 0; p < ports; p++)
194                         printf("\tport %d = %s\n", p + 1, safeStr(getVlanCodeStr(avc->ports[p])));
195                 break;
196         
197         case ATTR_VLAN_DESTROY:
198                 printf("\tdestroy VLAN = %u\n", *word);
199                 break;
200         
201         case ATTR_VLAN_PVID:
202                 printf("\tVLAN PVID\n");
203                 printf("\tport = %u\n", ap->port);
204                 printf("\tVLAN = %u\n", ap->vlan);
205                 break;
206         
207         case ATTR_QOS_TYPE:
208                 printf("\tQoS type = %s\n", safeStr(getQosTypeStr(*byte)));
209                 break;
210         
211         case ATTR_QOS_CONFIG:
212                 printf("\tQoS configuration\n");
213                 printf("\tport = %u\n", aq->port);
214                 printf("\tpriority = %s\n", safeStr(getQosPrioStr(aq->prio)));
215                 break;
216         
217         case ATTR_BITRATE_INPUT:
218                 printf("\tinput bitrate\n");
219                 printf("\tport = %u\n", ab->port);
220                 printf("\tbitrate = %s\n", safeStr(getBitrateStr(ab->bitrate)));
221                 break;
222         
223         case ATTR_BITRATE_OUTPUT:
224                 printf("\toutput bitrate\n");
225                 printf("\tport = %u\n", ab->port);
226                 printf("\tbitrate = %s\n", safeStr(getBitrateStr(ab->bitrate)));
227                 break;
228         
229         case ATTR_STORM_ENABLE:
230                 printf("\tstorm filtering = %s\n", *byte ? "yes" : "no");
231                 break;
232         
233         case ATTR_STORM_BITRATE:
234                 printf("\tstorm filtering bitrate\n");
235                 printf("\tport = %u\n", ab->port);
236                 printf("\tbitrate = %s\n", safeStr(getBitrateStr(ab->bitrate)));
237                 break;
238         
239         case ATTR_MIRROR:
240                 printf("\tport mirroring\n");
241                 if (am->outport == 0) {
242                         printf("\tdisabled\n");
243                         break;
244                 }
245                 
246                 printf("\toutput port = %u\n", am->outport);
247                 ports = at->size - sizeof(struct attr_mirror);
248                 for (p = 0; p < ports; p++)
249                         printf("\tport %u = %s\n", p + 1, am->ports[p] ? "yes" : "no");
250                 break;
251         
252         case ATTR_PORTS_COUNT:
253                 printf("\tports count = %u\n", *byte);
254                 break;
255         
256         case ATTR_IGMP_ENABLE_VLAN:
257                 printf("\tIGMP filtering\n");
258                 printf("\tenable = %s\n", aiv->enable ? "yes" : "no");
259                 printf("\tVLAN = %u\n", aiv->vlan);
260                 break;
261         
262         case ATTR_IGMP_BLOCK_UNK:
263                 printf("\tblock unknown IGMP = %s\n", *byte ? "yes" : "no");
264                 break;
265         
266         case ATTR_IGMP_VALID_V3:
267                 printf("\tvalidate IGMPv3 = %s\n", *byte ? "yes" : "no");
268                 break;
269         
270         default:
271                 printf("\tunknown\n");
272         }
273         
274         printf("\n");
275 }
276
277
278 static void print_packet (const List *attr, const struct nsdp_cmd *nc)
279 {
280         const ListNode *ln;
281         const struct attr *at;
282         
283         
284         printf("---------------------------------\n");
285         printf("code = %s (%u)\n", safeStr(getCodeStr(nc->code)), nc->code);
286         printf("error = %s (%u)\n", safeStr(getErrorStr(nc->error)), nc->error);
287         if (nc->attr_error != 0)
288                 printf("erroneous attribute = %04X\n", nc->attr_error);
289         printf("source address = %s:%u\n", inet_ntoa(nc->remote_addr.sin_addr), ntohs(nc->remote_addr.sin_port));
290         printf("client MAC = %s\n", ether_ntoa(&nc->client_mac));
291         printf("switch MAC = %s\n", ether_ntoa(&nc->switch_mac));
292         printf("sequence number = %u\n\n", nc->seqnum);
293         printf("received %d attribute(s)\n\n", attr->count);
294         
295         for (ln = attr->first; ln != NULL; ln = ln->next) {
296                 at = ln->data;
297                 print_attr(at);
298         }
299         
300         printf("---------------------------------\n\n");
301 }
302
303
304 static void handler (int sig)
305 {
306         (void)sig;
307         printf("interrupt\n");
308 }
309
310
311 int main (void)
312 {
313         int err = 0, sw_sock = -1, cl_sock = -1;
314         List *attr;
315         struct nsdp_cmd nc;
316         struct sockaddr_in sw_local, cl_local;
317         struct pollfd fds[2];
318         struct sigaction sa;
319         
320         
321         sw_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
322         if (sw_sock < 0) {
323                 perror("socket");
324                 err = 1;
325                 goto end;
326         };
327         
328         cl_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
329         if (cl_sock < 0) {
330                 perror("socket");
331                 err = 1;
332                 goto end;
333         };
334         
335         
336         memset(&sw_local, 0, sizeof(struct sockaddr_in));
337         sw_local.sin_family = AF_INET;
338         sw_local.sin_addr.s_addr = htonl(INADDR_ANY);
339         sw_local.sin_port = htons(SWITCH_PORT);
340         
341         cl_local = sw_local;
342         cl_local.sin_port = htons(CLIENT_PORT);
343         
344         if (bind(sw_sock, (struct sockaddr*)&sw_local, sizeof(struct sockaddr_in)) < 0) {
345                 perror("bind");
346                 err = 2;
347                 goto end;
348         }
349         
350         if (bind(cl_sock, (struct sockaddr*)&cl_local, sizeof(struct sockaddr_in)) < 0) {
351                 perror("bind");
352                 err = 2;
353                 goto end;
354         }
355         
356         fds[0].fd = sw_sock;
357         fds[0].events = POLLIN;
358         fds[0].revents = 0;
359         fds[1].fd = cl_sock;
360         fds[1].events = POLLIN;
361         fds[1].revents = 0;
362         
363         memset(&sa, 0, sizeof(struct sigaction));
364         sa.sa_handler = handler;
365         sigaction(SIGINT, &sa, NULL);
366         sigaction(SIGTERM, &sa, NULL);
367         
368         attr = createEmptyList();
369         
370         while (1) {
371                 err = poll(fds, 2, -1);
372                 if (err < 0) {
373                         perror("poll");
374                         break;
375                 } else if (err == 0) {
376                         continue;
377                 }
378                 
379                 memset(&nc, 0, sizeof(struct nsdp_cmd));
380                 nc.remote_addr.sin_family = AF_INET;
381                 
382                 if (fds[0].revents & POLLIN) {
383                         nc.remote_addr.sin_port = htons(CLIENT_PORT);
384                         err = recvNsdpPacket(sw_sock, &nc, attr, NULL);
385                 } else {
386                         nc.remote_addr.sin_port = htons(SWITCH_PORT);
387                         err = recvNsdpPacket(cl_sock, &nc, attr, NULL);
388                 }
389                 
390                 if (err < 0)
391                         continue;
392                 
393                 print_packet(attr, &nc);
394                 
395                 clearList(attr, (void(*)(void*))freeAttr);
396         }
397         
398         destroyList(attr, (void(*)(void*))freeAttr);
399         
400 end:
401         close(sw_sock);
402         close(cl_sock);
403         
404         return err;
405 }
406