1// LSHOSTS.C 2 3// BeOS-specific includes 4#include "TypeConstants.h" 5#include "Errors.h" 6#include "OS.h" 7 8// POSIX includes 9#include "stdio.h" 10#include "malloc.h" 11#include "string.h" 12#include "errno.h" 13#include "socket.h" 14#include "netdb.h" 15#include "signal.h" 16 17#include "betalk.h" 18#include "sysdepdefs.h" 19 20#ifndef NULL 21#define NULL 0L 22#endif 23 24#ifndef INVALID_SOCKET 25#define INVALID_SOCKET (int)(~0) 26#endif 27 28int main(int argc, char *argv[]); 29static void recvAlarm(int signal); 30static void usage(); 31 32 33int main(int argc, char *argv[]) 34{ 35 bt_request request; 36 struct sockaddr_in ourAddr, toAddr, fromAddr; 37 struct hostent *ent; 38 char buffer[8192]; 39 int sock, addrLen, bytes; 40 unsigned int serverIP; 41#ifdef SO_BROADCAST 42 int on = 1; 43#endif 44 45 if (argc > 2) 46 usage(); 47 48 memset(&toAddr, 0, sizeof(toAddr)); 49 toAddr.sin_family = AF_INET; 50 toAddr.sin_port = htons(BT_QUERYHOST_PORT); 51 if (argc == 1) 52 toAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); 53 else 54 { 55 ent = gethostbyname(argv[1]); 56 if (ent == NULL) 57 return 0; 58 59 serverIP = ntohl(*((unsigned int *) ent->h_addr)); 60 toAddr.sin_addr.s_addr = htonl(serverIP); 61 } 62 63 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 64 if (sock == INVALID_SOCKET) 65 return 0; 66 67 memset(&ourAddr, 0, sizeof(ourAddr)); 68 ourAddr.sin_family = AF_INET; 69 ourAddr.sin_port = htons(BT_QUERYHOST_PORT); 70 ourAddr.sin_addr.s_addr = htonl(INADDR_ANY); 71 72 if (bind(sock, (struct sockaddr *) &ourAddr, sizeof(ourAddr))) 73 if (errno != EADDRINUSE) 74 return 0; 75 76 // Normally, a setsockopt() call is necessary to turn broadcast mode on 77 // explicitly, although some versions of Unix don't care. BeOS doesn't 78 // currently even define SO_BROADCAST, unless you have BONE installed. 79#ifdef SO_BROADCAST 80 if (argc == 1) 81 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) 82 { 83 printf("Unable to obtain permission for a network broadcast.\n"); 84 closesocket(sock); 85 return 0; 86 } 87#endif 88 signal(SIGALRM, recvAlarm); 89 90 strcpy(request.signature, BT_RPC_SIGNATURE); 91 request.command = (argc == 1) ? BT_REQ_HOST_PROBE : BT_REQ_SHARE_PROBE; 92 if (sendto(sock, (char *) &request, sizeof(request), 0, (struct sockaddr *) &toAddr, sizeof(toAddr)) == -1) 93 { 94 printf("%s\n", strerror(errno)); 95 closesocket(sock); 96 return 0; 97 } 98 99 memset(buffer, 0, sizeof(buffer)); 100 alarm(3); 101 102 while (1) 103 { 104 addrLen = sizeof(fromAddr); 105 bytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &addrLen); 106 if (bytes < 0) 107 { 108 if (errno == EINTR) 109 break; 110 } 111 112 if (strncmp(buffer, BT_RPC_SIGNATURE, strlen(BT_RPC_SIGNATURE)) != 0) 113 if (argc == 1) 114 { 115 struct sockaddr_in *sin = (struct sockaddr_in *) &fromAddr; 116 ent = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); 117 if (ent) 118 printf("%s\n", ent->h_name); 119 else 120 { 121 uint8 *p = (uint8 *) &sin->sin_addr; 122 printf("%d.%d.%d.%d\n", p[0], p[1], p[2], p[3]); 123 } 124 } 125 else 126 { 127 bt_resource resource; 128 int bufPos = 0; 129 while (bufPos < bytes) 130 { 131 memcpy(&resource, buffer + bufPos, sizeof(bt_resource)); 132 resource.type = B_LENDIAN_TO_HOST_INT32(resource.type); 133 resource.subType = B_LENDIAN_TO_HOST_INT32(resource.subType); 134 if (resource.type == BT_SHARED_NULL) 135 break; 136 137 bufPos += sizeof(bt_resource); 138 printf("%s (%s)\n", resource.name, 139 resource.type == BT_SHARED_FOLDER ? "Shared Files" : "Shared Printer"); 140 } 141 } 142 } 143 144 alarm(0); 145 signal(SIGALRM, SIG_DFL); 146 closesocket(sock); 147} 148 149static void recvAlarm(int signal) 150{ 151 return; 152} 153 154static void usage() 155{ 156 printf("Usage: lshosts [host]\n"); 157 exit(0); 158} 159