[ekg2-commit] r4011 - trunk/plugins/sniff: trunk/plugins/sniff/sniff.c trunk/plugins/sniff/sniff_ip.h
SVN commit
svn w toxygen.net
Pią, 6 Cze 2008, 00:13:36 CEST
Author: darkjames
Date: 2008-06-06 00:13:36 +0200 (Fri, 06 Jun 2008)
New Revision: 4011
Modified:
trunk/plugins/sniff/sniff.c
trunk/plugins/sniff/sniff_ip.h
Log:
- allow sniffing LINUX_SLL link-type devices (for instance my ppp0 works on it)
- 1st. implementation of sniffing new GG80 packets: GG_NEW_STATUS80, GG_LOGIN80, GG_STATUS80, GG_NOTIFY_REPLY80, GG_SEND_MSG80, GG_RECV_MSG80
(later i'll write some stuff to recode from UTF-8 to latin2)
Modified: trunk/plugins/sniff/sniff.c
===================================================================
--- trunk/plugins/sniff/sniff.c 2008-06-05 11:14:10 UTC (rev 4010)
+++ trunk/plugins/sniff/sniff.c 2008-06-05 22:13:36 UTC (rev 4011)
@@ -259,8 +259,9 @@
0xb8, 0xb1, 0xba, '?', 0xa5, 0xbd, 0xb5, 0xbf,
};
-static unsigned char *gg_cp_to_iso(unsigned char *buf) {
- unsigned char *tmp = buf;
+static char *gg_cp_to_iso(char *b) {
+ char *tmp = b;
+ unsigned char *buf = (unsigned char *) b;
if (!buf)
return NULL;
@@ -278,13 +279,10 @@
#define MAX_BYTES_PER_LINE 16
int offset = 0;
- while (1) {
+ while (len) {
int display_len;
int i;
- if (len <= 0)
- break;
-
if (len > MAX_BYTES_PER_LINE)
display_len = MAX_BYTES_PER_LINE;
else display_len = len;
@@ -583,7 +581,7 @@
return 0;
}
-SNIFF_HANDLER(sniff_notify_reply60, gg_notify_reply60) {
+SNIFF_HANDLER(sniff_gg_notify_reply60, gg_notify_reply60) {
unsigned char *next;
uint32_t uin;
@@ -613,7 +611,7 @@
next += desc_len;
}
- descr = has_descr ? gg_cp_to_iso(xstrndup(&pkt->next[1], desc_len)) : NULL;
+ descr = has_descr ? gg_cp_to_iso(xstrndup((char *) &pkt->next[1], desc_len)) : NULL;
sniff_gg_print_status(s, hdr, uin, status, descr);
xfree(descr);
@@ -633,7 +631,7 @@
if (len > 0) {
debug_error("gg_notify_reply60: again? leftlen: %d\n", len);
- sniff_notify_reply60(s, hdr, (gg_notify_reply60 *) next, len);
+ sniff_gg_notify_reply60(s, hdr, (gg_notify_reply60 *) next, len);
}
return 0;
}
@@ -897,7 +895,7 @@
tcp_print_payload((u_char *) pkt->filename, sizeof(pkt->filename)); /* tutaj smieci */
- fname = xstrndup((u_char *) pkt->filename, sizeof(pkt->filename));
+ fname = xstrndup((char *) pkt->filename, sizeof(pkt->filename));
debug("sniff_gg_dcc_new7() code: %s from: %d to: %d fname: %s [%db]\n",
build_code(pkt->code1), pkt->uin_from, pkt->uin_to, fname, pkt->size);
xfree(fname);
@@ -947,7 +945,7 @@
return -1;
}
- ipport = xstrndup(pkt->ipport, 21);
+ ipport = xstrndup((char *) pkt->ipport, 21);
debug_error("XXX sniff_gg_dcc_2xx_in() uin: %d ip: %s code: %s\n", pkt->uin, ipport, build_code(pkt->code1));
xfree(ipport);
tcp_print_payload((u_char *) pkt->ipport, sizeof(pkt->ipport));
@@ -1022,7 +1020,70 @@
return 0;
}
-SNIFF_HANDLER(sniff_notify_reply77, gg_notify_reply77) {
+SNIFF_HANDLER(sniff_gg_login70, gg_login70) {
+ int status;
+ char *descr;
+ int has_time = 0; /* XXX */
+ int has_descr = 0;
+ int print_payload = 0;
+ int i;
+
+ int sughash_len;
+
+ CHECK_LEN(sizeof(gg_login70)); len -= sizeof(gg_login70);
+
+ if (pkt->hash_type == GG_LOGIN_HASH_GG32) {
+ sughash_len = 4;
+
+ print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
+ "sniff_gg_login70_hash",
+
+ build_gg_uid(pkt->uin),
+ build_hex(pkt->hash_type));
+
+ } else if (pkt->hash_type == GG_LOGIN_HASH_SHA1) {
+ sughash_len = 20;
+
+ print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
+ "sniff_gg_login70_sha1",
+
+ build_gg_uid(pkt->uin),
+ build_sha1(pkt->hash));
+ } else {
+ sughash_len = 0;
+
+ print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
+ "sniff_gg_login70_unknown",
+
+ build_gg_uid(pkt->uin), build_hex(pkt->hash_type));
+ }
+
+
+ status = gg_status_to_text(pkt->status, &has_descr);
+ descr = has_descr ? gg_cp_to_iso(xstrndup(pkt->status_data, len)) : NULL;
+ sniff_gg_print_new_status(s, hdr, pkt->uin, status, descr);
+ xfree(descr);
+
+ debug_error("sniff_gg_login70() XXX ip %d:%d\n", pkt->external_ip, pkt->external_port);
+
+ CHECK_PRINT(pkt->dunno1, 0x00);
+ CHECK_PRINT(pkt->dunno2, 0xbe);
+
+ for (i = sughash_len; i < sizeof(pkt->hash); i++)
+ if (pkt->hash[i] != 0) {
+ print_payload = 1;
+ break;
+ }
+
+ if (print_payload) {
+ tcp_print_payload((u_char *) pkt->hash, sizeof(pkt->hash));
+ print_window(build_windowip_name(hdr->srcip), s, 1,
+ "generic_error", "gg_login70() print_payload flag set, see debug");
+ }
+ return 0;
+}
+
+SNIFF_HANDLER(sniff_gg_notify_reply77, gg_notify_reply77) {
unsigned char *next;
uint32_t uin;
@@ -1055,7 +1116,7 @@
next += desc_len;
}
- descr = has_descr ? gg_cp_to_iso(xstrndup(&pkt->next[1], desc_len)) : NULL;
+ descr = has_descr ? gg_cp_to_iso(xstrndup((char *) &pkt->next[1], desc_len)) : NULL;
sniff_gg_print_status(s, hdr, uin, status, descr);
xfree(descr);
@@ -1076,7 +1137,7 @@
#endif
if (len > 0) {
debug_error("gg_notify_reply77: again? leftlen: %d\n", len);
- sniff_notify_reply77(s, hdr, (gg_notify_reply77 *) next, len);
+ sniff_gg_notify_reply77(s, hdr, (gg_notify_reply77 *) next, len);
}
return 0;
}
@@ -1121,7 +1182,26 @@
return 0;
}
-SNIFF_HANDLER(sniff_gg_login70, gg_login70) {
+#define GG_LOGIN80 0x29
+
+typedef struct {
+ uint32_t uin; /* mój numerek */
+ uint8_t hash_type; /* rodzaj hashowania hasła */
+ uint8_t hash[64]; /* hash hasła dopełniony zerami */
+ uint32_t status; /* status na dzień dobry */
+ uint32_t version; /* moja wersja klienta */
+ uint8_t dunno1; /* 0x00 */
+ uint32_t local_ip; /* mój adres ip */
+ uint16_t local_port; /* port, na którym słucham */
+ uint32_t external_ip; /* zewnętrzny adres ip (???) */
+ uint16_t external_port; /* zewnętrzny port (???) */
+ uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+ uint8_t dunno2; /* 0x64 */
+ char status_data[];
+} GG_PACKED gg_login80;
+ /* like gg_login70, pkt->dunno2 diff [0xbe vs 0x64] */
+
+SNIFF_HANDLER(sniff_gg_login80, gg_login80) {
int status;
char *descr;
int has_time = 0; /* XXX */
@@ -1131,13 +1211,13 @@
int sughash_len;
- CHECK_LEN(sizeof(gg_login70)); len -= sizeof(gg_login70);
+ CHECK_LEN(sizeof(gg_login80)); len -= sizeof(gg_login80);
- if (pkt->hash_type == GG_LOGIN_HASH_GG32) {
+ if (pkt->hash_type == GG_LOGIN_HASH_GG32) { /* untested */
sughash_len = 4;
print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
- "sniff_gg_login70_hash",
+ "sniff_gg_login80_hash",
build_gg_uid(pkt->uin),
build_hex(pkt->hash_type));
@@ -1146,7 +1226,7 @@
sughash_len = 20;
print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
- "sniff_gg_login70_sha1",
+ "sniff_gg_login80_sha1",
build_gg_uid(pkt->uin),
build_sha1(pkt->hash));
@@ -1154,10 +1234,9 @@
sughash_len = 0;
print_window(build_windowip_name(hdr->srcip) /* ip and/or gg# */, s, 1,
- "sniff_gg_login70_unknown",
+ "sniff_gg_login80_unknown",
build_gg_uid(pkt->uin), build_hex(pkt->hash_type));
-
}
@@ -1166,10 +1245,10 @@
sniff_gg_print_new_status(s, hdr, pkt->uin, status, descr);
xfree(descr);
- debug_error("sniff_gg_login70() XXX ip %d:%d\n", pkt->external_ip, pkt->external_port);
+ debug_error("sniff_gg_login80() XXX ip %d:%d\n", pkt->external_ip, pkt->external_port);
CHECK_PRINT(pkt->dunno1, 0x00);
- CHECK_PRINT(pkt->dunno2, 0xbe);
+ CHECK_PRINT(pkt->dunno2, 0x64);
for (i = sughash_len; i < sizeof(pkt->hash); i++)
if (pkt->hash[i] != 0) {
@@ -1180,11 +1259,193 @@
if (print_payload) {
tcp_print_payload((u_char *) pkt->hash, sizeof(pkt->hash));
print_window(build_windowip_name(hdr->srcip), s, 1,
- "generic_error", "gg_login70() print_payload flag set, see debug");
+ "generic_error", "gg_login80() print_payload flag set, see debug");
}
return 0;
}
+#define GG_NOTIFY_REPLY80 0x2b
+
+typedef struct {
+ uint32_t uin; /* [gg_notify_reply60] numerek plus flagi w MSB */
+ uint8_t status; /* [gg_notify_reply60] status danej osoby */
+ uint32_t remote_ip; /* [XXX] adres ip delikwenta */
+ uint16_t remote_port; /* [XXX] port, na którym słucha klient */
+ uint8_t version; /* [gg_notify_reply60] wersja klienta */
+ uint8_t image_size; /* [gg_notify_reply60] maksymalny rozmiar grafiki w KiB */
+ uint8_t dunno1; /* 0x00 */
+ uint32_t dunno2; /* 0x00000000 */
+ unsigned char next[]; /* [like gg_notify_reply60] nastepny (gg_notify_reply77), lub DLUGOSC_OPISU+OPIS + nastepny (gg_notify_reply77) */
+} GG_PACKED gg_notify_reply80;
+ /* identiko z gg_notify_reply77 */
+
+SNIFF_HANDLER(sniff_gg_notify_reply80, gg_notify_reply80) {
+ unsigned char *next;
+
+ uint32_t uin;
+ int desc_len;
+ int has_descr;
+ int status;
+ char *descr;
+
+ CHECK_LEN(sizeof(gg_notify_reply80)); len -= sizeof(gg_notify_reply80);
+
+ CHECK_PRINT(pkt->dunno2, 0x00);
+ CHECK_PRINT(pkt->dunno1, 0x00);
+
+ next = pkt->next;
+
+ uin = pkt->uin & 0x00ffffff;
+
+ status = gg_status_to_text(pkt->status, &has_descr);
+
+ if (has_descr) {
+ CHECK_LEN(1)
+ desc_len = pkt->next[0];
+ len--; next++;
+
+ if (!desc_len)
+ debug_error("gg_notify_reply80() has_descr BUT NOT desc_len?\n");
+
+ CHECK_LEN(desc_len)
+ len -= desc_len;
+ next += desc_len;
+ }
+
+ descr = has_descr ? gg_cp_to_iso(xstrndup((char *) &pkt->next[1], desc_len)) : NULL;
+ sniff_gg_print_status(s, hdr, uin, status, descr);
+ xfree(descr);
+
+ print_window(build_windowip_name(hdr->dstip) /* ip and/or gg# */, s, 1,
+ "sniff_gg_notify80",
+
+ inet_ntoa(*(struct in_addr *) &(pkt->remote_ip)),
+ itoa(pkt->remote_port),
+ itoa(pkt->version), build_hex(pkt->version),
+ itoa(pkt->image_size));
+
+ if (len > 0) {
+ debug_error("gg_notify_reply80: again? leftlen: %d\n", len);
+ sniff_gg_notify_reply77(s, hdr, (gg_notify_reply77 *) next, len);
+ }
+ return 0;
+}
+
+#define GG_STATUS80 0x2a
+
+typedef struct {
+ uint32_t uin; /* [gg_status60, gg_status77] numerek plus flagi w MSB [XXX?] */
+ uint8_t status; /* [gg_status60, gg_status77] status danej osoby */
+ uint32_t remote_ip; /* [XXX] adres ip delikwenta */
+ uint16_t remote_port; /* [XXX] port, na którym słucha klient */
+ uint8_t version; /* [gg_status60] wersja klienta */
+ uint8_t image_size; /* [gg_status60] maksymalny rozmiar grafiki w KiB */
+ uint8_t dunno1; /* 0x64 lub 0x00 */
+ uint32_t dunno2; /* 0x00 */
+ char status_data[];
+} GG_PACKED gg_status80;
+
+SNIFF_HANDLER(sniff_gg_status80, gg_status80) {
+ uint32_t uin;
+ int status;
+ int has_descr;
+ char *descr;
+
+ uint32_t dunno2;
+ uint8_t uinflag;
+
+ CHECK_LEN(sizeof(gg_status80)); len -= sizeof(gg_status80);
+
+ uin = pkt->uin & 0x00ffffff;
+
+ uinflag = pkt->uin >> 24;
+ dunno2 = pkt->dunno2;
+
+ if (dunno2 & GG_STATUS_VOICE_MASK) dunno2 -= GG_STATUS_VOICE_MASK;
+
+ CHECK_PRINT(uinflag, 0x00);
+ CHECK_PRINT(pkt->dunno1, 0x64);
+ /* 23:12:31 sniff_gg_status80() values not match: pkt->dunno1 [0 != 64] */
+
+ CHECK_PRINT(dunno2, 0x00);
+
+ status = gg_status_to_text(pkt->status, &has_descr);
+ descr = has_descr ? gg_cp_to_iso(xstrndup(pkt->status_data, len)) : NULL;
+ sniff_gg_print_status(s, hdr, uin, status, descr);
+ xfree(descr);
+
+ print_window(build_windowip_name(hdr->dstip) /* ip and/or gg# */, s, 1,
+ "sniff_gg_status80",
+
+ inet_ntoa(*(struct in_addr *) &(pkt->remote_ip)),
+ itoa(pkt->remote_port),
+ itoa(pkt->version), build_hex(pkt->version),
+ itoa(pkt->image_size));
+
+ return 0;
+}
+
+#define GG_RECV_MSG80 0x2e
+
+typedef struct {
+ uint32_t sender;
+ uint32_t seq;
+ uint32_t time;
+ uint32_t msgclass;
+ uint32_t offset_plaintext;
+ uint32_t offset_attr;
+ char msg_data[];
+ /* '\0' */
+ /* plaintext msg */
+ /* '\0' */
+ /* uint32_t dunno3; */ /* { 02 06 00 00 } */
+ /* uint8_t dunno4; */ /* { 00 } */
+ /* uint32_t dunno5; */ /* like msgclass? */ /* { 08 00 00 00 } */
+} GG_PACKED gg_recv_msg80;
+
+SNIFF_HANDLER(sniff_gg_recv_msg80, gg_recv_msg80) {
+ /* XXX, like sniff_gg_send_msg80() */
+}
+
+#define GG_SEND_MSG80 0x2d
+
+typedef struct {
+ uint32_t recipient;
+ uint32_t seq; /* time(0) */
+ uint32_t msgclass; /* GG_CLASS_CHAT { 08 00 00 00 } */
+ uint32_t offset_plaintext;
+ uint32_t offset_attr;
+ char html_data[];
+ /* '\0' */
+ /* plaintext msg */
+ /* '\0' */
+ /* uint32_t dunno3; */ /* { 02 06 00 00 } */
+ /* uint8_t dunno4; */ /* { 00 } */
+ /* uint32_t dunno5; */ /* like msgclass? */ /* { 08 00 00 00 } */
+} GG_PACKED gg_send_msg80;
+
+SNIFF_HANDLER(sniff_gg_send_msg80, gg_send_msg80) {
+ int orglen = len;
+ char *msg;
+
+ CHECK_LEN(sizeof(gg_send_msg80)) len -= sizeof(gg_send_msg80);
+
+ tcp_print_payload(pkt->html_data, len);
+
+ if (pkt->offset_plaintext < orglen)
+ tcp_print_payload(((char *) pkt) + pkt->offset_plaintext, orglen - pkt->offset_plaintext);
+ if (pkt->offset_attr < orglen)
+ tcp_print_payload(((char *) pkt) + pkt->offset_attr, orglen - pkt->offset_attr);
+
+ if (pkt->offset_plaintext < orglen) {
+ msg = gg_cp_to_iso(xstrndup(((char *) pkt) + pkt->offset_plaintext, orglen - pkt->offset_plaintext));
+ sniff_gg_print_message(s, hdr, pkt->recipient, EKG_MSGCLASS_SENT_CHAT, msg, time(NULL));
+ xfree(msg);
+ }
+
+ return 0;
+}
+
#undef CHECK_PRINT
typedef enum {
@@ -1215,7 +1476,7 @@
{ GG_ADD_NOTIFY, "GG_ADD_NOTIFY", SNIFF_OUTGOING, (void *) sniff_gg_add_notify, 0},
{ GG_REMOVE_NOTIFY, "GG_REMOVE_NOTIFY", SNIFF_OUTGOING, (void *) sniff_gg_del_notify, 0},
- { GG_NOTIFY_REPLY60, "GG_NOTIFY_REPLY60", SNIFF_INCOMING, (void *) sniff_notify_reply60, 0},
+ { GG_NOTIFY_REPLY60, "GG_NOTIFY_REPLY60", SNIFF_INCOMING, (void *) sniff_gg_notify_reply60, 0},
{ GG_LIST_EMPTY, "GG_LIST_EMPTY", SNIFF_OUTGOING, (void *) sniff_gg_list_empty, 0},
{ GG_NOTIFY_FIRST, "GG_NOTIFY_FIRST", SNIFF_OUTGOING, (void *) sniff_gg_list_first, 0},
@@ -1229,9 +1490,17 @@
{ GG_PUBDIR50_REQUEST, "GG_PUBDIR50_REQUEST", SNIFF_OUTGOING, (void *) sniff_gg_pubdir50_req, 0},
{ GG_DISCONNECTING, "GG_DISCONNECTING", SNIFF_INCOMING, (void *) sniff_gg_disconnecting, 0},
- { GG_NOTIFY_REPLY77, "GG_NOTIFY_REPLY77", SNIFF_INCOMING, (void *) sniff_notify_reply77, 0},
+ { GG_NOTIFY_REPLY77, "GG_NOTIFY_REPLY77", SNIFF_INCOMING, (void *) sniff_gg_notify_reply77, 0},
{ GG_STATUS77, "GG_STATUS77", SNIFF_INCOMING, (void *) sniff_gg_status77, 0},
+#define GG_NEW_STATUS80 0x28
+ { GG_LOGIN80, "GG_LOGIN80", SNIFF_OUTGOING, (void *) sniff_gg_login80, 0}, /* XXX, UTF-8 */
+ { GG_NEW_STATUS80, "GG_NEW_STATUS80", SNIFF_OUTGOING, (void *) sniff_gg_new_status, 0}, /* XXX, UTF-8 */
+ { GG_NOTIFY_REPLY80, "GG_NOTIFY_REPLY80", SNIFF_INCOMING, (void *) sniff_gg_notify_reply80, 0}, /* XXX, UTF-8 */
+ { GG_STATUS80, "GG_STATUS80", SNIFF_INCOMING, (void *) sniff_gg_status80, 0}, /* XXX, UTF-8 */
+ { GG_RECV_MSG80, "GG_RECV_MSG80", SNIFF_INCOMING, (void *) sniff_gg_recv_msg80, 0}, /* XXX, UTF-8 */
+ { GG_SEND_MSG80, "GG_SEND_MSG80", SNIFF_OUTGOING, (void *) sniff_gg_send_msg80, 0}, /* XXX, UTF-8 */
+
/* pakiety [nie] w libgadu: [czesc mozliwie ze nieaktualna] */
{ GG_DCC7_NEW, "GG_DCC7_NEW", SNIFF_INCOMING, (void *) sniff_gg_dcc7_new, 0},
{ GG_DCC7_NEW, "GG_DCC7_NEW", SNIFF_OUTGOING, (void *) sniff_gg_dcc7_new, 0},
@@ -1260,11 +1529,13 @@
pkt_way_t way = SNIFF_OUTGOING;
int ret = 0;
+// tcp_print_payload((u_char *) pkt, len);
+
CHECK_LEN(sizeof(gg_header)) len -= sizeof(gg_header);
CHECK_LEN(pkt->len)
/* XXX, check direction!!!!!111, in better way: */
- if (!xstrncmp(inet_ntoa(hdr->srcip), "217.17.", 7))
+ if (!xstrncmp(inet_ntoa(hdr->srcip), "91.197.13.41", 7))
way = SNIFF_INCOMING;
/* XXX, jesli mamy podejrzenia ze to nie jest pakiet gg, to wtedy powinnismy zwrocic -2 i pozwolic zeby inni za nas to przetworzyli */
@@ -1272,7 +1543,7 @@
if (sniff_gg_callbacks[i].type == pkt->type && sniff_gg_callbacks[i].way == way) {
debug("sniff_gg() %s [%d,%d,%db] %s\n", sniff_gg_callbacks[i].sname, pkt->type, way, pkt->len, inet_ntoa(way ? hdr->dstip : hdr->srcip));
if (sniff_gg_callbacks[i].handler)
- sniff_gg_callbacks[i].handler(s, hdr, pkt->data, pkt->len);
+ sniff_gg_callbacks[i].handler(s, hdr, (char *) pkt->data, pkt->len);
handled = 1;
}
@@ -1526,7 +1797,7 @@
char *program = gg_cp_to_iso(xstrndup(pkt->prog, sizeof(pkt->prog)));
char *username = gg_cp_to_iso(xstrndup(pkt->user, sizeof(pkt->user)));
- char program_ver[7]; /* ddd '.' ddd */
+ char program_ver[8]; /* ddd '.' ddd */
sprintf(program_ver, "%d.%d", pkt->version[0], pkt->version[1]);
@@ -1544,7 +1815,6 @@
return 0;
}
-
SNIFF_HANDLER(sniff_rivchat, rivchat_packet) {
int type = pkt->type; /* pkt->type is LE, if you're using BE you know what to do */
@@ -1627,161 +1897,155 @@
}
#undef CHECK_LEN
-void sniff_loop(u_char *data, const struct pcap_pkthdr *header, const u_char *packet) {
- const struct ethhdr *ethernet;
- const struct iphdr *ip;
- int size_ip;
- uint16_t ethtype; /* ntohs(ethernet->ether_type) */
-
#define CHECK_LEN(x) \
- if (header->caplen < x) {\
- debug_error("sniff_loop() * READ less than: %d (%d %d) (%s)\n", x, header->caplen, header->len, #x);\
- return;\
+ if (len < x) {\
+ debug_error("%s() * READ less than: %d (len: %d) (%s)\n", __FUNCTION__, x, len, #x); \
+ return; \
}
- CHECK_LEN(sizeof(struct ethhdr)) ethernet = (struct ethhdr *) (packet);
- ethtype = ntohs(ethernet->ether_type);
+/* XXX, some notes about tcp fragment*
+ * @ sniff_loop_tcp() we'll do: sniff_find_tcp_connection(connection_t *hdr);
+ * it'll find (or create) struct with inited string_t buf...
+ * than we append to that string_t recv data from packet, and than pass this to sniff_gg() [or anyother sniff handler]
+ * than in sniff_loop() we'll remove already data.. [of length len, len returned from sniff_gg()]
+ */
- if (ethtype == ETHERTYPE_ARP) {
- debug_function("sniff_loop() ARP\n");
- /* stub? display in __status? */
- return;
- }
+static inline void sniff_loop_tcp(session_t *s, int len, const u_char *packet, const struct iphdr *ip, int size_ip) {
+ /* XXX here, make some struct with known TCP services, and demangler-function */
+ const struct tcphdr *tcp;
+ int size_tcp;
+ connection_t *hdr;
- if (ethtype != ETHERTYPE_IP) {
- debug_error("sniff_loop() ethtype [0x%x] != ETHERTYPE_IP, CUL\n", ethtype);
- return;
- }
- /* HERE ONLY IP PROTO */
+ const char *payload;
+ int size_payload;
- CHECK_LEN(sizeof(struct ethhdr) + sizeof(struct iphdr)) ip = (struct iphdr *) (packet + SIZE_ETHERNET);
- size_ip = ip->ip_hl*4;
-
- if (size_ip < 20) {
- debug_error("sniff_loop() * Invalid IP header length: %u bytes\n", size_ip);
+ CHECK_LEN(sizeof(struct tcphdr)) tcp = (struct tcphdr*) (packet);
+ size_tcp = TH_OFF(tcp)*4;
+
+ if (size_tcp < 20) {
+ debug_error("sniff_loop_tcp() * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
-
- if (ip->ip_p == IPPROTO_TCP) { /* here TCP packets */
- /* XXX here, make some struct with known TCP services, and demangler-function */
- const struct tcphdr *tcp;
- int size_tcp;
- connection_t *hdr;
- const char *payload;
- int size_payload;
+ size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
- CHECK_LEN(sizeof(struct ethhdr) + size_ip + sizeof(struct tcphdr)) tcp = (struct tcphdr*) (packet + SIZE_ETHERNET + size_ip);
- size_tcp = TH_OFF(tcp)*4;
+ CHECK_LEN(size_tcp + size_payload);
- if (size_tcp < 20) {
- debug_error("sniff_loop() * Invalid TCP header length: %u bytes\n", size_tcp);
- return;
- }
+ payload = (char *) (packet + size_tcp);
- size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
+ hdr = sniff_tcp_find_connection(ip, tcp);
- CHECK_LEN(SIZE_ETHERNET + size_ip + size_tcp + size_payload);
+ debug_function("sniff_loop_tcp() IP/TCP %15s:%5d <==> %15s:%5d %s (SEQ: %lx ACK: %lx len: %d)\n",
+ _inet_ntoa(hdr->srcip), /* src ip */
+ hdr->srcport, /* src port */
+ _inet_ntoa(hdr->dstip), /* dest ip */
+ hdr->dstport, /* dest port */
+ tcp_print_flags(tcp->th_flags), /* tcp flags */
+ htonl(tcp->th_seq), /* seq */
+ htonl(tcp->th_ack), /* ack */
+ size_payload); /* payload len */
- payload = (u_char *) (packet + SIZE_ETHERNET + size_ip + size_tcp);
+ /* XXX check tcp flags */
+ if (!size_payload) return;
- hdr = sniff_tcp_find_connection(ip, tcp);
+ /* XXX what proto ? check based on ip + port? */
- debug_function("sniff_loop() IP/TCP %15s:%5d <==> %15s:%5d %s (SEQ: %lx ACK: %lx len: %d)\n",
- _inet_ntoa(hdr->srcip), /* src ip */
- hdr->srcport, /* src port */
- _inet_ntoa(hdr->dstip), /* dest ip */
- hdr->dstport, /* dest port */
- tcp_print_flags(tcp->th_flags), /* tcp flags */
- htonl(tcp->th_seq), /* seq */
- htonl(tcp->th_ack), /* ack */
- size_payload); /* payload len */
+ if (hdr->dstport == 80 || hdr->srcport == 80) { /* HTTP [basic check on magic values, ~80% hit] */
+ static const char http_magic11[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ' }; /* HTTP/1.1 */
+ static const char http_magic10[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '0', ' ' }; /* HTTP/1.0 */
- /* XXX check tcp flags */
- if (!size_payload) return;
+ static const char http_get_magic[] = { 'G', 'E', 'T', ' ' }; /* GET */
+ static const char http_post_magic[] = { 'P', 'O', 'S', 'T', ' ' }; /* POST */
- /* XXX what proto ? check based on ip + port? */
+ /* SERVER REPLIES: */
- if (hdr->dstport == 80 || hdr->srcport == 80) { /* HTTP [basic check on magic values, ~80% hit] */
- static const char http_magic11[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ' }; /* HTTP/1.1 */
- static const char http_magic10[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '0', ' ' }; /* HTTP/1.0 */
-
- static const char http_get_magic[] = { 'G', 'E', 'T', ' ' }; /* GET */
- static const char http_post_magic[] = { 'P', 'O', 'S', 'T', ' ' }; /* POST */
-
- /* SERVER REPLIES: */
-
- if ( (size_payload > sizeof(http_magic10) && !memcmp(payload, http_magic10, sizeof(http_magic10))) ||
+ if ( (size_payload > sizeof(http_magic10) && !memcmp(payload, http_magic10, sizeof(http_magic10))) ||
(size_payload > sizeof(http_magic11) && !memcmp(payload, http_magic11, sizeof(http_magic11)))
- ) {
+ ) {
// debug_error("HTTP DATA FOLLOW\n");
// tcp_print_payload((u_char *) payload, size_payload);
- return; /* done */
- }
+ return; /* done */
+ }
- /* CLIENT REQUESTs: */
+ /* CLIENT REQUESTs: */
- if ( (size_payload > sizeof(http_get_magic) && !memcmp(payload, http_get_magic, sizeof(http_get_magic))) ||
+ if ( (size_payload > sizeof(http_get_magic) && !memcmp(payload, http_get_magic, sizeof(http_get_magic))) ||
(size_payload > sizeof(http_post_magic) && !memcmp(payload, http_post_magic, sizeof(http_post_magic)))
- ) {
+ ) {
// debug_error("HTTP DATA FOLLOW?\n");
// tcp_print_payload((u_char *) payload, size_payload);
- return; /* done */
- }
+ return; /* done */
}
+ }
- sniff_gg((session_t *) data, hdr, (gg_header *) payload, size_payload); /* GG [no check, ~3% hit] */
+ sniff_gg(s, hdr, (gg_header *) payload, size_payload); /* GG [no check, ~3% hit] */
+}
- } else if (ip->ip_p == IPPROTO_UDP) { /* here UDP datagrams */
+static inline void sniff_loop_udp(session_t *s, int len, const u_char *packet, const struct iphdr *ip) {
#define RIVCHAT_PACKET_LEN 328
- static const char rivchat_magic[11] = { 'R', 'i', 'v', 'C', 'h', 'a', 't' /* here NULs */}; /* RivChat\0\0\0\0 */
+ static const char rivchat_magic[11] = { 'R', 'i', 'v', 'C', 'h', 'a', 't' /* here NULs */}; /* RivChat\0\0\0\0 */
- /* XXX here, make some struct with known UDP services, and demangler-function */
- const struct udphdr *udp;
- connection_t *hdr;
+ /* XXX here, make some struct with known UDP services, and demangler-function */
+ const struct udphdr *udp;
+ connection_t *hdr;
- const char *payload;
- int size_payload;
+ const char *payload;
+ int size_payload;
- /* XXX, it's enough? */
- /* code copied from: http://gpsbots.com/tutorials/sniff_packets.php */
- CHECK_LEN(sizeof(struct ethhdr) + size_ip + sizeof(struct udphdr)); udp = (struct udphdr *) (packet + SIZE_ETHERNET + size_ip);
+ /* XXX, it's enough? */
+ /* code copied from: http://gpsbots.com/tutorials/sniff_packets.php */
+ CHECK_LEN(sizeof(struct udphdr)); udp = (struct udphdr *) (packet);
- hdr = sniff_udp_get(ip, udp);
+ hdr = sniff_udp_get(ip, udp);
- payload = (u_char *) (packet + SIZE_ETHERNET + size_ip + sizeof(struct udphdr));
- size_payload = ntohs(udp->th_len)-sizeof(struct udphdr);
+ payload = (char *) (packet + sizeof(struct udphdr));
+ size_payload = ntohs(udp->th_len)-sizeof(struct udphdr);
- CHECK_LEN(SIZE_ETHERNET + size_ip + sizeof(struct udphdr) + size_payload);
+ CHECK_LEN(sizeof(struct udphdr) + size_payload);
- debug_error("sniff_loop() [%ld:%ld] IP/UDP %15s:%5d <==> %15s:%5d\n",
- header->ts.tv_sec,
- header->ts.tv_usec,
- _inet_ntoa(hdr->srcip), /* src ip */
- hdr->srcport, /* src port */
- _inet_ntoa(hdr->dstip), /* dest ip */
- hdr->dstport); /* dest port */
+ debug_error("sniff_loop_udp() IP/UDP %15s:%5d <==> %15s:%5d\n",
+ _inet_ntoa(hdr->srcip), /* src ip */
+ hdr->srcport, /* src port */
+ _inet_ntoa(hdr->dstip), /* dest ip */
+ hdr->dstport); /* dest port */
- if (size_payload == RIVCHAT_PACKET_LEN && !memcmp(payload, rivchat_magic, sizeof(rivchat_magic))) { /* RIVCHAT [check based on header (11b), ~100% hit] */
- sniff_rivchat((session_t *) data, hdr, (rivchat_packet *) payload, size_payload);
- } else if (hdr->srcport == 53 || hdr->dstport == 53) { /* DNS [check based on port, ~80% hit] */
- sniff_dns((session_t *) data, hdr, (DNS_HEADER *) payload, size_payload);
- } else { /* OTHER PROTOs, feel free */
- debug_error("NOT RIVCHAT/ NOT DNS:\n");
- tcp_print_payload((u_char *) payload, size_payload);
- }
+ if (size_payload == RIVCHAT_PACKET_LEN && !memcmp(payload, rivchat_magic, sizeof(rivchat_magic))) { /* RIVCHAT [check based on header (11b), ~100% hit] */
+ sniff_rivchat(s, hdr, (rivchat_packet *) payload, size_payload);
+ } else if (hdr->srcport == 53 || hdr->dstport == 53) { /* DNS [check based on port, ~80% hit] */
+ sniff_dns(s, hdr, (DNS_HEADER *) payload, size_payload);
+ } else { /* OTHER PROTOs, feel free */
+ debug_error("NOT RIVCHAT/ NOT DNS:\n");
+ tcp_print_payload((u_char *) payload, size_payload);
+ }
+}
- } else if (ip->ip_p == IPPROTO_ICMP) { /* ICMP, stub only */
+static inline void sniff_loop_ip(session_t *s, int len, const u_char *packet) {
+ const struct iphdr *ip;
+ int size_ip;
+
+ CHECK_LEN(sizeof(struct iphdr)) ip = (struct iphdr *) (packet);
+ size_ip = ip->ip_hl*4;
+
+ if (size_ip < 20) {
+ debug_error("sniff_loop_ip() * Invalid IP header length: %u bytes\n", size_ip);
+ return;
+ }
+
+ if (ip->ip_p == IPPROTO_TCP)
+ sniff_loop_tcp(s, len - size_ip, packet + size_ip, ip, size_ip);
+ else if (ip->ip_p == IPPROTO_UDP)
+ sniff_loop_udp(s, len - size_ip, packet + size_ip, ip);
+ else if (ip->ip_p == IPPROTO_ICMP) { /* ICMP, stub only */
const struct icmphdr *icmp;
- CHECK_LEN(sizeof(struct ethhdr) + size_ip + sizeof(struct icmphdr)); icmp = (struct icmphdr *) (packet + SIZE_ETHERNET + size_ip);
+ CHECK_LEN(size_ip + sizeof(struct icmphdr)); icmp = (struct icmphdr *) (packet + size_ip);
- debug_function("sniff_loop() IP/ICMP %15s <==> %15s TYPE: %d CODE: %d CHKSUM: %d\n",
+ debug_function("sniff_loop_ip() IP/ICMP %15s <==> %15s TYPE: %d CODE: %d CHKSUM: %d\n",
_inet_ntoa(ip->ip_src), /* src ip */
_inet_ntoa(ip->ip_dst), /* dest ip */
icmp->icmp_type,
@@ -1790,34 +2054,70 @@
/* XXX */
} else {
/* other, implement if u want to || die. */
- debug_error("sniff_loop() IP/0x%x %15s <==> %15s\n",
+ debug_error("sniff_loop_ip() IP/0x%x %15s <==> %15s\n",
ip->ip_p, /* protocol */
_inet_ntoa(ip->ip_src), /* src ip */
_inet_ntoa(ip->ip_dst)); /* dest ip */
}
-#undef CHECK_LEN
}
-/* XXX, some notes about tcp fragment*
- * @ sniff_loop() we'll do: sniff_find_tcp_connection(connection_t *hdr);
- * it'll find (or create) struct with inited string_t buf...
- * than we append to that string_t recv data from packet, and than pass this to sniff_gg() [or anyother sniff handler]
- * than in sniff_loop() we'll remove already data.. [of length len, len returned from sniff_gg()]
- */
+#undef CHECK_LEN
-static WATCHER_SESSION(sniff_pcap_read) {
- if (type)
- return 0;
+static inline void sniff_loop_ether(u_char *data, const struct pcap_pkthdr *header, const u_char *packet) {
+ const struct ethhdr *ethernet;
+ uint16_t ethtype; /* ntohs(ethernet->ether_type) */
- if (!s) {
- debug_error("sniff_pcap_read() no session!\n");
- return -1;
+ if (header->caplen < sizeof(struct ethhdr)) {
+ debug_error("sniff_loop_ether() %x %x\n", header->caplen, sizeof(struct ethhdr));
+ return;
}
- pcap_dispatch(GET_DEV(s), 1, sniff_loop, (void *) s);
- return 0;
+
+ ethernet = (const struct ethhdr *) packet;
+ ethtype = ntohs(ethernet->ether_type);
+
+ if (ethtype == ETHERTYPE_ARP)
+ debug_function("sniff_loop_ether() ARP\n");
+ else if (ethtype == ETHERTYPE_IP)
+ sniff_loop_ip((session_t *) data, header->caplen - sizeof(struct ethhdr), packet + SIZE_ETHERNET);
+ else
+ debug_error("sniff_loop_ether() ethtype [0x%x] != ETHERTYPE_IP, CUL\n", ethtype);
}
+void sniff_loop_sll(u_char *data, const struct pcap_pkthdr *header, const u_char *packet) {
+ const struct sll_header *sll;
+ uint16_t ethtype;
+
+ if (header->caplen < sizeof(struct sll_header)) {
+ debug_error("sniff_loop_ssl() %x %x\n", header->caplen, sizeof(struct sll_header));
+ return;
+ }
+
+ sll = (const struct sll_header *) packet;
+ ethtype = ntohs(sll->sll_protocol);
+
+ if (ethtype == ETHERTYPE_IP)
+ sniff_loop_ip((session_t *) data, header->caplen - sizeof(struct sll_header), packet + SIZE_SLL);
+ else
+ debug_error("sniff_loop_sll() ethtype [0x%x] != ETHERTYPE_IP, CUL\n", ethtype);
+}
+
+#define WATCHER_PCAP(x, y) \
+ static WATCHER_SESSION(x) { \
+ if (type) return 0; \
+ if (!s) { \
+ debug_error("sniff_pcap_read() no session!\n"); \
+ return -1; \
+ } \
+ pcap_dispatch(GET_DEV(s), 1, y, (void *) s); \
+ return 0; \
+ }
+
+
+WATCHER_PCAP(sniff_pcap_read_EN10MB, sniff_loop_ether);
+WATCHER_PCAP(sniff_pcap_read_SLL, sniff_loop_sll);
+WATCHER_PCAP(sniff_pcap_read, sniff_loop_ether);
+
#define DEFAULT_FILTER \
"(tcp and (net 217.17.41.80/28 or net 217.17.45.128/27 or net 85.232.236.0/24 or net 91.197.12.0/22)) or (udp and (port 16127 or port 53))"
@@ -1878,9 +2178,22 @@
}
session->priv = dev;
+
+ switch (pcap_datalink(dev)) {
+ case DLT_LINUX_SLL:
+ watch_add_session(session, pcap_fileno(dev), WATCH_READ, sniff_pcap_read_SLL);
+ break;
- watch_add_session(session, pcap_fileno(dev), WATCH_READ, sniff_pcap_read);
+ case DLT_EN10MB:
+ watch_add_session(session, pcap_fileno(dev), WATCH_READ, sniff_pcap_read_EN10MB);
+ break;
+ default:
+ debug_error("_connect() unk: %s\n", pcap_datalink_val_to_name(pcap_datalink(dev)));
+ watch_add_session(session, pcap_fileno(dev), WATCH_READ, sniff_pcap_read);
+ }
+
+
session->status = EKG_STATUS_AVAIL;
query_emit_id(NULL, PROTOCOL_CONNECTED, &(session->uid));
return 0;
@@ -2018,9 +2331,17 @@
format_add("sniff_gg_status60", ("%) %b[GG_STATUS60] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
format_add("sniff_gg_notify60", ("%) %b[GG_NOTIFY60] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
+
format_add("sniff_gg_status77", ("%) %b[GG_STATUS77] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
format_add("sniff_gg_notify77", ("%) %b[GG_NOTIFY77] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
+ format_add("sniff_gg_login80_sha1", ("%) %b[GG_LOGIN80] %gUIN: %W%1 %gSHA1: %W%2"), 1);
+ format_add("sniff_gg_login80_hash", ("%) %b[GG_LOGIN80] %gUIN: %W%1 %gHASH: %W%2"), 1); /* untested */
+ format_add("sniff_gg_login80_unknown", ("%) %b[GG_LOGIN80] %gUIN: %W%1 %gTYPE: %W%2"), 1);
+
+ format_add("sniff_gg_status80", ("%) %b[GG_STATUS80] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
+ format_add("sniff_gg_notify80", ("%) %b[GG_NOTIFY80] %gDCC: %W%1:%2 %gVERSION: %W#%3 (%4) %gIMGSIZE: %W%5KiB"), 1);
+
format_add("sniff_gg_addnotify", ("%) %b[GG_ADD_NOTIFY] %gUIN: %W%1 %gDATA: %W%2"), 1);
format_add("sniff_gg_delnotify", ("%) %b[GG_REMOVE_NOTIFY] %gUIN: %W%1 %gDATA: %W%2"), 1);
@@ -2063,7 +2384,6 @@
};
EXPORT int sniff_plugin_init(int prio) {
-
PLUGIN_CHECK_VER("sniff");
sniff_plugin.params = sniff_plugin_vars;
Modified: trunk/plugins/sniff/sniff_ip.h
===================================================================
--- trunk/plugins/sniff/sniff_ip.h 2008-06-05 11:14:10 UTC (rev 4010)
+++ trunk/plugins/sniff/sniff_ip.h 2008-06-05 22:13:36 UTC (rev 4011)
@@ -17,6 +17,19 @@
u_short ether_type; /* IP? ARP? RARP? etc */
};
+/* from tcpdump sll.h */
+
+#define SIZE_SLL 16 /* total header length */
+#define SLL_ADDRLEN 8 /* length of address field */
+
+struct sll_header {
+ u_int16_t sll_pkttype; /* packet type */
+ u_int16_t sll_hatype; /* link-layer address type */
+ u_int16_t sll_halen; /* link-layer address length */
+ u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
+ u_int16_t sll_protocol; /* protocol */
+};
+
struct iphdr { /* IP header */
// u_char ip_vhl; /* version << 4 | header length >> 2 */
unsigned int ip_hl:4; /* header length */
Więcej informacji o liście dyskusyjnej ekg2-commit