Discussion:
sniffex.c - libpcap example code proposal
Nathan Jennings
2005-06-29 19:11:52 UTC
Permalink
Hello,

I've attached "sniffex.c", which is intended to be libpcap example code.
It's based on Tim Carstens "sniffer.c" source.

I hope "sniffex" will serve as a decent working example of libpcap code
and provide basic documentation via comments for beginners. I also hope
this can serve as a template or "starting point" and be modified and
refined in the future.

I've added a "Tcpdump Group" copyright notice and terms while complying
(I think) with Tim Carstens terms. Please take a look at this copyright
and license and let me know what you think. Or go ahead and change it so
everyone agrees.

There's one issue I've run into: after displaying certain packets (see
function print_payload), my xterm/bash shell loses the ability to
display newlines (i.e scroll lines). I suppose this is due to the
display of a certain sequence of characters to my xterm/shell. Any ideas?

Any comments, suggestions or ideas are welcome.

-Nathan



-----------------------------------------
This e-mail and any attachments may contain CONFIDENTIAL information,
including PROTECTED HEALTH INFORMATION. If you are not the intended
recipient, any use or disclosure of this information is STRICTLY
PROHIBITED; you are requested to delete this e-mail and any
attachments, notify the sender immediately, and notify the LabCorp
Privacy Officer at ***@labcorp.com or call (877) 23-HIPAA /
(877) 234-4722.
Jefferson Ogata
2005-06-29 20:00:56 UTC
Permalink
Post by Nathan Jennings
There's one issue I've run into: after displaying certain packets (see
function print_payload), my xterm/bash shell loses the ability to
display newlines (i.e scroll lines). I suppose this is due to the
display of a certain sequence of characters to my xterm/shell. Any ideas?
Escape all non-printing characters, especially anything outside [\040-\176].

If you are passing arbitrary binary data to your terminal, an attacker
may be able to instruct your terminal to insert characters into your
terminal stream to execute arbitrary commands.
--
Jefferson Ogata <***@noaa.gov>
NOAA Computer Incident Response Team (N-CIRT) <***@noaa.gov>
Guy Harris
2005-06-29 20:20:50 UTC
Permalink
Post by Nathan Jennings
There's one issue I've run into: after displaying certain packets
(see function print_payload), my xterm/bash shell loses the ability
to display newlines (i.e scroll lines). I suppose this is due to
the display of a certain sequence of characters to my xterm/shell.
Any ideas?
Use "isprint()" rather than "isascii()" in "print_payload()".
Post by Nathan Jennings
Any comments, suggestions or ideas are welcome.
I might make "size_ethernet" into a #define:

#define SIZE_ETHERNET 14

