150 lines
2.6 KiB
C
150 lines
2.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip.h>
|
|
|
|
struct _entry {
|
|
u_int16_t gameid;
|
|
u_int32_t ip;
|
|
u_int16_t port1;
|
|
u_int16_t port2;
|
|
} __attribute__ ((packed));
|
|
|
|
static char scanmsg[] = "\xFF\xFF\xFF\xFFHLSWLANSEARCH";
|
|
|
|
char *gameid2name[] = { "Unknown", // 0
|
|
"HL",
|
|
"Q1",
|
|
"Q2",
|
|
"Q3Comp",
|
|
"UT",
|
|
"Q3",
|
|
"EF",
|
|
"RtCW",
|
|
"GSProt",
|
|
"CCR", // 10
|
|
"MoHAA",
|
|
"JK2",
|
|
"SoF2",
|
|
"UT2K3",
|
|
"AAO",
|
|
"BF1942",
|
|
"AvP2",
|
|
"Rune",
|
|
"IGI2",
|
|
"NWN", // 20
|
|
"MoHAAS",
|
|
"OPF",
|
|
"OPFR",
|
|
"DVS",
|
|
"ET",
|
|
"EF2",
|
|
"JK3",
|
|
"MoHAAB",
|
|
"Tribes2",
|
|
"HALO", // 30
|
|
"CoD",
|
|
"Savage",
|
|
"UT2K4",
|
|
"HLSteam",
|
|
"BFV",
|
|
"GS2Prot",
|
|
"PK",
|
|
"D3",
|
|
"OGPProt",
|
|
"HL2", // 40
|
|
"TribesV",
|
|
"CoDUO" };
|
|
|
|
int main(int argc, char *argv[]) {
|
|
struct sockaddr_in dst;
|
|
struct timeval tv;
|
|
struct _entry *srv;
|
|
fd_set fdsel, fdcpy;
|
|
int sock, i = 1, recvsize;
|
|
void *pkt;
|
|
|
|
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
perror("socket()");
|
|
exit(-1);
|
|
}
|
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i))) {
|
|
perror("setsockopt()");
|
|
exit(-1);
|
|
}
|
|
|
|
dst.sin_family = AF_INET;
|
|
dst.sin_port = htons(7130);
|
|
inet_aton("0.0.0.0", &dst.sin_addr);
|
|
|
|
if (bind(sock, (struct sockaddr *)&dst, sizeof(dst)) < 0) {
|
|
perror("bind()");
|
|
exit(-1);
|
|
}
|
|
|
|
dst.sin_port = htons(7140);
|
|
inet_aton("255.255.255.255", &dst.sin_addr);
|
|
|
|
if (sendto(sock, scanmsg, sizeof(scanmsg), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0) {
|
|
perror("sendto()");
|
|
exit(-1);
|
|
}
|
|
|
|
FD_ZERO(&fdsel);
|
|
FD_SET(sock, &fdsel);
|
|
|
|
tv.tv_sec = 1;
|
|
tv.tv_usec = 0;
|
|
|
|
while (1) {
|
|
memcpy(&fdcpy, &fdsel, sizeof(fdsel));
|
|
if (select(FD_SETSIZE, &fdcpy, NULL, NULL, &tv) < 0) {
|
|
perror("select");
|
|
exit(-1);
|
|
}
|
|
|
|
if (tv.tv_sec == 0 && tv.tv_usec == 0)
|
|
exit(0);
|
|
|
|
ioctl(sock, FIONREAD, &recvsize);
|
|
|
|
if (recvsize <= 0) {
|
|
continue;
|
|
}
|
|
|
|
if (!(pkt = malloc(recvsize))) {
|
|
perror("malloc()");
|
|
exit(-1);
|
|
}
|
|
|
|
i = sizeof(struct sockaddr_in);
|
|
recvsize = recvfrom(sock, pkt, recvsize, 0, (struct sockaddr *)&dst, &i);
|
|
|
|
printf("received packet from: %s:%d size=%d\n",
|
|
inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), recvsize);
|
|
|
|
srv = pkt + sizeof(scanmsg);
|
|
while ((void *)srv < pkt + recvsize) {
|
|
dst.sin_addr.s_addr = srv->ip;
|
|
printf(" ip=%s port1=%d port2=%d gameid=%d (%s)\n",
|
|
inet_ntoa(dst.sin_addr),
|
|
srv->port1,
|
|
srv->port2,
|
|
srv->gameid,
|
|
gameid2name[srv->gameid]);
|
|
srv++;
|
|
}
|
|
free(pkt);
|
|
}
|
|
|
|
return 0;
|
|
}
|