// dunstat.c - Winmain (built with dun.bat, dr.bat for resources) // XP manifest included in dunstat.rc // Version 2.1 // Date January 1, 2005 // Copyright NAT Software, 2005 #include #include #include "sockio.h" #include "..\src\h\dunstat.h" HANDLE hThread; HANDLE hSem; HINSTANCE hInst; HWND ghDlg; HWND hCtrlHangup; HWND hCtrlDial; HWND hCtrlList; HWND hCtrlEdit; HWND hCtrlOK; HMENU hMenu; NOTIFYICONDATA iconData; #define MYWM_NOTIFYICON 200 int icon_state; #define DOWN 0 #define DISCONNECTED 1 #define CONNECTED 2 #define BUSY 3 int dial; int busy, flag, wake_flag, stop_thread, tid; char gateway[256]; char mac_str[256]; char connection[1500]; char gbuf[1500]; char xbuf[1500]; int mac[6]; // int not char because of sscanf int wait_time; // Function prototypes BOOL APIENTRY DunDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); BOOL APIENTRY HelpDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); int parse(LPSTR CmdLine); int exec(char *cmdline, short flag); BOOL CenterWindow(HWND hWin); // // kprintf - low-level printf // int kprintf(char *fmt, ...) { va_list args; char buf[0x8000]; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); return MessageBox(NULL, buf, "DUN Status", MB_OKCANCEL | MB_SETFOREGROUND); } // // dprintf - low-level printf via OutputDebugString // Run www.sysinternals.com DebugView.exe // to view this output. // int dprintf(char *fmt, ...) { va_list args; char buf[0x8000]; int n; va_start(args, fmt); n = vsprintf(buf, fmt, args); va_end(args); if (n < 0) return SYSERR; buf[n] = 0; OutputDebugString(buf); return n; } /*------------------------------------------------------------------------ * * Add items to list box, but only if buf has changed * *------------------------------------------------------------------------ */ int AddItems(HWND hDlg, char *buf) { char *ptr1; char *ptr2; char tmp[1500]; if (!strcmp(buf, gbuf) && strlen(buf)) return 0; strcpy(gbuf, buf); strcpy(tmp, buf); SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_RESETCONTENT, 0, 0); ptr1 = tmp; while (1) { ptr2 = (char *) strchr(ptr1, '\n'); if (ptr2 == 0) break; *ptr2 = 0; SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_ADDSTRING, 0, (LPARAM) ptr1); ptr1 = ++ptr2; } return 0; } /*------------------------------------------------------------------------ * * Status thread function * *------------------------------------------------------------------------ */ DWORD WINAPI status(void *param) { int i, len, s, result; char buf[1500]; char tmp[256]; result = 0; busy = 0; while (!stop_thread) { // Use a new socket each time, or sReadT won't work // TODO: fix sReadT s = connectUDP(gateway, "echo"); if (result == 0) sWrite(s, "connect", 8); else sWrite(s, xbuf, strlen(xbuf) + 1); len = sReadT(s, buf, 1400, 1000); // If we got an ICMP response, retry the sReadT if (len == -1) len = sReadT(s, buf, 1400, 1000); if (len == -3) { // Server Unreachable if (busy) { strcpy(tmp, "Server is busy"); for (i=0; i= 1) { if (hThread == 0) hThread = CreateThread(0, 0, status, 0, 0, &tid); else { stop_thread = 1; ReleaseSemaphore(hSem, 1, NULL); WaitForSingleObject(hThread, INFINITE); stop_thread = 0; hThread = CreateThread(0, 0, status, 0, 0, &tid); } sprintf(tmp, "DUN connection status for %s", gateway); strcpy(iconData.szTip, tmp); Shell_NotifyIcon(NIM_MODIFY, &iconData); } if (hThread) { gbuf[0] = 0; ShowWindow(hDlg, SW_HIDE); flag = 0; return TRUE; } SetDlgItemText(hDlg, IDC_EDIT2, "No gateway specified"); SetFocus(hCtrlEdit); return FALSE; case IDCANCEL: EndDialog(hDlg, IDOK); return TRUE; case IDC_LISTBOX1: // Selection if (busy) return TRUE; connection[0] = 0; len = SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_GETCURSEL, 0, 0); if (len == LB_ERR) return TRUE; SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_GETTEXT, (WPARAM) len, (LPARAM) (LPCTSTR) tmp); str_esc(tmp); sscanf(tmp, "<%s", connection); if (strlen(connection) > 0) { ptr = strchr(connection, '>'); if (ptr) *ptr = 0; EnableWindow(hCtrlDial, 0); EnableWindow(hCtrlHangup, 1); } else { EnableWindow(hCtrlDial, 1); EnableWindow(hCtrlHangup, 0); strcpy(connection, tmp); } return TRUE; case IDC_PUSHBUTTON1: // HANGUP EnableWindow(hCtrlDial, 0); EnableWindow(hCtrlHangup, 0); sprintf(xbuf, "hangup %s", connection); ReleaseSemaphore(hSem, 1, NULL); dial = 0; return TRUE; case IDC_PUSHBUTTON2: // DIAL EnableWindow(hCtrlDial, 0); EnableWindow(hCtrlHangup, 0); sprintf(xbuf, "dial %s", connection); ReleaseSemaphore(hSem, 1, NULL); dial = 1; return TRUE; case IDC_PUSHBUTTON3: // WAKE EnableWindow(hCtrlDial, 0); EnableWindow(hCtrlHangup, 0); wol(); sprintf(tmp, "Magic Packet sent to %02X-%02X-%02X-%02X-%02X-%02X", mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff, mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff); SetDlgItemText(hDlg, IDC_EDIT2, tmp); return TRUE; } break; } return FALSE; } BOOL CenterWindow(HWND hWin) { int result; HWND hDesktop; RECT rc; RECT rcd; hDesktop = GetDesktopWindow(); result = GetWindowRect(hWin, &rc); if (result) result = GetWindowRect(hDesktop, &rcd); if (result == 0) return -1; SetWindowPos(hWin, HWND_TOP, rcd.right/2 - (rc.right - rc.left)/2, rcd.bottom/2 - (rc.bottom - rc.top)/2, 0, 0, SWP_NOSIZE); return 0; } /* sockio.c - connectUDP connectTCP passiveUDP passiveTCP sRead sWrite sReadFrom sWriteTo sClose sShutdown wname2ip wip2name */ u_short portbase = 0; /* port base, for non-root servers */ /*------------------------------------------------------------------------ * connectUDP - connect to a specified UDP service on a specified host *------------------------------------------------------------------------ */ int P32API connectUDP( host, service ) char *host; /* name of host to which connection is desired */ char *service; /* service associated with the desired port */ { return connectsock(host, service, "udp"); } /*------------------------------------------------------------------------ * connectTCP - connect to a specified TCP service on a specified host *------------------------------------------------------------------------ */ int P32API connectTCP( host, service ) char *host; /* name of host to which connection is desired */ char *service; /* service associated with the desired port */ { return connectsock( host, service, "tcp"); } /*------------------------------------------------------------------------ * passiveUDP - create a passive socket for use in a UDP server *------------------------------------------------------------------------ */ int P32API passiveUDP( service ) char *service; /* service associated with the desired port */ { return passivesock(service, "udp", 0); } /*------------------------------------------------------------------------ * passiveTCP - create a passive socket for use in a TCP server *------------------------------------------------------------------------ */ int P32API passiveTCP( service, qlen ) char *service; /* service associated with the desired port */ int qlen; /* maximum server request queue length */ { return passivesock(service, "tcp", qlen); } /*------------------------------------------------------------------------ * sAccept - accept a TCP connection *------------------------------------------------------------------------ */ int P32API sAccept( s, saddr) SOCKET s; struct saddr *saddr; { int alen = sizeof(struct sockaddr); return accept(s, (struct sockaddr *) saddr, &alen); } /*------------------------------------------------------------------------ * sRead - receive from a connected socket *------------------------------------------------------------------------ */ int P32API sRead(s, buf, len) SOCKET s; char *buf; int len; { return recv(s, buf, len, 0); } /*------------------------------------------------------------------------ * sReadT - receive from a connected socket with TIMEOUT in msec *------------------------------------------------------------------------ */ int P32API sReadT(s, buf, len, time) SOCKET s; char *buf; int len; int time; { struct timeval timeout; int result; fd_set rfds; timeout.tv_sec = 0; timeout.tv_usec = time * 1000; FD_ZERO(&rfds); FD_SET(s, &rfds); result = select(FD_SETSIZE, &rfds, (fd_set *) 0, (fd_set *) 0, &timeout); switch (result) { case 0: return TIMEOUT; case 1: return recv(s, buf, len, 0); case SOCKET_ERROR: dprintf("sReadT: select returned SOCKET_ERROR %d\n", WSAGetLastError()); return SYSERR; default: return SYSERR; } } /*------------------------------------------------------------------------ * sReadFrom - receive a datagram from a connected or unconnected socket *------------------------------------------------------------------------ */ int P32API sReadFrom(s, buf, len, saddr) SOCKET s; char *buf; int len; struct saddr *saddr; { int alen = sizeof(struct saddr); saddr->sin_family = AF_INET; return recvfrom(s, buf, len, 0, (struct sockaddr *) saddr, &alen); } /*------------------------------------------------------------------------ * sReadFromT - receive a datagram with timeout from (un)connected socket *------------------------------------------------------------------------ */ int P32API sReadFromT(s, buf, len, saddr, time) SOCKET s; char *buf; int len; struct saddr *saddr; int time; { struct timeval timeout; int result; fd_set rfds; int alen = sizeof(struct saddr); timeout.tv_sec = 0; timeout.tv_usec = time * 1000; FD_ZERO(&rfds); FD_SET(s, &rfds); result = select(FD_SETSIZE, &rfds, (fd_set *) 0, (fd_set *) 0, &timeout); switch (result) { case 0: return TIMEOUT; case 1: saddr->sin_family = AF_INET; return recvfrom(s, buf, len, 0, (struct sockaddr *) saddr, &alen); case SOCKET_ERROR: printf("sReadT: select returned SOCKET_ERROR\n"); return SYSERR; default: return SYSERR; } } /*------------------------------------------------------------------------ * sWrite - send to a connected socket *------------------------------------------------------------------------ */ int P32API sWrite(s, buf, len) SOCKET s; char *buf; int len; { return send(s, buf, len, 0); } /*------------------------------------------------------------------------ * sWriteTo - send to an unconnected socket *------------------------------------------------------------------------ */ int P32API sWriteTo(s, buf, len, saddr) SOCKET s; char *buf; int len; struct saddr *saddr; { int alen = sizeof(struct saddr); saddr->sin_family = AF_INET; if (sendto(s, buf, len, 0, (struct sockaddr *) saddr, alen) <= 0) return h_errno; return OK; // return sendto(s, buf, len, 0, (struct sockaddr *) saddr, alen); } /*------------------------------------------------------------------------ * sClose -- close a socket *------------------------------------------------------------------------ */ int P32API sClose(SOCKET s) { if (s == SYSERR) return SYSERR; return closesocket(s); } /*------------------------------------------------------------------------ * sShutdown -- shutdown a socket *------------------------------------------------------------------------ */ int P32API sShutdown(SOCKET s) { int status; status = shutdown(s, 1); /* disable sends */ if (status) printf("\nsockio: shutdown failed\n"); return status; } /*------------------------------------------------------------------------ * sockalloc - allocate a UDP socket *------------------------------------------------------------------------ */ int P32API sockalloc() { SOCKET s; if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { printf("\nsockio: can't create socket: error %d\n", h_errno); return SYSERR; } return s; } /*------------------------------------------------------------------------ * connectsock - allocate & connect a socket using TCP or UDP *------------------------------------------------------------------------ */ int P32API connectsock( host, service, protocol ) char *host; /* name of host to which connection is desired */ char *service; /* service associated with the desired port */ char *protocol; /* name of protocol to use ("tcp" or "udp") */ { struct hostent *phe; /* pointer to host information entry */ struct servent *pse; /* pointer to service information entry */ struct protoent *ppe; /* pointer to protocol information entry*/ struct sockaddr_in sin; /* an Internet endpoint address */ SOCKET s; /* socket descriptor */ int type; /* socket type */ char option = TRUE; /* enable the Boolean option */ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; /* Map service name to port number */ if ( pse = getservbyname(service, protocol) ) sin.sin_port = pse->s_port; else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0 ) { printf("\nsockio: can't get %s service entry\n", service); return SYSERR; } /* Map host name to IP address, allowing for dotted decimal */ /* CAUTION: inet_addr interprets an address such as 192.168.000.010 as 192.168.0.8 and NOT 192.168.0.10 In other words, it assumes that a leading zero indicates octal notation */ if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE ) if ( phe = gethostbyname(host) ) memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length); else { kprintf("\nsockio: can't get %s host entry\n", host); return SYSERR; } /* Map protocol name to protocol number */ if ( (ppe = getprotobyname(protocol)) == 0) { printf("\nsockio: can't get %s protocol entry\n", protocol); return SYSERR; } /* Use protocol to choose a socket type */ if (strcmp(protocol, "udp") == 0) type = SOCK_DGRAM; else type = SOCK_STREAM; /* Allocate a socket */ s = socket(PF_INET, type, ppe->p_proto); if (s == INVALID_SOCKET) { printf("\nsockio: can't create socket: error %d\n", h_errno); return SYSERR; } /* Connect the socket */ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { printf("\nsockio: can't connect to %s:%s error %d\n", host, service, h_errno); return SYSERR; } /* Enable UDP broadcasts */ if (type == SOCK_DGRAM) setsockopt(s, SOL_SOCKET, SO_BROADCAST, &option, sizeof(BOOL)); return s; } /*------------------------------------------------------------------------ * passivesock - allocate & bind a server socket using TCP or UDP *------------------------------------------------------------------------ */ int P32API passivesock( service, protocol, qlen ) char *service; /* service associated with the desired port */ char *protocol; /* name of protocol to use ("tcp" or "udp") */ int qlen; /* maximum length of the server request queue */ { struct servent *pse; /* pointer to service information entry */ struct protoent *ppe; /* pointer to protocol information entry*/ struct sockaddr_in sin; /* an Internet endpoint address */ int s, type; /* socket descriptor and socket type */ char option = TRUE; /* enable the Boolean option */ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; /* Map service name to port number */ if ( pse = getservbyname(service, protocol) ) sin.sin_port = htons(ntohs((u_short)((u_short)pse->s_port + portbase))); else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0 ) { printf("\nsockio: can't get %s service entry\n", service); return SYSERR; } /* Map protocol name to protocol number */ if ( (ppe = getprotobyname(protocol)) == 0) { printf("\nsockio: can't get %s protocol entry\n", protocol); return SYSERR; } /* Use protocol to choose a socket type */ if (strcmp(protocol, "udp") == 0) type = SOCK_DGRAM; else type = SOCK_STREAM; /* Allocate a socket */ s = socket(PF_INET, type, ppe->p_proto); if (s < 0) { printf("\nsockio: can't create socket: error %d\n", h_errno); return SYSERR; } /* Bind the socket */ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { closesocket(s); return SYSERR; } if (type == SOCK_STREAM && listen(s, qlen) < 0) { printf("\nsockio: can't listen on %s port: error %d\n", service, h_errno); return SYSERR; } /* Enable UDP broadcasts */ if (type == SOCK_DGRAM) setsockopt(s, SOL_SOCKET, SO_BROADCAST, &option, sizeof(BOOL)); return s; } /*------------------------------------------------------------------------ * wname2ip - resolve a DNS name *------------------------------------------------------------------------ */ int P32API wname2ip(ip, nam) IPaddr ip; /* resolved IP address */ char *nam; /* name to resolve */ { struct hostent *phe; /* pointer to host information entry */ struct sockaddr_in sin; /* an Internet endpoint address */ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; /* Map host name to IP address, allowing for dotted decimal */ if ((sin.sin_addr.s_addr = inet_addr(nam)) == INADDR_NONE) if ( phe = gethostbyname(nam)) memcpy(ip, phe->h_addr, phe->h_length); else return SYSERR; else { memcpy(ip, &sin.sin_addr.s_addr, 4); return OK; } return OK; } /*------------------------------------------------------------------------ * wip2name - find the DNS name for a given IP address *------------------------------------------------------------------------ */ int P32API wip2name(nam, ip) IPaddr ip; /* IP address to resolve */ char *nam; /* resolved name */ { struct hostent *phe; /* pointer to host information entry */ if (phe=gethostbyaddr(ip, 4, AF_INET)) { strcpy(nam, phe->h_name); return OK; } return SYSERR; } /*------------------------------------------------------------------------ * wip2dot - create the dotted decimal form of ip in pdot *------------------------------------------------------------------------ */ int P32API wip2dot(pdot, ip) char *pdot; IPaddr ip; { char *pch = pdot; int i; sprintf(pch, "%u", ip[0] & 0xff); pch += strlen(pch); for (i=1; i