2 * $Id: wmifinfo.c,v 1.4 2004/07/11 12:00:46 ico Exp $
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
21 #if defined(__OpenBSD__)
22 #include <net/if_dl.h>
23 #include <net/if_types.h>
24 #include <net/route.h>
25 #include <sys/param.h>
26 #include <sys/sysctl.h>
27 #include <netinet/if_ether.h>
28 #include <net/if_ieee80211.h>
29 #include <dev/ic/if_wi_ieee.h>
30 #include <dev/ic/if_wireg.h>
31 #include <dev/ic/if_wi_hostap.h>
33 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
37 #include <sys/types.h>
39 #ifdef ENABLE_NWN_SUPPORT
44 #include "bitmaps/wmifinfo_led.xbm"
45 #include "bitmaps/wmifinfo_led.xpm"
46 #include "bitmaps/wmifinfo_lcd.xbm"
47 #include "bitmaps/wmifinfo_lcd.xpm"
51 #define DELAY 1000000L
52 #define USEC_PER_SEC 1000000L
80 char LabelColor
[30] = "#79bdbf";
81 char WindGustColor
[30] = "#ff0000";
82 char DataColor
[30] = "#ffbf50";
83 char BackColor
[30] = "#181818";
84 char StationTimeColor
[30] = "#c5a6ff";
86 struct font_t font1
= { " 0123456789ABCDEF", 64, 74, 4, 5, 17};
87 struct font_t font2
= { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789: ", 1, 65, 5, 7, 26};
89 char *exec_dflt
= "echo Use the -u and -d options for setting ifup/ifdown commands.";
94 char startif
[16] = "";
95 char ifname
[MAXIFS
][16];
98 struct ifinfo_t ifinfo
;
101 volatile int exec_busy
=0;
104 void parse_cmdline(int argc
, char *argv
[]);
105 void ButtonPressEvent(XButtonEvent
*);
106 char *strupper(char *str
);
107 void getifnames(void);
108 int getifinfo(char *ifname
, struct ifinfo_t
*info
);
113 void drawtext(char *str
, struct font_t
*font
, int x
, int y
)
120 p
= strchr(font
->chars
, str
[i
]);
121 ix
= (p
) ? (p
- font
->chars
) : 0;
123 iy
= (ix
/ font
->charspline
);
124 ix
= (ix
% font
->charspline
);
126 copyXPMArea( font
->sx
+ ix
* font
->dx
,
127 font
->sy
+ iy
* font
->dy
,
138 void drawipaddr(uint32_t a
, int linenum
)
142 uint32_t addr
= ntohl(a
);
145 snprintf(buf
, 4, "%3d", (addr
>> ((3-i
)*8)) & 255);
146 drawtext(buf
, &font1
, 5 + i
*14, 19 + linenum
*9);
150 void drawhwaddr(unsigned char *addr
)
156 snprintf(buf
, 4, "%02X", addr
[i
]);
157 drawtext(buf
, &font1
, 6 + i
*9, 46);
161 int main(int argc
, char *argv
[])
172 int prev_exec_busy
=0;
175 exec_down
= exec_dflt
;
177 parse_cmdline(argc
, argv
);
179 initXwindow(argc
, argv
);
181 if(mode
== MODE_LED
) {
182 openXwindow(argc
, argv
, (char **) wmifinfo_led_xpm
,
183 (char*) wmifinfo_led_bits
, wmifinfo_led_width
,
184 wmifinfo_led_height
, BackColor
, LabelColor
,
185 WindGustColor
, DataColor
, StationTimeColor
);
187 openXwindow(argc
, argv
, (char **) wmifinfo_lcd_xpm
,
188 (char*) wmifinfo_lcd_bits
, wmifinfo_lcd_width
,
189 wmifinfo_lcd_height
, BackColor
, LabelColor
,
190 WindGustColor
, DataColor
, StationTimeColor
);
193 /* Initialize global variables */
195 fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
196 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
197 ifc
.ifc_buf
= malloc(ifc
.ifc_len
);
201 while (XPending(display
)) {
202 XNextEvent(display
, &event
);
204 switch (event
.type
) {
209 ButtonPressEvent(&event
.xbutton
);
217 if ((d
++ == 3) || (ifno
!= pifno
) || (exec_busy
!= prev_exec_busy
)) {
221 copyXPMArea(64, 0, 64, 64, 0, 0);
225 ifno
= ifno
% ifaces
;
227 getifinfo(ifname
[ifno
], &ifinfo
);
229 if(ifno
!= pifno
) lastbytes
= ifinfo
.bytes
;
231 sprintf(buf
, "%-7s", ifinfo
.id
);
233 drawtext(buf
, &font2
, 6, 4);
235 if(memcmp(ifinfo
.hw
, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
236 drawhwaddr(ifinfo
.hw
);
239 if(ifinfo
.ip
) drawipaddr(ifinfo
.ip
, 0);
240 if(ifinfo
.nm
) drawipaddr(ifinfo
.nm
, 1);
241 if(ifinfo
.gw
) drawipaddr(ifinfo
.gw
, 2);
243 /* WLAN signal level */
247 #elif defined(__OpenBSD__)
251 copyXPMArea(4, 82, x
*4, 4, 6, 53);
259 if(ifinfo
.state
) x
+= 8;
260 if(lastbytes
== ifinfo
.bytes
) x
+= 16;
262 copyXPMArea(64 + x
, 81, 8, 8, 50, 4);
263 lastbytes
= ifinfo
.bytes
;
268 prev_exec_busy
= exec_busy
;
273 tv
.tv_sec
= DELAY
/ USEC_PER_SEC
;
274 tv
.tv_usec
= DELAY
- (tv
.tv_sec
* USEC_PER_SEC
);
277 FD_SET(ConnectionNumber(display
), &fds
);
279 select(ConnectionNumber(display
)+1, &fds
, NULL
, NULL
, &tv
);
280 #elif defined(__OpenBSD__)
291 "usage: wmifinfo [-lh] [-i interface]\n"
292 " -d <cmd> Command to exec for iface-down\n"
293 " -i <interface> Start with given interface, if available\n"
294 " -l LCD display mode\n"
295 " -h Print this help\n"
296 " -u <cmd> Command to exec for iface-up\n"
297 " -v Show version info and exit\n"
304 printf("%s version %s, compile-time options: ", NAME
, VERSION
);
306 #ifdef ENABLE_NWN_SUPPORT
307 printf("ENABLE NWN SUPPORT ");
313 void parse_cmdline(int argc
, char *argv
[])
317 while((c
= getopt(argc
, argv
, "d:i:lhu:v")) != EOF
) {
320 exec_down
= strdup(optarg
);
323 strncpy(startif
, optarg
, sizeof(startif
));
332 exec_up
= strdup(optarg
);
342 void sigchldhandler(int a
)
348 void exec_cmd(char *cmd
)
352 signal(SIGCHLD
, sigchldhandler
);
354 if(exec_busy
) return;
359 if (system(cmd
) == -1) {
360 fprintf(stderr
, "%s failed\n", cmd
);
369 void ButtonPressEvent(XButtonEvent
* xev
)
373 if (xev
->type
!= ButtonPress
) return;
375 switch (xev
->button
) {
384 if(ifinfo
.state
== 0) {
385 sprintf(buf
, exec_up
, ifinfo
.id
);
387 sprintf(buf
, exec_down
, ifinfo
.id
);
397 char *strupper(char *str
)
402 for (i
= 0; i
< strlen(str
); i
++)
403 str
[i
] = toupper(str
[i
]);
410 int getifinfo(char *ifname
, struct ifinfo_t
*info
)
413 struct sockaddr_in
*sa
;
416 static FILE *froute
= NULL
;
417 static FILE *fwireless
= NULL
;
418 static FILE *fdev
= NULL
;
419 #elif defined(__OpenBSD__)
420 struct ifreq ibuf
[32];
422 struct ifreq
*ifrp
, *ifend
;
432 if(froute
== NULL
) froute
= fopen("/proc/net/route", "r");
433 if(fwireless
== NULL
) fwireless
= fopen("/proc/net/wireless", "r");
434 if(fdev
== NULL
) fdev
= fopen("/proc/net/dev", "r");
438 strcpy(parent
, ifname
);
439 p
=strchr(parent
, ':');
442 strcpy(info
->id
, ifname
);
444 strcpy(ifr
.ifr_name
, ifname
);
446 /* Get status (UP/DOWN) */
448 if(ioctl(fd
, SIOCGIFFLAGS
, &ifr
) != -1) {
449 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
450 info
->state
= (ifr
.ifr_flags
& 1) ? 1 : 0;
455 /* Get mac address */
458 if(ioctl(fd
, SIOCGIFHWADDR
, &ifr
) != -1) {
459 memcpy(info
->hw
, ifr
.ifr_hwaddr
.sa_data
, 6);
461 memset(info
->hw
, 0, 6);
463 #elif defined(__OpenBSD__)
464 ifc
.ifc_len
= sizeof(ibuf
);
465 ifc
.ifc_buf
= (caddr_t
) ibuf
;
466 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
467 ifc
.ifc_len
< sizeof(struct ifreq
)) {
468 memset(info
->hw
, 0, 6);
470 /* Search interface configuration list for link layer address. */
472 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
473 while (ifrp
< ifend
) {
474 /* Look for interface */
475 if (strcmp(ifname
, ifrp
->ifr_name
) == 0 &&
476 ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
477 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
478 memcpy(info
->hw
, LLADDR((struct sockaddr_dl
*) &ifrp
->ifr_addr
), 6);
481 /* Bump interface config pointer */
482 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
483 if (r
< sizeof(*ifrp
))
485 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
492 if(ioctl(fd
, SIOCGIFADDR
, &ifr
) != -1) {
493 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
494 info
->ip
= sa
->sin_addr
.s_addr
;
501 if(ioctl(fd
, SIOCGIFNETMASK
, &ifr
) != -1) {
502 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
503 info
->nm
= sa
->sin_addr
.s_addr
;
508 /* Get default gateway if on this interface */
515 while(fgets(buf
, sizeof(buf
), froute
)) {
516 sscanf(buf
, "%s %x %x", a
, (unsigned int *) &b
,
517 (unsigned int *) &c
);
519 if((strcmp(a
, info
->id
) == 0) && (b
== 0)) {
525 #elif defined(__OpenBSD__)
527 struct rt_msghdr
*rtm
= NULL
;
528 char *buf
= NULL
, *next
, *lim
= NULL
;
532 struct sockaddr_in
*sin
;
538 mib
[4] = NET_RT_DUMP
;
540 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1) {
541 perror("route-sysctl-estimate");
545 if ((buf
= malloc(needed
)) == 0) {
546 printf("out of space\n");
549 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1) {
550 perror("sysctl of routing table");
557 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
558 rtm
= (struct rt_msghdr
*)next
;
559 sa
= (struct sockaddr
*)(rtm
+ 1);
560 sin
= (struct sockaddr_in
*)sa
;
562 if (sin
->sin_addr
.s_addr
== 0) {
563 sa
= (struct sockaddr
*)(ROUNDUP(sa
->sa_len
) + (char *)sa
);
564 sin
= (struct sockaddr_in
*)sa
;
565 info
->gw
= sin
->sin_addr
.s_addr
;
574 /* Get wireless link status if wireless */
578 if(fwireless
!= NULL
) {
579 fseek(fwireless
, 0, 0);
581 while(fgets(buf
, sizeof(buf
), fwireless
)) {
582 sscanf(buf
, "%s %d %d ", a
, &b
, &c
);
583 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
584 if(strcmp(a
, parent
) == 0) {
590 #ifdef ENABLE_NWN_SUPPORT
592 info
->sl
= nwn_get_link(parent
);
595 #elif defined(__OpenBSD__)
600 wreq
.wi_len
= WI_MAX_DATALEN
;
601 wreq
.wi_type
= WI_RID_COMMS_QUALITY
;
603 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
604 ifr
.ifr_data
= (caddr_t
)&wreq
;
606 if (ioctl(fd
, SIOCGWAVELAN
, &ifr
) != -1)
607 info
->sl
= letoh16(wreq
.wi_val
[0]);
611 /* Get Total tx/rx bytes */
617 while(fgets(buf
, sizeof(buf
), fdev
)) {
618 sscanf(buf
, "%s %d %d %d %d %d %d %d %d %d", a
, &b
, &d
,&d
,&d
,&d
,&d
,&d
,&d
, &c
);
619 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
620 if(strcmp(a
, parent
) == 0) {
631 void addifname(char *name
)
635 if(strcmp(name
, "lo") == 0) return;
636 if(strncmp(name
, "vlan", 4) == 0) return;
638 for(i
=0; i
<ifaces
; i
++) {
639 if(strcmp(ifname
[i
], name
) == 0) return;
642 strcpy(ifname
[ifaces
], name
);
652 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
655 void getifnames(void)
657 char pifname
[MAXIFS
][16];
669 * Copy list of interface names and clean the old list
672 for(i
=0; i
<ifaces
; i
++) strncpy(pifname
[i
], ifname
[i
], sizeof(pifname
[i
]));
677 f
= fopen("/proc/net/dev", "r");
680 fprintf(stderr
, "Can't open /proc/net/dev\n");
684 while(fgets(buf
, sizeof(buf
), f
)) {
686 while(*p1
== ' ') p1
++;
688 while(*p2
&& (*p2
!= ':')) p2
++;
697 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
699 if(ioctl(fd
, SIOCGIFCONF
, &ifc
) == -1) {
700 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
704 ifcount
= ifc
.ifc_len
/ sizeof(struct ifreq
);
706 for(i
=0; i
<ifcount
; i
++) {
707 addifname(ifc
.ifc_req
[i
].ifr_name
);
711 struct ifreq ibuf
[32];
713 struct ifreq
*ifrp
, *ifend
;
716 ifc
.ifc_len
= sizeof(ibuf
);
717 ifc
.ifc_buf
= (caddr_t
) ibuf
;
718 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
719 ifc
.ifc_len
< sizeof(struct ifreq
)) {
720 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
723 /* Search interface configuration list for link layer address. */
725 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
726 while (ifrp
< ifend
) {
727 if (ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
728 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
729 addifname(ifrp
->ifr_name
);
731 /* Bump interface config pointer */
732 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
733 if (r
< sizeof(*ifrp
))
735 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
740 * Check if the new list contains interfaces that were not in the old list. If a new
741 * interface is found, make it the current one to display. (-i will override)
744 for(i
=0; i
<ifaces
; i
++) {
746 for(j
=0; j
<pifaces
; j
++) if(strcmp(ifname
[i
], pifname
[j
]) == 0) isnew
= 0;
750 for(i
=0; i
<ifaces
; i
++) {
751 if(strcasecmp(ifname
[i
], startif
) == 0) {