From a833fb5b68200cfb5fa6d5548cc2971ef5f12dca Mon Sep 17 00:00:00 2001 From: Florian Lehner Date: Tue, 12 Apr 2022 09:00:30 +0200 Subject: [PATCH] add netlink/rule (#139) * add netlink/rule Signed-off-by: Florian Lehner * Add some fuzzing corpus Signed-off-by: Jeroen Simonetti Co-authored-by: Jeroen Simonetti --- conn.go | 4 + example_rule_list_test.go | 27 ++ fuzz.go | 14 + go.mod | 2 +- go.sum | 2 + internal/unix/types_linux.go | 28 ++ internal/unix/types_other.go | 28 ++ rule.go | 394 ++++++++++++++++++ rule_test.go | 200 +++++++++ ...00c54925a3391eba539f847d3c4937a22a82a50-20 | Bin 0 -> 16 bytes ...09c1e6326977ed570af9d0a3d82cbe44150fb0e-23 | Bin 0 -> 132 bytes ...0b211ddd3949e326bbcb839b5676b98da7e8446-25 | Bin 0 -> 52 bytes ...38b07fe763eeff1f396be5d2b20093f7506a1ad-20 | Bin 0 -> 26 bytes ...41f0e6825e25cb64a77c98991b7377577fe7597-29 | Bin 0 -> 56 bytes ...99c634ff82ad664151d46cb60b97069d441a407-26 | Bin 0 -> 60 bytes ...b942a751646e82a0105ac6886368617cc46a414-23 | Bin 0 -> 42 bytes ...e6c24ef9886932fc194197746267d78fde85fdf-20 | Bin 0 -> 64 bytes ...0cdf79db931be0fe2187daab653329f9088ab93-24 | Bin 0 -> 164 bytes ...0f2b0ec0e92605d64c22e84712f8f449c587652-28 | Bin 0 -> 88 bytes ...32ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 | Bin 0 -> 56 bytes ...33c6203a11d34d494460e0ccd5860bc8e56c8b1-24 | Bin 0 -> 41 bytes ...44b30b754b40adc16300bede112114a23f7874e-21 | Bin 0 -> 20 bytes ...49a633ccd3b6b6209876c15406b9dbd43bc001d-26 | Bin 0 -> 348 bytes ...4ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 | Bin 0 -> 56 bytes ...5dc0cfaddd1bbd33c62ea16c339d520cb654616-22 | Bin 0 -> 25 bytes ...898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 | Bin 0 -> 188 bytes ...bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 | Bin 0 -> 28 bytes ...c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 | Bin 0 -> 36 bytes ...da46a06af7e4f65ba414cbad322e8bdb7035003-27 | Bin 0 -> 24 bytes ...4026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 | Bin 0 -> 64 bytes ...57b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 | Bin 0 -> 152 bytes ...592ea9e0fd7b42419b54de73c05d2d99b13df24-18 | Bin 0 -> 48 bytes ...6b2b4d750c52d006493c4e319ba349658d4a61f-26 | Bin 0 -> 64 bytes ...c35a00089c0fb60511083386c7033e1f4347143-22 | Bin 0 -> 36 bytes ...5cbabd1b4813019bc384933383dd526d18d59e2-26 | Bin 0 -> 57 bytes ...6786d46f73cb119fc6638c6e29fb2e9c74396e2-26 | Bin 0 -> 44 bytes ...ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 | Bin 0 -> 100 bytes ...f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 | Bin 0 -> 80 bytes ...21f3fe64fd443a5e2311b6b91d4444df441f420-24 | Bin 0 -> 129 bytes ...3b3231898ad43ca71f2e5676fe3d996eee720af-22 | Bin 0 -> 28 bytes ...3cf95eed2b63d204c5e5c488cf27382124e5ccf-28 | Bin 0 -> 88 bytes ...602005c8b057564c7915fb995d9b5493e43c8b8-23 | Bin 0 -> 36 bytes ...6f7d66e2363f6cf626df43782fbb422f9a5250b-22 | Bin 0 -> 100 bytes ...9ed76feb9bc20c4ad39a26a31d481f6e3efb001-26 | Bin 0 -> 44 bytes ...a2ee3a20fdea57760bc9ed8b8eff048044b22c5-19 | Bin 0 -> 48 bytes ...faa81537e211ad2a5e7c2976e9068326f7b8ae5-22 | Bin 0 -> 48 bytes ...07831810eb04b0ab951b933c46e35a228b57e71-26 | Bin 0 -> 89 bytes ...10580a628376865dc1af7d36bb17342f1b7afd6-15 | Bin 0 -> 32 bytes ...3ee26032f00098aee0f1a18f06c43bd7deff445-22 | Bin 0 -> 100 bytes ...b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 | Bin 0 -> 16 bytes ...bd1e85c8266889abce74d54a8405220a5ee6779-22 | Bin 0 -> 34 bytes ...c96e253b991e3683b48e88b521324924cb20489-23 | Bin 0 -> 33 bytes ...d45a18789afa6bfe420f3b92624733e1b6b400d-26 | Bin 0 -> 82 bytes ...fee9480466c6bd457ab0973ed1773f201423dcf-22 | Bin 0 -> 28 bytes ...137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 | Bin 0 -> 20 bytes ...2c46be36964f1e076447829594dfb379860946a-16 | Bin 0 -> 28 bytes ...daf24135b70a74d6c4b227044fa6ddce6b07fe3-20 | Bin 0 -> 24 bytes ...10e3342b121a02db40b8bbdeb24ead8dadfd7cd-21 | Bin 0 -> 88 bytes ...3faac654b2668bdeda7c30be1dd134c3bed0c1c-15 | Bin 0 -> 36 bytes ...54a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 | Bin 0 -> 33 bytes ...5867803304877cf925c2fb8339867de26e0125a-22 | Bin 0 -> 33 bytes ...844bd2f24c49dd9e86b785f35b9f6654dcd30ea-24 | Bin 0 -> 41 bytes ...852ae0ac17fc6d9c941454945ce6e319aef222e-22 | Bin 0 -> 25 bytes ...8f7070e047be466596fa9028fa7103ba851d238-25 | Bin 0 -> 57 bytes ...9079a1b4dd13427a4dd4b3cedc1bbcb7e1d2368-19 | Bin 0 -> 24 bytes ...99960a900389c990c5303154e1a01d236bd991f-17 | Bin 0 -> 16 bytes ...ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 | Bin 0 -> 96 bytes ...c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 | Bin 0 -> 96 bytes ...d238709fb1566509ae01e8be2329af666d8996d-21 | Bin 0 -> 172 bytes ...049ea23c981c73734e540b3313ddad4080b8dfe-25 | Bin 0 -> 52 bytes ...2b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 | Bin 0 -> 76 bytes ...353d46921b6fde028f970a604c2849cc5aa810c-24 | Bin 0 -> 36 bytes ...9e9ef3ebb14109ac96d689aeb6feccb3400da24-32 | Bin 0 -> 94 bytes ...c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 | Bin 0 -> 60 bytes ...c5db57d3a45d4ebd00f1f5a64dea8c59120cb34-27 | Bin 0 -> 44 bytes ...d17753428489bd447512e86803ff91b5cd4a618-23 | Bin 0 -> 25 bytes ...05486ceb3c7a06f5ba779bdf8c7b9b7fe52d166-23 | Bin 0 -> 56 bytes ...0d6e4244cf25054afb865d8f5b100afdb9311ea-22 | Bin 0 -> 25 bytes ...1bb3e18e2358e1f90017ff4524edd54e304cc62-22 | Bin 0 -> 33 bytes ...4161383e168655eec9c6560cc3fcf11559c0644-24 | Bin 0 -> 40 bytes ...58236df30daef0dabef7c95f7d9c4ae8674147d-20 | Bin 0 -> 80 bytes ...e35b7dd88c61d43565909b39d7062be8ced6b59-20 | Bin 0 -> 32 bytes ...045a8219d4c35f1ee204edc87d9488524ed644a-26 | Bin 0 -> 52 bytes ...27377086a04fda74ea2b153153fe88a2ceae6f0-22 | Bin 0 -> 60 bytes ...282e300b54d73d83f2eb94160c721a3c632c849-24 | Bin 0 -> 44 bytes ...6e20dcf12412996120dbd1c2e5e6f523d677887-27 | Bin 0 -> 89 bytes ...8f496ff9fbeebd3de79cccb57180543d7c796d2-31 | Bin 0 -> 72 bytes ...97c70f84b45e6db9a1f5ded724b37a8352bb521-25 | Bin 0 -> 49 bytes ...a54bb91bce9e07e00982df872b42edc13f84d55-19 | Bin 0 -> 24 bytes ...fc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 | Bin 0 -> 28 bytes ...04b3d040073e2f6e350a4b4ed4624fcdab39409-20 | Bin 0 -> 16 bytes ...1678cda7c01da8024141f32c90dba72632ed561-27 | Bin 0 -> 84 bytes ...5a5683b55006b63277d7e4e279002b6ff28bec9-24 | Bin 0 -> 41 bytes ...7f4fcd62ea8fdd1ae9ce3d3fb65ac3dfbe7fb94-26 | Bin 0 -> 60 bytes ...8064c73a17105178426ee811fd7e8ddbd3c8a6e-22 | Bin 0 -> 28 bytes ...92c421ae18794c90bb78245ffefc69891a1b212-29 | Bin 0 -> 608 bytes ...a1fe7e80d257cf0f97e3cf5056a065dd182c612-27 | Bin 0 -> 160 bytes ...b950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 | Bin 0 -> 50 bytes ...c3012d99f051d8f6dd72f64bfe30c8825413774-15 | Bin 0 -> 18 bytes ...f35de24da6b93b24b8203e34f2c91f85aa23358-25 | Bin 0 -> 49 bytes ...fdebdd9e5d0987fc0443b654ffc7a077928a394-15 | Bin 0 -> 52 bytes ...d5f295b6d021868a7ab632ec03eb316d6c6e010-22 | Bin 0 -> 52 bytes ...d74cca3dc346b8b47b61ac987f03db93703f1c7-25 | Bin 0 -> 156 bytes ...e1224c07048279cf433284b765ce88ad68aad5c-25 | Bin 0 -> 56 bytes ...0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 | Bin 0 -> 26 bytes ...2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 | Bin 0 -> 17 bytes ...42027a23e1cb69b41589b40bff7a4f236cd1627-27 | Bin 0 -> 152 bytes ...46958bfff37ee5dfaa20c39b568919ff92ead31-17 | Bin 0 -> 36 bytes ...49629bbf737e162754b52f3e1263f1970d58510-27 | Bin 0 -> 81 bytes ...57646a730378c58a8d1fda915b72e8a48914bbd-21 | Bin 0 -> 17 bytes ...68b0c4a65d86db5b580bb1c646885557a3becbd-19 | Bin 0 -> 20 bytes ...9e4fa2225f4b0a9106cbbcff0ee687c5c35233a-33 | Bin 0 -> 100 bytes ...f557b134cb1bda39a310cbbf71af8f6c2f0e216-28 | Bin 0 -> 52 bytes ...13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 | Bin 0 -> 16 bytes ...166514671b2011e5aafacc02bceb53258e6661b-23 | Bin 0 -> 28 bytes ...1cca7ed8a9b496b4737d863060d1364934de5a8-21 | Bin 0 -> 20 bytes ...206695f09384b7e00bfb83f8420ae32b7c2468e-26 | Bin 0 -> 57 bytes ...574d4af4c3638b3386727fabd64678186033c81-24 | Bin 0 -> 16 bytes ...5770d61def8b575787aae9457d1bc02261dbd84-27 | Bin 0 -> 160 bytes ...5acbead07330bf8c34eadaf884576e644b5b2e7-23 | Bin 0 -> 20 bytes ...72b2cb44601f2daf18194eb005807209d2774bf-20 | Bin 0 -> 20 bytes ...8834ab47f71c54992875b749345b701c715d779-24 | Bin 0 -> 44 bytes ...8a1f0be9b3443fa8adf9911c6e4c67429bc929f-21 | Bin 0 -> 40 bytes ...f42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 | Bin 0 -> 28 bytes ...fceaac6e39bceeee8337474c1e39118a8a097ce-25 | Bin 0 -> 58 bytes ...1efa9fe4886b61179e874c621c887428bbf81a1-27 | Bin 0 -> 60 bytes ...3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 | Bin 0 -> 24 bytes ...62f967416a52b4f25c977c5c1487555ac8e043d-23 | Bin 0 -> 36 bytes ...860e7d60c6f3ddf697c4eda7a528688021be855-25 | Bin 0 -> 52 bytes ...cce47777757315234c70eb38fec6916aa8e998d-23 | Bin 0 -> 33 bytes ...f93f3b0f00620af4bddf6d7003216bc6813c214-21 | Bin 0 -> 17 bytes ...fb32ecf19c83fa1e7810c60d343c4cdc06423e0-25 | Bin 0 -> 52 bytes 132 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 example_rule_list_test.go create mode 100644 rule.go create mode 100644 rule_test.go create mode 100644 testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 create mode 100644 testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 create mode 100644 testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 create mode 100644 testdata/corpus/038b07fe763eeff1f396be5d2b20093f7506a1ad-20 create mode 100644 testdata/corpus/041f0e6825e25cb64a77c98991b7377577fe7597-29 create mode 100644 testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 create mode 100644 testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 create mode 100644 testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 create mode 100644 testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 create mode 100644 testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 create mode 100644 testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 create mode 100644 testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 create mode 100644 testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 create mode 100644 testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 create mode 100644 testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 create mode 100644 testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 create mode 100644 testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 create mode 100644 testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 create mode 100644 testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 create mode 100644 testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 create mode 100644 testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 create mode 100644 testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 create mode 100644 testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 create mode 100644 testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 create mode 100644 testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 create mode 100644 testdata/corpus/35cbabd1b4813019bc384933383dd526d18d59e2-26 create mode 100644 testdata/corpus/36786d46f73cb119fc6638c6e29fb2e9c74396e2-26 create mode 100644 testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 create mode 100644 testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 create mode 100644 testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 create mode 100644 testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 create mode 100644 testdata/corpus/43cf95eed2b63d204c5e5c488cf27382124e5ccf-28 create mode 100644 testdata/corpus/4602005c8b057564c7915fb995d9b5493e43c8b8-23 create mode 100644 testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 create mode 100644 testdata/corpus/49ed76feb9bc20c4ad39a26a31d481f6e3efb001-26 create mode 100644 testdata/corpus/4a2ee3a20fdea57760bc9ed8b8eff048044b22c5-19 create mode 100644 testdata/corpus/4faa81537e211ad2a5e7c2976e9068326f7b8ae5-22 create mode 100644 testdata/corpus/507831810eb04b0ab951b933c46e35a228b57e71-26 create mode 100644 testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 create mode 100644 testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 create mode 100644 testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 create mode 100644 testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 create mode 100644 testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 create mode 100644 testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 create mode 100644 testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 create mode 100644 testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 create mode 100644 testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 create mode 100644 testdata/corpus/6daf24135b70a74d6c4b227044fa6ddce6b07fe3-20 create mode 100644 testdata/corpus/710e3342b121a02db40b8bbdeb24ead8dadfd7cd-21 create mode 100644 testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 create mode 100644 testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 create mode 100644 testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 create mode 100644 testdata/corpus/7844bd2f24c49dd9e86b785f35b9f6654dcd30ea-24 create mode 100644 testdata/corpus/7852ae0ac17fc6d9c941454945ce6e319aef222e-22 create mode 100644 testdata/corpus/78f7070e047be466596fa9028fa7103ba851d238-25 create mode 100644 testdata/corpus/79079a1b4dd13427a4dd4b3cedc1bbcb7e1d2368-19 create mode 100644 testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 create mode 100644 testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 create mode 100644 testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 create mode 100644 testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 create mode 100644 testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 create mode 100644 testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 create mode 100644 testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 create mode 100644 testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 create mode 100644 testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 create mode 100644 testdata/corpus/8c5db57d3a45d4ebd00f1f5a64dea8c59120cb34-27 create mode 100644 testdata/corpus/8d17753428489bd447512e86803ff91b5cd4a618-23 create mode 100644 testdata/corpus/905486ceb3c7a06f5ba779bdf8c7b9b7fe52d166-23 create mode 100644 testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 create mode 100644 testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 create mode 100644 testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 create mode 100644 testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 create mode 100644 testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 create mode 100644 testdata/corpus/a045a8219d4c35f1ee204edc87d9488524ed644a-26 create mode 100644 testdata/corpus/a27377086a04fda74ea2b153153fe88a2ceae6f0-22 create mode 100644 testdata/corpus/a282e300b54d73d83f2eb94160c721a3c632c849-24 create mode 100644 testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 create mode 100644 testdata/corpus/a8f496ff9fbeebd3de79cccb57180543d7c796d2-31 create mode 100644 testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 create mode 100644 testdata/corpus/aa54bb91bce9e07e00982df872b42edc13f84d55-19 create mode 100644 testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 create mode 100644 testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 create mode 100644 testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 create mode 100644 testdata/corpus/b5a5683b55006b63277d7e4e279002b6ff28bec9-24 create mode 100644 testdata/corpus/b7f4fcd62ea8fdd1ae9ce3d3fb65ac3dfbe7fb94-26 create mode 100644 testdata/corpus/b8064c73a17105178426ee811fd7e8ddbd3c8a6e-22 create mode 100644 testdata/corpus/b92c421ae18794c90bb78245ffefc69891a1b212-29 create mode 100644 testdata/corpus/ba1fe7e80d257cf0f97e3cf5056a065dd182c612-27 create mode 100644 testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 create mode 100644 testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 create mode 100644 testdata/corpus/bf35de24da6b93b24b8203e34f2c91f85aa23358-25 create mode 100644 testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 create mode 100644 testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 create mode 100644 testdata/corpus/cd74cca3dc346b8b47b61ac987f03db93703f1c7-25 create mode 100644 testdata/corpus/ce1224c07048279cf433284b765ce88ad68aad5c-25 create mode 100644 testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 create mode 100644 testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 create mode 100644 testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 create mode 100644 testdata/corpus/d46958bfff37ee5dfaa20c39b568919ff92ead31-17 create mode 100644 testdata/corpus/d49629bbf737e162754b52f3e1263f1970d58510-27 create mode 100644 testdata/corpus/d57646a730378c58a8d1fda915b72e8a48914bbd-21 create mode 100644 testdata/corpus/d68b0c4a65d86db5b580bb1c646885557a3becbd-19 create mode 100644 testdata/corpus/d9e4fa2225f4b0a9106cbbcff0ee687c5c35233a-33 create mode 100644 testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 create mode 100644 testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 create mode 100644 testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 create mode 100644 testdata/corpus/e1cca7ed8a9b496b4737d863060d1364934de5a8-21 create mode 100644 testdata/corpus/e206695f09384b7e00bfb83f8420ae32b7c2468e-26 create mode 100644 testdata/corpus/e574d4af4c3638b3386727fabd64678186033c81-24 create mode 100644 testdata/corpus/e5770d61def8b575787aae9457d1bc02261dbd84-27 create mode 100644 testdata/corpus/e5acbead07330bf8c34eadaf884576e644b5b2e7-23 create mode 100644 testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 create mode 100644 testdata/corpus/e8834ab47f71c54992875b749345b701c715d779-24 create mode 100644 testdata/corpus/e8a1f0be9b3443fa8adf9911c6e4c67429bc929f-21 create mode 100644 testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 create mode 100644 testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 create mode 100644 testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 create mode 100644 testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 create mode 100644 testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 create mode 100644 testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 create mode 100644 testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 create mode 100644 testdata/corpus/ff93f3b0f00620af4bddf6d7003216bc6813c214-21 create mode 100644 testdata/corpus/ffb32ecf19c83fa1e7810c60d343c4cdc06423e0-25 diff --git a/conn.go b/conn.go index 54254ae..048a624 100644 --- a/conn.go +++ b/conn.go @@ -17,6 +17,7 @@ type Conn struct { Address *AddressService Route *RouteService Neigh *NeighService + Rule *RuleService } var _ conn = &netlink.Conn{} @@ -54,6 +55,7 @@ func newConn(c conn) *Conn { rtc.Address = &AddressService{c: rtc} rtc.Route = &RouteService{c: rtc} rtc.Neigh = &NeighService{c: rtc} + rtc.Rule = &RuleService{c: rtc} return rtc } @@ -179,6 +181,8 @@ func unpackMessages(msgs []netlink.Message) ([]Message, error) { m = &RouteMessage{} case unix.RTM_GETNEIGH, unix.RTM_NEWNEIGH, unix.RTM_DELNEIGH: m = &NeighMessage{} + case unix.RTM_GETRULE, unix.RTM_NEWRULE, unix.RTM_DELRULE: + m = &RuleMessage{} default: continue } diff --git a/example_rule_list_test.go b/example_rule_list_test.go new file mode 100644 index 0000000..02647ce --- /dev/null +++ b/example_rule_list_test.go @@ -0,0 +1,27 @@ +package rtnetlink_test + +import ( + "log" + + "github.com/jsimonetti/rtnetlink" +) + +// List all rules +func Example_listRule() { + // Dial a connection to the rtnetlink socket + conn, err := rtnetlink.Dial(nil) + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + // Request a list of rules + rules, err := conn.Rule.List() + if err != nil { + log.Fatal(err) + } + + for _, rule := range rules { + log.Printf("%+v", rule) + } +} diff --git a/fuzz.go b/fuzz.go index 8a2267e..5e176e0 100644 --- a/fuzz.go +++ b/fuzz.go @@ -58,3 +58,17 @@ func FuzzNeighMessage(data []byte) int { return 1 } + +// FuzzRuleMessage will fuzz a RuleMessage +func FuzzRuleMessage(data []byte) int { + m := &RuleMessage{} + if err := (m).UnmarshalBinary(data); err != nil { + return 0 + } + + if _, err := m.MarshalBinary(); err != nil { + panic(err) + } + + return 1 +} diff --git a/go.mod b/go.mod index 69e0525..af27a0f 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/cilium/ebpf v0.8.1 github.com/google/go-cmp v0.5.7 github.com/mdlayher/netlink v1.6.0 - golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 + golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f ) diff --git a/go.sum b/go.sum index 4f367f4..e7d4e64 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/internal/unix/types_linux.go b/internal/unix/types_linux.go index 58bbaed..b9655e9 100644 --- a/internal/unix/types_linux.go +++ b/internal/unix/types_linux.go @@ -108,4 +108,32 @@ const ( RT_SCOPE_UNIVERSE = linux.RT_SCOPE_UNIVERSE RT_SCOPE_HOST = linux.RT_SCOPE_HOST RT_SCOPE_LINK = linux.RT_SCOPE_LINK + RTM_NEWRULE = linux.RTM_NEWRULE + RTM_GETRULE = linux.RTM_GETRULE + RTM_DELRULE = linux.RTM_DELRULE + FRA_UNSPEC = linux.FRA_UNSPEC + FRA_DST = linux.FRA_DST + FRA_SRC = linux.FRA_SRC + FRA_IIFNAME = linux.FRA_IIFNAME + FRA_GOTO = linux.FRA_GOTO + FRA_UNUSED2 = linux.FRA_UNUSED2 + FRA_PRIORITY = linux.FRA_PRIORITY + FRA_UNUSED3 = linux.FRA_UNUSED3 + FRA_UNUSED4 = linux.FRA_UNUSED4 + FRA_UNUSED5 = linux.FRA_UNUSED5 + FRA_FWMARK = linux.FRA_FWMARK + FRA_FLOW = linux.FRA_FLOW + FRA_TUN_ID = linux.FRA_TUN_ID + FRA_SUPPRESS_IFGROUP = linux.FRA_SUPPRESS_IFGROUP + FRA_SUPPRESS_PREFIXLEN = linux.FRA_SUPPRESS_PREFIXLEN + FRA_TABLE = linux.FRA_TABLE + FRA_FWMASK = linux.FRA_FWMASK + FRA_OIFNAME = linux.FRA_OIFNAME + FRA_PAD = linux.FRA_PAD + FRA_L3MDEV = linux.FRA_L3MDEV + FRA_UID_RANGE = linux.FRA_UID_RANGE + FRA_PROTOCOL = linux.FRA_PROTOCOL + FRA_IP_PROTO = linux.FRA_IP_PROTO + FRA_SPORT_RANGE = linux.FRA_SPORT_RANGE + FRA_DPORT_RANGE = linux.FRA_DPORT_RANGE ) diff --git a/internal/unix/types_other.go b/internal/unix/types_other.go index b98d4cc..39866ed 100644 --- a/internal/unix/types_other.go +++ b/internal/unix/types_other.go @@ -104,4 +104,32 @@ const ( RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_HOST = 0xfe RT_SCOPE_LINK = 0xfd + RTM_NEWRULE = 0x20 + RTM_GETRULE = 0x22 + RTM_DELRULE = 0x21 + FRA_UNSPEC = 0x0 + FRA_DST = 0x1 + FRA_SRC = 0x2 + FRA_IIFNAME = 0x3 + FRA_GOTO = 0x4 + FRA_UNUSED2 = 0x5 + FRA_PRIORITY = 0x6 + FRA_UNUSED3 = 0x7 + FRA_UNUSED4 = 0x8 + FRA_UNUSED5 = 0x9 + FRA_FWMARK = 0xa + FRA_FLOW = 0xb + FRA_TUN_ID = 0xc + FRA_SUPPRESS_IFGROUP = 0xd + FRA_SUPPRESS_PREFIXLEN = 0xe + FRA_TABLE = 0xf + FRA_FWMASK = 0x10 + FRA_OIFNAME = 0x11 + FRA_PAD = 0x12 + FRA_L3MDEV = 0x13 + FRA_UID_RANGE = 0x14 + FRA_PROTOCOL = 0x15 + FRA_IP_PROTO = 0x16 + FRA_SPORT_RANGE = 0x17 + FRA_DPORT_RANGE = 0x18 ) diff --git a/rule.go b/rule.go new file mode 100644 index 0000000..9d62b4f --- /dev/null +++ b/rule.go @@ -0,0 +1,394 @@ +package rtnetlink + +import ( + "bytes" + "encoding/binary" + "errors" + "net" + + "github.com/jsimonetti/rtnetlink/internal/unix" + "github.com/mdlayher/netlink" +) + +var ( + // errInvalidRuleMessage is returned when a RuleMessage is malformed. + errInvalidRuleMessage = errors.New("rtnetlink RuleMessage is invalid or too short") + + // errInvalidRuleAttribute is returned when a RuleMessage contains an unknown attribute. + errInvalidRuleAttribute = errors.New("rtnetlink RuleMessage contains an unknown Attribute") +) + +var _ Message = &RuleMessage{} + +// A RuleMessage is a route netlink link message. +type RuleMessage struct { + // Address family + Family uint8 + + // Length of destination prefix + DstLength uint8 + + // Length of source prefix + SrcLength uint8 + + // Rule TOS + TOS uint8 + + // Routing table identifier + Table uint8 + + // Rule action + Action uint8 + + // Rule flags + Flags uint32 + + // Attributes List + Attributes *RuleAttributes +} + +// MarshalBinary marshals a LinkMessage into a byte slice. +func (m *RuleMessage) MarshalBinary() ([]byte, error) { + b := make([]byte, 12) + + // fib_rule_hdr + b[0] = m.Family + b[1] = m.DstLength + b[2] = m.SrcLength + b[3] = m.TOS + b[4] = m.Table + b[7] = m.Action + nativeEndian.PutUint32(b[8:12], m.Flags) + + if m.Attributes != nil { + ae := netlink.NewAttributeEncoder() + ae.ByteOrder = nativeEndian + err := m.Attributes.encode(ae) + if err != nil { + return nil, err + } + + a, err := ae.Encode() + if err != nil { + return nil, err + } + + return append(b, a...), nil + } + + return b, nil +} + +// UnmarshalBinary unmarshals the contents of a byte slice into a LinkMessage. +func (m *RuleMessage) UnmarshalBinary(b []byte) error { + l := len(b) + if l < 12 { + return errInvalidRuleMessage + } + m.Family = b[0] + m.DstLength = b[1] + m.SrcLength = b[2] + m.TOS = b[3] + m.Table = b[4] + // b[5] and b[6] are reserved fields + m.Action = b[7] + m.Flags = nativeEndian.Uint32(b[8:12]) + + if l > 12 { + m.Attributes = &RuleAttributes{} + ad, err := netlink.NewAttributeDecoder(b[12:]) + if err != nil { + return err + } + ad.ByteOrder = nativeEndian + return m.Attributes.decode(ad) + } + return nil +} + +// rtMessage is an empty method to sattisfy the Message interface. +func (*RuleMessage) rtMessage() {} + +// RuleService is used to retrieve rtnetlink family information. +type RuleService struct { + c *Conn +} + +func (r *RuleService) execute(m Message, family uint16, flags netlink.HeaderFlags) ([]RuleMessage, error) { + msgs, err := r.c.Execute(m, family, flags) + + rules := make([]RuleMessage, len(msgs)) + for i := range msgs { + rules[i] = *msgs[i].(*RuleMessage) + } + + return rules, err +} + +// Add new rule +func (r *RuleService) Add(req *RuleMessage) error { + flags := netlink.Request | netlink.Create | netlink.Acknowledge | netlink.Excl + _, err := r.c.Execute(req, unix.RTM_NEWRULE, flags) + + return err +} + +// Replace or add new rule +func (r *RuleService) Replace(req *RuleMessage) error { + flags := netlink.Request | netlink.Create | netlink.Replace | netlink.Acknowledge + _, err := r.c.Execute(req, unix.RTM_NEWRULE, flags) + + return err +} + +// Delete existing rule +func (r *RuleService) Delete(req *RuleMessage) error { + flags := netlink.Request | netlink.Acknowledge + _, err := r.c.Execute(req, unix.RTM_DELRULE, flags) + + return err +} + +// Get Rule(s) +func (r *RuleService) Get(req *RuleMessage) ([]RuleMessage, error) { + flags := netlink.Request | netlink.DumpFiltered + return r.execute(req, unix.RTM_GETRULE, flags) +} + +// List all rules +func (r *RuleService) List() ([]RuleMessage, error) { + flags := netlink.Request | netlink.Dump + return r.execute(&RuleMessage{}, unix.RTM_GETRULE, flags) +} + +// RuleAttributes contains all attributes for a rule. +type RuleAttributes struct { + Src, Dst *net.IP + IIFName, OIFName *string + Goto *uint32 + Priority *uint32 + FwMark, FwMask *uint32 + SrcRealm *uint16 + DstRealm *uint16 + TunID *uint64 + Table *uint32 + L3MDev *uint8 + Protocol *uint8 + IPProto *uint8 + SuppressPrefixLen *uint32 + SuppressIFGroup *uint32 + UIDRange *RuleUIDRange + SPortRange *RulePortRange + DPortRange *RulePortRange +} + +// unmarshalBinary unmarshals the contents of a byte slice into a RuleMessage. +func (r *RuleAttributes) decode(ad *netlink.AttributeDecoder) error { + for ad.Next() { + switch ad.Type() { + case unix.FRA_UNSPEC: + // unused + continue + case unix.FRA_DST: + r.Dst = &net.IP{} + ad.Do(decodeIP(r.Dst)) + case unix.FRA_SRC: + r.Src = &net.IP{} + ad.Do(decodeIP(r.Src)) + case unix.FRA_IIFNAME: + v := ad.String() + r.IIFName = &v + case unix.FRA_GOTO: + v := ad.Uint32() + r.Goto = &v + case unix.FRA_UNUSED2: + // unused + continue + case unix.FRA_PRIORITY: + v := ad.Uint32() + r.Priority = &v + case unix.FRA_UNUSED3: + // unused + continue + case unix.FRA_UNUSED4: + // unused + continue + case unix.FRA_UNUSED5: + // unused + continue + case unix.FRA_FWMARK: + v := ad.Uint32() + r.FwMark = &v + case unix.FRA_FLOW: + dst32 := ad.Uint32() + src32 := uint32(dst32 >> 16) + src32 &= 0xFFFF + dst32 &= 0xFFFF + src16 := uint16(src32) + dst16 := uint16(dst32) + r.SrcRealm = &src16 + r.DstRealm = &dst16 + case unix.FRA_TUN_ID: + v := ad.Uint64() + r.TunID = &v + case unix.FRA_SUPPRESS_IFGROUP: + v := ad.Uint32() + r.SuppressIFGroup = &v + case unix.FRA_SUPPRESS_PREFIXLEN: + v := ad.Uint32() + r.SuppressPrefixLen = &v + case unix.FRA_TABLE: + v := ad.Uint32() + r.Table = &v + case unix.FRA_FWMASK: + v := ad.Uint32() + r.FwMask = &v + case unix.FRA_OIFNAME: + v := ad.String() + r.OIFName = &v + case unix.FRA_PAD: + // unused + continue + case unix.FRA_L3MDEV: + v := ad.Uint8() + r.L3MDev = &v + case unix.FRA_UID_RANGE: + r.UIDRange = &RuleUIDRange{} + err := r.UIDRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + case unix.FRA_PROTOCOL: + v := ad.Uint8() + r.Protocol = &v + case unix.FRA_IP_PROTO: + v := ad.Uint8() + r.IPProto = &v + case unix.FRA_SPORT_RANGE: + r.SPortRange = &RulePortRange{} + err := r.SPortRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + case unix.FRA_DPORT_RANGE: + r.DPortRange = &RulePortRange{} + err := r.DPortRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + default: + return errInvalidRuleAttribute + } + } + return ad.Err() +} + +// MarshalBinary marshals a RuleAttributes into a byte slice. +func (r *RuleAttributes) encode(ae *netlink.AttributeEncoder) error { + if r.Table != nil { + ae.Uint32(unix.FRA_TABLE, *r.Table) + } + if r.Protocol != nil { + ae.Uint8(unix.FRA_PROTOCOL, *r.Protocol) + } + if r.Src != nil { + ae.Do(unix.FRA_SRC, encodeIP(*r.Src)) + } + if r.Dst != nil { + ae.Do(unix.FRA_DST, encodeIP(*r.Dst)) + } + if r.IIFName != nil { + ae.String(unix.FRA_IIFNAME, *r.IIFName) + } + if r.OIFName != nil { + ae.String(unix.FRA_OIFNAME, *r.OIFName) + } + if r.Goto != nil { + ae.Uint32(unix.FRA_GOTO, *r.Goto) + } + if r.Priority != nil { + ae.Uint32(unix.FRA_PRIORITY, *r.Priority) + } + if r.FwMark != nil { + ae.Uint32(unix.FRA_FWMARK, *r.FwMark) + } + if r.FwMask != nil { + ae.Uint32(unix.FRA_FWMASK, *r.FwMask) + } + if r.DstRealm != nil { + value := uint32(*r.DstRealm) + if r.SrcRealm != nil { + value |= (uint32(*r.SrcRealm&0xFFFF) << 16) + } + ae.Uint32(unix.FRA_FLOW, value) + } + if r.TunID != nil { + ae.Uint64(unix.FRA_TUN_ID, *r.TunID) + } + if r.L3MDev != nil { + ae.Uint8(unix.FRA_L3MDEV, *r.L3MDev) + } + if r.IPProto != nil { + ae.Uint8(unix.FRA_IP_PROTO, *r.IPProto) + } + if r.SuppressIFGroup != nil { + ae.Uint32(unix.FRA_SUPPRESS_IFGROUP, *r.SuppressIFGroup) + } + if r.SuppressPrefixLen != nil { + ae.Uint32(unix.FRA_SUPPRESS_PREFIXLEN, *r.SuppressPrefixLen) + } + if r.UIDRange != nil { + data, err := marshalRuleUIDRange(*r.UIDRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_UID_RANGE, data) + } + if r.SPortRange != nil { + data, err := marshalRulePortRange(*r.SPortRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_SPORT_RANGE, data) + } + if r.DPortRange != nil { + data, err := marshalRulePortRange(*r.DPortRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_DPORT_RANGE, data) + } + return nil +} + +// RulePortRange defines start and end ports for a rule +type RulePortRange struct { + Start, End uint16 +} + +func (r *RulePortRange) unmarshalBinary(data []byte) error { + b := bytes.NewReader(data) + return binary.Read(b, nativeEndian, r) +} + +func marshalRulePortRange(s RulePortRange) ([]byte, error) { + var buf bytes.Buffer + err := binary.Write(&buf, nativeEndian, s) + return buf.Bytes(), err +} + +// RuleUIDRange defines the start and end for UID matches +type RuleUIDRange struct { + Start, End uint16 +} + +func (r *RuleUIDRange) unmarshalBinary(data []byte) error { + b := bytes.NewReader(data) + return binary.Read(b, nativeEndian, r) +} + +func marshalRuleUIDRange(s RuleUIDRange) ([]byte, error) { + var buf bytes.Buffer + err := binary.Write(&buf, nativeEndian, s) + return buf.Bytes(), err +} diff --git a/rule_test.go b/rule_test.go new file mode 100644 index 0000000..97c822f --- /dev/null +++ b/rule_test.go @@ -0,0 +1,200 @@ +package rtnetlink + +import ( + "bytes" + "errors" + "net" + "reflect" + "testing" +) + +func TestRuleMessage(t *testing.T) { + skipBigEndian(t) + + tests := map[string]struct { + m Message + b []byte + marshalErr error + unmarshalErr error + }{ + "empty": { + m: &RuleMessage{}, + b: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + }, + "no attributes": { + m: &RuleMessage{ + Family: 1, + DstLength: 2, + SrcLength: 3, + TOS: 4, + Table: 5, + Action: 6, + Flags: 7, + }, + b: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00}, + }, + "with attributes": { + m: &RuleMessage{ + Family: 7, + DstLength: 6, + SrcLength: 5, + TOS: 4, + Table: 3, + Action: 2, + Flags: 1, + Attributes: &RuleAttributes{ + Src: netIPPtr(net.ParseIP("8.8.8.8")), + Dst: netIPPtr(net.ParseIP("1.1.1.1")), + IIFName: strPtr("eth0"), + OIFName: strPtr("br0"), + Goto: uint32Ptr(1), + Priority: uint32Ptr(2), + FwMark: uint32Ptr(3), + FwMask: uint32Ptr(5), + L3MDev: uint8Ptr(7), + DstRealm: uint16Ptr(11), + SrcRealm: uint16Ptr(13), + TunID: uint64Ptr(17), + Protocol: uint8Ptr(19), + IPProto: uint8Ptr(23), + Table: uint32Ptr(29), + SuppressPrefixLen: uint32Ptr(31), + SuppressIFGroup: uint32Ptr(37), + UIDRange: &RuleUIDRange{ + Start: 22, + End: 25, + }, + SPortRange: &RulePortRange{ + Start: 23, + End: 26, + }, + DPortRange: &RulePortRange{ + Start: 24, + End: 27, + }, + }, + }, + b: []byte{ + 0x07, 0x06, 0x05, 0x04, 0x03, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0f, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x15, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x09, 0x00, 0x03, 0x00, 0x65, 0x74, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x11, 0x00, 0x62, 0x72, 0x30, 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x13, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x16, 0x00, + 0x19, 0x00, 0x08, 0x00, 0x17, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x08, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x1b, 0x00, + }, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + var b []byte + t.Run("marshal", func(t *testing.T) { + var marshalErr error + b, marshalErr = tt.m.MarshalBinary() + + if !errors.Is(marshalErr, tt.marshalErr) { + t.Fatalf("Expected error '%v' but got '%v'", tt.marshalErr, marshalErr) + } + }) + + t.Run("compare bytes", func(t *testing.T) { + if want, got := tt.b, b; !bytes.Equal(want, got) { + t.Fatalf("unexpected Message bytes:\n- want: [%# x]\n- got: [%# x]", want, got) + } + }) + + m := &RuleMessage{} + t.Run("unmarshal", func(t *testing.T) { + unmarshalErr := (m).UnmarshalBinary(b) + if !errors.Is(unmarshalErr, tt.unmarshalErr) { + t.Fatalf("Expected error '%v' but got '%v'", tt.unmarshalErr, unmarshalErr) + } + }) + + t.Run("compare messages", func(t *testing.T) { + if !reflect.DeepEqual(tt.m, m) { + t.Fatalf("unexpected Message:\n- want: %#v\n- got: %#v", tt.m, m) + } + }) + }) + } + + t.Run("invalid length", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{0x00, 0x01, 0x2, 0x03}) + if !errors.Is(unmarshalErr, errInvalidRuleMessage) { + t.Fatalf("Expected 'errInvalidRuleMessage' but got '%v'", unmarshalErr) + } + }) + + t.Run("skipped attributes", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{ + 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x07, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x09, 0x00, 0x04, 0x00, 0x12, 0x00, + }) + if !errors.Is(unmarshalErr, nil) { + t.Fatalf("Expected no error but got '%v'", unmarshalErr) + } + expected := &RuleMessage{ + Family: 1, + TOS: 2, + Table: 3, + Action: 4, + Flags: 5, + Attributes: &RuleAttributes{}, + } + if !reflect.DeepEqual(expected, m) { + t.Fatalf("unexpected Message:\n- want: %#v\n- got: %#v", expected, m) + } + }) + + t.Run("invalid attribute", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{ + 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x2a, 0x00, + }) + if !errors.Is(unmarshalErr, errInvalidRuleAttribute) { + t.Fatalf("Expected 'errInvalidRuleAttribute' error but got '%v'", unmarshalErr) + } + }) +} + +func uint64Ptr(v uint64) *uint64 { + return &v +} + +func uint32Ptr(v uint32) *uint32 { + return &v +} + +func uint16Ptr(v uint16) *uint16 { + return &v +} + +func uint8Ptr(v uint8) *uint8 { + return &v +} + +func netIPPtr(v net.IP) *net.IP { + if ip4 := v.To4(); ip4 != nil { + // By default net.IP returns the 16 byte representation. + // But netlink requires us to provide only four bytes + // for legacy IPs. + return &ip4 + } + return &v +} + +func strPtr(v string) *string { + return &v +} diff --git a/testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 b/testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 new file mode 100644 index 0000000000000000000000000000000000000000..6827c5e11a534ea5d016b7db5e9c2330c5810a71 GIT binary patch literal 16 PcmZQ!U}j)}V^IbG0W<(F literal 0 HcmV?d00001 diff --git a/testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 b/testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 new file mode 100644 index 0000000000000000000000000000000000000000..f44c95cc5947198bcd32c0da8bfecbd33b1bb975 GIT binary patch literal 132 zcmaF=z)^&Om4SgleZM0Ig9yWZT@Wn+q;r6@IFt{f_n`4X>d?hW(Ff7*`ux;S0E0Oq ANdN!< literal 0 HcmV?d00001 diff --git a/testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 b/testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 new file mode 100644 index 0000000000000000000000000000000000000000..2e66c8dc0168a07458d014ee1efb66ce984585f8 GIT binary patch literal 52 pcmaFAzc@2}!hA;tg`bWb47?2c?0@Ql=$o$~d?1a&-{LJAvA~u;)^f<09XA2j{pDw literal 0 HcmV?d00001 diff --git a/testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 b/testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 new file mode 100644 index 0000000000000000000000000000000000000000..3e35ac3ac1cec92b103e4fb5960519ac45460eda GIT binary patch literal 60 rcmaFAzc@2}!hA;tg`bWb47?2c?0@Ql=$o$~d?1a&-v?9Y@Y4|hu$>i< literal 0 HcmV?d00001 diff --git a/testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 b/testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 new file mode 100644 index 0000000000000000000000000000000000000000..b3a7eb3d839f6b0453015a15b8345ebcbd4b1f7d GIT binary patch literal 42 dcmZQ!_+QV)z|6pMpP7M;L6Ct3$VQ>z;s9zf1I7RV literal 0 HcmV?d00001 diff --git a/testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 b/testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 new file mode 100644 index 0000000000000000000000000000000000000000..3a00dbaa1249d4167e103556d7dd9480090f5cee GIT binary patch literal 64 ucmcco>ZgDZ0~^C-h6YCt1_=-erVl~+jzCF}xZ|s%U~!l_kT}ETte*hr84hg# literal 0 HcmV?d00001 diff --git a/testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 b/testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 new file mode 100644 index 0000000000000000000000000000000000000000..f1b60712f6b4baa30a9e20b0660c1c2c57ae63a0 GIT binary patch literal 164 zcmaF=z)^&Om4SgleZM0IgE+%}-91nm#Fqf_bCCEVKt48cbbTN`G3H_F%MoT|fVcyq J-}U*ap8)p=D6{|o literal 0 HcmV?d00001 diff --git a/testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 b/testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 new file mode 100644 index 0000000000000000000000000000000000000000..6d215f20a03f1eddafcf23bba02e70081ed89d41 GIT binary patch literal 88 dcmaF<>Zc)|)!|69rKB+X!5CAg!3UmMf literal 0 HcmV?d00001 diff --git a/testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 b/testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 new file mode 100644 index 0000000000000000000000000000000000000000..1e4e4e246962edd1de2011bc12674cc7cb11827d GIT binary patch literal 56 ncmcco>ZhX+0~^C-h6YCt1_=-eruRenj<1e_`7n8i;;f$lsFDsM literal 0 HcmV?d00001 diff --git a/testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 b/testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 new file mode 100644 index 0000000000000000000000000000000000000000..c30838d7921761800216f390513ab35f83262f7c GIT binary patch literal 41 ZcmZQ!U}j(gVitz)|5+JC5i|=L9{`(a2x$NS literal 0 HcmV?d00001 diff --git a/testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 b/testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 new file mode 100644 index 0000000000000000000000000000000000000000..cbb43a2062044f2316cc9d12d73796a48898f78f GIT binary patch literal 20 ccmaFAzc@2}!hF}8uYNjmFz_<$bNJ~90CB|$umAu6 literal 0 HcmV?d00001 diff --git a/testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 b/testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 new file mode 100644 index 0000000000000000000000000000000000000000..dcdd7250a6d8e7e1617751c6845b7df24dfc3aa8 GIT binary patch literal 348 zcmaF=z)^&Om4SgleZM0IgE+%}T^OB%%HOjGl@C{^izF@q)Sn0DGcYtTK+HqeM=Nt- o?nbsxf?<&^nti&+^5P6R!i-RN!t}#vWOani=|D5b_4%ov0PvntOaK4? literal 0 HcmV?d00001 diff --git a/testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 b/testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 new file mode 100644 index 0000000000000000000000000000000000000000..a3533ec9af6b7643ae6049e7ef6df76da595e8ae GIT binary patch literal 56 lcmaF<>ZcDd{WM?%(J(%YMim!e002d25@Y}X literal 0 HcmV?d00001 diff --git a/testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 b/testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 new file mode 100644 index 0000000000000000000000000000000000000000..a34a94e61a7d84ed56c7e668adddbb49c8f00df5 GIT binary patch literal 25 WcmZQ!U}j(gVitz)|5+JC5i|fSiv&FY literal 0 HcmV?d00001 diff --git a/testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 b/testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 new file mode 100644 index 0000000000000000000000000000000000000000..3ffe6d66e7d41a5204fcf0890d8227e834440074 GIT binary patch literal 188 zcmaF=z)^&Om4SgleZM0IgE+%}T^OB%#@~a+hp9srmjLR|LsN$=k8D1&I7lCU`*MUC M8IaxQ`ux;S03(qu)&Kwi literal 0 HcmV?d00001 diff --git a/testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 b/testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 new file mode 100644 index 0000000000000000000000000000000000000000..2dce38bf49370f4ff983cd955569e5b1223de997 GIT binary patch literal 28 icmaFQ$iX1Mz{JR*{?n0zfsuiQ!2l@2#Bll5PX+)%GX--1 literal 0 HcmV?d00001 diff --git a/testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 b/testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 new file mode 100644 index 0000000000000000000000000000000000000000..7d1fb844a5fe54d793dbffdb1613c57f5dbfa2ce GIT binary patch literal 36 acmaF<>Zc)|)GrU2gLE-?7dj&lJ literal 0 HcmV?d00001 diff --git a/testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 b/testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 new file mode 100644 index 0000000000000000000000000000000000000000..536fdaf8ec242e03ce876a228fa5e157a1065649 GIT binary patch literal 24 ccmaE_&fv(wz{s#)cR!F8VPIge0%8#c06zu;w*UYD literal 0 HcmV?d00001 diff --git a/testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 b/testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 new file mode 100644 index 0000000000000000000000000000000000000000..7981a8d4e1e219c96a9524340bff910cd73a4165 GIT binary patch literal 64 ucmZQbVSoWg5e5+kMg~U)21gM&Mur9k1E35CP>g|*1408yFdrrklmh^8(*nr= literal 0 HcmV?d00001 diff --git a/testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 b/testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 new file mode 100644 index 0000000000000000000000000000000000000000..afb5c6b367839b050ea56d87995930aef065f094 GIT binary patch literal 152 zcmZR2DDSAvpwF<+VZS2>0~f=7U1kO_4duhd9ri1uiaSEpH)B^%zBwEmKxY5|b;Kgr literal 0 HcmV?d00001 diff --git a/testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 b/testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 new file mode 100644 index 0000000000000000000000000000000000000000..d510f55c8ba3bb14148781bd06ab94c960fadcf9 GIT binary patch literal 48 kcmcco>ZhX+0~^C-h6YCt1_=-eruV-(3Z`M=5Jg!(0aIlS00000 literal 0 HcmV?d00001 diff --git a/testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 b/testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 new file mode 100644 index 0000000000000000000000000000000000000000..7b0d4b8ff07581e3d2ba5b5745c5df25a24939c7 GIT binary patch literal 64 ncmZR2$l<8XpwF<+VZS2>0~f=7U1kO_4duhd9rmM%LzDvm-&+o< literal 0 HcmV?d00001 diff --git a/testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 b/testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 new file mode 100644 index 0000000000000000000000000000000000000000..7e9446e800f67379b82a9654e0ae8ab893a9b616 GIT binary patch literal 36 gcmZQ!U}j(gViqV3VzV&_GVIsQapYhS2h#f;0Ua;{Zc)|)GrYk;gX96i+6F%W literal 0 HcmV?d00001 diff --git a/testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 b/testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 new file mode 100644 index 0000000000000000000000000000000000000000..8255da82183bf3e7d2056162bba9a23bec296503 GIT binary patch literal 100 rcmaF=z)^&Om4SgleZM0IgE+%}T^OB%#@~a+hpEFQ4v}|#e(EOx>-QRT literal 0 HcmV?d00001 diff --git a/testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 b/testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 new file mode 100644 index 0000000000000000000000000000000000000000..9da27c3de3edde41af64563b522b943cf45be15b GIT binary patch literal 80 mcmcco|ECNG0~^DupN@_k415fifed6CmpDuvOdhNas2>2qR~zC0 literal 0 HcmV?d00001 diff --git a/testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 b/testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 new file mode 100644 index 0000000000000000000000000000000000000000..ad5fbe8ee411d794ebee2dd12236ab4b05ba1a23 GIT binary patch literal 129 zcmaF=z)^&Om4SgleZM0Ig9yWZT@Wn+q;r6@IFt{f_n`4X>d?hW(YN1`6{z1803Qn< AoB#j- literal 0 HcmV?d00001 diff --git a/testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 b/testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 new file mode 100644 index 0000000000000000000000000000000000000000..ccc9da43d828c8a8d5f285305415e802d43eea31 GIT binary patch literal 28 dcmaFAzc@2}!hFY@uYNjmFz_0~f=7U1kO_jl>54mtqH) literal 0 HcmV?d00001 diff --git a/testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 b/testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 new file mode 100644 index 0000000000000000000000000000000000000000..c89db95d094f16fffb46fae75bd9c877a4f4cf01 GIT binary patch literal 100 ycmaF=z)^&Om4SgleZM0Ig9yWZT@Wn+q;r6@IFt{f_n`4X>hOs}kJ literal 0 HcmV?d00001 diff --git a/testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 b/testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 new file mode 100644 index 0000000000000000000000000000000000000000..719f1ad90fcae436255178bf88a4d148f4a114d8 GIT binary patch literal 32 ecmaFAzc^E>BtP@=tDlY{3|tH#;0Wh4G5`SGVhf)D literal 0 HcmV?d00001 diff --git a/testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 b/testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 new file mode 100644 index 0000000000000000000000000000000000000000..2795bc8de74ce47cb4c37f5492f1d1ba7c330dc5 GIT binary patch literal 100 tcmaF=z)^&Om4SgleZM0Ig9yWZT@Wn}q;sG&jK2qsPe>dh@A~}IPXOxm8gT#s literal 0 HcmV?d00001 diff --git a/testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 b/testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 new file mode 100644 index 0000000000000000000000000000000000000000..fd8bedb09e3b7773abd8d60770907957a0e7beb9 GIT binary patch literal 16 RcmZQzfPnu%z`!8F000^u1Q7rL literal 0 HcmV?d00001 diff --git a/testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 b/testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 new file mode 100644 index 0000000000000000000000000000000000000000..b3c2d89d9ffc136a4239cd2eaa1bda2c0000f75b GIT binary patch literal 34 WcmZQ!_+QV)z|6n`#B2!vX35 literal 0 HcmV?d00001 diff --git a/testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 b/testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 new file mode 100644 index 0000000000000000000000000000000000000000..e7aa4c8126fc4f64056ca703522cb326032b46f9 GIT binary patch literal 33 XcmZQ!U}j(gVitz)|5+KtFlaUaTdf9G literal 0 HcmV?d00001 diff --git a/testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 b/testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 new file mode 100644 index 0000000000000000000000000000000000000000..93a0efd74c1512a90b1d259fbb877015e79d5d4b GIT binary patch literal 82 icmZQz6pm$KU}gYeHU>ckmiuV50vaDC4--e%#{d8b^adsX literal 0 HcmV?d00001 diff --git a/testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 b/testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 new file mode 100644 index 0000000000000000000000000000000000000000..4f633012d93190654ea4385d65c0a8bb17512f9f GIT binary patch literal 28 bcmaF<>Zc)|)GcbT@9xxvORU!jW literal 0 HcmV?d00001 diff --git a/testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 b/testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 new file mode 100644 index 0000000000000000000000000000000000000000..bbd1126cf56383704522e5f6458ebdea667d0556 GIT binary patch literal 20 WcmZQ!U}EH8;9y_?(>x3;KpFr7LjX1a literal 0 HcmV?d00001 diff --git a/testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 b/testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 new file mode 100644 index 0000000000000000000000000000000000000000..755930d80fd6b7cd74d6b0cfa5fc590e7e94c972 GIT binary patch literal 28 bcmcco>ZcZgDZ0~^C-h6YCt1_=-erVl~+jzCF}xZ|s%U~yv9F#t6I09;}br~m)} literal 0 HcmV?d00001 diff --git a/testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 b/testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 new file mode 100644 index 0000000000000000000000000000000000000000..d938a569929fd08b0b1ef36414ce5ed951e441c0 GIT binary patch literal 36 dcmaFAzd6&fBtP@=s|OAYaKH*@F);l94*=QZ2?ziH literal 0 HcmV?d00001 diff --git a/testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 b/testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 new file mode 100644 index 0000000000000000000000000000000000000000..a79efcc72084070d16cafe28482b78fe6fa19777 GIT binary patch literal 33 WcmZQ!U}j(gVitz)|5+JCF=+r>iUv^t literal 0 HcmV?d00001 diff --git a/testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 b/testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 new file mode 100644 index 0000000000000000000000000000000000000000..cc210f05ca7de6cc80e17ac4d0bfc1a0ecf2e057 GIT binary patch literal 33 fcmZQ!U}j(gVitz)|5+JCp|ltSix7w}%)kZ!TpZc3`0~^ETS3ey&82A{#6p#-9emV#s literal 0 HcmV?d00001 diff --git a/testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 b/testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 new file mode 100644 index 0000000000000000000000000000000000000000..378de723f0b135f23844a6fb1443542fa25265ee GIT binary patch literal 16 XcmaFMchB)HgC8RY0|x^OgCGL{E%pO^ literal 0 HcmV?d00001 diff --git a/testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 b/testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 new file mode 100644 index 0000000000000000000000000000000000000000..8cf8a6391cd455dce7d5bff598a66a09ea2600f7 GIT binary patch literal 96 wcmZR2DDSAvpwF<+VZS2>0~f=7U1kO_4duhd9ri1uiaSEpH{(*z!2vW506p^-p8x;= literal 0 HcmV?d00001 diff --git a/testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 b/testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 new file mode 100644 index 0000000000000000000000000000000000000000..002c3b5d6bb5933b3031bc06ee5558ac84a60b68 GIT binary patch literal 96 ocmaF<>ZcDd{WM?%(J(%YCRQ9-9RtuD076e5$^ZZW literal 0 HcmV?d00001 diff --git a/testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 b/testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 new file mode 100644 index 0000000000000000000000000000000000000000..c558928a454f145e0feac9752ba74558a047321e GIT binary patch literal 172 RcmaFMz|6n~#4JMq0{{gL0vP}R literal 0 HcmV?d00001 diff --git a/testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 b/testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 new file mode 100644 index 0000000000000000000000000000000000000000..a60eb5b067e5575096114a10c259bb1fa99abc0b GIT binary patch literal 52 icmZR2$l<8XpwF<+VZS2>0~f=7U1kO_4duhdk>mkBQwzBO literal 0 HcmV?d00001 diff --git a/testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 b/testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 new file mode 100644 index 0000000000000000000000000000000000000000..17da21d639c662c0105fff5e792045bfcdf220bf GIT binary patch literal 76 gcmZQ!U}EH85NBWj(mV`249M*7Kruq%KzX=k0CGbE6aWAK literal 0 HcmV?d00001 diff --git a/testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 b/testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 new file mode 100644 index 0000000000000000000000000000000000000000..3df8508436c08408e03235ea33c25bf1862b958b GIT binary patch literal 36 jcmaF<>ZcDd{WM?%(J;OMg8?G|{U!?e literal 0 HcmV?d00001 diff --git a/testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 b/testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 new file mode 100644 index 0000000000000000000000000000000000000000..1531f4d7f60bf4ea9264c8ba30285f7156794331 GIT binary patch literal 94 zcmZQbVSoWg5e5+kMg~U)21gM&Mur9k1E35CP>g|*141)cKxzEqEDX#HY#@CM0NAzz An*aa+ literal 0 HcmV?d00001 diff --git a/testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 b/testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 new file mode 100644 index 0000000000000000000000000000000000000000..bc6124d162bce8c01701fb3747872ea6e2c387f0 GIT binary patch literal 60 zcmdn5yWf$6fra7utDiuc4ahQJu7 literal 0 HcmV?d00001 diff --git a/testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 b/testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 new file mode 100644 index 0000000000000000000000000000000000000000..607447bb6c0949eeb847ca1e709591c5ca3f2e9b GIT binary patch literal 25 acmZQ!U}j(gVitz)|5+J?8CZlMG#dad0R&9| literal 0 HcmV?d00001 diff --git a/testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 b/testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 new file mode 100644 index 0000000000000000000000000000000000000000..46cf5a86b32946d2072946fb127968455a323c7b GIT binary patch literal 33 fcmZQ!U}j(gVitz)|5+JCp|mgqix7w}%)kZ!TmS}P literal 0 HcmV?d00001 diff --git a/testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 b/testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 new file mode 100644 index 0000000000000000000000000000000000000000..2aa7b77eb464f8d0fd1775b2e8aad5a4f6bc240d GIT binary patch literal 40 fcmZQ!U}EH85NBWj(mV`249IL2pxCdbelP_99J&LK literal 0 HcmV?d00001 diff --git a/testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 b/testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 new file mode 100644 index 0000000000000000000000000000000000000000..ad0650e184a98d527e11294e5995c189ba25e278 GIT binary patch literal 80 dcmZQbVE}>5%dZ|dfLUOI6~V;HN0Ub40ssl#1GNAE literal 0 HcmV?d00001 diff --git a/testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 b/testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 new file mode 100644 index 0000000000000000000000000000000000000000..bc5f19ab9cc773d81c3bd94be4f1c8477d743f61 GIT binary patch literal 32 ccmcco|ECNG0~^ETS3ey&82I2cm0~f=7U1kO_4dcUTpf~{HnF*-? literal 0 HcmV?d00001 diff --git a/testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 b/testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 new file mode 100644 index 0000000000000000000000000000000000000000..986748f330f39b1fe4bc4db8f3979c4a38a9cd78 GIT binary patch literal 89 hcmZQ!U}j(gVitz)|5+JC5i|>wk4^*Cg4Gcc2LKX`5f1g|*1408yFdrrk=Zi1^0EdGD?EnA( literal 0 HcmV?d00001 diff --git a/testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 b/testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 new file mode 100644 index 0000000000000000000000000000000000000000..39e2fd66501a85b74f22baef66a1d3c4a1f21363 GIT binary patch literal 49 ecmZQ!U}j(gVitz)|5+JC5i|>w52JxZc3`0~^ETS3ey&82A{#6p#i0eo6=^ literal 0 HcmV?d00001 diff --git a/testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 b/testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 new file mode 100644 index 0000000000000000000000000000000000000000..8a9655c9df4219eac7a2019824c2640f33c68b77 GIT binary patch literal 28 fcmaE_{?n0zfstXq?tUOG&hY#dh%do#8At;Fj*JS2 literal 0 HcmV?d00001 diff --git a/testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 b/testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 new file mode 100644 index 0000000000000000000000000000000000000000..cf17ff8ca12807447b0cbe1ec9aeef6bd521af6f GIT binary patch literal 16 PcmZQ!U}j)}V+jTT0XhIO literal 0 HcmV?d00001 diff --git a/testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 b/testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 new file mode 100644 index 0000000000000000000000000000000000000000..ba22ee69a00f65ef9a35b5d80b436fd42120b43b GIT binary patch literal 84 xcmd;J;9%rn;9y{3U;@&-4EyYV>VoK-ui&&JSX|*JmT_|h- literal 0 HcmV?d00001 diff --git a/testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 b/testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 new file mode 100644 index 0000000000000000000000000000000000000000..2edee5d30716ddf3c21c80a926b019d3927187f6 GIT binary patch literal 50 gcmZQ!U}9uo6pm$KU}j)r5M*Gv52Y2LG`ctg07(A=@c;k- literal 0 HcmV?d00001 diff --git a/testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 b/testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 new file mode 100644 index 0000000000000000000000000000000000000000..aa8218687d1646c0a1fb14749692b46b63d4c1ca GIT binary patch literal 18 WcmZQzW?*3e;&Xg$ literal 0 HcmV?d00001 diff --git a/testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 b/testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 new file mode 100644 index 0000000000000000000000000000000000000000..2f2c51c48c827c1b1294706d3691cafe65d26bcc GIT binary patch literal 52 mcmaFAzd6&fBtP@=s|SuE3``6N@E-^mfMSdYAqJob5C8za9}R2( literal 0 HcmV?d00001 diff --git a/testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 b/testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 new file mode 100644 index 0000000000000000000000000000000000000000..945a741544df32ed5877820d5c0c7427e0446b2a GIT binary patch literal 52 zcmdn5yWf$6fra7utDiuc4ahQJZcDd{WM?%(J(%YMiyrP$^!sJD-uos literal 0 HcmV?d00001 diff --git a/testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 b/testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 new file mode 100644 index 0000000000000000000000000000000000000000..5876a5101ff8012672b71a4842766ab3f40bb152 GIT binary patch literal 26 TcmZQ!U}j(gViqthh(rSb1JVFd literal 0 HcmV?d00001 diff --git a/testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 b/testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 new file mode 100644 index 0000000000000000000000000000000000000000..d37d9a0c352fffb0bad5f469f43339c31e681032 GIT binary patch literal 17 WcmZQ!U}j(gVitz)|5+Kt7}x*~F#;?A literal 0 HcmV?d00001 diff --git a/testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 b/testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 new file mode 100644 index 0000000000000000000000000000000000000000..881b55348e2d198045d9da9a722684fc06b51496 GIT binary patch literal 152 xcmZQz6pm$KU}gYeHU>ckmiuV50vaDC4-<#!gV8W~7!6YgZcZcg|*141)cKxuSwC?8Fpg@KuY4X7Ug D?6?EB literal 0 HcmV?d00001 diff --git a/testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 b/testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 new file mode 100644 index 0000000000000000000000000000000000000000..df1c5e7ceaf12760f542a975038ceffbf5de983a GIT binary patch literal 52 qcmZQbVSoWg5e5+kMg~U)1|W-(p@G4Gk%NH)D8>LJAv8#-2m=63$pUi# literal 0 HcmV?d00001 diff --git a/testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 b/testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 new file mode 100644 index 0000000000000000000000000000000000000000..af6c0b68b01d130ccb6573a7037834f06a9b0b53 GIT binary patch literal 16 PcmZQ!U}j)}V_^mW0Wbh9 literal 0 HcmV?d00001 diff --git a/testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 b/testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 new file mode 100644 index 0000000000000000000000000000000000000000..abe31b432ae3ac6067e395ae90294098044abf22 GIT binary patch literal 28 hcmaF<>Zcw52JxZcDd{WM?%(J($bjY}R~oDd&oEZc)|)GcW*Y06N_RH2?qr literal 0 HcmV?d00001 diff --git a/testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 b/testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 new file mode 100644 index 0000000000000000000000000000000000000000..f0ef0af8b81d9a2bf443de89e381720d02068de8 GIT binary patch literal 20 Ycmcco>Zc3`0~^ETS3ey&82G?60AA(@@08&m4R{#J2 literal 0 HcmV?d00001 diff --git a/testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 b/testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 new file mode 100644 index 0000000000000000000000000000000000000000..3dfdb9435013bf6932dfd7065a3dfc8fdea82311 GIT binary patch literal 28 acmaF<>Zc)|)GrWP)AU*(KECf3M literal 0 HcmV?d00001 diff --git a/testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 b/testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 new file mode 100644 index 0000000000000000000000000000000000000000..ce9f6ea9f235e9cfe289c2a668e44c8a60e52618 GIT binary patch literal 58 gcmZQ!U}9uo6pm$KU}j)r5M*Gvk47s%`RMWt0Cm;_?f?J) literal 0 HcmV?d00001 diff --git a/testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 b/testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 new file mode 100644 index 0000000000000000000000000000000000000000..67c369f2fe07305d2b4b84ba10712f234485c7cd GIT binary patch literal 60 dcmaF<>Zc)|)!|69rJ}w%h9snKp2U`FD literal 0 HcmV?d00001 diff --git a/testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 b/testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 new file mode 100644 index 0000000000000000000000000000000000000000..7e014052914eca76483914144f69326db08144fe GIT binary patch literal 24 ccmZQ!U}EH85NBWj(mV`23@kwUSChau01Dj#%K!iX literal 0 HcmV?d00001 diff --git a/testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 b/testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 new file mode 100644 index 0000000000000000000000000000000000000000..17e6122c146405dd0af06be5ca0af29a32c1e28e GIT binary patch literal 36 gcmaFAzc@2}!hFY@uYT%sFz_-U(T*VgK8K%<06)GDr~m)} literal 0 HcmV?d00001 diff --git a/testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 b/testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 new file mode 100644 index 0000000000000000000000000000000000000000..e307d201ca645638462b2e621f738b58282739f9 GIT binary patch literal 52 mcmZQbVSoWg5e6oP%TKKs7-V5W3_vkPh6Xs7fq{#efdK${PXn$1 literal 0 HcmV?d00001 diff --git a/testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 b/testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 new file mode 100644 index 0000000000000000000000000000000000000000..852c278ec51e71a26b051e7fc95175629dc00c7f GIT binary patch literal 33 ccmZQ!U}j(gVitz)|5+J?8CZm%G?dQ<09