{"id":17526313,"url":"https://github.com/nixcloud/ip2unix","last_synced_at":"2026-01-20T08:34:41.625Z","repository":{"id":144957984,"uuid":"152703097","full_name":"nixcloud/ip2unix","owner":"nixcloud","description":"Turn IP sockets into Unix domain sockets","archived":false,"fork":false,"pushed_at":"2024-07-07T11:44:38.000Z","size":520,"stargazers_count":354,"open_issues_count":7,"forks_count":10,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-07-07T12:54:22.521Z","etag":null,"topics":["ld-preload","linux","sockets","systemd","unix-domain-socket"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nixcloud.png","metadata":{"files":{"readme":"README.adoc","changelog":"CHANGELOG.md","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-10-12T06:19:22.000Z","updated_at":"2024-07-07T11:44:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"9a627df3-daef-4705-9db3-32cd2401b744","html_url":"https://github.com/nixcloud/ip2unix","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/nixcloud/ip2unix","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixcloud%2Fip2unix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixcloud%2Fip2unix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixcloud%2Fip2unix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixcloud%2Fip2unix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nixcloud","download_url":"https://codeload.github.com/nixcloud/ip2unix/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixcloud%2Fip2unix/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28599078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T02:08:49.799Z","status":"ssl_error","status_checked_at":"2026-01-20T02:08:44.148Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ld-preload","linux","sockets","systemd","unix-domain-socket"],"created_at":"2024-10-20T15:01:36.990Z","updated_at":"2026-01-20T08:34:41.606Z","avatar_url":"https://github.com/nixcloud.png","language":"C++","readme":"ip2unix(1)\n==========\nifndef::manmanual[]\n:doctitle: IP2Unix - Turn IP sockets into Unix domain sockets\nendif::[]\n:revdate: November 2018\nifndef::manmanual[]\n:toc: macro\n:numbered:\n:toc-title:\nendif::[]\n\nifdef::manmanual[]\n== Name\n\nip2unix - Turn IP sockets into Unix domain sockets\n\n== Synopsis\n\n:rule_or_file: pass:attributes,quotes[*-r* 'RULE' | *-f* 'FILE']\n:rulespec: {{rule_or_file}} [{rule_or_file}]...\n\n[verse]\n*ip2unix* [*-v*...] [*-p*] {rulespec} 'PROGRAM' ['ARGS'...]\n*ip2unix* [*-v*...] [*-p*] *-c* {rulespec}\n*ip2unix* *-h*\n*ip2unix* *--version*\n\nendif::[]\n\nifndef::manmanual[]\n:man_url: http://man7.org/linux/man-pages\n:sysdman_url: https://www.freedesktop.org/software/systemd/man\n\n:1: {man_url}/man8/ld.so.8.html#ENVIRONMENT\n:2: {man_url}/man2/accept.2.html\n:3: {sysdman_url}/systemd.socket.html\n:4: pass:attributes,quotes[{3}#FileDescriptorName=]\n:5: {man_url}/man7/glob.7.html\n\n:xt_owner_url: {man_url}/man8/iptables-extensions.8.html\n:xt_owner: pass:attributes,quotes[{xt_owner_url}[iptables owner module]]\n:socat: pass:attributes,quotes[http://www.dest-unreach.org/socat/[*socat*]]\n\n:LD_PRELOAD: pass:attributes,quotes[*LD_PRELOAD* ({1}[*ld.so*(8)])]\n:syscall_accept: pass:attributes,quotes[{2}[*accept*(2)]]\n:systemd_socket: pass:attributes,quotes[{3}[*systemd.socket*(5)]]\n:man_glob: pass:attributes,quotes[{5}[*glob*(7)]]\n:fdname: pass:attributes,quotes[{4}[FileDescriptorName]]\n:rulespec: \u003c\u003crule-specification,Rule specification\u003e\u003e\n:copy: (C) 2018 aszlig\nendif::[]\nifdef::manmanual[]\n:LD_PRELOAD: pass:quotes[*LD_PRELOAD* (see *ld.so*(8))]\n:syscall_accept: pass:quotes[*accept*(2)]\n:systemd_socket: pass:quotes[*systemd.socket*(5)]\n:man_glob: pass:quotes[*glob*(7)]\n:fdname: pass:quotes[FileDescriptorName (see *systemd.socket*(5))]\n:rulespec: pass:quotes[*RULE SPECIFICATION*]\n:copy: \\(C) 2018 aszlig\nendif::[]\n\n:lgpl_url: https://www.gnu.org/licenses/lgpl-3.0.html\n\nifndef::without-systemd[:systemd_comma: ,]\nifdef::without-systemd[:systemd_comma:]\n\nifndef::without-systemd[:systemd_backslash: \\]\nifdef::without-systemd[:systemd_backslash:]\n\nifdef::manmanual[]\n== Description\nendif::manmanual[]\n\nExecutes a program and converts IP to Unix domain sockets at runtime via\n{LD_PRELOAD} based on a list of rules, either given via short command line\noptions (see {rulespec}) or via a file containing a list of rules separated via\nnewline. The first matching rule causes *ip2unix* to replace the current IP\nsocket with a Unix domain socket based on the options given. For example if a\n\u003c\u003crule-socket-path,*path*\u003e\u003e is specified, the Unix domain socket will bind or\nlisten to the file given.\n\nifndef::manmanual[]\n\n[discrete]\n== Problem statement\n\nA lot of programs are designed to only work with IP sockets, however very few\nof them allow to communicate via Unix domain sockets. Unix domain sockets\nusually are just files, so standard Unix file permissions apply to them.\n\nIP sockets also have the disadvantage that other programs on the same host are\nable to connect to them, unless you use complicated netfilter rules or network\nnamespaces.\n\nSo if you either have a multi-user system or just want to separate privileges,\nUnix domain sockets are a good way to achieve that.\n\nAnother very common use case in nowadays systems is when you're using systemd\nand want to use socket units for services that don't support socket activation.\nApart from getting rid of the necessity to specify explicit dependencies, this\nis also very useful for privilege separation, since a lot of services can be\nrun in a separate network namespace.\n\nThe systemd use case is also useful even when not using Unix domain sockets in\nsocket units, since it allows to add IP-based socket activation to services\nthat don't support it.\n\n[discrete]\n== Short example\n\nLet's say you have a small HTTP server you want to make available behind a HTTP\nreverse proxy.\n\n[source,sh-session]\n---------------------------------------------------------------------\n$ ip2unix -r path=/run/my-http-server.socket my-http-server\n---------------------------------------------------------------------\n\nThis will simply convert all IP sockets to the Unix domain socket available at\n`/run/my-http-server.socket`. If you use a web server like\nhttps://nginx.org/[nginx], you can use the following directive to connect to\nthat socket:\n\n[source,nginx]\n---------------------------------------------------------------------\nproxy_pass http://unix:/run/my-http-server.socket;\n---------------------------------------------------------------------\n\nMore examples can be found further below in section \u003c\u003cexamples,Examples\u003e\u003e.\n\nA short summary of all the options is available via `ip2unix --help` or\n`man ip2unix` if you want to see all the details and options available.\n\nifndef::manmanual[]\n[discrete]\n= Table of Contents\n\ntoc::[]\nendif::[]\n\n== Build from source\n\nSee link:INSTALL.adoc[*INSTALL.adoc*] for information on how to build and/or\ninstall *ip2unix* on your system.\n\nendif::[]\n\nifdef::manmanual[]\n\n== Options\n\n*-c, --check*::\n  This is to validate whether the given rules are correct and the program\n  just prints all validation errors to stderr and exits with exit code `0`\n  if validation was successful and `1` if not.\n\n*-h, --help*::\n  Show command line usage and exit.\n\n*--version*::\n  Show version information and exit.\n\n*-p, --print*::\n  Print out the rules that are in effect in a tabular format. If you do not\n  want to run the 'PROGRAM', you can use the *-c* option to exit after\n  printing the rules.\n\n*-r, --rule*='RULE'::\n  A single rule for one particular socket to match. Can be specified multiple\n  times to add more rules.\n\n*-f, --file*='FILE'::\n  Read rules from 'FILE', which contains a newline-separated list of rules as\n  specified via `-r`. Empty lines as well as lines starting with `#` are\n  skipped. Whitespace characters at the beginning of each line are stripped as\n  well.\n\n*-v, --verbose*::\n  Increases the level of verbosity, according to the following table:\n\n  'FATAL' (default);;\n    Only print fatal errors which cause program termination.\n  'ERROR' (*-v*);;\n    Also print errors that are recoverable.\n  'WARNING' (*-vv*);;\n    Also print messages that might indicate possible problems.\n  'INFO' (*-vvv*);;\n    Also print informational messages about *ip2unix* behavior.\n  'DEBUG' (*-vvvv*);;\n    Also show messages about *ip2unix* internals along with source information.\n  'TRACE' (*-vvvvv*);;\n    Print every log message possible.\n\nendif::[]\n\n== Rule specification\n\nArguments specified via *-r* contain a comma-separated list of matches and a\nsingle action of what to do when a match is found. If a value contains a comma\n(`,`), it has to be escaped using a backslash (`\\`) character. If you want to\nhave a verbatim backslash character just use two consecutive backslashes\ninstead.\n\n=== Matches\nThe following matches are available:\n\n*in* | *out*::\nMatch either a server-side socket (`in`), a client-side socket (`out`) or both\nif neither `in` nor `out` is specified.\n\n*tcp* | *udp* | *stream* | *d*[*ata*]*gram*::\nMatch the socket type, which currently is either a `stream` (alias: `tcp`)\nor `datagram` (aliases: `dgram` or `udp`).\n\n*addr*[*ess*]='ADDRESS'::\nThe IP address to match, which can be either an IPv4 or an IPv6 address.\n\n*port*='PORT'[-'PORT_END']::\nMatch the UDP or TCP port number which for outgoing connections specifies the\ntarget port and for incoming connections the port that the socket is bound to.\n+\nIf a range is specified by separating two port numbers via `-`, the given\nrange is matched instead of just a single port. The range is inclusive, so if\n`2000-3000` is specified, both port 2000 and port 3000 are matched as well.\n\n[[rule-from-unix]]*from-unix*='PATTERN'::\nUse an existing Unix domain socket with a filename matching 'PATTERN'. This is\nuseful for example if a program hardcodes the socket path and you want to\nchange it.\n+\nThe syntax for 'PATTERN' is similar to {man_glob} and allows the following\nwildcards:\n+\n[horizontal]\n*?*;; Match any single character except `/`\n*\u0026ast;*;; Match zero or more characters except `/`\n*\u0026ast;\u0026ast;*;; Match zero or more path components, eg. `a/**/z` matches `a/z`,\n               `a/b/z`, `a/b/cde/z`, `a/b/c/c/d/z` and so on\n*[\u0026mldr;]*;; Match a single character via a series of either verbatim\n             characters or ranges, eg. `[a-cijq-s]` matches either `a`, `b`,\n             `c`, `i`, `j`, `q`, `r` or `s`\n*[!\u0026mldr;]*;; Same as above, but negates the match\n*\\X*;; Remove the special meaning of the character 'X',\n       eg. `\\?` literally matches `?`\n\nifndef::without-abstract[]\n*from-abstract*='PATTERN'::\nSimilar to \u003c\u003crule-from-unix,*from-unix*\u003e\u003e but matches 'PATTERN' against an\nabstract socket name.\nendif::[]\n\n=== Actions\n\n[[reject]]*reject*[='ERRNO']::\nReject calls to *connect* and *bind* with `EACCES` by default or the 'ERRNO'\nspecified either via name or as an integer.\n\n[[blackhole]]*blackhole*::\nTurn the socket into a Unix domain socket but do not make it available for\nclients to connect. This is useful to deactivate certain sockets without\ncausing errors in the application (unlike \u003c\u003creject,*reject*\u003e\u003e).\n+\nTechnically, this means that we *bind* to a Unix socket using a temporary file\nsystem path and *unlink* it shortly thereafter.\n\n*ignore*::\nPrevent a socket from being converted to a Unix domain socket if this is set.\nThis is useful to exempt specific sockets from being matched when another rule\nmatches a broad scope.\n\n[[rule-socket-path]]*path*='SOCKET_PATH'::\nConvert the socket into a Unix domain socket at the file specified by\n'SOCKET_PATH', which is either created during bind or used as the target when\nconnecting.\n+\nPlaceholders are allowed here and are substituted accordingly:\n+\n[horizontal]\n*%p*;; port number or `unknown` if not an IP socket\n*%a*;; IP address or `unknown` if not an IP socket\n*%t*;; socket type (`tcp`, `udp` or `unknown` if it's neither a stream nor\n                    datagram socket)\n*%%*;; verbatim `%`\n\n*noremove*::\nIf this flag is given in conjunction with a \u003c\u003crule-socket-path,*path*\u003e\u003e, the\nsocket file is not removed when the socket is closed.\n+\nThis works around an issue with more complex programs that spawn subprocesses\nor threads without sharing memory or cloning the file descriptor table. In some\nscenarios *ip2unix* might be unable to correctly track sockets and might\naccidentally remove the socket file too early.\n\nifndef::without-abstract[]\n*abstract*='NAME'::\nConvert the socket into an abstract namespace Unix domain socket. Unlike the\n\u003c\u003crule-socket-path,*path*\u003e\u003e action, the 'NAME' provided here has no connection\nwith file system pathnames. This also means that file system permissions do not\napply.\n+\nThe placeholders supported in \u003c\u003crule-socket-path,*path*\u003e\u003e are also supported\nhere.\nendif::[]\n\nifndef::without-systemd[]\n*systemd*[='FD_NAME']::\nUse an existing socket file descriptor provided by systemd instead of creating\na new socket.\n+\nAn optional file descriptor name ('FD_NAME') can be specified to\ndistinguish between several socket units. This corresponds to the {fdname}\nsystemd socket option.\nendif::[]\n\n== Rule matching behaviour\n\nEach rule is matched in the specified order and the first socket (regardless of\nspecificity) that matches is either turned into a Unix domain socket,\nblackholed, rejected or ignored depending on the action specified.\n\nIf a listening socket is matched by the same rule multiple times, subsequent\nsockets are automatically \u003c\u003cblackhole,blackholed\u003e\u003e (that is, deactivated\nwithout the application noticing). The reason for doing this is that it\nrequires fewer rules for common things, such as for example handling services\nthat bind to *both* IPv4 and IPv6 addresses.\n\nLet's say we have *someprogram*, which binds to +127.0.0.1:1234+ and\n+[::1]:1234+ in that order. All we need to do here is match on port 1234 and\nonly the first (+127.0.0.1:1234+) socket will actually bind to +/foo/bar+, the\nsecond (+[::1]:1234+) will be blackholed and is not reachable:\n\n[source,sh-session]\n-----------------------------------------------------------------------------\n$ ip2unix -r in,port=1234,path=/foo/bar someprogram\n-----------------------------------------------------------------------------\n\nNote that this is *only* the case if both end up using the *same* socket path.\nIf instead something like this is used, none of the two sockets is blackholed:\n\n[source,sh-session]\n-----------------------------------------------------------------------------\n$ ip2unix -r in,port=1234,path=/foo/bar-%a someprogram\n-----------------------------------------------------------------------------\n\nThis will result in two sockets:\n\n. +/foo/bar-127.0.0.1+ for the socket originally binding to +127.0.0.1:1234+.\n. +/foo/bar-::1+ for the socket originally binding to +[::1]:1234+.\n\nThe reason we blackhole subsequent sockets that lead to the same part is to\nmake the common case less verbose to express.\n\nIf we would not blackhole the socket and the matcher would simply fall through\nto the next rule, the following would be required to achieve the same behaviour\nthat we have in the first example:\n\n[source,sh-session]\n-----------------------------------------------------------------------------\n$ ip2unix -r in,port=1234,path=/foo/bar -r in,port=1234,blackhole someprogram\n-----------------------------------------------------------------------------\n\n== Examples\n\n=== Simple HTTP client/server\n\nThe following command spawns a small test web server listening on\n`/tmp/test.socket`:\n\n[source,sh-session]\n---------------------------------------------------------------------\n$ ip2unix -r in,path=/tmp/test.socket python3 -m http.server 8000\n---------------------------------------------------------------------\n\nThis connects to the above test server listening on `/tmp/test.socket` and\nshould show a directory listing:\n\n[source,sh-session]\n---------------------------------------------------------------------\n$ ip2unix -r out,path=/tmp/test.socket curl http://1.2.3.4/\n---------------------------------------------------------------------\n\n=== More complicated example\n\nFor example the following could be put into a file given by the *-f* command\nline argument:\n\n--------------------------------------------\nout,port=53,ignore\nout,tcp,path=/run/some.socket\nin,addr=1.2.3.4,path=/run/another.socket\nin,port=80,address=abcd::1,blackhole\nin,port=80,reject=EADDRINUSE\nifndef::without-systemd[]\nin,tcp,port=22,systemd=ssh\nendif::without-systemd[]\n--------------------------------------------\n\nEach line corresponds to a single rule, that is processed in order of\nappearance and the above example would result in the following:\n\n. All outgoing connections to port 53 (no matter if it's TCP or UDP) will not\n  be converted into Unix domain sockets.\n. This rule will redirect all TCP connections except to port 53 (see above) to\n  use the Unix domain socket at `/run/some.socket`.\n. Matches the socket that listens to any port on the IPv4 address `1.2.3.4` and\n  instead binds it to the Unix domain socket at `/run/another.socket`.\n. The application may bind to the IPv6 address `abcd::1` on port 80 but it will\n  not receive any connections, because no socket path exists.\n. Trying to bind to port 80 on addresses other than `abcd::1` will result in an\n  `EADDRINUSE` error.\nifndef::without-systemd[]\n. Will prevent the TCP socket that would listen on port 22 to not listen at all\n  and instead use the systemd-provided file descriptor named `ssh` for\n  operations like {syscall_accept}.\nendif::[]\n\nThe same can be achieved solely using *-r* commandline arguments:\n\n[source,sh-session]\n[subs=\"attributes\"]\n----------------------------------------------------------------------------\n$ ip2unix -r out,port=53,ignore \\\n          -r out,tcp,path=/run/some.socket \\\n          -r in,addr=1.2.3.4,path=/run/another.socket \\\n          -r in,port=80,address=abcd::1,blackhole \\\n          -r in,port=80,reject=EADDRINUSE {systemd_backslash}\nifndef::without-systemd[]\n          -r in,tcp,port=22,systemd=ssh\nendif::without-systemd[]\n----------------------------------------------------------------------------\n\n== Limitations\n\n* The program uses {LD_PRELOAD}, so it will only work with programs that are\ndynamically linked against the C library. Using ip2unix on statically linked\nexecutables or on executables that don't use the socket family functions of the\nC library (like Go programs) will not work at the moment.\n\n* If a client which is already using Unix *datagram* sockets sends packets via\n*sendto* or *sendmsg* to a socket provided by *ip2unix* without binding first,\n*ip2unix* is not able to identify the peer and will subsequently reject the\npacket. This is not the case when using *ip2unix* itself on the the client side\nand it also does not seem to be very common as the author so far did not find\nsuch an application in the wild.\n+\nHowever, if this really is an issue to you, the recommended workaround is\neither to use *ip2unix* to wrap the client (if it supports IP sockets) or fix\nthe server to natively use Unix domain sockets.\n\nifdef::manmanual[]\n\n== See also\n\n*accept*(2),\n*bind*(2),\n*connect*(2),\n*listen*(2),\n*recvfrom*(2),\n*recvmsg*(2),\n*sendmsg*(2),\n*sendto*(2),\n*socket*(2),\n*glob*(7),\n*unix*(7){systemd_comma}\nifndef::without-systemd[*systemd.socket*(5)]\n\nendif::[]\n\nifndef::manmanual[]\n\n== Frequently Asked Questions\n\n=== Isn't this functionality already covered by {socat}?\n\nThe {socat} tool has a very different purpose: It is essentially a way of\nconnecting streams between different address types. Apart from a myriad of\noptions, it supports quite a lot of address types and it's really good at\nproviding great flexibility to connect bidirectional streams.\n\nHowever what it doesn't do is change the behaviour of the target application,\nwhich is what *ip2unix* does.\n\nFor example, if you have an application that listens to TCP port 1234, you can\nuse {socat} to create a Unix domain socket listening on `foo.sock` and proxying\nall requests to TCP port 1234:\n\n[source,sh-session]\n---------------------------------------------------------------------\n$ socat UNIX-LISTEN:foo.sock,fork TCP:localhost:1234\n---------------------------------------------------------------------\n\nHere, the application will still listen to TCP port 1234, but we now have two\nadditional sockets (Unix inbound and TCP/IP outbound) we need to take care of.\n\n*ip2unix* on the other side redirects the C library calls of the application in\nquestion, so that TCP port 1234 will not be bound in the first place and\ninstead the application directly binds to a Unix domain socket.\n\nThis not only allows for better privilege separation (because local users need\nfile system access permissions to the socket file) but also involves less\noverhead since only one socket (the listening socket of the application itself)\nis used.\n\n=== Yes, but can't this still be done via {socat} and the {xt_owner}?\n\nOf course you could use *iptables* to only allow access to the user running\nsocat. But again, this still needs additional sockets and also still doesn't\ndecrease the attack surface by a large margin (eg. there could be race\nconditions in loading *iptables* rules or simply human error specifying the\nrules).\n\nNot binding to an IP socket in the first place however gets rid of that attack\nsurface, since you can't attack things that don't exist.\n\n== Similar projects\n\nhttps://cwrap.org/socket_wrapper.html[socket_wrapper]::\n\nThe goal is a different one here and its main use is testing. Instead of\nusing rules, *socket_wrapper* turns *all* of the IP sockets into Unix sockets\nand uses a central directory to do the mapping.\n+\nContaining all Unix sockets into one directory has the nice effect that it is\neasy to map *any* address/port combination to Unix sockets. While this is way\neasier to implement than our approach it has the drawback that everything is\ncontained and no IP communication is possible anymore.\n\nhttps://github.com/mildred/force-bind-seccomp[force-bind-seccomp]::\n\nVery similar in nature but instead of focusing on Unix domain sockets it allows\nto replace *bind* arguments for IP sockets. Unlike *ip2unix* however, it uses\nseccomp BPF in conjunction with *ptrace*, so it's much more effective if you\nhave to deal eg. with a statically linked program (see\n\u003c\u003climitations,Limitations\u003e\u003e above).\n+\nThe rule matching syntax also is very similar and it also has a way to force\nprograms to use systemd socket activation. If Unix domain sockets are not what\nyou want, you might want to give it a try.\n\n== Thanks\n\nSpecial thanks to the https://nlnet.nl/[NLnet foundation] for sponsoring the\ninitial work on this project.\n\nendif::[]\n\nifdef::manmanual[]\n\n== Author\n\nWritten by aszlig \u003caszlig@nix.build\u003e\n\nendif::[]\n\n== Copyright\n\nCopyright {copy}. License LGPLv3: GNU LGPL version 3 only\n\u003c{lgpl_url}\u003e.\n\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n","funding_links":[],"categories":["\u003ca name=\"cpp\"\u003e\u003c/a\u003eC++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixcloud%2Fip2unix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnixcloud%2Fip2unix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixcloud%2Fip2unix/lists"}