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
, (char **) wmifinfo_led_xpm
,
182 (char*) wmifinfo_led_bits
, wmifinfo_led_width
,
183 wmifinfo_led_height
, BackColor
, LabelColor
,
184 WindGustColor
, DataColor
, StationTimeColor
);
186 openXwindow(argc
, argv
, (char **) wmifinfo_lcd_xpm
,
187 (char*) wmifinfo_lcd_bits
, wmifinfo_lcd_width
,
188 wmifinfo_lcd_height
, BackColor
, LabelColor
,
189 WindGustColor
, DataColor
, StationTimeColor
);
192 /* Initialize global variables */
194 fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
195 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
196 ifc
.ifc_buf
= malloc(ifc
.ifc_len
);
200 while (XPending(display
)) {
201 XNextEvent(display
, &event
);
203 switch (event
.type
) {
208 ButtonPressEvent(&event
.xbutton
);
216 if ((d
++ == 3) || (ifno
!= pifno
) || (exec_busy
!= prev_exec_busy
)) {
220 copyXPMArea(64, 0, 64, 64, 0, 0);
224 ifno
= ifno
% ifaces
;
226 getifinfo(ifname
[ifno
], &ifinfo
);
228 if(ifno
!= pifno
) lastbytes
= ifinfo
.bytes
;
230 sprintf(buf
, "%-7s", ifinfo
.id
);
232 drawtext(buf
, &font2
, 6, 4);
234 if(memcmp(ifinfo
.hw
, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
235 drawhwaddr(ifinfo
.hw
);
238 if(ifinfo
.ip
) drawipaddr(ifinfo
.ip
, 0);
239 if(ifinfo
.nm
) drawipaddr(ifinfo
.nm
, 1);
240 if(ifinfo
.gw
) drawipaddr(ifinfo
.gw
, 2);
242 /* WLAN signal level */
246 #elif defined(__OpenBSD__)
250 copyXPMArea(4, 82, x
*4, 4, 6, 53);
258 if(ifinfo
.state
) x
+= 8;
259 if(lastbytes
== ifinfo
.bytes
) x
+= 16;
261 copyXPMArea(64 + x
, 81, 8, 8, 50, 4);
262 lastbytes
= ifinfo
.bytes
;
267 prev_exec_busy
= exec_busy
;
276 FD_SET(ConnectionNumber(display
), &fds
);
278 select(ConnectionNumber(display
)+1, &fds
, NULL
, NULL
, &tv
);
279 #elif defined(__OpenBSD__)
290 "usage: wmifinfo [-lh] [-i interface]\n"
291 " -d <cmd> Command to exec for iface-down\n"
292 " -i <interface> Start with given interface, if available\n"
293 " -l LCD display mode\n"
294 " -h Print this help\n"
295 " -u <cmd> Command to exec for iface-up\n"
296 " -v Show version info and exit\n"
303 printf("%s version %s, compile-time options: ", NAME
, VERSION
);
305 #ifdef ENABLE_NWN_SUPPORT
306 printf("ENABLE NWN SUPPORT ");
312 void parse_cmdline(int argc
, char *argv
[])
316 while((c
= getopt(argc
, argv
, "d:i:lhu:v")) != EOF
) {
319 exec_down
= strdup(optarg
);
322 strncpy(startif
, optarg
, sizeof(startif
));
331 exec_up
= strdup(optarg
);
341 void sigchldhandler(int a
)
347 void exec_cmd(char *cmd
)
351 signal(SIGCHLD
, sigchldhandler
);
353 if(exec_busy
) return;
358 if (system(cmd
) == -1) {
359 fprintf(stderr
, "%s failed\n", cmd
);
368 void ButtonPressEvent(XButtonEvent
* xev
)
372 if (xev
->type
!= ButtonPress
) return;
374 switch (xev
->button
) {
383 if(ifinfo
.state
== 0) {
384 sprintf(buf
, exec_up
, ifinfo
.id
);
386 sprintf(buf
, exec_down
, ifinfo
.id
);
396 char *strupper(char *str
)
401 for (i
= 0; i
< strlen(str
); i
++)
402 str
[i
] = toupper(str
[i
]);
409 int getifinfo(char *ifname
, struct ifinfo_t
*info
)
412 struct sockaddr_in
*sa
;
415 static FILE *froute
= NULL
;
416 static FILE *fwireless
= NULL
;
417 static FILE *fdev
= NULL
;
418 #elif defined(__OpenBSD__)
419 struct ifreq ibuf
[32];
421 struct ifreq
*ifrp
, *ifend
;
431 if(froute
== NULL
) froute
= fopen("/proc/net/route", "r");
432 if(fwireless
== NULL
) fwireless
= fopen("/proc/net/wireless", "r");
433 if(fdev
== NULL
) fdev
= fopen("/proc/net/dev", "r");
437 strcpy(parent
, ifname
);
438 p
=strchr(parent
, ':');
441 strcpy(info
->id
, ifname
);
443 strcpy(ifr
.ifr_name
, ifname
);
445 /* Get status (UP/DOWN) */
447 if(ioctl(fd
, SIOCGIFFLAGS
, &ifr
) != -1) {
448 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
449 info
->state
= (ifr
.ifr_flags
& 1) ? 1 : 0;
454 /* Get mac address */
457 if(ioctl(fd
, SIOCGIFHWADDR
, &ifr
) != -1) {
458 memcpy(info
->hw
, ifr
.ifr_hwaddr
.sa_data
, 6);
460 memset(info
->hw
, 0, 6);
462 #elif defined(__OpenBSD__)
463 ifc
.ifc_len
= sizeof(ibuf
);
464 ifc
.ifc_buf
= (caddr_t
) ibuf
;
465 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
466 ifc
.ifc_len
< sizeof(struct ifreq
)) {
467 memset(info
->hw
, 0, 6);
469 /* Search interface configuration list for link layer address. */
471 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
472 while (ifrp
< ifend
) {
473 /* Look for interface */
474 if (strcmp(ifname
, ifrp
->ifr_name
) == 0 &&
475 ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
476 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
477 memcpy(info
->hw
, LLADDR((struct sockaddr_dl
*) &ifrp
->ifr_addr
), 6);
480 /* Bump interface config pointer */
481 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
482 if (r
< sizeof(*ifrp
))
484 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
491 if(ioctl(fd
, SIOCGIFADDR
, &ifr
) != -1) {
492 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
493 info
->ip
= sa
->sin_addr
.s_addr
;
500 if(ioctl(fd
, SIOCGIFNETMASK
, &ifr
) != -1) {
501 sa
= (struct sockaddr_in
*)&(ifr
.ifr_addr
);
502 info
->nm
= sa
->sin_addr
.s_addr
;
507 /* Get default gateway if on this interface */
514 while(fgets(buf
, sizeof(buf
), froute
)) {
515 sscanf(buf
, "%s %x %x", a
, &b
, &c
);
517 if((strcmp(a
, info
->id
) == 0) && (b
== 0)) {
523 #elif defined(__OpenBSD__)
525 struct rt_msghdr
*rtm
= NULL
;
526 char *buf
= NULL
, *next
, *lim
= NULL
;
530 struct sockaddr_in
*sin
;
536 mib
[4] = NET_RT_DUMP
;
538 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1) {
539 perror("route-sysctl-estimate");
543 if ((buf
= malloc(needed
)) == 0) {
544 printf("out of space\n");
547 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1) {
548 perror("sysctl of routing table");
555 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
556 rtm
= (struct rt_msghdr
*)next
;
557 sa
= (struct sockaddr
*)(rtm
+ 1);
558 sin
= (struct sockaddr_in
*)sa
;
560 if (sin
->sin_addr
.s_addr
== 0) {
561 sa
= (struct sockaddr
*)(ROUNDUP(sa
->sa_len
) + (char *)sa
);
562 sin
= (struct sockaddr_in
*)sa
;
563 info
->gw
= sin
->sin_addr
.s_addr
;
572 /* Get wireless link status if wireless */
576 if(fwireless
!= NULL
) {
577 fseek(fwireless
, 0, 0);
579 while(fgets(buf
, sizeof(buf
), fwireless
)) {
580 sscanf(buf
, "%s %d %d ", a
, &b
, &c
);
581 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
582 if(strcmp(a
, parent
) == 0) {
588 #ifdef ENABLE_NWN_SUPPORT
590 info
->sl
= nwn_get_link(parent
);
593 #elif defined(__OpenBSD__)
598 wreq
.wi_len
= WI_MAX_DATALEN
;
599 wreq
.wi_type
= WI_RID_COMMS_QUALITY
;
601 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
602 ifr
.ifr_data
= (caddr_t
)&wreq
;
604 if (ioctl(fd
, SIOCGWAVELAN
, &ifr
) != -1)
605 info
->sl
= letoh16(wreq
.wi_val
[0]);
609 /* Get Total tx/rx bytes */
615 while(fgets(buf
, sizeof(buf
), fdev
)) {
616 sscanf(buf
, "%s %d %d %d %d %d %d %d %d %d", a
, &b
, &d
,&d
,&d
,&d
,&d
,&d
,&d
, &c
);
617 if(strchr(a
, ':')) *(strchr(a
, ':')) = 0;
618 if(strcmp(a
, parent
) == 0) {
629 void addifname(char *name
)
633 if(strcmp(name
, "lo") == 0) return;
634 if(strncmp(name
, "vlan", 4) == 0) return;
636 for(i
=0; i
<ifaces
; i
++) {
637 if(strcmp(ifname
[i
], name
) == 0) return;
640 strcpy(ifname
[ifaces
], name
);
650 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
653 void getifnames(void)
655 char pifname
[MAXIFS
][16];
661 * Copy list of interface names and clean the old list
664 for(i
=0; i
<ifaces
; i
++) strncpy(pifname
[i
], ifname
[i
], sizeof(pifname
[i
]));
674 f
= fopen("/proc/net/dev", "r");
677 fprintf(stderr
, "Can't open /proc/net/dev\n");
681 while(fgets(buf
, sizeof(buf
), f
)) {
683 while(*p1
== ' ') p1
++;
685 while(*p2
&& (*p2
!= ':')) p2
++;
694 ifc
.ifc_len
= sizeof(struct ifreq
) * 10;
696 if(ioctl(fd
, SIOCGIFCONF
, &ifc
) == -1) {
697 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
701 ifcount
= ifc
.ifc_len
/ sizeof(struct ifreq
);
703 for(i
=0; i
<ifcount
; i
++) {
704 addifname(ifc
.ifc_req
[i
].ifr_name
);
708 struct ifreq ibuf
[32];
710 struct ifreq
*ifrp
, *ifend
;
713 ifc
.ifc_len
= sizeof(ibuf
);
714 ifc
.ifc_buf
= (caddr_t
) ibuf
;
715 if (ioctl(fd
, SIOCGIFCONF
, (char *) &ifc
) == -1 ||
716 ifc
.ifc_len
< sizeof(struct ifreq
)) {
717 fprintf(stderr
, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno
));
720 /* Search interface configuration list for link layer address. */
722 ifend
= (struct ifreq
*) ((char *) ibuf
+ ifc
.ifc_len
);
723 while (ifrp
< ifend
) {
724 if (ifrp
->ifr_addr
.sa_family
== AF_LINK
&&
725 ((struct sockaddr_dl
*) &ifrp
->ifr_addr
)->sdl_type
== IFT_ETHER
) {
726 addifname(ifrp
->ifr_name
);
728 /* Bump interface config pointer */
729 r
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
730 if (r
< sizeof(*ifrp
))
732 ifrp
= (struct ifreq
*) ((char *) ifrp
+ r
);
737 * Check if the new list contains interfaces that were not in the old list. If a new
738 * interface is found, make it the current one to display. (-i will override)
741 for(i
=0; i
<ifaces
; i
++) {
743 for(j
=0; j
<pifaces
; j
++) if(strcmp(ifname
[i
], pifname
[j
]) == 0) isnew
= 0;
747 for(i
=0; i
<ifaces
; i
++) {
748 if(strcasecmp(ifname
[i
], startif
) == 0) {