{"id":17396845,"url":"https://github.com/faern/rips-old","last_synced_at":"2025-05-13T01:26:05.921Z","repository":{"id":90202584,"uuid":"77478104","full_name":"faern/rips-old","owner":"faern","description":"Rust IP Stack - A userspace IP stack written in Rust (Work in progress) ","archived":false,"fork":false,"pushed_at":"2017-02-12T21:09:16.000Z","size":388,"stargazers_count":32,"open_issues_count":0,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-10-16T13:13:32.788Z","etag":null,"topics":["networking","packets","rust","stack","tcp-ip","userspace"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/faern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","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":"2016-12-27T19:30:00.000Z","updated_at":"2021-02-21T19:23:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"f4c7bc51-8104-465d-855e-b863bc1c87ea","html_url":"https://github.com/faern/rips-old","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/faern%2Frips-old","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faern%2Frips-old/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faern%2Frips-old/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faern%2Frips-old/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/faern","download_url":"https://codeload.github.com/faern/rips-old/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233694821,"owners_count":18715508,"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":["networking","packets","rust","stack","tcp-ip","userspace"],"created_at":"2024-10-16T13:13:34.441Z","updated_at":"2025-01-13T05:00:02.436Z","avatar_url":"https://github.com/faern.png","language":"Rust","readme":"# rips - Rust IP Stack\n\n**This repository is in a messy state. I kind of had UDP working, but then\nI realized the design was flawed. So now everything is torn apart and I'm\nslowly putting it back together again. Don't expect beautiful code, nor\ngreat functionality, before the 0.1.0 release.**\n\n[`rips`](https://github.com/faern/rips) is a TCP/IP stack implemented in\nRust and backed by [`pnet`](https://github.com/libpnet/libpnet) for its\nraw ethernet access.\n\n**WARNING**: This is not a *complete* TCP/IP stack at the moment.\n**It's a work in progress**. Continue to read to see what works at the\nmoment (But the docs might be outdated as well). Feedback and ideas on the\nimplementation and this documentation is very welcome. This is my first\nTCP/IP stack implementation so help will probably be needed in order to\nmake this library complete and correct.\nMost of this is implemented from observations of how other stacks seem to\nwork, I have not studied any other implementations in detail.\n\nLinux and OS X builds:\n[![Build Status](https://api.travis-ci.org/faern/rips.\nsvg?branch=master)](https://travis-ci.org/faern/rips)\n\n- [rnetcat](https://github.com/faern/rnetcat) - A Netcat like program based\non rips.\n- [ripstest](https://github.com/faern/ripstest) - A small crate with some\nusage examples of different layers of rips.\n\n## Usage\n\n```rust,ignore\nextern crate rips;\n\nlet stack = rips::default_stack();\n...\n```\n\n## Features\n\nAn incomplete list of what rips supports and is missing at the moment.\n\n- [x] Sending and receiving Ethernet frames\n- [x] Arp\n  - [x] Sending\n  - [x] Parsing incoming responses\n  - [ ] Timing out old entries in table\n- [ ] IPv4\n  - [x] Standard send\n  - [x] Validate lengths and checksums as part of parsing incoming\n  - [x] Fragmenting outgoing packets\n    - [x] Works in standard case\n    - [x] Correctly picking an identification field\n  - [ ] Reassembling incoming packets\n    - [x] Works in standard case\n    - [ ] Timing out caches of packets that were never completed\n    - [ ] Support reassemble out of order fragments?\n  - [ ] Header options\n  - [ ] Routing\n    - [x] Works in standard case\n    - [ ] Invalidate existing Tx on update\n    - [ ] Metrics\n  - [ ] Possible to change TTL\n- [ ] IPv6\n  - [ ] Path MTU discovery\n- [ ] Icmp\n  - [ ] Send generic Icmp packet\n  - [ ] Send Echo Request\n  - [ ] Receive Echo Reply\n  - [ ] Provide convenient way to implement a ping alternative\n- [ ] Udp\n  - [x] Sending Udp packets\n  - [x] Provide API similar to Rusts standard `UdpSocket`\n  - [ ] Provide improved API for separated sending and receiving\n  - [ ] Correctly close and clean up closed sockets\n- [ ] Tcp\n\n## Architecture and terminology\n\n### Sending\n\nRips contains a number of structs with names ending in *Tx*,\neg. `EthernetTx`, `ArpTx`, `Ipv4Tx`, `UdpTx`. We call them *tx-objects*, or\ntransmit objects. The tx-objects are building the header for their protocols\nand are supposed to be as simple as possible.\nThe constructors of the tx-objects take an instance of a tx-object\nbelonging to the underlying protocol, eg. both `ArpTx` and `Ipv4Tx`\ntakes an `EthernetTx`, while `UdpTx` takes an `Ipv4Tx`[1].\nThe constructors also take whatever values are needed to build their\nrespective packets, usually source and destination addresses and similar.\n\nAt the bottom of the stack there is a `Tx` instance for every interface in\nthe stack. View the `Tx` struct as the base tx-object.\nThe `Tx` holds the sending part of the `pnet` backend and a simple counter\nbehind a `Mutex`. Whenever anything in the stack changes, such as updates\nto the Arp or routing tables, the counter inside the `Tx` is incremented\nautomatically by the stack. The `Tx` also holds the counter value from when\nit was created. When any tx-object is used to send a packet the sending\nwill propagate down and eventually reach the `Tx` at the bottom. There the\n`Mutex` is locked and the counter from the creation of that `Tx` is\ncompared to the counter behind the lock.\nIf the counters are equal the packet is transmitted on the network,\notherwise a `TxError::InvalidTx` is returned. The reason for this is that\nevery tx-object should be kept simple and not do any lookups against routing\ntables etc when they construct their packets.\nAs long as nothing changes inside the stack all transmissions can go ahead\nwith no locking or lookups inside their `send` methods. As soon as a change\nhappens inside the stack all existing tx-objects become invalid and must be\nrecreated (which is cheap).\n\n[1]: This will change when IPv6 is implemented so that `UdpTx` can be used\non top of both.\n\n### Receiving\n\nJust as every protocol in the stack has a struct whose name ends in *Tx*\nfor transmission, it has a corresponding struct ending in *Rx* that is\nused for parsing incoming packets.\n\nThe rx-objects behave a little bit different on different levels of the\nstack. At the bottom the listeners are fixed and given in the constructor\nto avoid locking at each level on every incoming packets. Further up the\nstack the listeners are `HashMap`s behind `Mutex`es that can be changed\nthroughout the life of the stack to accomodate added and removed sockets.\n\nWork will be done to reduce locking on the receiving end. However,\noptimization comes after functionality, so that will be done later.\n\n### tests\n\nThis crate contains both unit tests and integration tests, both placed\nwhere the Rust book recommends them to be. The problem is that I need\nto do some mocking in the unit tests to be able to swap out the real\ndependencies with fake ones, so I can test individual structs without\ninitializing too many other structs. At the moment this is solved\nwith conditional compilation. When the feature \"unit-tests\" is active\ndependencies will be swapped out for mocks that exist in `rips::test`.\n\nThe bundled script `test.sh` is a tiny script that will execute both the\nunit tests and the integration tests.\n\nIdeas on how to solve this in a better way is welcome. However, the\nrequirements are that the solution does not bloat the production version\nof the code noticeably. Static dispatch can't be changed into dynamic\ndispatch just to allow testing.\n\n## Unsolved Questions\n\nHere are a few problems that I ran into that I still did not solve.\nFeedback is welcome.\n\n* If it's possible to have the same IP on multiple interfaces, which one\n  will a socket bound to that local IP receive packets from? Both?\n* Should the IP layer reassemble fragmented packets that are out of order?\n* Should the `FooTx` structs not contain the underlying `BarTx` and do the\n  sending internally. But instead be agnostic of the underlying protocol.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaern%2Frips-old","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaern%2Frips-old","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaern%2Frips-old/lists"}