{"id":18151267,"url":"https://github.com/msantos/epcap","last_synced_at":"2025-04-05T16:06:10.202Z","repository":{"id":743401,"uuid":"394656","full_name":"msantos/epcap","owner":"msantos","description":"Erlang packet capture interface using pcap","archived":false,"fork":false,"pushed_at":"2023-11-22T12:25:31.000Z","size":377,"stargazers_count":178,"open_issues_count":1,"forks_count":55,"subscribers_count":22,"default_branch":"master","last_synced_at":"2024-03-23T07:03:16.980Z","etag":null,"topics":["bpf","pcap"],"latest_commit_sha":null,"homepage":"http://listincomprehension.com/2009/12/erlang-packet-sniffer-using-ei-and.html","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"mattn/goveralls","license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msantos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2009-12-03T22:04:36.000Z","updated_at":"2023-12-20T11:34:31.000Z","dependencies_parsed_at":"2023-11-22T13:45:47.622Z","dependency_job_id":null,"html_url":"https://github.com/msantos/epcap","commit_stats":{"total_commits":286,"total_committers":16,"mean_commits":17.875,"dds":0.1503496503496503,"last_synced_commit":"faaea7b41c3e03022df393ce64ea746f0eb06af8"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fepcap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fepcap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fepcap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fepcap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msantos","download_url":"https://codeload.github.com/msantos/epcap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247361681,"owners_count":20926643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bpf","pcap"],"created_at":"2024-11-02T01:07:08.564Z","updated_at":"2025-04-05T16:06:10.178Z","avatar_url":"https://github.com/msantos.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Package Version](https://img.shields.io/hexpm/v/epcap)](https://hex.pm/packages/epcap)\n[![Hex Docs](https://img.shields.io/badge/hex-docs)](https://hexdocs.pm/epcap/)\n\nAn Erlang port interface to libpcap.\n\nepcap includes a small example program called sniff.\n\n## QUICK SETUP\n\n```\n$ rebar3 compile\n```\n\nTo compile the examples:\n\n```\n$ mkdir -p ebin\n$ erlc +debug_info -I _build/default/lib -o ebin examples/*.erl\n\n# Allow your user to epcap with root privs\nsudo visudo\nyouruser ALL = NOPASSWD: /path/to/epcap/priv/epcap\n# And if requiretty is enabled, disable it by using one of these\nDefaults!/path/to/epcap/priv/epcap !requiretty\nDefaults:youruser !requiretty\n\nrebar3 shell\n\n% Start the sniffer process\nsniff:start_link().\n\n% Use your interface, or leave it out and trust in pcap\nsniff:start([{interface, \"eth0\"}]).\n\n% To change the filter\nsniff:start([{filter, \"icmp or (tcp and port 80)\"},{interface, \"eth0\"}]).\n\n% To stop sniffing\nsniff:stop().\n```\n\n## USAGE\n\n```\nepcap:start() -\u003e {ok, pid()}\nepcap:start(Args) -\u003e {ok, pid()}\nepcap:start_link() -\u003e {ok, pid()}\nepcap:start_link(Args) -\u003e {ok, pid()}\n\n    Types   Args = [Options]\n            Options = {chroot, string()} | {group, string()} | {interface, string()} | {promiscuous, boolean()} |\n                        {user, string()} | {filter, string()} | {progname, string()} | {file, string()} |\n                        {monitor, boolean()} | {cpu_affinity, string()} | {cluster_id, non_neg_integer()}} |\n                        {inject, boolean()} | {snaplen, non_neg_integer} | {buffer, non_neg_integer()} |\n                        {time_unit, microsecond | timestamp} | {direction, in | out | inout} |\n                        {timeout, pos_integer() | infinity | immediate},\n                        {env, string()}\n\n    Packets are delivered as messages:\n\n        {packet, DataLinkType, Time, Length, Packet}\n\n    The DataLinkType is an integer representing the link layer,\n    e.g., ethernet, Linux cooked socket.\n\n    The Time can be either in microseconds or a timestamp in the same\n    format as erlang:now/0 depending on the value of the time_unit\n    option (default: timestamp):\n\n    {MegaSecs, Secs, MicroSecs}\n\n    The Length corresponds to the actual packet length on the\n    wire. The captured packet may have been truncated. To get the\n    captured packet length, use byte_size(Packet).\n\n    The Packet is a binary holding the captured data.\n\n    If the version of the pcap library supports it, the pcap buffer\n    size can be set to avoid dropped packets by using the 'buffer'\n    option. The buffer size must be larger than the snapshot\n    length (default: 65535) plus some overhead for the pcap data\n    structures. Using some multiple of the snapshot length is\n    suggested. The timeout used when appending subsequent packets\n    to the buffer can be controlled by the 'timeout' option on some\n    platforms (value in msecs), the special values 'infinity' (wait\n    until the pcap buffer is filled) and 'immediate' (do not wait\n    after the first packet). The value 0 is equivalent to\n    'immediate' which differs from the definition given in pcap(3PCAP).\n\nepcap:send(Ref, Packet) -\u003e ok\n\n    Types   Ref = pid()\n            Packet = binary()\n\n    Inject a packet on the network interface. To enable sending\n    packets, start_link/1 must be called with the {inject, true} option\n    (default: {inject, false}). When disabled, any data sent\n    to the epcap port is silently discarded.\n\n    Packet injection failures are treated as fatal errors, terminating\n    the epcap port. Partial writes are not considered to be errors\n    and are ignored (an error message will be printed to stderr if\n    the verbose option is used).\n```\n\n## PF_RING\n\nIn case you want to compile epcap with PF_RING support, just specify\nthe path to the libpfring and modified libpcap libraries via shell\nvariable PFRING.\n\n```\nPFRING=/home/user/pfring rebar3 do clean, compile\n```\n\nTo complete the configuration you need to set up the cluster_id option.\nThe value of the cluster_id option is integer and should be in range\nbetween 0 and 255.\n\n```\nepcap:start_link([{interface, \"lo\"}, {cluster_id, 2}]).\n```\n\nYou can also specify the option cpu_affinity to set up CPU affinity for\nepcap port:\n\n```\nepcap:start_link([{interface, \"lo\"}, {cluster_id, 2}, {cpu_affinity, \"1,3,5-7\"}]).\n```\n\n## PROCESS RESTRICTIONS\n\nSetting the `RESTRICT_PROCESS` environment variable controls which\nmode of process restriction is used. The available modes are:\n\n* seccomp: linux\n\n* pledge: openbsd (default)\n\n* capsicum: freebsd (default)\n\n* rlimit: all (default: linux)\n\n* null: all\n\nFor example, to force using the seccomp process restriction on linux:\n\n```\nRESTRICT_PROCESS=rlimit rebar3 do clean, compile\n```\n\nThe `null` mode disables process restrictions and can be used for debugging.\n\n```\nRESTRICT_PROCESS=null rebar3 do clean, compile\n\nepcap:start([{exec, \"sudo strace -f -s 4096 -o rlimit.trace\"}, {filter, \"port 9997\"}]).\n\nRESTRICT_PROCESS=seccomp rebar3 do clean, compile\n\nepcap:start([{exec, \"sudo strace -f -s 4096 -o seccomp.trace\"}, {filter, \"port 9997\"}]).\n```\n\n## SCREENSHOT\n\n```\n=INFO REPORT==== 27-Oct-2013::11:47:43 ===\n    pcap: [{time,\"2013-10-27 11:47:43\"},\n           {caplen,653},\n           {len,653},\n           {datalink,en10mb}]\n    ether: [{source_macaddr,\"F0:BD:4F:AA:BB:CC\"},\n            {destination_macaddr,\"B3:4B:19:00:11:22\"}]\n    ipv6: [{protocol,tcp},\n           {source_address,\"2607:F8B0:400B:80B::1000\"},\n           {destination_address,\"2002:26F:92:AE::123\"}]\n    tcp: [{source_port,80},\n          {destination_port,47980},\n          {flags,[ack,psh]},\n          {seq,686139900},\n          {ack,725208397},\n          {win,224}]\n    payload_size: 567\n    payload: \"HTTP/1.0 301 Moved Permanently..Location: http://www.google.ca/..Content-Type: text/html; charset=UTF-8..Date: Sun, 27 Oct 2013 15:47:49 GMT..Expires: Tue, 26 Nov 2013 15:47:49 GMT..Cache-Control: public, max-age=2592000..Server: gws..Content-Length: 218..X-XSS-Protection: 1; mode=block..X-Frame-Options: SAMEORIGIN..Alternate-Protocol: 80:quic....\u003cHTML\u003e\u003cHEAD\u003e\u003cmeta http-equiv=\\\"content-type\\\" content=\\\"text/html;charset=utf-8\\\"\u003e.\u003cTITLE\u003e301 Moved\u003c/TITLE\u003e\u003c/HEAD\u003e\u003cBODY\u003e.\u003cH1\u003e301 Moved\u003c/H1\u003e.The document has moved.\u003cA HREF=\\\"http://www.google.ca/\\\"\u003ehere\u003c/A\u003e...\u003c/BODY\u003e\u003c/HTML\u003e..\" \n```\n\nAnd a screenshot of the number of packets epcap is processing on a\nproduction system:\n\n![IPTraf Screenshot](https://cloud.githubusercontent.com/assets/13721/4917083/8fe7754c-64e0-11e4-9165-17e21c57ee06.png)\n\n## TODO\n\n* return error atoms/tuples instead of using errx\n\n* add support for retrieving packet statistics using pcap\\_stats(3PCAP)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fepcap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsantos%2Fepcap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fepcap/lists"}