/*************************************************************************** * Copyright (C) 03/2005 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #define __USE_GNU #include #include #include #include #include #include #include "hlswmaster.h" #include "netpkt.h" #include "plugin.h" #include "plugin_helper.h" /** * pkt_queue_portarr() * sendet an eine reihe von ports * * @param *dstip destination IP, wenn NULL wird broadcast angenommen * @param *portarr ports an die gesendet wird * @param *buf daten die gesendet werden * @param size groesse der daten * @return false bei fehler */ int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *buf, unsigned int size) { unsigned short port; int ret = 1; while (portarr && portarr->portlo) { for (port = portarr->portlo; port <= portarr->porthi; port++) if (!pkt_send(dstip, port, buf, size)) ret = 0; portarr++; } return ret; } /** * pkt_check_portarr() * prueft ob der src-port des pakets in der portliste vorhanden ist * * @param *pkt paket vom gameserver * @param *portarr ports die angenommen werden * @return die gameid der portrange oder 0 wenn nicht vorhanden */ int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr) { unsigned short port; while (portarr && portarr->portlo) { for (port = portarr->portlo; port <= portarr->porthi; port++) if (port == ntohs(pkt->addr.sin_port)) return portarr->gameid; portarr++; } return 0; } /** * pkt_memcmp() * vergleicht das Paket mit einem Speicherbereich * * @param *pkt paket vom gameserver * @param offset offset ab dem verglichen wird * @param *search daten nach denen gesucht wird * @param size laenge der daten * @return false wenn gleich * * @todo return false wenn offset + size >= pkt->size ? */ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { if (offset >= pkt->size) return 1; /* nicht ueber das paket hinaus vergleichen */ if (offset + size >= pkt->size) size = pkt->size - offset; return memcmp(pkt->buf + offset, search, size); } /** * pkt_memmem() * sucht einen Speicherbereich in dem Paket * * @param *pkt paket vom gameserver * @param offset offset ab dem gesucht wird * @param *search daten nach denen gesucht wird * @param size laenge der daten * @return offset auf den string im Paket, oder -1 wenn nicht gefunden */ int pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { void *found; if (offset >= pkt->size) return -1; found = memmem(pkt->buf + offset, pkt->size, search, size); return (found == NULL) ? -1 : (found - (void *)pkt->buf); } /** * pkt_merge() * fuegt zwei pakete zu einem zusammen * die header werden vom ersten Paket uebernommen * die pakete werden nicht gefreed(!) * * @param *pkt1 erstes Paket * @param *pkt2 zweites Paket * @return zusammengefasstes Paket */ struct net_pkt * pkt_merge(struct net_pkt *pkt1, struct net_pkt *pkt2) { struct net_pkt *ret; ret = malloc(sizeof(struct net_pkt) + pkt1->size + pkt2->size); memcpy(&ret->addr, &pkt1->addr, sizeof(ret->addr)); ret->size = pkt1->size + pkt2->size; memcpy(ret->buf, pkt1->buf, pkt1->size); memcpy(ret->buf + pkt1->size, pkt2->buf, pkt2->size); return ret; } /** * server_add_pkt() * fuegt der serverliste einen server hinzu * * @param gameid gameid des gameservers * @param *pkt daten vom gameserver (fuer ip/port) * @return false bei fehler */ int server_add_pkt(unsigned int gameid, struct net_pkt *pkt) { return server_add(gameid, pkt->addr.sin_addr.s_addr, ntohs(pkt->addr.sin_port), 0); } /** * pkt_ntoa() * gibt die IP des Pakets als String zurueck * * @param *pkt daten vom gameserver * @return pointer auf String */ char * pkt_ntoa(struct net_pkt *pkt) { return inet_ntoa(pkt->addr.sin_addr); } /** * pkt_getport() * gibt den Port des Pakets als short zurueck * * @param *pkt daten vom gameserver * @return portnummer */ unsigned short pkt_getport(struct net_pkt *pkt) { return ntohs(pkt->addr.sin_port); } /** * pkt_sameaddr() * vergleicht die Adressen zweier Pakete * * @param *pkt1 Paket 1 * @param *pkt2 Paket 2 * @return true wenn Adressen gleich */ int pkt_sameaddr(struct net_pkt *pkt1, struct net_pkt *pkt2) { return (pkt1->addr.sin_addr.s_addr == pkt2->addr.sin_addr.s_addr) && (pkt1->addr.sin_port == pkt2->addr.sin_port); } /** * pkt_parse_int() * gibt die dezimalzahl in dem paket ab einer position zurueck * * @param *pkt daten vom gameserver * @param offset offset auf den begin des integers * @param *val pointer auf das ergebnis * @return Anzahl der gelesenen Zeichen oder 0 bei fehler */ int pkt_parse_int(struct net_pkt *pkt, unsigned int offset, int *val) { unsigned char *max = pkt->buf + pkt->size; unsigned char *c = pkt->buf + offset; /* untere grenze abtesten */ if (pkt->buf > c || c > max) return -1; *val = 0; /* ziffern einlesen */ while (isdigit(*c) && c < max) *val = (*val * 10) + (*c++ - 0x30); return (c - (pkt->buf + offset)); } /** * pkt_parse_ip() * gibt die IP in *.*.*.* ab p als integer zurueck * * @param *pkt daten vom gameserver * @param offset offset auf den begin der IP * @param *ip pointer auf eine in_addr struct * @return Anzahl der gelesenen Zeichen oder 0 bei Fehler */ int pkt_parse_ip(struct net_pkt *pkt, int offset, struct in_addr *ip) { int i, tmp, count, pos = offset; ip->s_addr = 0; for (i = 0; i < 4; i++) { count = pkt_parse_int(pkt, pos, &tmp); pos += count; if (count == 0 || tmp < 0 || tmp > 255) return 0; ip->s_addr = ip->s_addr>>8 | tmp<<24; if (i != 3 && pkt->buf[pos++] != '.') return 0; } return pos - offset; } /** * pkt_print() * gibt ein paket als hex-dump aus * * @param *pkt daten vom gameserver * @return char pointer auf hex-dump */ char * pkt_print(struct net_pkt *pkt) { int pos = 0, i = 0, j; char *buf = malloc(pkt->size * 4 + 64); while (pos < pkt->size) { i += sprintf(buf + i, "%04X: ", pos); for (j = 0; j < 16; j++) { if (pos + j < pkt->size) i += sprintf(buf + i, "%02X", pkt->buf[pos + j]); else i += sprintf(buf + i, " "); if (j % 2) buf[i++] = ' '; } for (j = 0; j < 16; j++) { if (pos + j < pkt->size) { unsigned char val = pkt->buf[pos + j]; if (val >= 0x20 && val < 0x80) buf[i++] = val; else buf[i++] = '.'; } else { buf[i++] = ' '; } } pos += 16; buf[i++] = '\r'; buf[i++] = '\n'; } buf[i] = 0; return buf; }