10 #include <sys/filio.h>
13 #if defined(__sparc__) || (defined(WIN32) && !defined(__CYGWIN__))
14 #define SOCKOPT_TYPE char *
16 #define SOCKOPT_TYPE void *
20 #define SOCKOPT_LEN_TYPE unsigned
22 #define SOCKOPT_LEN_TYPE int
27 template <typename A, typename B> bool MIN(const A &a, const B &b) {
28 return ((a < b) ? a : b);
32 int GetSockType(const SOCK fd) {
34 SOCKOPT_LEN_TYPE len = sizeof(int);
36 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (SOCKOPT_TYPE)&type, &len)) {
44 int IsSocket(const SOCK fd) {
45 return (GetSockType(fd) >= 0);
48 int IsStreamSocket(const SOCK fd) {
49 return (GetSockType(fd) == SOCK_STREAM);
52 int IsDatagramSocket(const SOCK fd) {
53 return (GetSockType(fd) == SOCK_DGRAM);
57 int IsVirtualSocket(const SOCK fd) {
61 return S_ISFIFO(mystat.st_mode);
65 int IsValidIPMulticastAddress(const unsigned adx) {
67 //int x=(ntohl(port)>>24)&0xff;
68 int x = (adx >> 24) & 0xff;
70 if ((x < 224) || (x > 239)) {
77 void IPToHostname(const unsigned ip, char *name, const int namesize) {
83 he = gethostbyaddr((const char *)&ia, sizeof(ia), AF_INET);
85 strncpy(name, he ? he->h_name : "UNKNOWN HOST", namesize - 1);
89 void PrintIPAddress(const unsigned adx, FILE *out) {
90 fprintf(out,"%3d.%3d.%3d.%3d",
97 unsigned ToIPAddress(const char * hostname) {
100 if ((x = inet_addr(hostname)) != INADDR_NONE) {
105 if ((he = gethostbyname(hostname)) == NULL) {
108 memcpy(&x, he->h_addr, 4);
115 unsigned long GetRemoteSockAddress(SOCK sock) {
116 struct sockaddr_in remote_addr;
117 unsigned long remote_ip;
119 if (GetRemoteSockAddress(sock, (struct sockaddr *)&remote_addr) == -1) {
123 assert(remote_addr.sin_family == AF_INET);
124 remote_ip = ntohl(remote_addr.sin_addr.s_addr);
128 int GetRemoteSockAddress(SOCK sock, struct sockaddr * addr) {
129 SOCKOPT_LEN_TYPE addr_len = sizeof(struct sockaddr);
135 if (getpeername(sock, addr, &addr_len) == -1) {
143 unsigned long GetLocalSockAddress(SOCK sock) {
144 struct sockaddr_in local_addr;
145 unsigned long local_ip;
147 if (GetLocalSockAddress(sock, (struct sockaddr *)&local_addr) == -1) {
151 assert(local_addr.sin_family == AF_INET);
152 local_ip = ntohl(local_addr.sin_addr.s_addr);
156 int GetLocalSockAddress(SOCK sock, struct sockaddr * addr) {
157 SOCKOPT_LEN_TYPE addr_len = sizeof(struct sockaddr);
163 if (getsockname(sock, addr, &addr_len) == -1) {
171 int GetLocalMacAddress(const string dev_name, char * buf) {
172 return GetLocalMacAddress(dev_name.c_str(), buf);
175 int GetLocalMacAddress(const char * dev_name, char * buf) {
177 struct ifreq mac_req;
178 SOCK fd = socket(AF_INET, SOCK_STREAM, 0);
180 snprintf(mac_req.ifr_name, IF_NAMESIZE, "%s", dev_name);
182 if (ioctl(fd, SIOCGIFHWADDR, &mac_req) < 0) {
183 cerr << "Error Could not get the local MAC Address" << endl;
188 memcpy(buf, mac_req.ifr_hwaddr.sa_data, 6);
190 char temp_dev_name[256];
191 PIP_ADAPTER_INFO temp_adapter;
192 IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information
194 DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
196 DWORD dwStatus = GetAdaptersInfo(AdapterInfo, // [out] buffer to receive data
197 &dwBufLen); // [in] size of receive data buffer
199 assert(dwStatus == ERROR_SUCCESS); // Verify return value
201 temp_adapter = AdapterInfo;
203 while(temp_adapter) {
204 sprintf(temp_dev_name, "\\Device\\NPF_%s", temp_adapter->AdapterName);
206 if (strcmp(dev_name, temp_dev_name) == 0) {
207 memcpy(buf, temp_adapter->Address, 6);
210 temp_adapter = temp_adapter->Next;
217 int GetOpenTcpPorts(int ** ports) {
221 unsigned long rxq, txq, time_len, retr, inode, local_addr, rem_addr;
222 int d, local_port, rem_port, scan_num, timer_run, uid, timeout, state;
238 TCP_CLOSING /* now a valid state */
242 We do this because we use realloc,
243 so the first ptr-value must be null or we will realloc on some randome address
247 proc_fd = open("/proc/net/tcp", O_RDONLY);
252 /* This supports IPv6 which we will ignore for now...
254 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
255 &d, local_addr, &local_port, rem_addr, &rem_port, &state,
256 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
258 GetLine(proc_fd, proc_str);
260 while (GetLine(proc_fd, proc_str)) {
262 // We pretty much stole this from netstat.c in the net-tools package
263 scan_num = sscanf(proc_str.c_str(),
264 "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
265 &d, &local_addr, &local_port, &rem_addr, &rem_port, &state,
266 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
268 if (state == TCP_LISTEN) {
269 //printf("%s (%d)\n", ip_to_string(ntohl(local_addr)), local_port);
270 *ports = (int *)realloc((*ports), sizeof(int) * (num_ports + 1));
272 (*ports)[num_ports] = local_port;
282 DWORD table_size = 0;
283 PMIB_TCPTABLE tcp_table;
287 // AllocateAndGetTcpExTableFromStack(&tcp_table, TRUE, GetProcessHeap(), 2, 2);
289 dwError = GetTcpTable(NULL, &table_size, TRUE);
290 if (dwError != ERROR_INSUFFICIENT_BUFFER) {
291 cerr << "Error: " <<dwError << endl;
292 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
294 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
295 (LPTSTR) &error_msg, 0, NULL );
296 cerr << (char *)error_msg << endl;
300 tcp_table = (PMIB_TCPTABLE)malloc(table_size);
302 if (GetTcpTable(tcp_table, &table_size, TRUE)) {
306 *ports = (int *)malloc(sizeof(int) * tcp_table->dwNumEntries);
308 for (unsigned int i = 0; i < tcp_table->dwNumEntries; i++) {
309 //cerr << htons((WORD)tcp_table->table[i].dwLocalPort) << endl;
310 (*ports)[i] = ntohs((WORD)tcp_table->table[i].dwLocalPort);
313 return tcp_table->dwNumEntries;
317 int GetOpenUdpPorts(int ** ports) {
322 int local_port, rem_port, d, state, timer_run, uid, timeout;
323 unsigned long local_addr, rem_addr;
324 unsigned long rxq, txq, time_len, retr, inode;
328 We do this because we use realloc,
329 so the first ptr-value must be null or we will realloc on some randome address
333 proc_fd = open("/proc/net/udp", O_RDONLY);
339 GetLine(proc_fd, proc_str);
341 while (GetLine(proc_fd, proc_str)) {
343 // We pretty much stole this from netstat.c in the net-tools package
344 scan_num = sscanf(proc_str.c_str(),
345 "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
346 &d, &local_addr, &local_port,
347 &rem_addr, &rem_port, &state,
348 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
352 //printf("%s (%d)\n", ip_to_string(ntohl(local_addr)), local_port);
354 *ports = (int *)realloc((*ports), sizeof(int) * (num_ports + 1));
356 (*ports)[num_ports] = local_port;
366 DWORD table_size = 0;
367 PMIB_UDPTABLE udp_table;
371 // AllocateAndGetTcpExTableFromStack(&tcp_table, TRUE, GetProcessHeap(), 2, 2);
373 dwError = GetUdpTable(NULL, &table_size, TRUE);
374 if (dwError != ERROR_INSUFFICIENT_BUFFER) {
375 cerr << "Error: " <<dwError << endl;
376 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
378 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
379 (LPTSTR) &error_msg, 0, NULL );
380 cerr << (char *)error_msg << endl;
384 udp_table = (PMIB_UDPTABLE)malloc(table_size);
386 if (GetUdpTable(udp_table, &table_size, TRUE)) {
390 *ports = (int *)malloc(sizeof(int) * udp_table->dwNumEntries);
392 for (unsigned int i = 0; i < udp_table->dwNumEntries; i++) {
393 //cerr << htons((WORD)udp_table->table[i].dwLocalPort) << endl;
394 (*ports)[i] = ntohs((WORD)udp_table->table[i].dwLocalPort);
397 return udp_table->dwNumEntries;
403 #define WELL_KNOWN_HOST ((char*)"www.cnn.com")
404 #define WELL_KNOWN_PORT 80
406 unsigned GetMyIPAddress() {
407 static unsigned adx = 0;
408 //static bool setup = false;
413 host = getenv("RPS_WELL_KNOWN_HOST") ? getenv("RPS_WELL_KNOWN_HOST") : WELL_KNOWN_HOST;
414 port = getenv("RPS_WELL_KNOWN_PORT") ? atoi(getenv("RPS_WELL_KNOWN_PORT")) : WELL_KNOWN_PORT;
419 // Connect to a well known machine and check out our socket's address
420 if ((fd = CreateAndSetupTcpSocket()) == -1) {
423 if (ConnectToHost(fd, host, port) == -1) {
428 adx = GetLocalSockAddress(fd);
436 SOCK CreateAndSetupUdpSocket(const int bufsize, const bool nonblocking) {
440 // create socket for connections
441 if ((mysocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
445 // set reuseaddr to avoid binding problems
446 if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
452 if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
453 (const char*) &val, sizeof(val)) < 0) {
460 if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
461 (const char*)&val, sizeof(val)) < 0) {
468 if (IOCTL(mysocket, FIONBIO, &val)) {
478 SOCK CreateAndSetupTcpSocket(const int bufsize, const bool nodelay, const bool nonblocking) {
482 // create socket for connections
483 if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
487 // set reuseaddr to avoid binding problems
488 if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
492 // Set nodelay so that our messages get
495 if (setsockopt(mysocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(int))) {
503 if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
504 (const char*) &val, sizeof(val)) < 0) {
511 if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
512 (const char*)&val, sizeof(val)) < 0) {
519 if (IOCTL(mysocket, FIONBIO, &val)) {
529 SOCK CreateAndSetupUnixDomainSocket(const int bufsize, const bool nonblocking) {
533 // create socket for connections
534 if ((mysocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
538 // set reuseaddr to avoid binding problems
539 if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
545 if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
546 (const char*)&val, sizeof(val)) < 0) {
553 if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
554 (const char*)&val, sizeof(val)) < 0) {
561 if (IOCTL(mysocket, FIONBIO, &val)) {
571 int SetNoDelaySocket(const SOCK fd, const bool nodelay) {
572 int val = nodelay == true;
574 // Set nodelay so that our messages get
575 return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(int));
579 int BindSocket(const SOCK mysocket, const unsigned adx, const int myport) {
580 struct sockaddr_in my_sa;
582 memset(&my_sa, 0, sizeof(my_sa));
583 my_sa.sin_port = htons(myport);
584 my_sa.sin_addr.s_addr = htonl(adx);
585 my_sa.sin_family = AF_INET;
587 if (bind(mysocket, (struct sockaddr *)&my_sa, sizeof(my_sa))) {
593 int BindSocket(const SOCK mysocket, const int myport) {
594 return BindSocket(mysocket, (unsigned)INADDR_ANY, myport);
597 int BindSocket(const SOCK mysocket, const char *host_or_ip, const int myport) {
598 return BindSocket(mysocket, ToIPAddress(host_or_ip), myport);
601 int BindSocket(const SOCK mysocket, const char *pathname) {
602 #if defined(WIN32) && !defined(__CYGWIN__)
605 struct sockaddr_un my_sa;
608 memset(&my_sa, 0, sizeof(my_sa));
609 my_sa.sun_family = AF_UNIX;
610 strcpy(my_sa.sun_path, pathname);
611 len = strlen(my_sa.sun_path) + sizeof(my_sa.sun_family);
613 if (bind(mysocket, (struct sockaddr *)&my_sa,len)) {
621 int ListenSocket(const SOCK mysocket, const int maxc) {
622 int maxcon = MIN(maxc, SOMAXCONN);
623 return listen(mysocket, maxcon);
626 int ConnectToHost(const SOCK mysocket, const int hostip, const int port) {
627 struct sockaddr_in sa;
629 memset(&sa, 0, sizeof(sa));
630 sa.sin_port = htons(port);
631 sa.sin_addr.s_addr = htonl(hostip);
632 sa.sin_family = AF_INET;
634 return connect(mysocket, (struct sockaddr *)&sa, sizeof(sa));
638 int ConnectToHost(const SOCK mysocket, const char *host, const int port) {
639 return ConnectToHost(mysocket, ToIPAddress(host), port);
643 int ConnectToPath(const SOCK mysocket, const char *pathname) {
644 #if defined(WIN32) && !defined(__CYGWIN__)
647 struct sockaddr_un my_sa;
650 memset(&my_sa, 0, sizeof(my_sa));
651 my_sa.sun_family = AF_UNIX;
652 strcpy(my_sa.sun_path, pathname);
653 len = strlen(my_sa.sun_path) + sizeof(my_sa.sun_family);
655 if (connect(mysocket, (struct sockaddr *)&my_sa,len)) {
664 int JoinMulticastGroup(const SOCK mysocket, const unsigned adx) {
665 if (!IsValidIPMulticastAddress(adx)) {
671 memset(&req, 0, sizeof(req));
673 req.imr_multiaddr.s_addr = htonl(adx);
674 req.imr_interface.s_addr = htonl(INADDR_ANY);
676 if (setsockopt(mysocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
677 (const char*)&req, sizeof(req)) < 0) {
683 int JoinMulticastGroup(const SOCK mysocket, const char *IP) {
684 return JoinMulticastGroup(mysocket, ToIPAddress(IP));
688 int LeaveMulticastGroup(const SOCK mysocket, const unsigned adx) {
689 if (!IsValidIPMulticastAddress(adx)) {
695 memset(&req, 0, sizeof(req));
697 req.imr_multiaddr.s_addr = htonl(adx);
698 req.imr_interface.s_addr = htonl(INADDR_ANY);
700 if (setsockopt(mysocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
701 (const char *) &req, sizeof(req)) < 0) {
709 int LeaveMulticastGroup(const SOCK mysocket, const char *IP) {
710 return LeaveMulticastGroup(mysocket, ToIPAddress(IP));
715 int SetMulticastTimeToLive(const SOCK mysocket, const unsigned char ttl) {
716 if (setsockopt(mysocket, IPPROTO_IP, IP_MULTICAST_TTL,
717 (SOCKOPT_TYPE)&ttl, (SOCKOPT_LEN_TYPE)sizeof(ttl)) < 0) {
723 int SendTo(const SOCK mysocket,
724 const unsigned ip, const int port,
725 const char *buf, const int len, const bool sendall) {
726 struct sockaddr_in sa;
728 memset(&sa, 0, sizeof(sockaddr_in));
729 sa.sin_family = AF_INET;
730 sa.sin_addr.s_addr = htonl(ip);
731 sa.sin_port = htons(port);
734 return sendto(mysocket, buf, len, 0, (struct sockaddr *)&sa, sizeof(sockaddr_in));
739 sent = sendto(mysocket, &(buf[len - left]), left, 0, (struct sockaddr *)&sa, sizeof(sockaddr_in));
741 if (errno == EINTR) {
755 int ReceiveFrom(const SOCK mysocket,
756 const unsigned ip, const int port,
757 char *buf, const int len,
760 struct sockaddr_in sa;
761 SOCKOPT_LEN_TYPE size = sizeof(sockaddr_in);
763 memset(&sa, 0, sizeof(sockaddr_in));
764 sa.sin_family = AF_INET;
765 sa.sin_addr.s_addr = htonl(ip);
766 sa.sin_port = htons(port);
769 return recvfrom(mysocket, buf, len, 0, (struct sockaddr *)&sa, &size);
774 received = recvfrom(mysocket, &(buf[len - left]), left, 0, (struct sockaddr *)&sa, &size);
776 if (errno == EINTR) {
781 } else if (received == 0) {
791 int SendTo(const SOCK mysocket,
792 const char *host_or_ip, const int port,
793 const char *buf, const int len, const bool sendall) {
794 return SendTo(mysocket, ToIPAddress(host_or_ip), port, buf, len, sendall);
797 int ReceiveFrom(const SOCK mysocket,
798 const char *host_or_ip, const int port,
799 char *buf, const int len, const bool recvall) {
800 return ReceiveFrom(mysocket, ToIPAddress(host_or_ip), port, buf, len, recvall);
806 int Send(SOCK fd, SSL *ssl, const char *buf, const int len, const bool sendall) {
809 return SSL_write(ssl, buf, len);
811 return write(fd, buf, len);
818 sent = SSL_write(ssl, &(buf[len - left]), left);
820 sent = write(fd, &(buf[len - left]), left);
824 if (errno == EINTR) {
829 } else if (sent == 0) {
839 int Receive(SOCK fd, SSL *ssl, char *buf, const int len, const bool recvall) {
842 return SSL_read(ssl, buf, len);
844 return read(fd, buf, len);
852 received = SSL_read(ssl, &(buf[len - left]), left);
854 received = read(fd, &(buf[len - left]), left);
858 if (errno == EINTR) {
863 } else if (received == 0) {
874 int GetLine(SOCK fd, SSL *ssl, string &s) {
876 s.erase(s.begin(), s.end());
878 int rc = Receive(fd, ssl, &c, 1, true);
882 if ((rc == 0) || (c == '\n')) {
890 int PutLine(SOCK fd, SSL *ssl, const string &s) {
893 return (Send(fd, ssl, s2.c_str(), s2.size(), true) - 1);
897 int Send(SOCK fd, const char *buf, const int len, const bool sendall) {
899 return WRITE(fd, buf, len);
904 sent = WRITE(fd, &(buf[len - left]), left);
907 if (errno == EINTR) {
912 } else if (sent == 0) {
922 int Receive(SOCK fd, char *buf, const int len, const bool recvall) {
924 return READ(fd, buf, len);
930 received = READ(fd, &(buf[len - left]), left);
933 if (errno == EINTR) {
938 } else if (received == 0) {
949 int GetLine(SOCK fd, string &s) {
951 s.erase(s.begin(), s.end());
954 int rc = Receive(fd, &c, 1, true);
960 if ((rc == 0) || (c == '\n')) {
969 int PutLine(SOCK fd, const string &s) {
972 return (Send(fd, s2.c_str(), s2.size(), true) - 1);
978 int SetSignalHandler(const int signum, void (*handler)(int), const bool oneshot)
980 #if defined(WIN32) || defined(CYGWIN) // cygwin does not appear to have sigaction, so...
981 signal(signum,handler); //notice that this is oneshot
986 #if defined(__sparc__)
987 sa.sa_handler= (void (*)(...)) handler; // SUN FREAKS
989 sa.sa_handler=handler;
992 sigemptyset(&(sa.sa_mask));
994 #define SIGHAND_ONESHOT SA_ONESHOT
996 #if defined(__osf__) || defined(__FreeBSD__) || defined(__sparc__)
997 #define SIGHAND_ONESHOT SA_RESETHAND
1000 sa.sa_flags = ((oneshot == true) ? SIGHAND_ONESHOT : 0);
1005 return sigaction(signum, &sa, 0);
1010 int IgnoreSignal(const int signum)
1012 return SetSignalHandler(signum, SIG_IGN);
1015 int ListenToSignal(const int signum)
1017 return SetSignalHandler(signum, SIG_DFL);
1020 #if defined(WIN32) && !defined(__CYGWIN__)
1026 WSAStartup(MAKEWORD(2,0),&foo);
1029 if (WSAIsBlocking()) {
1030 WSACancelBlockingCall();
1036 SockInit thesockinit; // constructor should get called on startup.