#include #include #include #include #include #include #include #include #include #include #include #include struct _entry { u_int16_t gameid; u_int32_t ip; u_int16_t port1; u_int16_t port2; } __attribute__ ((packed)); static char hlswheader[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH"; static char *id2name[] = { "Unknown", // 0 "Halflife", "Quake 1", "Quake 2", "Q3Comp", "Unreal Tournament", "Quake 3 Arena", "Elite Force", "Return to Castle Wolfenstein", "GSProt", "Command & Conquer Renegade", // 10 "Medal of Honor: Allied Assault", "Jedi Knight 2", "Soldier of Fortune", "Unreal Tournament 2003", "America's Army: Operations", "Battlefield 1942", "Alien vs. Predator 2", "Rune", "Project IGI2: Covert Strike", "Never Winter Nights", // 20 "Medal of Honor: Allied Assault Spearhead", "Operation Flashpoint", "Operation Flashpoint Resistance", "Devastation", "Wolfenstein - Enemy Territory", "Elite Force 2", "Jedi Knight 3", "Medal of Honor: Allied Assault Breakthrough", "Tribes 2", "Halo", // 30 "Call of Duty", "Savage: The Battle for Newerth", "Unreal Tournament 2004", "HLSteam", "Battlefield Vietnam", "GS2Prot", "Pain Killer", "Doom 3", "OGPProt", "Halflife 2", // 40 "Tribes Vengeance", "Call of Duty: United Offensive" }; static struct option opts[] = { {"destination", 1, 0, 'd'}, {"intervall", 1, 0, 'i'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; static int sock; static void parse_pkt(struct sockaddr_in *src, void *pkt, unsigned int size) { struct _entry *server; struct in_addr tmp; if (size < sizeof(hlswheader) || strncmp(pkt, hlswheader, sizeof(hlswheader))) { printf("received INVALID packet from: %15s:%-5d size=%d\n", inet_ntoa(src->sin_addr), ntohs(src->sin_port), size); } else { printf("received hlsw packet from: %15s:%-5d size=%d\n", inet_ntoa(src->sin_addr), ntohs(src->sin_port), size); server = pkt + sizeof(hlswheader); while ((void *)server < pkt + size) { tmp.s_addr = server->ip; printf(" ip=%15s port1=%5d port2=%5d gameid=%2d (%s)\n", inet_ntoa(tmp), server->port1, server->port2, server->gameid, id2name[server->gameid]); server++; } } } static int scan_init() { int i = 1; if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket()"); return -1; } if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i))) { perror("setsockopt()"); return -1; } return 0; } static int scan_transmit(struct sockaddr_in *dst) { if (sendto(sock, hlswheader, sizeof(hlswheader), 0, (struct sockaddr *)dst, sizeof(struct sockaddr_in)) < 0) { perror("sendto()"); return -1; } return 0; } static int scan_receive() { struct sockaddr_in src; struct timeval tv; fd_set fdsel; unsigned int i = 1, recvsize; void *pkt; FD_ZERO(&fdsel); FD_SET(sock, &fdsel); tv.tv_sec = 1; tv.tv_usec = 0; while (1) { if (select(FD_SETSIZE, &fdsel, NULL, NULL, &tv) < 0) { perror("select"); return -1; } /* timeout: our exit */ if (tv.tv_sec == 0 && tv.tv_usec == 0) break; /* get packetsize */ if (ioctl(sock, FIONREAD, &recvsize) == -1) { perror("ioctl"); return -1; } if (recvsize > 0) { if (!(pkt = malloc(recvsize))) { perror("malloc()"); return -1; } i = sizeof(struct sockaddr_in); recvsize = recvfrom(sock, pkt, recvsize, 0, (struct sockaddr *)&src, &i); parse_pkt(&src, pkt, recvsize); free(pkt); } } return 0; } int main(int argc, char *argv[]) { struct sockaddr_in dst; int arg = 0, code = 0; int freq = -1; dst.sin_family = AF_INET; dst.sin_port = htons(7140); inet_aton("255.255.255.255", &dst.sin_addr); while (code != -1) { code = getopt_long(argc, argv, "d:i:h", opts, &arg); switch (code) { case 'd': /* destination */ if (inet_pton(dst.sin_family, optarg, &dst.sin_addr) <= 0) { fprintf(stderr, "invalid destination: %s\n", optarg); exit(-1); } break; case 'i': /* intervall */ freq = atoi(optarg); if (freq < 1) { fprintf(stderr, "invalid interval: %s\n", optarg); exit(-1); } break; case 'h': /* help */ printf("Usage: masterquery [options]\n" "Options: \n" " --destination -d scan destination \n" " --intervall -i scan intervall in seconds\n" " --help -h this help\n" "\n"); exit(0); break; case '?': /* error */ exit(-1); break; default: /* unknown / all options parsed */ break; } } if (scan_init()) exit(-1); while (1) { if (scan_transmit(&dst)) exit(-1); if (scan_receive()) exit(-1); if (freq < 0) break; sleep(freq -1); } close(sock); return 0; }