Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packet capture prototype #229

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

boba-buba
Copy link

@boba-buba boba-buba commented Dec 15, 2023

Ticket 629 (http://www.helenos.org/ticket/629).

That is a prototype of the support for network packet capture. I am doing it as a bachelor thesis at MFF UK. I will be grateful for any kind of feedback.

The support is implemented for e1k driver. And I tested it on ia32 architecture mostly. Now there are only two requests supported: start dumping all packets, stop dumping.

Usage

Application: pcapctl

pcapctl start (Example: pcapctl start data.pcap , file format is .pcap)

pcapctl stop

If someone is trying to start dumping, when it is already started the original file will be closed and saved, new file will be created and packets will be dumped to new file. If trying to stop when already stopped nothing will happen.

Then after getting the file out of HelenOS (through websrv for example) it can be opened with WireShark to see the packets, that were dumped.

Implementation

During start of the system pcap category created and e1k driver is added to pcap category. User uses application pcapctl. pcapctl start data.pcap will send request for start of the dumping. Location server will forward it to the first device in category pcap. And driver will start dumping packets. For stopping it is the same.

@vhotspur vhotspur marked this pull request as ready for review January 5, 2024 14:32
@vhotspur
Copy link
Member

vhotspur commented Jan 5, 2024

I have switched the PR into the ready state because I think it is in good enough shape to be tried and tested :-).

BTW, the following commands can be used to capture our webserver traffic:

pcapctl start capture.pcap
webserv
# From host, open localhost:8080 and browse the pages
pcapctl stop
cp capture.pcap data/web

And on host we can open it in Wireshark.

wget "http://localhost:8080/capture.pcap"
wireshark capture.pcap

The plan is now to write the thesis text but I think it would be really nice if Nataliia can get some feedback from the rest of the community too (and not only my complaints).


void pcap_add_packet(const void *data, size_t size)
{
if (&pcap_writer.data == NULL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a typo: the & should not be here.

Copy link
Contributor

@jxsvoboda jxsvoboda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. I added some comments, most of them pretty minor. I really wonder if we can avoid repeating the same code in all nic drivers. Why not do it in libnic, any particular reason?

@@ -1188,6 +1191,8 @@ static void e1000_receive_frames(nic_t *nic)
nic_frame_t *frame = nic_alloc_frame(nic, frame_size);
if (frame != NULL) {
memcpy(frame->data, e1000->rx_frame_virt[next_tail], frame_size);
pcapdump_packet(nic_get_pcap_iface(nic), frame->data, frame->size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call the packet capture hooks here? Any reason not to do it inside libnic? Then it would work for all the drivers.

if (pcap_rc != EOK) {
printf("Failed creating pcapdump port\n");
}
rc = ddf_fun_add_to_category(fun, "pcap");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I would expect this to be handled inside libnic.

uint32_t reserved2;
uint32_t snaplen;
uint32_t additional; /** The LinkType and additional information field is in the form */
} __attribute__((packed, aligned(4))) pcap_file_header_t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attribute is not needed. Since all the structure fields are naturally aligned, there won't be any padding and so packed is not needed. aligned(4) is not needed either, because 4 already is the alignment of the structure.

pcap_writer_add_packet(&pcap_writer, data, size);
}

void pcap_close_file()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be pcap_close_file(void)


#define NAME "pcapctl"

#define LOGGER(msg, ...) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is used anywhere.

* @brief Headers and functions for .pcap file and packets to be dumped
*/

#define LOGGER(msg, ...) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like overkill given it's used in one place only. I don't really thnk this is needed.

}
assert((count > 0) && "TODO: not implemented when no services are available\n");

rc = loc_service_get_name(pcap_svcs[0], &svc_name); // Note: for now [0], because only one driver is in pcap_svcs and there is no need to find particular
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably something that needs addressing.

async_exchange_end(exch);
}

errno_t pcapctl_dump_init(pcapctl_sess_t *sess)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep in line with the general object-oriented style, I would suggest that the constructor function should allocate the instance object (pcapctl_sess_t). Normally I would expect something like errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess). There should also be a corresponding destructor function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants