OSDN Git Service

v10
[android-x86/external-wireless-tools.git] / wireless_tools / iwspy.c
1 /*
2  * Warning : this program need to be link against libsupport.a
3  * in net-tools-1.2.0
4  * This program need also wireless extensions...
5  */
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/ioctl.h>
9 #include <linux/netdevice.h>
10 #include <linux/if.h>
11 #include <linux/if_arp.h>
12 #include <linux/if_ether.h>
13 #include <linux/ipx.h>
14 #include <linux/wireless.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include "support.h"
23
24 int skfd = -1;                          /* generic raw socket desc.     */
25 int ipx_sock = -1;                      /* IPX socket                   */
26 int ax25_sock = -1;                     /* AX.25 socket                 */
27 int inet_sock = -1;                     /* INET socket                  */
28 int ddp_sock = -1;                      /* Appletalk DDP socket         */
29
30 static int sockets_open()
31 {
32         inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
33         ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
34         ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
35         ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
36         /*
37          *      Now pick any (exisiting) useful socket family for generic queries
38          */
39         if(inet_sock!=-1)
40                 return inet_sock;
41         if(ipx_sock!=-1)
42                 return ipx_sock;
43         if(ax25_sock!=-1)
44                 return ax25_sock;
45         /*
46          *      If this is -1 we have no known network layers and its time to jump.
47          */
48          
49         return ddp_sock;
50 }
51
52 int
53 main(int        argc,
54      char **    argv)
55 {
56   struct ifreq          ifr;
57   struct iwreq          wrq;
58   struct aftype *ap;
59   struct hwtype *hw;
60   char *        ifname = argv[1];
61
62   if(argc < 2)
63     exit(0);
64
65   /* Create a channel to the NET kernel. */
66   if((skfd = sockets_open()) < 0)
67     {
68       perror("socket");
69       exit(-1);
70     }
71
72   /* Get the type of interface address */
73   strcpy(ifr.ifr_name, ifname);
74   if((ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0) ||
75      ((ap = get_afntype(ifr.ifr_addr.sa_family)) == NULL))
76     {
77       /* Deep trouble... */
78       fprintf(stderr, "Interface %s unavailable\n", ifname);
79       exit(0);
80     }
81
82 #ifdef DEBUG
83   printf("Interface : %d - %s - %s\n", ifr.ifr_addr.sa_family,
84          ap->name, ap->sprint(&ifr.ifr_addr, 1));
85 #endif
86
87   /* Get the type of hardware address */
88   strcpy(ifr.ifr_name, ifname);
89   if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
90      ((hw = get_hwntype(ifr.ifr_hwaddr.sa_family)) == NULL))
91     {
92       /* Deep trouble... */
93       fprintf(stderr, "Unable to get hardware address of the interface %s\n",
94              ifname);
95       exit(0);
96     }
97
98 #ifdef DEBUG
99   printf("Hardware : %d - %s - %s\n", ifr.ifr_hwaddr.sa_family,
100          hw->name, hw->print(ifr.ifr_hwaddr.sa_data));
101 #endif
102
103   /* Is there any arguments ? */
104   if(argc < 3)
105     {   /* Nope : read out from kernel */
106       char              buffer[(sizeof(struct iw_quality) +
107                                 sizeof(struct sockaddr)) * IW_MAX_SPY];
108       struct sockaddr * hwa;
109       struct iw_quality *qual;
110       int               n;
111       int               i;
112
113       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
114       wrq.u.data.pointer = (caddr_t) buffer;
115       wrq.u.data.length = 0;
116       wrq.u.data.flags = 0;
117       if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
118         {
119           fprintf(stderr, "Interface doesn't accept reading addresses...\n");
120           fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
121           return(-1);
122         }
123
124       n = wrq.u.data.length;
125
126       hwa = (struct sockaddr *) buffer;
127       qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
128
129       for(i = 0; i < n; i++)
130         printf("%s : Quality %d ; Signal %d ; Noise %d %s\n",
131                hw->print(hwa[i].sa_data),
132                qual[i].qual, qual[i].level, qual[i].noise,
133                qual[i].updated & 0x7 ? "(updated)" : "");
134     }
135   else
136     {   /* Send addresses to kernel */
137       int               i;
138       int               nbr;            /* Number of valid addresses */
139       struct sockaddr   hw_address[IW_MAX_SPY];
140       struct sockaddr   if_address;
141       struct arpreq     arp_query;
142
143       /* Read command line */
144       i = 2;    /* first arg to read */
145       nbr = 0;  /* Number of args readen so far */
146
147       /* "off" : disable functionality (set 0 addresses) */
148       if(!strcmp(argv[2], "off"))
149         i = argc;       /* hack */
150
151       /* "+" : add all addresses already in the driver */
152       if(!strcmp(argv[2], "+"))
153         {
154           char          buffer[(sizeof(struct iw_quality) +
155                                 sizeof(struct sockaddr)) * IW_MAX_SPY];
156
157           strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
158           wrq.u.data.pointer = (caddr_t) buffer;
159           wrq.u.data.length = 0;
160           wrq.u.data.flags = 0;
161           if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
162             {
163               fprintf(stderr, "Interface doesn't accept reading addresses...\n");
164               fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
165               return(-1);
166             }
167
168           /* Copy old addresses */
169           nbr = wrq.u.data.length;
170           memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
171
172           i = 3;        /* skip the "+" */
173         }
174
175       /* Read other args on command line */
176       while((i < argc) && (nbr < IW_MAX_SPY))
177         {
178           /* If it is not a hardware address (prefixed by hw)... */
179           if(strcmp(argv[i], "hw"))
180             {
181               /* Read interface address */
182               if(ap->input(argv[i++], &if_address) < 0)
183                 {
184                   fprintf(stderr, "Invalid interface address %s\n", argv[i - 1]);
185                   continue;
186                 }
187
188               /* Translate IP addresses to MAC addresses */
189               memcpy((char *) &(arp_query.arp_pa),
190                      (char *) &if_address,
191                      sizeof(struct sockaddr));
192               arp_query.arp_ha.sa_family = 0;
193               arp_query.arp_flags = 0;
194               /* The following restrict the search to the interface only */
195               strcpy(arp_query.arp_dev, ifname);
196               if((ioctl(inet_sock, SIOCGARP, &arp_query) < 0) ||
197                  !(arp_query.arp_flags & ATF_COM))
198                 {
199                   fprintf(stderr, "Arp failed for %s... (%d) Try to ping the address before.\n",
200                          ap->sprint(&if_address, 1), errno);
201                   continue;
202                 }
203
204               /* Store new MAC address */
205               memcpy((char *) &(hw_address[nbr++]),
206                      (char *) &(arp_query.arp_ha),
207                      sizeof(struct sockaddr));
208
209 #ifdef DEBUG
210               printf("IP Address %s => Hw Address = %s - %d\n",
211                      ap->sprint(&if_address, 1),
212                      hw->print(hw_address[nbr - 1].sa_data));
213 #endif
214             }
215           else  /* If it's an hardware address */
216             {
217               if(++i >= argc)
218                 {
219                   fprintf(stderr, "hw must be followed by an address...\n");
220                   continue;
221                 }
222
223               /* Get the hardware address */
224               if(hw->input(argv[i++], &(hw_address[nbr])) < 0)
225                 {
226                   fprintf(stderr, "Invalid hardware address %s\n", argv[i - 1]);
227                   continue;
228                 }
229               nbr++;
230
231 #ifdef DEBUG
232               printf("Hw Address = %s - %d\n",
233                      hw->print(hw_address[nbr - 1].sa_data));
234 #endif
235             }
236         }       /* Loop on all addresses */
237
238
239       /* Check the number of addresses */
240       if((nbr == 0) && strcmp(argv[2], "off"))
241         {
242           fprintf(stderr, "No valid addresses found : exiting...\n");
243           exit(0);
244         }
245
246       /* Check if there is some remaining arguments */
247       if(i < argc)
248         {
249           fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY);
250         }
251
252       /* Time to do send addresses to the driver */
253       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
254       wrq.u.data.pointer = (caddr_t) hw_address;
255       wrq.u.data.length = nbr;
256       wrq.u.data.flags = 0;
257       if(ioctl(skfd, SIOCSIWSPY, &wrq) < 0)
258         {
259           fprintf(stderr, "Interface doesn't accept addresses...\n");
260           fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
261           return(-1);
262         }
263     }
264
265   /* Close the socket. */
266   close(skfd);
267
268   return(1);
269 }