diff options
author | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2011-07-14 16:40:14 +0200 |
---|---|---|
committer | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2011-07-14 16:54:37 +0200 |
commit | 93af6831e28da9c46aaccf087d3020198b8dfe18 (patch) | |
tree | 36619e069cc19c61fa5776dc407b1eebbd04628b /gst/pcapparse/gstpcapparse.c | |
parent | 04f0b55609becae064febe2ff92fbcaff4bcc209 (diff) |
pcapparse: also support extracting tcp data
Diffstat (limited to 'gst/pcapparse/gstpcapparse.c')
-rw-r--r-- | gst/pcapparse/gstpcapparse.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/gst/pcapparse/gstpcapparse.c b/gst/pcapparse/gstpcapparse.c index 47bf0ace2..c559a5855 100644 --- a/gst/pcapparse/gstpcapparse.c +++ b/gst/pcapparse/gstpcapparse.c @@ -20,8 +20,8 @@ /** * SECTION:element-pcapparse * - * Extracts payloads from Ethernet-encapsulated IP packets, currently limited - * to UDP. Use #GstPcapParse:src-ip, #GstPcapParse:dst-ip, + * Extracts payloads from Ethernet-encapsulated IP packets. + * Use #GstPcapParse:src-ip, #GstPcapParse:dst-ip, * #GstPcapParse:src-port and #GstPcapParse:dst-port to restrict which packets * should be included. * @@ -324,6 +324,8 @@ gst_pcap_parse_read_uint32 (GstPcapParse * self, const guint8 * p) #define UDP_HEADER_LEN 8 #define IP_PROTO_UDP 17 +#define IP_PROTO_TCP 6 + static gboolean gst_pcap_parse_scan_frame (GstPcapParse * self, @@ -331,16 +333,16 @@ gst_pcap_parse_scan_frame (GstPcapParse * self, gint buf_size, const guint8 ** payload, gint * payload_size) { const guint8 *buf_ip = 0; - const guint8 *buf_udp; + const guint8 *buf_proto; guint16 eth_type; guint8 b; guint8 ip_header_size; guint8 ip_protocol; guint32 ip_src_addr; guint32 ip_dst_addr; - guint16 udp_src_port; - guint16 udp_dst_port; - guint16 udp_len; + guint16 src_port; + guint16 dst_port; + guint16 len; switch (self->linktype) { case DLT_ETHER: @@ -375,33 +377,52 @@ gst_pcap_parse_scan_frame (GstPcapParse * self, return FALSE; ip_protocol = *(buf_ip + 9); - if (ip_protocol != IP_PROTO_UDP) - return FALSE; + GST_LOG_OBJECT (self, "ip proto %d", (gint) ip_protocol); - ip_src_addr = *((guint32 *) (buf_ip + 12)); - if (self->src_ip >= 0 && ip_src_addr != self->src_ip) + if (ip_protocol != IP_PROTO_UDP && ip_protocol != IP_PROTO_TCP) return FALSE; + /* ip info */ + ip_src_addr = *((guint32 *) (buf_ip + 12)); ip_dst_addr = *((guint32 *) (buf_ip + 16)); - if (self->dst_ip >= 0 && ip_dst_addr != self->dst_ip) - return FALSE; + buf_proto = buf_ip + ip_header_size; - buf_udp = buf_ip + ip_header_size; + /* ok for tcp and udp */ + src_port = GUINT16_FROM_BE (*((guint16 *) (buf_proto + 0))); + dst_port = GUINT16_FROM_BE (*((guint16 *) (buf_proto + 2))); - udp_src_port = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 0))); - if (self->src_port >= 0 && udp_src_port != self->src_port) + /* extract some params and data according to protocol */ + if (ip_protocol == IP_PROTO_UDP) { + len = GUINT16_FROM_BE (*((guint16 *) (buf_proto + 4))); + if (len < UDP_HEADER_LEN || buf_proto + len > buf + buf_size) + return FALSE; + + *payload = buf_proto + UDP_HEADER_LEN; + *payload_size = len - UDP_HEADER_LEN; + } else { + if (buf_proto + 12 >= buf + buf_size) + return FALSE; + len = (buf_proto[12] >> 4) * 4; + if (buf_proto + len > buf + buf_size) + return FALSE; + + /* all remaining data following tcp header is payload */ + *payload = buf_proto + len; + *payload_size = self->cur_packet_size - (buf_proto - buf) - len; + } + + /* but still filter as configured */ + if (self->src_ip >= 0 && ip_src_addr != self->src_ip) return FALSE; - udp_dst_port = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 2))); - if (self->dst_port >= 0 && udp_dst_port != self->dst_port) + if (self->dst_ip >= 0 && ip_dst_addr != self->dst_ip) return FALSE; - udp_len = GUINT16_FROM_BE (*((guint16 *) (buf_udp + 4))); - if (udp_len < UDP_HEADER_LEN || buf_udp + udp_len > buf + buf_size) + if (self->src_port >= 0 && src_port != self->src_port) return FALSE; - *payload = buf_udp + UDP_HEADER_LEN; - *payload_size = udp_len - UDP_HEADER_LEN; + if (self->dst_port >= 0 && dst_port != self->dst_port) + return FALSE; return TRUE; } |