and put it immediately after the "struct sniff_ethernet" definition
(perhaps with a comment noting that some compilers might pad that
structure to a multiple of 4 bytes - I think some versions of GCC for
ARM do - which is why "sizeof (struct sniff_ethernet)" isn't used).

You might also want to put in a comment noting that the filter of
"ip" ensures that you'll only get IP packets, which is why the
example program doesn't check the type/length field of the Ethernet
header.
Post by Nathan Jennings
int main()
{
char *dev = "/dev/eth0"; /* capture device */
You might want to make the device on which to capture a command-line
argument, so it's not so Linux-specific - and specific to capturing
on the first Ethernet.
Post by Nathan Jennings
/* open capture device */
descr = pcap_open_live(dev, SNAP_LEN, 1, 0, errbuf);
if (descr == NULL) {
printf("pcap_open_live failed: %s\n", errbuf);
exit(EXIT_FAILURE);
}
In addition, I'd check the link-layer type of the device you're
opening, so that if it's not Ethernet, the program won't try to
process it:

/* make sure it's an Ethernet device */
if (pcap_datalink(descr) != DLT_EN10MB) {
printf("device is not an Ethernet\n");
exit(EXIT_FAILURE);
}
Post by Nathan Jennings
/* apply the rules */
if (pcap_compile(descr, &fp, filter_app, 0, netp) == -1) {
printf("pcap_compile failed\n");
exit(EXIT_FAILURE);
}
I'd make that

printf("pcap_compile failed: %s\n", pcap_geterr(descr));

to report the reason why the compile failed.
Post by Nathan Jennings
if (pcap_setfilter(descr, &fp) == -1) {
printf("pcap_setfilter failed\n");
exit(EXIT_FAILURE);
}
And I'd do the same there.
Guy Harris
2005-06-29 21:22:47 UTC
Permalink
Post by Guy Harris
Use "isprint()" rather than "isascii()" in "print_payload()".
...and, while you're at it, print the payload in hex, as well as
ASCII, to emphasize that there's *no* guarantee that TCP data is
text. A format such as

00000000 00 00 48 65 6c 6c 6f 2c 20 73 61 69 7c 6f 72
21 ..Hello, sailor!

with an offset (perhaps hex), a sequence of hex byte values (perhaps
with an extra space separating the first 8 from the second 8 values),
and the same byte values as text (with values that don't correspond
to printable ASCII characters shown as ".") might be reasonable.
Robert Lowe
2005-06-29 22:07:58 UTC
Permalink
Post by Guy Harris
Use "isprint()" rather than "isascii()" in "print_payload()".
...and, while you're at it, print the payload in hex, as well as ASCII,
to emphasize that there's *no* guarantee that TCP data is text. A
format such as
00000000 00 00 48 65 6c 6c 6f 2c 20 73 61 69 7c 6f 72 21
..Hello, sailor!
with an offset (perhaps hex), a sequence of hex byte values (perhaps
with an extra space separating the first 8 from the second 8 values),
and the same byte values as text (with values that don't correspond to
printable ASCII characters shown as ".") might be reasonable.
Seems like that kind of functionality might be a good candidate for
inclusion in libpcap itself, no?? There are already functions to
dump to a savefile; why not printable output as well??

-Robert
Guy Harris
2005-06-29 22:19:40 UTC
Permalink
Post by Robert Lowe
Seems like that kind of functionality might be a good candidate for
inclusion in libpcap itself, no?? There are already functions to
dump to a savefile; why not printable output as well??
How much printable output do you want? Should libpcap incorporate
all of tcpdump as a library - or all of Analyzer or Ethereal?

The ability to write to a savefile complements the ability to read
from a savefile, and neither of them involve interpreting packet
data. The ability to *analyze* packet data is a different matter;
what's appropriate for tcpdump or Ethereal, for example, might not be
appropriate for snort or ntop, etc..

I view libpcap's job as capturing and sending packet data, with the
analysis or construction of that data belonging elsewhere; reading
capture files is there primarily to allow programs to fairly easily
process either live data or saved data.
Robert Lowe
2005-06-30 16:08:35 UTC
Permalink
Post by Robert Lowe
Seems like that kind of functionality might be a good candidate for
inclusion in libpcap itself, no?? There are already functions to
dump to a savefile; why not printable output as well??
How much printable output do you want? Should libpcap incorporate all
of tcpdump as a library - or all of Analyzer or Ethereal?
Of course not.
The ability to write to a savefile complements the ability to read from
a savefile, and neither of them involve interpreting packet data. The
ability to *analyze* packet data is a different matter; what's
appropriate for tcpdump or Ethereal, for example, might not be
appropriate for snort or ntop, etc..
I agree with your distinction between the capture and
interpretation/analysis of packet data and libpcap's role
in those processes. I was not thinking of something so
specific as to be useful only in a limited set of situations.
However, perhaps if it becomes too generic, everyone deserves
the joy of duplicating it for themselves. ;-)
I view libpcap's job as capturing and sending packet data, with the
analysis or construction of that data belonging elsewhere; reading
capture files is there primarily to allow programs to fairly easily
process either live data or saved data.
I understand, and agree.

-Robert
广星
2005-06-30 00:50:44 UTC
Permalink
Post by Nathan Jennings
I've attached "sniffex.c", which is intended to be libpcap example code.
It's based on Tim Carstens "sniffer.c" source.
I hope "sniffex" will serve as a decent working example of libpcap code
and provide basic documentation via comments for beginners. I also hope
this can serve as a template or "starting point" and be modified and
refined in the future.
I've added a "Tcpdump Group" copyright notice and terms while complying
(I think) with Tim Carstens terms. Please take a look at this copyright
and license and let me know what you think. Or go ahead and change it so
everyone agrees.
There's one issue I've run into: after displaying certain packets (see
function print_payload), my xterm/bash shell loses the ability to
display newlines (i.e scroll lines). I suppose this is due to the
display of a certain sequence of characters to my xterm/shell. Any ideas?
What I most concern about is how to print the payload in the correct format?
For example, there is a HTTP packet, how can I print the HTTP payload according to
its real content, such as"HTTP/1.1 206 Partial".
Post by Nathan Jennings
Any comments, suggestions or ideas are welcome.
-Nathan
        ***@ict.ac.cn
          2005-06-30
Guy Harris
2005-06-30 02:10:21 UTC
Permalink
Post by 广星
What I most concern about is how to print the payload in the
correct format?
For example, there is a HTTP packet, how can I print the HTTP
payload according to
its real content, such as"HTTP/1.1 206 Partial".
Well, the first thing you have to determine is what the right format is.

You would, for example, have to determine whether the packet is HTTP
or not; you might have to check for specific port numbers to do that
(for example, treat port 80 traffic as HTTP).

However, you wouldn't want to show *all* port 80 traffic as text -
consider an HTTP reply that contains a GIF or JPEG, for example.

Then you'd have to worry about an HTTP response that requires more
than one TCP segment.
广星
2005-06-30 03:06:19 UTC
Permalink
Thank you very much for the earnest detailed reply:-)~
But there are still some questions in my mind.
======= 2005-06-30 10:10:21 Guy Harris wrote:=======
Post by Guy Harris
Post by 广星
What I most concern about is how to print the payload in the
correct format?
For example, there is a HTTP packet, how can I print the HTTP
payload according to
its real content, such as"HTTP/1.1 206 Partial".
Well, the first thing you have to determine is what the right format is.
You would, for example, have to determine whether the packet is HTTP
or not; you might have to check for specific port numbers to do that
(for example, treat port 80 traffic as HTTP).
However, you wouldn't want to show *all* port 80 traffic as text -
consider an HTTP reply that contains a GIF or JPEG, for example.
Then you'd have to worry about an HTTP response that requires more
than one TCP segment.
How can I determine the right format?
For example a packet has been identified as an HTTP packet,
How can I know what its format is and are there many formats of the content of http?
All I what to do is to show the text content of the HTTP payload and the object of the HTTP reply will be ignored.
Is there any advises or documents which can help me?

