{"id":18151472,"url":"https://github.com/shun159/netlink","last_synced_at":"2025-09-03T20:32:56.979Z","repository":{"id":92369794,"uuid":"120767052","full_name":"shun159/netlink","owner":"shun159","description":"gen_netlink wrapper for Elixir (My Hobby Project)","archived":false,"fork":false,"pushed_at":"2018-09-28T07:53:14.000Z","size":20,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2024-12-20T11:32:39.315Z","etag":null,"topics":["elixir","netfilter","netlink","nftables"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shun159.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-08T13:47:47.000Z","updated_at":"2024-07-20T15:19:51.000Z","dependencies_parsed_at":"2023-05-17T00:30:17.538Z","dependency_job_id":null,"html_url":"https://github.com/shun159/netlink","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shun159%2Fnetlink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shun159%2Fnetlink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shun159%2Fnetlink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shun159%2Fnetlink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shun159","download_url":"https://codeload.github.com/shun159/netlink/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231918572,"owners_count":18445746,"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":["elixir","netfilter","netlink","nftables"],"created_at":"2024-11-02T01:07:43.540Z","updated_at":"2024-12-30T21:40:24.960Z","avatar_url":"https://github.com/shun159.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Netlink\n\n## Installation\n\nAdd `:netlink` as a dependency to your project's `mix.exs`:\n\n```elixir\ndefp deps do\n  [{:netlink, github: \"shun159/netlink\", branch: \"develop\"}]\nend\n```\n\n## Usage\n\n### Netlink.Event functions\n\n- subscribe/1\n- stop/1\n\n```elixir\n\u003e {:ok, pid} = Netlink.Event.subscribe(:rtnetlink)\n\u003e flush()\n\u003e _ = Netlink.Event.stop(pid)\n```\n\n- event types:\n  - :rtnetlink\n  - :ctnetlink\n\n### Netlink.Route functions\n\nthis module can be Linux network setup via rtnl.\n\n- start_link/0\n- stop/1\n- iplink\\_add/4, iplink\\_add/5\n- iplink_del/2\n- iplink_set/3\n- ipaddr_replace/4\n- ipaddr_show/2\n- ipneigh_replace/4\n- ipneigh_del/4\n- iproute_replace/5\n- iproute\\_add\\_with\\_dev/4, iproute\\_add\\_with\\_dev/5\n- iproute_del/5\n- bridge\\_fdb\\_append/4\n- bridge\\_fdb\\_del/4\n- iprule\\_add/3, iprule\\_add/4\n- iprule\\_del/3, iprule\\_del/4\n\n#### Example\n\n```elixir\n{:ok, pid} = Netlink.Route.start_link\n{:ok, []} = Netlink.Route.iplink_add(pid, \"vxlan0\", \"vxlan\", 5, 4789)\n{:ok, []} = Netlink.Route.iplink_set(pid, \"vxlan0\", address: \u003c\u003c0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff\u003e\u003e)\n{:ok, []} = Netlink.Route.ipaddr_replace(pid, {192,168,5,1}, 24, \"vxlan0\")\n{:ok, {{192,168,5,1}, 24}} = Netlink.Route.ipaddr_show(pid, \"vxlan0\")\n{:ok, []} = Netlink.Route.ipneigh_replace(pid, {99,99,99,99}, \"00faceb00c\", \"docker0\")\n{:ok, []} = Netlink.Route.iproute_replace(pid, {100,100,100,0}, 24, {172,18,0,1})\n{:ok, []} = Netlink.Route.iproute_add_with_dev(pid, {200,200,200,0}, 24, 8)\n{:ok, []} = Netlink.Route.bridge_fdb_append(pid, {200,200,200,200}, \"00cafebabe\", \"vxlan0\")\n{:ok, []} = Netlink.Route.iprule_add(pid, _prefix_len = 0, _table = 1, fwmark: 1, fwmask: 1)\n```\n\n### Netfilter.Queue\n\nCallback module must implement `module.nfq_init/1` and `module.nfq_verdict/3`, like the following example:\n\n#### Example\n\n```elixir\ndefmodule Example do\n  @moduledoc false\n\n  @nf_accept 1\n\n  def start_link do\n    Netfilter.Queue.start_link(_queue_id = 0, callback_mod: __MODULE__)\n  end\n\n  def nfq_init(_opts) do\n    {}\n  end\n  \n  def nfq_verdict(_family, info, state) do\n    IO.puts \"THIS IS NFQUEUE message!!!!\"\n    IO.inspect(info)\n    {@nf_accept, _nfq_attrs = [mark: 0xabc], state}\n  end\nend\n```\n\n```elixir\nTHIS IS NFQUEUE message!!!!\n[{:packet_hdr, 123229, 2048, 3}, {:ifindex_outdev, 1}, {:mark, 2748},\n {:ct,\n  [tuple_orig: [ip: [v4_src: {127, 0, 0, 1}, v4_dst: {127, 0, 0, 53}],\n    proto: [num: :udp, src_port: 33610, dst_port: 53]],\n   tuple_reply: [ip: [v4_src: {127, 0, 0, 53}, v4_dst: {127, 0, 0, 1}],\n    proto: [num: :udp, src_port: 53, dst_port: 33610]], id: 1834526272,\n   status: [:dst_nat_done], timeout: 0]}, {:ct_info, :new},\n {:payload,\n  \u003c\u003c69, 0, 0, 59, 243, 49, 64, 0, 64, 17, 73, 74, 127, 0, 0, 1, 127, 0, 0, 53,\n    131, 74, 0, 53, 0, 39, 28, 148, 44, 182, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 5,\n    112, 114, 111, ...\u003e\u003e}]\n```\n\n#### Verdict:\n\n- nf_drop:   0\n- nf_accept: 1\n- nf_stolen: 2\n- nf_queue:  3\n- nf_repeat: 4\n- nf_stop:   5\n\n#### Supported NFQ attributes:\n\n- mark:           `1..0xffffffff`\n- label:          `1..0xffffffff`\n- payload:        `binary()`\n- ct:             `term()`\n- ifindex_indev:  `non_neg_integer()`\n- ifindex_outdev: `non_neg_integer()`\n- hwaddr:         `\u003c\u003c_::6-bytes\u003e\u003e`\n\n### Netfilter.Table\n\nnftables intarface.  \nImplemented functions in this module are follows:\n\n```elixir\n{:ok, pid} = Netfilter.Table.start_link\nNetfilter.Table.stop(pid)\n```\n\n#### Connection tracking\n\n- get\\_conntrack/1, get\\_conntrack/2, get\\_conntrack/3\n- set\\_conntrack/1, set\\_conntrack/2, set\\_conntrack/3\n- delete\\_conntrack/1, delete\\_conntrack/2, delete\\_conntrack/3\n\n##### Examples:\n\n```elixir\n{:ok, entries} = Netfilter.Table.get_conntrack(pid, [], :inet)\n{:ok, []} = Netfilter.Table.set_conntrack(pid,\n  timeout:     3,\n  tuple_orig:  [ip: [v4_src: {192,168,5,25}, v4_dst: {192,168,5,128}], proto: [num: :icmp, icmp_id: 12102, icmp_type: 8, icmp_code: 0]],\n  tuple_reply: [ip: [v4_dst: {192,168,5,25}, v4_src: {192,168,5,128}], proto: [num: :icmp, icmp_id: 12102, icmp_type: 0, icmp_code: 0]]\n)\n\nattrs = \n  pid\n  |\u003e Netfilter.Table.get_conntrack()\n  |\u003e Kernel.elem(1)\n  |\u003e Enum.at(0)\n  |\u003e Kernel.elem(5)\n  |\u003e Kernel.elem(3)\n  |\u003e Enum.filter(fn({key, _v}) -\u003e key in [:tuple_orig, :tuple_reply] end)\n\n{:ok, []} = Netfilter.Table.delete_conntrack(pid, attrs)\n```\n\n#### Table-related\n\n- gettables/1\n- newtable/2, newtable/3\n- deltable/2, deltable/3\n\n##### Examples:\n\n```elixir\n{:ok, tables} = Netfilter.Table.gettables(pid)\n{:ok, []} = Netfilter.Table.newtable(pid, \"foo\")\n{:ok, []} = Netfilter.Table.newtable(pid, _family = :inet6, \"foo6\")\n{:ok, []} = Netfilter.Table.deltable(pid, \"foo\")\n{:ok, []} = Netfilter.Table.deltable(pid, _family = :inet6, \"foo6\")\n```\n\n##### Types:\n\n- family: `:inet | :inet6`\n\n#### Chain-related\n\n- getchains/1\n- newchain/3, newchain/4, newchain/5\n- delchain/3, delchain/4\n\n##### Examples:\n\n```elixir\n{:ok, chains} = Netfilter.Table.getchains(pid)\n{:ok, []} = Netfilter.Table.newchain(pid, _table = \"foo\", _name  = \"blah\",\n  policy: :accept,\n  type: \"nat\",\n  hook: [hooknum: :prerouting, priority: 0]\n)\n{:ok, []} = Netfilter.Table.delchain(pid, \"foo\", \"blah\")\n```\n\n##### Chain Attributes\n\n- handle: `0..0xffffffffffffffff`\n- hook: `nft_chain_hook_attrs()`\n- policy: `:drop | :accept, | :stolen | :queue | :repeat | :stop`\n- type: `\"filter\" | \"nat\" | \"route\"`\n- `nft_chain_hook_attrs()`\n  - hooknum: `:prerouting | :input | :forward | :postrouting | :output | :ingress`\n  - priority: `0..0xffffffff`\n  - dev: `String.t`\n\n#### Rule-related\n\n- getrules/1\n- newrule/4, newrule/5\n- delrule/4, delrule/5\n\n##### Examples\n\n```elixir\n{:ok, rules} = Netfilter.Table.getrules(pid)\n{:ok, []} = Netfilter.Table.newrule(pid,\n  _table = \"foo\",\n  _chain = \"blah\",\n   expressions: [\n     expr: [name: 'payload', data: [dreg: 1, base: :network_header, offset: 12, len: 4]],\n     expr: [\n       name: 'bitwise',\n       data: [sreg: 1, dreg: 1, len: 4, mask: [value: \u003c\u003c255, 255, 255, 224\u003e\u003e], xor: [value: \u003c\u003c0, 0, 0, 0\u003e\u003e]]\n     ],\n     expr: [name: 'cmp', data: [sreg: 1, op: :eq, data: [value: \u003c\u003c10, 5, 6, 0\u003e\u003e]]],\n     expr: [name: 'meta', data: [key: :oif, dreg: 1]],\n     expr: [name: 'cmp', data: [sreg: 1, op: :eq, data: [value: \u003c\u003c15, 0, 0, 0\u003e\u003e]]],\n     expr: [name: 'masq', data: \"\"]\n   ]\n)\n{:ok, []} = Netfilter.Table.delrule(pid, \"foo\", \"postrouting\", _handle = 15)\n```\n\nAbove is equivalent to below....(´；ω；`)\n\n```\ntable ip foo {\n  chain postrouting {\n    ip saddr 10.5.6.0/27 oif \"veth0\" masquerade\n　}\n}\n```\n\n#### Set-related\n\n- getsets/1\n- newset/4, newset/5 # newset/4 and /5 doen't work\n- delset/3, delset/4\n\n##### Examples\n\n```elixir\n{:ok, rules} = Netfilter.Table.getsets(pid)\nNetfilter.Table.newset(pid, _table = \"foo\", _name = \"blahblah\",\n  flags: [:timeout],\n  key_type: 13,\n  key_len: 2,\n  timeout: 10845000,\n  userdata: \"\",\n  desc: \"\"\n)\n{:ok, []} = Netfilter.Table.delset(pid, \"foo\", \"blahblah\")\n```\n\n#### Setelement-related\n\n\n\nLicense\n-------\nTres is released under the __SUSHI-WARE LICENSE__.\n\n__私に寿司をおごってください__\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshun159%2Fnetlink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshun159%2Fnetlink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshun159%2Fnetlink/lists"}