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
79 char LabelColor
[30] = "#79bdbf";
80 char WindGustColor
[30] = "#ff0000";
81 char DataColor
[30] = "#ffbf50";
82 char BackColor
[30] = "#181818";
83 char StationTimeColor
[30] = "#c5a6ff";
85 struct font_t font1
= { " 0123456789ABCDEF", 64, 74, 4, 5, 17};
86 struct font_t font2
= { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789: ", 1, 65, 5, 7, 26};
88 char *exec_dflt
= "echo Use the -u and -d options for setting ifup/ifdown commands.";
93 char startif
[16] = "";
94 char ifname
[MAXIFS
][16];
97 struct ifinfo_t ifinfo
;
100 volatile int exec_busy
=0;
103 void parse_cmdline(int argc
, char *argv
[]);
104 void ButtonPressEvent(XButtonEvent
*);
105 char *strupper(char *str
);
106 void getifnames(void);
107 int getifinfo(char *ifname
, struct ifinfo_t
*info
);
112 void drawtext(char *str
, struct font_t
*font
, int x
, int y
)
119 p
= strchr(font
->chars
, str
[i
]);
120 ix
= (p
) ? (p
- font
->chars
) : 0;
122 iy
= (ix
/ font
->charspline
);
123 ix
= (ix
% font
->charspline
);
125 copyXPMArea( font
->sx
+ ix
* font
->dx
,
126 font
->sy
+ iy
* font
->dy
,
137 void drawipaddr(uint32_t a
, int linenum
)
141 uint32_t addr
= ntohl(a
);
144 snprintf(buf
, 4, "%3d", (addr
>> ((3-i
)*8)) & 255);
145 drawtext(buf
, &font1
, 5 + i
*14, 19 + linenum
*9);
149 void drawhwaddr(unsigned char *addr
)
155 snprintf(buf
, 4, "%02X", addr
[i
]);
156 drawtext(buf
, &font1
, 6 + i
*9, 46);
160 int main(int argc
, char *argv
[])
171 int prev_exec_busy
=0;
174 exec_down
= exec_dflt
;
176 parse_cmdline(argc
, argv
);
178 initXwindow(argc
, argv
);
180 if(mode
== MODE_LED
) {
181 openXwindow(argc
, argv
, wmifinfo_led_xpm
, wmifinfo_led_bits
,
182 wmifinfo_led_width
, wmifinfo_led_height
, BackColor
,
183 LabelColor
, WindGustColor
, DataColor
, StationTimeColor
);
185 openXwindow(argc
, argv
, wmifinfo_lcd_xpm
, wmifinfo_lcd_bits
,
186 wmifinfo_lcd_width
, wmifinfo_lcd_height
, BackColor
,
187 LabelColor
, WindGustColor
, DataColor
, StationTimeColor
);
190 // Initialize global variables
192 fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
193 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
194 ifc
.ifc_buf
= malloc(ifc
.ifc_len
);
198 while (XPending(display
)) {
199 XNextEvent(display
, &event
);
201 switch (event
.type
) {
206 ButtonPressEvent(&event
.xbutton
);
214 if ((d
++ == 3) || (ifno
!= pifno
) || (exec_busy
!= prev_exec_busy
)) {
218 copyXPMArea(64, 0, 64, 64, 0, 0);
222 ifno
= ifno
% ifaces
;
224 getifinfo(ifname
[ifno
], &ifinfo
);
226 if(ifno
!= pifno
) lastbytes
= ifinfo
.bytes
;
228 sprintf(buf
, "%-7s", ifinfo
.id
);
230 drawtext(buf
, &font2
, 6, 4);
232 if(memcmp(ifinfo
.hw
, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
233 drawhwaddr(ifinfo
.hw
);
236 if(ifinfo
.ip
) drawipaddr(ifinfo
.ip
, 0);
237 if(ifinfo
.nm
) drawipaddr(ifinfo
.nm
, 1);
238 if(ifinfo
.gw
) drawipaddr(ifinfo
.gw
, 2);
244 #elif defined(__OpenBSD__)
248 copyXPMArea(4, 82, x
*4, 4, 6, 53);
256 if(ifinfo
.state
) x
+= 8;
257 if(lastbytes
== ifinfo
.bytes
) x
+= 16;
259 copyXPMArea(64 + x
, 81, 8, 8, 50, 4);
260 lastbytes
= ifinfo
.bytes
;
265 prev_exec_busy
= exec_busy
;
274 FD_SET(ConnectionNumber(display
), &fds
);
276 select(ConnectionNumber(display
)+1, &fds
, NULL
, NULL
, &tv
);
277 #elif defined(__OpenBSD__)
288 "usage: wmifinfo [-lh] [-i interface]\n"
289 " -d <cmd> Command to exec for iface-down\n"
290 " -i <interface> Start with given interface, if available\n"
291 " -l LCD display mode\n"
292 " -h Print this help\n"
293 " -u <cmd> Command to exec for iface-up\n"
294 " -v Show version info and exit\n"
301 printf("%s version %s, compile-time options: ", NAME
, VERSION
);
303 #ifdef ENABLE_NWN_SUPPORT
304 printf("ENABLE NWN SUPPORT ");
310 void parse_cmdline(int argc
, char *argv
[])
314 while((c
= getopt(argc
, argv
, "d:i:lhu:v")) != EOF
) {
317 exec_down
= strdup(optarg
);
320 strncpy(startif
, optarg
, sizeof(startif
));
329 exec_up
= strdup(optarg
);
339 void sigchldhandler(int a
)
345 void exec_cmd(char *cmd
)
349 signal(SIGCHLD
, sigchldhandler
);
351 if(exec_busy
) return;
363 void ButtonPressEvent(XButtonEvent
* xev
)
367 if (xev
->type
!= ButtonPress
) return;
369 switch (xev
->button
) {
378 if(ifinfo
.state
== 0) {
379 sprintf(buf
, exec_up
, ifinfo
.id
);
381 sprintf(buf
, exec_down
, ifinfo
.id
);
391 char *strupper(char *str
)
396 for (i
= 0; i
< strlen(str
); i
++)
397 str
[i
] = toupper(str
[i
]);
404 int getifinfo(char *ifname
, struct ifinfo_t
*info
)
408 struct sockaddr_in
*sa
;
411 static FILE *froute
= NULL
;
412 static FILE *fwireless
= NULL
;
413 static FILE *fdev
= NULL
;
414 #elif defined(__OpenBSD__)
415 struct ifreq ibuf
[32];
417 struct ifreq
*ifrp
, *ifend
;
427 if(froute
== NULL
) froute
= fopen("/proc/net/route", "r");
428 if(fwireless
== NULL
) fwireless
= fopen("/proc/net/wireless", "r");
429 if(fdev
== NULL
) fdev
= fopen("/proc/net/dev", "r");
433 strcpy(parent
, ifname
);
434 p
=strchr(parent
, ':');
437 strcpy(info
->id
, ifname
);
439 strcpy(ifr
.ifr_name
, ifname
);
441 // Get status (UP/DOWN)
443 if(ioctl(fd
, SIOCGIFFLAGS
, &ifr
) != -1) {
444 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
445 info
->state
= (ifr
.ifr_flags
& 1) ? 1 : 0;
453 if(ioctl(fd
, SIOCGIFHWADDR
, &ifr
) != -1) {
454 memcpy(info
->hw
, ifr
.ifr_hwaddr
.sa_data
, 6);
456 memset(info
->hw
, 0, 6);
458 #elif defined(__OpenBSD__)
459 ifc
.ifc_len
= sizeof(ibuf
);
460 ifc
.ifc_buf
= (caddr_t
) ibuf
;
461 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
462 ifc
.ifc_len
< sizeof(struct ifreq
)) {
463 memset(info
->hw
, 0, 6);
465 /* Search interface configuration list for link layer address. */
467 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
468 while (ifrp
< ifend
) {
469 /* Look for interface */
470 if (strcmp(ifname
, ifrp
->ifr_name
) == 0 &&
471 ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
472 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
473 memcpy(info
->hw
, LLADDR((struct sockaddr_dl
*) &ifrp
->ifr_addr
), 6);
476 /* Bump interface config pointer */
477 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
478 if (r
< sizeof(*ifrp
))
480 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
487 if(ioctl(fd
, SIOCGIFADDR
, &ifr
) != -1) {
488 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
489 info
->ip
= sa
->sin_addr
.s_addr
;
496 if(ioctl(fd
, SIOCGIFNETMASK
, &ifr
) != -1) {
497 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
498 info
->nm
= sa
->sin_addr
.s_addr
;
503 // Get default gateway if on this interface
510 while(fgets(buf
, sizeof(buf
), froute
)) {
511 r
= sscanf(buf
, "%s %x %x", a
, &b
, &c
);
513 if((strcmp(a
, info
->id
) == 0) && (b
== 0)) {
519 #elif defined(__OpenBSD__)
521 struct rt_msghdr
*rtm
= NULL
;
522 char *buf
= NULL
, *next
, *lim
= NULL
;
526 struct sockaddr_in
*sin
;
532 mib
[4] = NET_RT_DUMP
;
534 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1) {
535 perror("route-sysctl-estimate");
539 if ((buf
= malloc(needed
)) == 0) {
540 printf("out of space\n");
543 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1) {
544 perror("sysctl of routing table");
551 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
552 rtm
= (struct rt_msghdr
*)next
;
553 sa
= (struct sockaddr
*)(rtm
+ 1);
554 sin
= (struct sockaddr_in
*)sa
;
556 if (sin
->sin_addr
.s_addr
== 0) {
557 sa
= (struct sockaddr
*)(ROUNDUP(sa
->sa_len
) + (char *)sa
);
558 sin
= (struct sockaddr_in
*)sa
;
559 info
->gw
= sin
->sin_addr
.s_addr
;
568 // Get wireless link status if wireless
572 if(fwireless
!= NULL
) {
573 fseek(fwireless
, 0, 0);
575 while(fgets(buf
, sizeof(buf
), fwireless
)) {
576 r
= sscanf(buf
, "%s %d %d ", a
, &b
, &c
);
577 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
578 if(strcmp(a
, parent
) == 0) {
584 #ifdef ENABLE_NWN_SUPPORT
586 info
->sl
= nwn_get_link(parent
);
589 #elif defined(__OpenBSD__)
594 wreq
.wi_len
= WI_MAX_DATALEN
;
595 wreq
.wi_type
= WI_RID_COMMS_QUALITY
;
597 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
598 ifr
.ifr_data
= (caddr_t
)&wreq
;
600 if (ioctl(fd
, SIOCGWAVELAN
, &ifr
) != -1)
601 info
->sl
= letoh16(wreq
.wi_val
[0]);
605 // Get Total tx/rx bytes
611 while(fgets(buf
, sizeof(buf
), fdev
)) {
612 r
= sscanf(buf
, "%s %d %d %d %d %d %d %d %d %d", a
, &b
, &d
,&d
,&d
,&d
,&d
,&d
,&d
, &c
);
613 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
614 if(strcmp(a
, parent
) == 0) {
625 void addifname(char *name
)
629 if(strcmp(name
, "lo") == 0) return;
630 if(strncmp(name
, "vlan", 4) == 0) return;
632 for(i
=0; i
<ifaces
; i
++) {
633 if(strcmp(ifname
[i
], name
) == 0) return;
636 strcpy(ifname
[ifaces
], name
);
646 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
649 void getifnames(void)
651 char pifname
[MAXIFS
][16];
657 * Copy list of interface names and clean the old list
660 for(i
=0; i
<ifaces
; i
++) strncpy(pifname
[i
], ifname
[i
], sizeof(pifname
[i
]));
670 f
= fopen("/proc/net/dev", "r");
673 fprintf(stderr
, "Can't open /proc/net/dev\n");
677 fgets(buf
, sizeof(buf
),f
);
678 while(fgets(buf
, sizeof(buf
), f
)) {
680 while(*p1
== ' ') p1
++;
682 while(*p2
&& (*p2
!= ':')) p2
++;
691 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
693 if(ioctl(fd
, SIOCGIFCONF
, &ifc
) == -1) {
694 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
698 ifcount
= ifc
.ifc_len
/ sizeof(struct ifreq
);
700 for(i
=0; i
<ifcount
; i
++) {
701 addifname(ifc
.ifc_req
[i
].ifr_name
);
705 struct ifreq ibuf
[32];
707 struct ifreq
*ifrp
, *ifend
;
710 ifc
.ifc_len
= sizeof(ibuf
);
711 ifc
.ifc_buf
= (caddr_t
) ibuf
;
712 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
713 ifc
.ifc_len
< sizeof(struct ifreq
)) {
714 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
717 /* Search interface configuration list for link layer address. */
719 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
720 while (ifrp
< ifend
) {
721 if (ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
722 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
723 addifname(ifrp
->ifr_name
);
725 /* Bump interface config pointer */
726 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
727 if (r
< sizeof(*ifrp
))
729 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
734 * Check if the new list contains interfaces that were not in the old list. If a new
735 * interface is found, make it the current one to display. (-i will override)
738 for(i
=0; i
<ifaces
; i
++) {
740 for(j
=0; j
<pifaces
; j
++) if(strcmp(ifname
[i
], pifname
[j
]) == 0) isnew
= 0;
744 for(i
=0; i
<ifaces
; i
++) {
745 if(strcasecmp(ifname
[i
], startif
) == 0) {