Thank you again in advance.
Post by Guy Harris
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.
        ***@ict.ac.cn
          2005-06-30
Guy Harris
2005-06-30 08:52:26 UTC
Permalink
Post by 广星
How can I determine the right format?
For example a packet has been identified as an HTTP packet,
How can I know what its format is and are there many formats of the content of http?
Note that a TCP segment, in a link-layer frame, doesn't necessarily
correspond to a single HTTP request or response; a request or response
might require more than one TCP segment - and a single TCP segment could
conceivably contain more than one HTTP request or response.

An HTTP request starts with a request line, and an HTTP response starts
with a status line. Those lines are ASCII text. Following that are
message headers, also ASCII, until a blank line. After the blank line,
there might be a message body.
Post by 广星
All I what to do is to show the text content of the HTTP payload
and the object of the HTTP reply will be ignored.
"The HTTP payload" is probably the message body. Note, however, that
the HTTP payload is *not* necessarily text; if, for example, a GIF or
JPEG is being fetched, the payload will be binary.
Post by 广星
Is there any advises or documents which can help me?
RFC 2616?
广星
2005-06-30 00:59:34 UTC
Permalink
Post by Nathan Jennings
I've attached "sniffex.c", which is intended to be libpcap example code.
It's based on Tim Carstens "sniffer.c" source.
I hope "sniffex" will serve as a decent working example of libpcap code
and provide basic documentation via comments for beginners. I also hope
this can serve as a template or "starting point" and be modified and
refined in the future.
I've added a "Tcpdump Group" copyright notice and terms while complying
(I think) with Tim Carstens terms. Please take a look at this copyright
and license and let me know what you think. Or go ahead and change it so
everyone agrees.
There's one issue I've run into: after displaying certain packets (see
function print_payload), my xterm/bash shell loses the ability to
display newlines (i.e scroll lines). I suppose this is due to the
display of a certain sequence of characters to my xterm/shell. Any ideas?
What I most concern about is how to print the payload in the correct format?
For example, there is a HTTP packet, how can I print the HTTP payload according to
its real content, such as"HTTP/1.1 206 Partial".
Post by Nathan Jennings
Any comments, suggestions or ideas are welcome.
-Nathan
        ***@ict.ac.cn
          2005-06-30
Nathan Jennings
2005-07-05 15:59:16 UTC
Permalink
Post by Guy Harris
Post by Guy Harris
Use "isprint()" rather than "isascii()" in "print_payload()".
...and, while you're at it, print the payload in hex, as well as
ASCII, to emphasize that there's *no* guarantee that TCP data is text.
A format such as
00000000 00 00 48 65 6c 6c 6f 2c 20 73 61 69 7c 6f 72 21
..Hello, sailor!
with an offset (perhaps hex), a sequence of hex byte values (perhaps
with an extra space separating the first 8 from the second 8 values),
and the same byte values as text (with values that don't correspond to
printable ASCII characters shown as ".") might be reasonable.
Thanks for the help and suggestions. They are implemented in the updated
attached "sniffex.c" source file, v0.1.1.

The offset counter I printed in decimal, since the total payload is
printed in decimal and it just seemed more intuitive, at least for me (I
have enough trouble with base10 :). I also added a "Comments" section
and referenced these comments in the code with footnotes (e.g. [1]). I
think this is a good compromise between readability and explanation and
not having to give up one for the other.

Please let me know if you think of additional things that might help.

-Nathan



-----------------------------------------
This e-mail and any attachments may contain CONFIDENTIAL information,
including PROTECTED HEALTH INFORMATION. If you are not the intended
recipient, any use or disclosure of this information is STRICTLY
PROHIBITED; you are requested to delete this e-mail and any
attachments, notify the sender immediately, and notify the LabCorp
Privacy Officer at ***@labcorp.com or call (877) 23-HIPAA /
(877) 234-4722.
Guy Harris
2005-08-24 03:05:24 UTC
Permalink
Post by Nathan Jennings
Thanks for the help and suggestions. They are implemented in the updated
attached "sniffex.c" source file, v0.1.1.
I've checked that in to the Web site, with some changes, and updated the
tutorial to refer to it (I changed both the tutorial code and sniffex.c
code to resemble each other somewhat more).

Loading...