From patchwork Fri Jun 1 07:44:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn via Selinux X-Patchwork-Id: 10443201 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3866A601D3 for ; Fri, 1 Jun 2018 12:05:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19C0E28CBD for ; Fri, 1 Jun 2018 12:05:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0CC1228D1E; Fri, 1 Jun 2018 12:05:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from UCOL19PA10.eemsg.mail.mil (ucol19pa10.eemsg.mail.mil [214.24.24.83]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 05E3428CBD for ; Fri, 1 Jun 2018 12:04:54 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.49,465,1520899200"; d="scan'208";a="525724382" Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.3]) by UCOL19PA10.eemsg.mail.mil with ESMTP/TLS/AES256-SHA; 01 Jun 2018 12:04:52 +0000 X-IronPort-AV: E=Sophos;i="5.49,465,1520899200"; d="scan'208";a="14032673" IronPort-PHdr: =?us-ascii?q?9a23=3ABIiULxcF2RoWNIjkOygQpoHulGMj4u6mDksu8p?= =?us-ascii?q?Mizoh2WeGdxcq7ZBGN2/xhgRfzUJnB7Loc0qyK6/2mATRIyK3CmUhKSIZLWR?= =?us-ascii?q?4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBx?= =?us-ascii?q?rwKxd+KPjrFY7OlcS30P2594HObwlSizexfbN/IA+qoQnNq8IbnZZsJqEtxx?= =?us-ascii?q?XTv3BGYf5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM3?= =?us-ascii?q?0u683wqRbDVwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xy?= =?us-ascii?q?mp46dtRh/vhiYMKjA58GbNisx/kq1UvQ+qpwdnw4HOZYGaKOBxfr7GfdwEWG?= =?us-ascii?q?FNWslcWzBEDo66YYQPFe4BNvtGoYf7qVUFsB+yCRCxCO/zzzNFgGL9068n3O?= =?us-ascii?q?Q7CQzI3BIuEc8AvnrXq9v4L7seXfyvwaXU1zjPc+9a1DHg44bIaBAhpvSMUK?= =?us-ascii?q?psf8rQ1UYvFxnKjk+Npof4PT2azOUNs26F4Op7SOmvlW8npBtsqTay2Mgsjo?= =?us-ascii?q?jJhoQIylHL6C50x501KsO8SE56Z96kDZRRujqGN4p2XswiQ2ZotDw8yr0do5?= =?us-ascii?q?G3ZicKyJM5xxPGbfGMbouG4gr7WeqMLjp1i2hpdbKiixqo70StxfPwWtOp3F?= =?us-ascii?q?pSrSdIk8PAum0D2hHc8MSKSvVw8l281TuAygze7PxPL1oumqrBMZEhx6Y9lp?= =?us-ascii?q?8UsUveACD7gF72jKqKdkU8/eio9vjnbq3mppCCM490jRnzMrg0lcylAOQ4Lx?= =?us-ascii?q?MOU3KH+eW8yLLj/Ur5TK9MjvIqianWrIrWJcEapq69GwNV04Aj5AijDzq+zd?= =?us-ascii?q?gVknYKIEhFdR6alYTlJV7DLO7iAfuim1islS1kx/HCPr3vGJXNKX3Dna/6fb?= =?us-ascii?q?lj705cyQwzzc1Q5p5NEb4BJ+/zWkntu9PGFR80KBC0wub7B9V90YMSQ2SPAr?= =?us-ascii?q?SDP6/Ivl+I4fwvL/GWZIAJoDb9N+Ql5/n2gH87nl8de7Om3YcXaH+iGPRrOE?= =?us-ascii?q?eZYX3qgtcEC2gKpRY+Q/LwiF2ZSzJTYGyyX60k7DEhFI2mFZvDRpyqgLGZ3i?= =?us-ascii?q?e7HIdZaXxFClCXFnfocYSEW+kXZSKcJs9hjzMFWqO8S48nyRGuqRX2y719Lu?= =?us-ascii?q?rb4icYr47s1MBp5+3PkhE/7TJ1D8WZ02GIUW50hHgFRzEo069ipkx90E2M0b?= =?us-ascii?q?Big/xfF9xc+e9GUhsgOZ7b1ex6BMj4WhjdcdeRVFamXtKmDCksQd0txt8OZE?= =?us-ascii?q?B9G8m/gh3YwSqlHaUVl72KBZwz9KLQxX7xKNhhy3zezqkuk0EmQtdTNW2hnq?= =?us-ascii?q?Nw6hTTCJTTk0iCi6mqcqEc0zLX+2eY0WqCpkdYXxBsUa/dR3AQelPWrcjl5k?= =?us-ascii?q?PFV7KhF6wnPRFbyc6DMatHccXpgk9cRPfiI9Tee2axlH2sChmW3L+Ma5Dqe2?= =?us-ascii?q?oF1iXHFEcEixwT/WqBNQUmCCehuXjRDDpyGlLueEPh6ux+qGu6TkMt1AGLYV?= =?us-ascii?q?Zh26Cy+h4PivyWU+kT0a4cuCc9tzV0G06w39HMBNqDoAphYb5RYdAn71dE0m?= =?us-ascii?q?LZqhZxPpu6L6BtnlQeaRh4v1vy1xVrDYVNidIlo24wzApzN62YykhMeCmE0p?= =?us-ascii?q?D1ILHXLXPy/B+3Ya7Mxl7eyMqW+rsI6PkgsVXsoRymG1Et83Vi3NhZyX2c6Y?= =?us-ascii?q?vWDAAKS5L+Tl439wRmp7HdeiQ9/I3U1WdrMamvrj/PwMkpBO0iyheuetdQKq?= =?us-ascii?q?WEGBX0E8IEG8ikMPYqlESxbhIYIOBS87Y5Ps28ePuCxK6kIvxgnCm9gGRZ/o?= =?us-ascii?q?99yFmD9zd5SuLS2JYF2f6Y1BOdVzjglFehrtz3mYdcaDEUH2q/zSzkC5BKZq?= =?us-ascii?q?BpZ4kEF32uI8qtytV5nZ7tVGZS9ES/CFMexM+pZR2SYkTj3Q1RyUsXvXunmT?= =?us-ascii?q?GiwzNokzEpqayf3CPVzuTmdRoHPHRERHNljVv2Joi0ld8aVlCybwc1jBul+V?= =?us-ascii?q?r6x69DqaR7LmnTWltIczHtL258Vquwt7yCY9NA6Z4zqiVXSOW8YVabSrHhuB?= =?us-ascii?q?sWySXjEHVCxDojbTGlpo35nwBmiGKaNHtztn3ZecV0xRjB/tzTWflR3zQdSS?= =?us-ascii?q?ljlDnYGkO8M8Ou/dWOmJfJqvq+WH65Vp1PbSnrypuNtCil6m1sGh2yhPOzlc?= =?us-ascii?q?PhEQgh1y/0ycVqWT/PrBbmbYnhz766Pv5/fkl0GF/87NJ3GplknYstgJEfx2?= =?us-ascii?q?AaiY+T/Xobj2jzK85W2b/lbHUTXz4L2MTZ4BPi2E1+NHKG25z2Vnuawst7aN?= =?us-ascii?q?m1fHka2iQj4MBWEK2U9qBLnTNpolqkqgLceeZ9njEAxvY19n4ahfwGuAo3wi?= =?us-ascii?q?WbHL8SAVFSPTbwmBSQ89C+sKJXaX63cbeqyUp+mcusA62DogFAWHf1Y5kiEj?= =?us-ascii?q?V27sllN1LMynLz4Jn+eNbMddITqgGUkxDYguhbMp0xkOYKhS1iOW/ms30q1f?= =?us-ascii?q?M0jRt03Z6gpIiHMWJt/KCnDRFEKj35fcQT+ivijaxGhMaZw5ivHol9GjUMRJ?= =?us-ascii?q?boSOinEDYWtfv5KwaODCczpW2AFLrZAwCf9FxmoG7VHJCzKX6bPn8Zwst+RB?= =?us-ascii?q?OFPkxQnBgUXCkmnp4+Dg2qytbhf1lk6TAK/FH4rAdMyuVzNxTkSGjQuAKoZi?= =?us-ascii?q?0zSJiFIxpc9htC6FvNMcyC8uJzGDlV/pu7rAOXMmybfx9FDW8IWkyeHFDjIr?= =?us-ascii?q?eu5djG8+eCAOqxM/rObq+KqeBEUPeI352v2JN8/zmQLsWPImViD/oj10pbQ3?= =?us-ascii?q?92ANrWmzMOSywLkCLAdM+bqwmi9SJptMy/9+7rWA3374uVF7RSKclv+wyxga?= =?us-ascii?q?qbLOGfnyF1KTJZ1pMX2X/I06IT3EUMhC5ybTWtCqoPtSrMTKLWh69WAAUWZD?= =?us-ascii?q?9zNctS8qI8xRNBOMDBhdPpzb54ifg1B01CVVz7lcGjfdYKLH2lNFPbGEaLM6?= =?us-ascii?q?yLKibKw8H4ZqO8T6Zdg/hKuBKruDaUCUnjMi6ElznzWBClKftMgz2DPBxCpI?= =?us-ascii?q?G9dQ5gBnLsTN38dB20LsR6jTouwbIqgHPKMHQTMTl4c0xWqb2R4jlUgvJlG2?= =?us-ascii?q?xO9nBlN/WLmz6F7+nELZYbqedrAiNxl+5A+nQ6zLpU4z9CRPNugivSqcBho1?= =?us-ascii?q?K9n+aTzTpnVQZBpSxQhIKXp0liP7vW9oVYU3be4B0N9XmQCwgNp9Z9CN3vu6?= =?us-ascii?q?BRysDIlKL3KTdC78zb8NAZB8jVNMKHKmQuPQDuGD7OAwsPVSSrOn3Hh0xBjP?= =?us-ascii?q?GS8WWYrps6q5johpUDUbpbVFs7FvMUFEtlAMACIJdwXjMhj7GXlsgI6mSirB?= =?us-ascii?q?PJXsVVoojHVu6OAfXoMDuZi6dLaAEMwb7jLoQTMZb721B4ZVl8h4TKGEvQUc?= =?us-ascii?q?pLoiJ/cg8+uF9N/2RmTm0vx0LlbRug4GUNGv6vgBE5kBF+bvgt9Dr3+Fg3J0?= =?us-ascii?q?DKqzY3kEk/gdXlmy6ecT7rIKe2Q45WFzL+t1ItPZPjXwZ1cQqykFR5OzfDQb?= =?us-ascii?q?JRiaZven5viA/dopZAA+BTTbdDYBMKwvGXffoo20xGqiq73U9H+ffFCZx6mQ?= =?us-ascii?q?Q3a5GssXNA1B94bNMuP6PQPrBJzl9eh6KVoCCnyv0xwBUfJ0YR8GKeYigIt1?= =?us-ascii?q?IUNrM+PSqn4vRs6RCemztEYGUMU/0qouh0+UM7OuWAyDnt07FFKkCsLeCfKL?= =?us-ascii?q?mZu2fYn86SXlwwzl8Il1VC/bVuyscsbU6UV0EpzLuMGBUELtbNKQZQb8VO7n?= =?us-ascii?q?fTZjqOvf/LwZ1rI4W3DvroQvOWtKYInkKkGx4kH5gN7sQEGZmszEHYLMf8Ib?= =?us-ascii?q?EYyBUs5B7kK06fAPRPZh2LjC8No9ujw59vwYldOjYdDH1nPiWz57bYuhElj+?= =?us-ascii?q?KGXNY2ZHcaWY0EOWgtVcKhmi5WpXJAACC50uIE0gSC6SHzpjjIBjnmc9VjfO?= =?us-ascii?q?uUZQ9rCNyu4jow7a62hEXN/ZrDOWH1K85iusTV5uMAp5eLEfRUTaNys03EgY?= =?us-ascii?q?lXW2SqU3LTEd6yP5XwZJQsbd3wCna+TFO/jik4QNrvM9m2L6iHmwfoSZxTsI?= =?us-ascii?q?mB0zApLdW9GS0GGxdsu+ED47pxZRcFY5o6fRHotwM+N6ikIAmAy9ugXnyjJC?= =?us-ascii?q?dRQfRE0eq6YLlXwDY2Ye+h1HssVJc6wPer8UQVXpEFkgnexeq/Z4lZSSXzAG?= =?us-ascii?q?ZSex/IpSUijGVhKvwyzf0hwBzWtVkcMjaLdONtaGxFsNE8BU+SIXtsBWoiQl?= =?us-ascii?q?+Ql4zD7RCw37oK5StSg85U0fFZsHj5ppLebiigV7CrqZXUtiogbMIpo65qPI?= =?us-ascii?q?ziPMSJqo3RkibYTJnKvQ2PSDS6GOZCmthMPCJYR+FFmWQ/NswcuopO91YxVs?= =?us-ascii?q?Y4J7xAE6QtqKqlaTx4Ai4Wyi8ZSp6P3CcYjue6xbTaig+acI4+PxwcrJVCnt?= =?us-ascii?q?wdXjZsbSMEua+jUZ/al2yfR2gKIQcT7BhM6xkamo92YO/l/JLCTIVQxD5Ov/?= =?us-ascii?q?J0TizLG4Fp91v9VmGZn1z4R+ukk+O3wQJS1vLt38IcWB5nF0ddweNWmVEpKL?= =?us-ascii?q?FzMKYQuYHLviWPdUPgs2Ln0PGmK0VJyc3Ia134C5LItXb7Ui0Z4nAUWZNDyH?= =?us-ascii?q?TEGpgIlQp2drorrk1WII+6Ykb++yAkx4NxErm4T8+r3UwqrXIbSCqxDtVOFf?= =?us-ascii?q?lmsErJVz1hfZ+rso/pO5JIQm9f4JedsUtWkF1xMy6lzppRM8NN4jkSUzVUvD?= =?us-ascii?q?qSosCyR9NZ2c9qEZADP81zu3HjF6NYIJKRuWE5uqTzyn/F/DAxqEu6yyiuFK?= =?us-ascii?q?+5Ve1Z+3YTFRkuJ2SbtkYgFfAs8nvI/lDLrF904/9RBqKTgkVpvDZ9ApdOCy?= =?us-ascii?q?5S2nCrM1t/UHtLv/hUJanOb8NcRPwyagO1NBwlCf4qxUqJ8l9onX3heSx9qh?= =?us-ascii?q?Na+zzBXwkzTSQVmKniliAeqs69JT8XUJZIbTI/byjbNQ6UhSdXswtBZE1wXZ?= =?us-ascii?q?AWHMpF8akB3YRI5srCVVqsKSYdURx6LQI4zeBQmlNfsEiDYiDdCheodezTvR?= =?us-ascii?q?Jpe8eRsNSpI+79/AtdjYPnqu84/b0ZR3K6gQ2tXczer4jku92WrEuBarn3PP?= =?us-ascii?q?CnbH/cSDjMkQqwiq06D5nL+CjTNBRUK4VgxXoje5jhBnbBPQ5aKKIDO0pbSa?= =?us-ascii?q?d6ZM1Eou9Afc9kf70J+at3CRKZXR7vHZGvrP1aLlbSWTveLj+O8uqkoY7J6r?= =?us-ascii?q?zdU+fgbNSWx3nbW6J3Iot66T7jFrfoy4Be/ET22u1q9kxnV1fLKDyBo87nJg?= =?us-ascii?q?MQ48mubE3isYM1HTnOGpd/jGLtxl1cd8oQWyCq9pAYxYhY6Hb2TOJ0yEnzsO?= =?us-ascii?q?tc97l+84Y3+Kxpyd2pJajONfRarFVnDQaOCgVt7JUtD3B1R3pNbe8JNPfRYa?= =?us-ascii?q?MZgNjoq+D2C6MX7xmV9PZCadfdJkHBnc6/CiqHSRFfmQcMpjEbIhGb1/6flK?= =?us-ascii?q?9+UdylqvTh2kIx/1i+KQYLw6x36oeA5KWIv/PXbhvWzbUfQajlWsLzoaoqu0?= =?us-ascii?q?OO5P0rjqQCemprbA27COIdTNISxn/8zaA2yiIhC8fDH6nl+PNDTH85kCzvlI?= =?us-ascii?q?16H1UMAPwUBaCL/YNcnmgmh+PZKscacqdYmmaADRSkCKMNyWa36yuLJ2lomh?= =?us-ascii?q?PO0xD1QW6o6V/5sy95TjXWz9filEpVWaO7BUFMUCq1IUV4qi+APBL0tNrrvq?= =?us-ascii?q?Q49EA2M23+u92XiGSsI6hXENPjJNOCPSY4vlUXjIc+Rta3w4AUBcK9IMsN8H?= =?us-ascii?q?F5dvbR8GKrkzRPoqhdhYre492V+u3NEnm9i62XsKmCxDdFxXcmp14/98qgNv?= =?us-ascii?q?bU59KQWfio0HwRTyhnsQvbQxG1sqDbr0wTOUGTyEfEgpAKMc1Z3Xg20UHm/u?= =?us-ascii?q?sjTMso9ApAEobAZvUCpS38OTbv2VaQec43WTWe0zpZGVL1C1p4FLI/2G3ups?= =?us-ascii?q?LJk2nf+1kySol3bUznigR9D58kJkI19FgX3i0DHBACaR+BFrGnG1jlLYsfWE?= =?us-ascii?q?gHaBSHwKa1eqct0k1u2bOj/unTYvJgB6AVLPZSkhaOnERHGpIRqaAeT6xze1?= =?us-ascii?q?lB9K7QoQjuDJPnUObilXoxM/21X89b/Nsdt3Q8+Aa+RwCv5Y1F77kFlJCCbr?= =?us-ascii?q?REboTUvMBg80dn4iYCeTBPgBdlkxy0SvwTpOfn4tjfsZqn9PyuVLozSOoL9x?= =?us-ascii?q?g4HWN+j4H/gFo7u9HYy/9cSpHJiYT46A1NJnmKuIDG0xlzN+UDMIerfLd6+H?= =?us-ascii?q?UBOSceO3wPPd2Ma/k/+C9hKjPT6EJeAskUf9MXINLNmRxIik3uQLxT+dbUGk?= =?us-ascii?q?SDC4tqas4m4Gz5yDEz8ZshXeft8zC2JZXF4FFLIfxPliJslMjNpOIN2/rdFD?= =?us-ascii?q?AX4WWFaxhy2i6CyZ6NC/b2/emW1N7UV1cGHjMrXIZcJTqC/xenRum0lJjyTA?= =?us-ascii?q?OU69Hzj4g6dE2NR3y9hqIFvbhQEeRYkCX0wiBeFpzph/KSq9es6XVXuUdBEI?= =?us-ascii?q?to6R3FBbhQPpR8ORTjjMWrQVJ8BiTncsHOahUuoPaWxvsL4+hmNUvxe4EbIh?= =?us-ascii?q?wAy7/h53taVA1uR6DqvlqDW+IeesdmQuvern9J8YJgN7MPPF+FqZzlqjdIr1?= =?us-ascii?q?43DxEtaL80tTFabU7OnAtUW6noorIAjBUTUcJhs09WBW2wIH4+5ybAValNia?= =?us-ascii?q?mRCf8V8jaUTqEVUUVnKCB+QxSz2Jpwfbulh/ZHvX1anilluvglzyRmRAeguS?= =?us-ascii?q?3rv68Cwiwv+LektDgaonxFSuKekzvUCVVd0vsFkL0QC3H46VyzeHMDdpf94K?= =?us-ascii?q?F7JcT88oks+2w/YRInfyIcR+ShBSbwj6eGAoGUtdJcgxmNuN7QYrCvNygSMa?= =?us-ascii?q?89yQniR3h73QjShhFo8HEEQj+49t8rOJ29Odo5xiqvAWXbekgD4qdIsMvpq1?= =?us-ascii?q?EGV+o3aVJkwGVmzMeHXCkNS9LVF2YylAgkZn1OcIhf5h8CC6konjGIs7FI/w?= =?us-ascii?q?EMejfUE5iq9ZfLkMfN2Hk9Uc1qyXzMqq2CnJMq32Vvm8lo4S6WpHQSa+vYXt?= =?us-ascii?q?drAnj3yIhS0vT+Z/G3veAcVItmyaiuUOMYMsa952S6wpNqVVG5xr4GBVq2LP?= =?us-ascii?q?cDxqvHUyeiUWCYXeWLc26Rnzc2K0Ly4RioLkYraMdRtEI9M/HNhphblwH7Vr?= =?us-ascii?q?N0XCqQr0fBzGM/KeMaax42uIC/dgwPVuEee+icJekowP05E1YMcX7JHS1oBO?= =?us-ascii?q?+ysF6tmpV7Onp67UX9e+Tt/RjsMMGOFRkcDY7asplx9OS4Rm2bOn9gywZ9MV?= =?us-ascii?q?Jp9+fZC1Qxtuhcc4uendjQm9R3y+gFeOlxMScloN4chppj6ZWI0MeNaRzRzJ?= =?us-ascii?q?PyJdbPoviCAv3f1F8nemdAXbocfwz15p82PtkjW73cBbFZpwgTBbAmQJw9MG?= =?us-ascii?q?f87Lp0LA12cgHNZbm5gdLnpvyVaZtOpn/X71UwLCHGtx0F1PO0URR3b5C0iH?= =?us-ascii?q?X2J5A9XjZBr9pxBRR8GItPG8QArxG7A5KOnKG7jMO+9Fl+u+AXtqrwD+rF1N?= =?us-ascii?q?W/34lpXpha41KEPCrJCaRog0lplPm+j/nP35XrCc7vd8kIWPV0T2LYcrPGG5?= =?us-ascii?q?+wKjOKOsLyYU5G9Luc3ap+XxWLZSD2Q6qGuze+NPp5+Uo01pR3fOrJwzws6b?= =?us-ascii?q?HUxsDyanpAqSe/rH6JModf40LQBezYQR1UVeCJ/3piHa0SdIb47P0OPsA6wN?= =?us-ascii?q?iA/wlz6yxP3cydI6e7s0/M3ll2dYrBI0v03yY1QIwKIBO4MUs2n2DVsGjSAX?= =?us-ascii?q?NZLsW9McVtmsqaDgTx50ltnmEgfmlMGnDpRdiNOWgUwdi+axCS+w1XF9kDn/?= =?us-ascii?q?S4eU8+tqKsUullIY5KmfmrtLUBjdZmNTvPRM5EMCHMNrN5Ij1RDuDWqVQweB?= =?us-ascii?q?4Lr6A1WpspZZiJOE4KN1yAxj32zQvD1030atOt2b2VICcW7npHz7XF3SJKpw?= =?us-ascii?q?mio/mVmMLjULfHbJzvWvPZLTQoVjWHRTQpDUam502ktecFvPuZP2gSukwYMW?= =?us-ascii?q?quD1sIq6Ruq8XAJnPCku1kOpsRjbaVXD60ADVxia4aHi9WsQWJRP0ZGE/daH?= =?us-ascii?q?qyumdEvB2eIap2/HnlZqeUjopcWuobGcMYaPySQ9LCdcdVEDchlzMUI862Y9?= =?us-ascii?q?zas7sj1F/UC2AeFv+b2keZSRusQ/eczijnFaUcvo45oWI2+9uYpSJzEqLVL/?= =?us-ascii?q?7LvDOq84ilnA6EqObeUS8reEVzj+UcVjrSiCJcIX0JXolG8HrmRbSNMh0U2Q?= =?us-ascii?q?=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2BDAQD+NRFb/wHyM5BcGQEBAQEBAQEBAQEBAQcBAQEBA?= =?us-ascii?q?YMVBCpiI0oSKIt7X4wIjleHbhQLgVYmAw8BAYZHITQYAQIBAQEBAQECAWscD?= =?us-ascii?q?II1DIJvAhcBDBMUIA4DCQJACAgDAS0VGAcLBRgEgkFAAiiBPwEBARUDAadeM?= =?us-ascii?q?4N0VoN2gWiIPg6CBYEPhFiBBIFeDwQBEgEIAYVqAoc0CAIIhgqLGwmFbHCHe?= =?us-ascii?q?oFHQIYahH6SWDhhcSsIAhgIIQ87gTAaeQmCFxeHTYZLbnkBAQEojHsPFwSCH?= =?us-ascii?q?QEB?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 01 Jun 2018 12:04:48 +0000 Received: from prometheus.infosec.tycho.ncsc.mil (prometheus.infosec.tycho.ncsc.mil [192.168.25.40]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id w51C41gq010553; Fri, 1 Jun 2018 08:04:15 -0400 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id w517jXT3003886 for ; Fri, 1 Jun 2018 03:45:33 -0400 Received: from goalie.tycho.ncsc.mil (goalie.infosec.tycho.ncsc.mil [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id w517jcZf020041 for ; Fri, 1 Jun 2018 03:45:38 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1CyAABG+BBbly0YGNZcGwEBAQEDAQEBC?= =?us-ascii?q?QEBAYMVBChlbRIoi3tfjAiDCItPh24UgWQmDwKEQIIGITQYAQIBAQEBAQECFAE?= =?us-ascii?q?BAQEBBhgGS4VVAQwZATgBFYEpEoMiAiiBPgEDFQMBqBgzgnAFf2SDYgeBXAQIh?= =?us-ascii?q?z2BBIITgQ+EWIEEgV4PIAGFagKHNAgCCIYKixoJBYVncId6gUc+hhqEfpJXggo?= =?us-ascii?q?zGiNQgkMJggsMDgmDRYQIhktueSuMSg8XBIIdAQE?= X-IPAS-Result: =?us-ascii?q?A1CyAABG+BBbly0YGNZcGwEBAQEDAQEBCQEBAYMVBChlbRI?= =?us-ascii?q?oi3tfjAiDCItPh24UgWQmDwKEQIIGITQYAQIBAQEBAQECFAEBAQEBBhgGS4VVA?= =?us-ascii?q?QwZATgBFYEpEoMiAiiBPgEDFQMBqBgzgnAFf2SDYgeBXAQIhz2BBIITgQ+EWIE?= =?us-ascii?q?EgV4PIAGFagKHNAgCCIYKixoJBYVncId6gUc+hhqEfpJXggozGiNQgkMJggsMD?= =?us-ascii?q?gmDRYQIhktueSuMSg8XBIIdAQE?= X-IronPort-AV: E=Sophos;i="5.49,465,1520913600"; d="scan'208";a="290269" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 01 Jun 2018 03:45:34 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3AEdZccRZbnPiRzo1THo2I853/LSx+4OfEezUN45?= =?us-ascii?q?9isYplN5qZps66Yx7h7PlgxGXEQZ/co6odzbaO7ua4ASQp2tWoiDg6aptCVh?= =?us-ascii?q?sI2409vjcLJ4q7M3D9N+PgdCcgHc5PBxdP9nC/NlVJSo6lPwWB6nK94iQPFR?= =?us-ascii?q?rhKAF7Ovr6GpLIj8Swyuu+54Dfbx9HiTahYb5+Ngm6oRnMvcQKnIVuLbo8xA?= =?us-ascii?q?HUqXVSYeRWwm1oJVOXnxni48q74YBu/SdNtf8/7sBMSar1cbg2QrxeFzQmLn?= =?us-ascii?q?s65Nb3uhnZTAuA/WUTX2MLmRdVGQfF7RX6XpDssivms+d2xSeXMdHqQb0yRD?= =?us-ascii?q?+v6bpgRh31hycdLzM38H/ZhNF+gqxYpxysvABzz5LObY2JLvdyYr/RcNUHTm?= =?us-ascii?q?RBRMZRUClBD5ugYYsOE+UBPfxXr5PgqFATrxWxHwisBOXxxT9Tm3T72rc60+?= =?us-ascii?q?U9HgHGxgMgBc8Bv2zIo9rtNKcdS+G1zK/WwjXYdP5Zwiv96InOchA9v/6MR7?= =?us-ascii?q?RwftTNyUU1CwzFiVCQpJXjMjiI1eoNq3CW4/R9We+gkWIrtQ58riKxysojkI?= =?us-ascii?q?XEiYIYxkjH+Ch42oo5ONO1RUFhbdOkHpZcrTyWOoRrTs4kXmpmojw1yqcctp?= =?us-ascii?q?6+ZCUKyIooxxrYa/GffYeF/AvtWuCfLDpmnnxoZK6zihSo/Ue+1OL8U9K00F?= =?us-ascii?q?lQoipAiNbMt3QN2wbW6siGTvtx5kah2TCR2ADP8uxIP104mKXBJ5I/zbM8jI?= =?us-ascii?q?QfvEvZEiL5mEj6lKqWeV8l+uis5eTneLLmppqEOo9uiwHxLqQuldalAeslKg?= =?us-ascii?q?cBQ3CU+eSm273i+032Xq5Kg+YtnanFsZDaI9gbqbCjAw9TzIkj9wyzACuh0N?= =?us-ascii?q?QdhXUHNk5KeAqbj4j1PFHDOOv4Aum7g1Stljdr2v/HM6b9ApTNMnfDkLDhca?= =?us-ascii?q?x7605H0gU/199f55VKCr0ZIPL8REvxtNvAAx89NAy73/zoCNF91oMZQmKPHr?= =?us-ascii?q?WVMKfVsVCU/O0vJ/SDZIgQuDnnKvgl4ebijX4/mVADYamkxZgaZXGiEvh7LU?= =?us-ascii?q?iUbmDgj9cPHGsQowYzQ/HmhEWHUTFJZnayW6w85is8CIKjFYrOQZqtgL2d0y?= =?us-ascii?q?e7BJJWfH1JBUiQHnjwd4WLQfYMaCSMLc96iTELTqShS44n1RGyqgD60bxnIf?= =?us-ascii?q?TI+iECqZ3j09116vTLmREo6TN0F9id032KT2xsmW4IXyU53L17oUFm0leMy7?= =?us-ascii?q?V4g/hBGdxW4PNJVR06OoDGw+NmDNDyXxvMcs+TSFm6WtWmHS0xTtUpztIJeU?= =?us-ascii?q?Z9GsmtjhDZ0CqwHrAaj6CEC4Q08q3G3njxIdhyy23d2aY6k1kmQ81PNXG4ia?= =?us-ascii?q?5l8QjcGZLJn1+FmKatcKQRxTbB9H2fwmqWoEFYTAlwXL3CUHAEeETWqdX55k?= =?us-ascii?q?XfT76hErknLgtAxtKCKqtNcNHpi05GS+35NNTRZGKxhX69CBCVzb6SaIrqZn?= =?us-ascii?q?4d3DnDB0gejg4T/HeHOhYmCyu98CriC2l1GFbuZV782fVvo3O8CEkvxkeFaF?= =?us-ascii?q?Mln6K85xo9nfWBT7YW2bUetWEqrDAnMky62ofsCtGArhBtNIVVYNUw+x8Tz2?= =?us-ascii?q?PStwVnMqurGKBrh1gTaCx9o0LoyxhtDIhc18MtqSV5n0JJNauE3QYZJHuj1p?= =?us-ascii?q?fqN+iPcDOg9Q2za6PQxlDV2cqX/aFK8vkjtlH/p1HzRHcJ1FE8+OF8iyDa65?= =?us-ascii?q?jPFwVUVJvwVgAy9hwp773ZYyxo/47O0HB2K66u+n/B1sNhGOwigg2ldtNbce?= =?us-ascii?q?uEGQb+HtdcBp2GIvArnUSkdBQJIKZZ86s5?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CyAAAG+RBbly0YGNZcGwEBAQEDAQE?= =?us-ascii?q?BCQEBAYMVBChlbRIoi3tfjAiDCItPh24UgWQmDwKEQIIGITQYAQIBAQEBAQE?= =?us-ascii?q?CARMBAQEBAQYYBksMgjUignIBDBkBOAEVgSkSgyICKIE+AQMVAwGoGjOCcAV?= =?us-ascii?q?/ZINiB4FcBAiHPYEEghOBD4RYgQSBXg8gAYVqAoc0CAIIhgqLGgkFhWdwh3q?= =?us-ascii?q?BRz6GGoR+kleCCjMaI1CCQwmCCwwOCYNFhAiGS255K4xKDxcEgh0BAQ?= X-IPAS-Result: =?us-ascii?q?A0CyAAAG+RBbly0YGNZcGwEBAQEDAQEBCQEBAYMVBChlb?= =?us-ascii?q?RIoi3tfjAiDCItPh24UgWQmDwKEQIIGITQYAQIBAQEBAQECARMBAQEBAQYYB?= =?us-ascii?q?ksMgjUignIBDBkBOAEVgSkSgyICKIE+AQMVAwGoGjOCcAV/ZINiB4FcBAiHP?= =?us-ascii?q?YEEghOBD4RYgQSBXg8gAYVqAoc0CAIIhgqLGgkFhWdwh3qBRz6GGoR+kleCC?= =?us-ascii?q?jMaI1CCQwmCCwwOCYNFhAiGS255K4xKDxcEgh0BAQ?= X-IronPort-AV: E=Sophos;i="5.49,465,1520899200"; d="scan'208";a="12378902" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from ucol3cpa07.eemsg.mail.mil ([214.24.24.45]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 01 Jun 2018 07:45:31 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;93231fbb-505d-45b4-93f1-944d8ca7adb1 X-EEMSG-check-008: 524354288|UCOL3CPA03_EEMSG_MP18.csd.disa.mil X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.219 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0BVAAA7+RBbh9sAFEFcGgEBAQEBAgEBAQEIAQEBAYMVBIENbRIoi3tfjxCLT4duFIFkEBYPAoRAgic0GAECAQEBAQEBAhQBAQEKCwkIKCMMhUkBDBkBOAEVgSkSgyICKIE+AQMVBKgaM4JwBX9kg2IHgVwECIc9gxeBD4RYgQSBXg8gAYVqAoc0CAIIhgqLGgkFhWdwh3qBRz6GGoR+kleCCjMaI1CCQwmCCwwOCYNFhAiGS255K4xKDxcEgh0BAQ X-IPAS-Result: A0BVAAA7+RBbh9sAFEFcGgEBAQEBAgEBAQEIAQEBAYMVBIENbRIoi3tfjxCLT4duFIFkEBYPAoRAgic0GAECAQEBAQEBAhQBAQEKCwkIKCMMhUkBDBkBOAEVgSkSgyICKIE+AQMVBKgaM4JwBX9kg2IHgVwECIc9gxeBD4RYgQSBXg8gAYVqAoc0CAIIhgqLGgkFhWdwh3qBRz6GGoR+kleCCjMaI1CCQwmCCwwOCYNFhAiGS255K4xKDxcEgh0BAQ Received: from rgout0406.bt.lon5.cpcloud.co.uk (HELO rgout04.bt.lon5.cpcloud.co.uk) ([65.20.0.219]) by UCOL3CPA03.eemsg.mail.mil with ESMTP; 01 Jun 2018 07:44:58 +0000 X-OWM-Source-IP: 86.134.53.141 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-RazorGate-Vade-Classification: clean X-RazorGate-Vade-Verdict: clean 0 X-VadeSecure-score: verdict=clean score=0/300, class=clean X-SNCR-VADESECURE: CLEAN X-RazorGate-Vade-Verdict: clean 0 X-RazorGate-Vade-Classification: clean X-RazorGate-Vade: gggruggvucftvghtrhhoucdtuddrgedthedrieefgdduvdehucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuueftkffvkffujffvgffngfevqffopdfqfgfvnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffosedttdertdertddtnecuhfhrohhmpeftihgthhgrrhguucfjrghinhgvshcuoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqeenucfkphepkeeirddufeegrdehfedrudegudenucfrrghrrghmpehhvghloheplhhotggrlhhhohhsthdrlhhotggrlhguohhmrghinhdpihhnvghtpeekiedrudefgedrheefrddugedupdhmrghilhhfrhhomhepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeophgruhhlsehprghulhdqmhhoohhrvgdrtghomheqpdhrtghpthhtohepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeoshgvlhhinhhugiesthihtghhohdrnhhsrgdrghhovheqnecuvehluhhsthgvrhfuihiivgeptd Received: from localhost.localdomain (86.134.53.141) by rgout04.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as richard_c_haines@btinternet.com) id 5B0550EE00C6A06E; Fri, 1 Jun 2018 08:44:54 +0100 X-EEMSG-check-009: 444-444 To: selinux@tycho.nsa.gov, paul@paul-moore.com Date: Fri, 1 Jun 2018 08:44:47 +0100 Message-Id: <20180601074447.14112-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.17.0 X-Mailman-Approved-At: Fri, 01 Jun 2018 08:03:54 -0400 Subject: [PATCH V2] selinux-testsuite: Add SCTP test support X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: From: Richard Haines via Selinux Reply-To: Richard Haines MIME-Version: 1.0 Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP The sctp testsuite tests all new sctp SELinux functionality. Signed-off-by: Richard Haines --- V2 Changes: Add -v option to test Add info in README.md regarding lksctp-tools-devel requirements Fix asconf parameter chunk processing in test Fix merge error for policy/Makefile Fix buffer overflow in sctp_asconf_params_client.c README.md | 4 +- policy/Makefile | 4 + policy/test_sctp.te | 159 +++++ tests/Makefile | 4 + tests/sctp/Makefile | 13 + tests/sctp/calipso-flush | 5 + tests/sctp/calipso-load | 7 + tests/sctp/cipso-fl-flush | 5 + tests/sctp/cipso-fl-load | 7 + tests/sctp/cipso-flush | 5 + tests/sctp/cipso-load-t1 | 7 + tests/sctp/cipso-load-t2 | 7 + tests/sctp/cipso-load-t5 | 7 + tests/sctp/fb-deny-label-flush | 6 + tests/sctp/fb-deny-label-load | 7 + tests/sctp/fb-label-flush | 6 + tests/sctp/fb-label-load | 8 + tests/sctp/iptables-flush | 4 + tests/sctp/iptables-load | 27 + tests/sctp/sctp_asconf_params_client.c | 298 +++++++++ tests/sctp/sctp_asconf_params_server.c | 236 +++++++ tests/sctp/sctp_bind.c | 81 +++ tests/sctp/sctp_bindx.c | 116 ++++ tests/sctp/sctp_client.c | 220 +++++++ tests/sctp/sctp_common.c | 101 +++ tests/sctp/sctp_common.h | 27 + tests/sctp/sctp_connectx.c | 124 ++++ tests/sctp/sctp_peeloff_server.c | 260 ++++++++ tests/sctp/sctp_server.c | 335 ++++++++++ tests/sctp/sctp_set_params.c | 205 +++++++ tests/sctp/sctp_set_peer_addr.c | 414 +++++++++++++ tests/sctp/sctp_set_pri_addr.c | 135 ++++ tests/sctp/test | 814 +++++++++++++++++++++++++ 33 files changed, 3657 insertions(+), 1 deletion(-) create mode 100644 policy/test_sctp.te create mode 100644 tests/sctp/Makefile create mode 100644 tests/sctp/calipso-flush create mode 100644 tests/sctp/calipso-load create mode 100644 tests/sctp/cipso-fl-flush create mode 100644 tests/sctp/cipso-fl-load create mode 100644 tests/sctp/cipso-flush create mode 100644 tests/sctp/cipso-load-t1 create mode 100644 tests/sctp/cipso-load-t2 create mode 100644 tests/sctp/cipso-load-t5 create mode 100644 tests/sctp/fb-deny-label-flush create mode 100644 tests/sctp/fb-deny-label-load create mode 100644 tests/sctp/fb-label-flush create mode 100644 tests/sctp/fb-label-load create mode 100644 tests/sctp/iptables-flush create mode 100644 tests/sctp/iptables-load create mode 100644 tests/sctp/sctp_asconf_params_client.c create mode 100644 tests/sctp/sctp_asconf_params_server.c create mode 100644 tests/sctp/sctp_bind.c create mode 100644 tests/sctp/sctp_bindx.c create mode 100644 tests/sctp/sctp_client.c create mode 100644 tests/sctp/sctp_common.c create mode 100644 tests/sctp/sctp_common.h create mode 100644 tests/sctp/sctp_connectx.c create mode 100644 tests/sctp/sctp_peeloff_server.c create mode 100644 tests/sctp/sctp_server.c create mode 100644 tests/sctp/sctp_set_params.c create mode 100644 tests/sctp/sctp_set_peer_addr.c create mode 100644 tests/sctp/sctp_set_pri_addr.c create mode 100755 tests/sctp/test diff --git a/README.md b/README.md index 60a249e..2c871d3 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ similar dependencies): * net-tools _(for `ifconfig`, used by `capable_net/test`)_ * netlabel\_tools _(to load NetLabel configuration during `inet_socket` tests)_ * iptables _(to load the `iptables SECMARK` rules during `inet_socket` tests)_ +* lksctp-tools-devel _(to build the SCTP test programs)_ On a modern Fedora system you can install these dependencies with the following command: @@ -61,7 +62,8 @@ following command: libselinux-devel \ net-tools \ netlabel_tools \ - iptables + iptables \ + lksctp-tools-devel The testsuite requires a pre-existing base policy configuration of SELinux, using either the old example policy or the reference policy as the baseline. diff --git a/policy/Makefile b/policy/Makefile index 15e3a0c..cc70d33 100644 --- a/policy/Makefile +++ b/policy/Makefile @@ -67,6 +67,10 @@ ifeq ($(shell grep -q binder $(POLDEV)/include/support/all_perms.spt && echo tru TARGETS += test_binder.te endif +ifeq ($(shell grep -q corenet_sctp_bind_all_nodes $(POLDEV)/include/kernel/corenetwork.if && echo true),true) +TARGETS += test_sctp.te +endif + ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6)) TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te, $(TARGETS)) endif diff --git a/policy/test_sctp.te b/policy/test_sctp.te new file mode 100644 index 0000000..6d43208 --- /dev/null +++ b/policy/test_sctp.te @@ -0,0 +1,159 @@ +# +################# SCTP selinux-testsuite policy module ###################### +# + +attribute sctpsocketdomain; + +# +######################## NetLabel labels ############################ +# +# Fall-back labeling label: +type netlabel_sctp_peer_t; +corenet_in_generic_node(netlabel_sctp_peer_t) +corenet_in_generic_if(netlabel_sctp_peer_t) + +# Default label for CIPSO/CALIPSO: +gen_require(` + type netlabel_peer_t; +') + +# +############### Declare an attribute that will hold all peers ############### +############### allowed an association ############### +# +attribute sctp_assoc_peers; + +typeattribute netlabel_peer_t sctp_assoc_peers; +typeattribute netlabel_sctp_peer_t sctp_assoc_peers; +allow sctp_assoc_peers sctp_assoc_peers:sctp_socket { association }; + +# +##################### SCTP portcon for ports 1024-65535 ###################### +# +corenet_sctp_bind_all_unreserved_ports(sctpsocketdomain) +corenet_sctp_connect_all_unreserved_ports(sctpsocketdomain) + +# +################################## Server ################################### +# +type test_sctp_server_t; +domain_type(test_sctp_server_t) +unconfined_runs_test(test_sctp_server_t) +typeattribute test_sctp_server_t testdomain; +typeattribute test_sctp_server_t sctpsocketdomain; +allow test_sctp_server_t self:sctp_socket create_stream_socket_perms; +allow test_sctp_server_t netlabel_sctp_peer_t:peer { recv }; +corenet_sctp_bind_all_nodes(test_sctp_server_t) +corenet_inout_generic_node(test_sctp_server_t) +corenet_inout_generic_if(test_sctp_server_t) + +# +############################### Client ################################# +# +type test_sctp_client_t; +domain_type(test_sctp_client_t) +unconfined_runs_test(test_sctp_client_t) +typeattribute test_sctp_client_t testdomain; +typeattribute test_sctp_client_t sctpsocketdomain; +allow test_sctp_client_t self:sctp_socket create_stream_socket_perms; +allow test_sctp_server_t test_sctp_client_t:peer { recv }; +allow test_sctp_client_t test_sctp_server_t:peer { recv }; +allow test_sctp_client_t netlabel_sctp_peer_t:peer { recv }; +corenet_inout_generic_node(test_sctp_client_t) +corenet_inout_generic_if(test_sctp_client_t) + +# +#################### Deny peer recv permission Client ######################## +# +type test_sctp_deny_peer_client_t; +domain_type(test_sctp_deny_peer_client_t) +unconfined_runs_test(test_sctp_deny_peer_client_t) +typeattribute test_sctp_deny_peer_client_t testdomain; +typeattribute test_sctp_deny_peer_client_t sctpsocketdomain; +allow test_sctp_deny_peer_client_t self:sctp_socket create_stream_socket_perms; +corenet_inout_generic_node(test_sctp_deny_peer_client_t) +corenet_inout_generic_if(deny_assoc_sctp_peer_t) + +# +####################### Deny association permission ######################### +# + +# Declare this type for NetLabel etc. to allow the packet through the system, +# however do not allow an association: +type deny_assoc_sctp_peer_t; +allow test_sctp_server_t deny_assoc_sctp_peer_t:peer { recv }; +allow test_sctp_client_t deny_assoc_sctp_peer_t:peer {recv }; +corenet_inout_generic_node(deny_assoc_sctp_peer_t) +corenet_inout_generic_if(deny_assoc_sctp_peer_t) + +# +############################# Connectx ################################# +# +type test_sctp_connectx_t; +domain_type(test_sctp_connectx_t) +unconfined_runs_test(test_sctp_connectx_t) +typeattribute test_sctp_connectx_t testdomain; +typeattribute test_sctp_connectx_t sctpsocketdomain; +allow test_sctp_connectx_t self:sctp_socket create_stream_socket_perms; +allow test_sctp_server_t test_sctp_connectx_t:peer { recv }; +allow test_sctp_connectx_t test_sctp_server_t:peer { recv }; +corenet_sctp_bind_all_nodes(test_sctp_connectx_t) +corenet_inout_generic_node(test_sctp_connectx_t) +corenet_inout_generic_if(test_sctp_connectx_t) + +# +############################## Bindx ##################################### +# +type test_sctp_bindx_t; +domain_type(test_sctp_bindx_t) +unconfined_runs_test(test_sctp_bindx_t) +typeattribute test_sctp_bindx_t testdomain; +typeattribute test_sctp_bindx_t sctpsocketdomain; +allow test_sctp_bindx_t self:sctp_socket create_stream_socket_perms; +allow test_sctp_server_t test_sctp_bindx_t:peer { recv }; +allow test_sctp_bindx_t test_sctp_server_t:peer { recv }; +corenet_sctp_bind_all_nodes(test_sctp_bindx_t) +corenet_inout_generic_node(test_sctp_bindx_t) +corenet_inout_generic_if(test_sctp_bindx_t) + +# +########## SET_PRI_ADDR + SET_PEER ADDR for ASCONF process testing ########## +# +type test_sctp_set_peer_addr_t; +domain_type(test_sctp_set_peer_addr_t) +unconfined_runs_test(test_sctp_set_peer_addr_t) +typeattribute test_sctp_set_peer_addr_t testdomain; +typeattribute test_sctp_set_peer_addr_t sctpsocketdomain; +allow test_sctp_set_peer_addr_t self:sctp_socket create_stream_socket_perms; +allow test_sctp_server_t test_sctp_set_peer_addr_t:peer { recv }; +allow test_sctp_set_peer_addr_t test_sctp_server_t:peer { recv }; +corenet_sctp_bind_all_nodes(test_sctp_set_peer_addr_t) +corenet_inout_generic_node(test_sctp_set_peer_addr_t) +corenet_inout_generic_if(test_sctp_set_peer_addr_t) + +# +######################### SECMARK-specific policy ############################ +# +type test_sctp_server_packet_t; +allow unconfined_t test_sctp_server_packet_t:packet { relabelto }; +allow test_sctp_server_t test_sctp_server_packet_t:packet { send recv }; +allow test_sctp_client_t test_sctp_server_packet_t:packet { send recv }; + +# +####### Required for getaddrinfo(3), if_nametoindex(3) type functions ######## +########## when resolving IPv6 link local addresses e.g. addr% ########### +# +gen_require(` + type sysctl_net_t; +') + +allow sctpsocketdomain proc_net_t:file { read }; +allow sctpsocketdomain sysctl_net_t:dir { search }; +allow sctpsocketdomain self:udp_socket { create }; +allow sctpsocketdomain self:unix_dgram_socket { create ioctl }; + +# +############ Allow these domains to be entered from sysadm domain ############ +# +miscfiles_domain_entry_test_files(sctpsocketdomain) +userdom_sysadm_entry_spec_domtrans_to(sctpsocketdomain) diff --git a/tests/Makefile b/tests/Makefile index 7082661..fb6de5c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -23,6 +23,10 @@ ifeq ($(shell grep -q icmp_socket $(POLDEV)/include/support/all_perms.spt && gre SUBDIRS += extended_socket_class endif +ifeq ($(shell grep -q corenet_sctp_bind_all_nodes $(POLDEV)/include/kernel/corenetwork.if && grep -q 1 /sys/fs/selinux/policy_capabilities/extended_socket_class && echo true),true) +SUBDIRS += sctp +endif + ifeq ($(shell grep -q netlink_iscsi_socket $(POLDEV)/include/support/all_perms.spt && echo true),true) SUBDIRS += netlink_socket endif diff --git a/tests/sctp/Makefile b/tests/sctp/Makefile new file mode 100644 index 0000000..1debf82 --- /dev/null +++ b/tests/sctp/Makefile @@ -0,0 +1,13 @@ +TARGETS = sctp_client sctp_server sctp_bind sctp_bindx sctp_connectx sctp_set_params sctp_set_peer_addr sctp_set_pri_addr sctp_asconf_params_client sctp_asconf_params_server sctp_peeloff_server + +DEPS = sctp_common.c sctp_common.h +CFLAGS ?= -Wall + +LDLIBS += -lselinux -lsctp + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) + +$(TARGETS): $(DEPS) diff --git a/tests/sctp/calipso-flush b/tests/sctp/calipso-flush new file mode 100644 index 0000000..5143962 --- /dev/null +++ b/tests/sctp/calipso-flush @@ -0,0 +1,5 @@ +#!/bin/sh +# Reset NetLabel configuration to unlabeled after CALIPSO/IPv6 tests. +netlabelctl map del default +netlabelctl calipso del doi:16 +netlabelctl map add default protocol:unlbl diff --git a/tests/sctp/calipso-load b/tests/sctp/calipso-load new file mode 100644 index 0000000..4bb9c7f --- /dev/null +++ b/tests/sctp/calipso-load @@ -0,0 +1,7 @@ +#!/bin/sh +# Define a doi for testing loopback for CALIPSO/IPv6. +netlabelctl calipso add pass doi:16 +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl map add default address:::1 protocol:calipso,16 diff --git a/tests/sctp/cipso-fl-flush b/tests/sctp/cipso-fl-flush new file mode 100644 index 0000000..032960d --- /dev/null +++ b/tests/sctp/cipso-fl-flush @@ -0,0 +1,5 @@ +#!/bin/sh + +netlabelctl map del default +netlabelctl cipsov4 del doi:1 +netlabelctl map add default protocol:unlbl diff --git a/tests/sctp/cipso-fl-load b/tests/sctp/cipso-fl-load new file mode 100644 index 0000000..3ef85b4 --- /dev/null +++ b/tests/sctp/cipso-fl-load @@ -0,0 +1,7 @@ +#!/bin/sh + +netlabelctl cipsov4 add local doi:1 +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl map add default address:127.0.0.1 protocol:cipsov4,1 diff --git a/tests/sctp/cipso-flush b/tests/sctp/cipso-flush new file mode 100644 index 0000000..6da5b05 --- /dev/null +++ b/tests/sctp/cipso-flush @@ -0,0 +1,5 @@ +#!/bin/sh +# Reset NetLabel configuration to unlabeled for all after CIPSO/IPv4 tests. +netlabelctl map del default +netlabelctl cipsov4 del doi:16 +netlabelctl map add default protocol:unlbl diff --git a/tests/sctp/cipso-load-t1 b/tests/sctp/cipso-load-t1 new file mode 100644 index 0000000..6e9a161 --- /dev/null +++ b/tests/sctp/cipso-load-t1 @@ -0,0 +1,7 @@ +#!/bin/sh + +netlabelctl cipsov4 add pass doi:16 tags:1 +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl map add default address:127.0.0.1 protocol:cipsov4,16 diff --git a/tests/sctp/cipso-load-t2 b/tests/sctp/cipso-load-t2 new file mode 100644 index 0000000..3227ba5 --- /dev/null +++ b/tests/sctp/cipso-load-t2 @@ -0,0 +1,7 @@ +#!/bin/sh + +netlabelctl cipsov4 add pass doi:16 tags:2 +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl map add default address:127.0.0.1 protocol:cipsov4,16 diff --git a/tests/sctp/cipso-load-t5 b/tests/sctp/cipso-load-t5 new file mode 100644 index 0000000..661afb8 --- /dev/null +++ b/tests/sctp/cipso-load-t5 @@ -0,0 +1,7 @@ +#!/bin/sh + +netlabelctl cipsov4 add pass doi:16 tags:5 +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl map add default address:127.0.0.1 protocol:cipsov4,16 diff --git a/tests/sctp/fb-deny-label-flush b/tests/sctp/fb-deny-label-flush new file mode 100644 index 0000000..059e0b7 --- /dev/null +++ b/tests/sctp/fb-deny-label-flush @@ -0,0 +1,6 @@ +#!/bin/sh + +netlabelctl map del default +netlabelctl map add default protocol:unlbl +netlabelctl unlbl del interface:lo address:127.0.0.0/8 label:system_u:object_r:netlabel_sctp_peer_t:s0 +netlabelctl unlbl del interface:lo address:::1/128 label:system_u:object_r:deny_assoc_sctp_peer_t:s0 diff --git a/tests/sctp/fb-deny-label-load b/tests/sctp/fb-deny-label-load new file mode 100644 index 0000000..7c0bd87 --- /dev/null +++ b/tests/sctp/fb-deny-label-load @@ -0,0 +1,7 @@ +#!/bin/sh + +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl unlbl add interface:lo address:127.0.0.0/8 label:system_u:object_r:netlabel_sctp_peer_t:s0 +netlabelctl unlbl add interface:lo address:::1/128 label:system_u:object_r:deny_assoc_sctp_peer_t:s0 diff --git a/tests/sctp/fb-label-flush b/tests/sctp/fb-label-flush new file mode 100644 index 0000000..13573a8 --- /dev/null +++ b/tests/sctp/fb-label-flush @@ -0,0 +1,6 @@ +#!/bin/sh + +netlabelctl map del default +netlabelctl map add default protocol:unlbl +netlabelctl unlbl del interface:lo address:127.0.0.0/8 label:system_u:object_r:netlabel_sctp_peer_t:s0 +netlabelctl unlbl del interface:lo address:::1/128 label:system_u:object_r:netlabel_sctp_peer_t:s0 diff --git a/tests/sctp/fb-label-load b/tests/sctp/fb-label-load new file mode 100644 index 0000000..a501515 --- /dev/null +++ b/tests/sctp/fb-label-load @@ -0,0 +1,8 @@ +#!/bin/sh + +netlabelctl map del default +netlabelctl map add default address:0.0.0.0/0 protocol:unlbl +netlabelctl map add default address:::/0 protocol:unlbl +netlabelctl unlbl add interface:lo address:127.0.0.0/8 label:system_u:object_r:netlabel_sctp_peer_t:s0 +netlabelctl unlbl add interface:lo address:::1/128 label:system_u:object_r:netlabel_sctp_peer_t:s0 +#netlabelctl -p unlbl list diff --git a/tests/sctp/iptables-flush b/tests/sctp/iptables-flush new file mode 100644 index 0000000..e74271a --- /dev/null +++ b/tests/sctp/iptables-flush @@ -0,0 +1,4 @@ +#!/bin/sh +# Flush the security table after IPv4 and IPv6 tests. +iptables -t security -F +ip6tables -t security -F diff --git a/tests/sctp/iptables-load b/tests/sctp/iptables-load new file mode 100644 index 0000000..9dac576 --- /dev/null +++ b/tests/sctp/iptables-load @@ -0,0 +1,27 @@ +#!/bin/sh +############################ SECMARK IPTABLE ENTRIES ######################## +# +# Flush the security table first: +iptables -t security -F +ip6tables -t security -F + +#-------------- INPUT IP Stream --------------------# +# These rules will replace the above context if sctp ports 1024:1035 are found in the packets: +iptables -t security -A INPUT -i lo -p sctp -m multiport --port 1024:1035 -j SECMARK --selctx system_u:object_r:test_sctp_server_packet_t:s0 + +iptables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --save + +ip6tables -t security -A INPUT -i lo -p sctp -m multiport --port 1024:1035 -j SECMARK --selctx system_u:object_r:test_sctp_server_packet_t:s0 + +ip6tables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --save + +#-------------- OUTPUT IP Stream --------------------# +# These rules will replace the above context if sctp ports 1024:1035 are found in the packets: +iptables -t security -A OUTPUT -o lo -p sctp -m multiport --port 1024:1035 -j SECMARK --selctx system_u:object_r:test_sctp_server_packet_t:s0 + +iptables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --save + +ip6tables -t security -A OUTPUT -o lo -p sctp -m multiport --port 1024:1035 -j SECMARK --selctx system_u:object_r:test_sctp_server_packet_t:s0 + +ip6tables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --save + diff --git a/tests/sctp/sctp_asconf_params_client.c b/tests/sctp/sctp_asconf_params_client.c new file mode 100644 index 0000000..12522f3 --- /dev/null +++ b/tests/sctp/sctp_asconf_params_client.c @@ -0,0 +1,298 @@ +/* This test will allow the server side to add/remove bindx addresses and + * inform the client side via ASCONF chunks. It will also allow the server + * side to inform the client that the peer primary address is being updated. + * The code for checking these parameters are in net/sctp/sm_make_chunk.c + * sctp_process_asconf_param(). + * + * To enable the processing of these incoming ASCONF parameters for: + * SCTP_PARAM_SET_PRIMARY, SCTP_PARAM_ADD_IP and SCTP_PARAM_DEL_IP + * the following options must be enabled: + * echo 1 > /proc/sys/net/sctp/addip_enable + * echo 1 > /proc/sys/net/sctp/addip_noauth_enable + * + * If these are not enabled the SCTP_SET_PEER_PRIMARY_ADDR setsockopt + * fails with EPERM "Operation not permitted", however the bindx calls + * will complete but the client side will not be informed. + * + * NOTES: + * 1) SCTP_SET_PEER_PRIMARY_ADDR requires a non-loopback IP address. + * 2) Both addresses used by the client/server MUST be the same type + * (i.e. IPv4 or IPv6). + * 3) The iptables default for Fedora does not allow SCTP remote traffic. + * To allow this set the following: + * iptables -I INPUT 1 -p sctp -j ACCEPT + * ip6tables -I INPUT 1 -p sctp -j ACCEPT + */ + +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] [-n] addr port\n" + "\nWhere:\n\t" + "-v Print status information.\n\t" + "-n No bindx_rem will be received from server. This happens\n\t" + " when the client and server are on different systems.\n\t" + "addr IPv4 or IPv6 address (MUST NOT be loopback address).\n\t" + "port port.\n", progname); + + fprintf(stderr, + "Notes:\n\t" + "1) addr and the server side new_pri_addr address MUST be\n\t" + " same type (IPv4 or IPv6).\n\t" + "2) IPv6 link-local addresses require the %% to\n\t" + " obtain scopeid. e.g. fe80::7629:afff:fe0f:8e5d%%wlp6s0\n"); + exit(1); +} + +static int peer_count, peer_count_err; +static void getpaddrs_alarm(int sig) +{ + fprintf(stderr, + "Get peer address count timer expired - carry on test\n"); + peer_count += 1; + peer_count_err = true; +} + +static void getprimaddr_alarm(int sig) +{ + fprintf(stderr, "Get primary address timer expired - end test.\n"); + exit(1); +} + +static void get_primaddr(char *addr_buf, int socket) +{ + int result; + struct sctp_prim prim; + struct sockaddr_in *in_addr; + struct sockaddr_in6 *in6_addr; + struct sockaddr *paddr; + socklen_t prim_len; + const char *addr_ptr = NULL; + + memset(&prim, 0, sizeof(struct sctp_prim)); + prim_len = sizeof(struct sctp_prim); + + result = getsockopt(socket, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, + &prim, &prim_len); + if (result < 0) { + perror("getsockopt: SCTP_PRIMARY_ADDR"); + exit(1); + } + + paddr = (struct sockaddr *)&prim.ssp_addr; + if (paddr->sa_family == AF_INET) { + in_addr = (struct sockaddr_in *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET, &in_addr->sin_addr, addr_buf, + INET6_ADDRSTRLEN); + } else if (paddr->sa_family == AF_INET6) { + in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET6, &in6_addr->sin6_addr, addr_buf, + INET6_ADDRSTRLEN); + } + if (!addr_ptr) { + perror("inet_ntop"); + exit(1); + } +} + +int main(int argc, char **argv) +{ + int opt, client_sock, result, len; + struct addrinfo client_hints, *client_res; + struct sockaddr *paddrs; + bool verbose = false, no_bindx_rem = false; + char client_prim_addr1[INET6_ADDRSTRLEN]; + char client_prim_addr2[INET6_ADDRSTRLEN]; + char buffer[1024]; + + while ((opt = getopt(argc, argv, "vn")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + case 'n': + no_bindx_rem = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 2) + usage(argv[0]); + + /* Set up client side and connect */ + memset(&client_hints, 0, sizeof(struct addrinfo)); + client_hints.ai_socktype = SOCK_STREAM; + client_hints.ai_protocol = IPPROTO_SCTP; + result = getaddrinfo(argv[optind], argv[optind + 1], + &client_hints, &client_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - client: %s\n", + gai_strerror(result)); + exit(1); + } + + + /* printf("Client scopeID: %d\n", + * ((struct sockaddr_in6 *)client_res->ai_addr)->sin6_scope_id); + */ + + client_sock = socket(client_res->ai_family, client_res->ai_socktype, + client_res->ai_protocol); + if (client_sock < 0) { + perror("socket"); + exit(1); + } + + result = connect(client_sock, client_res->ai_addr, + client_res->ai_addrlen); + if (result < 0) { + if (errno != EINPROGRESS) + perror("connect"); + else + fprintf(stderr, "connect timeout\n"); + + close(client_sock); + exit(1); + } + + /* Get number of peer addresses on CLIENT (should be 1) for a check + * later as sctp_bindx SERVER -> CLIENT is non-blocking. + */ + peer_count = sctp_getpaddrs(client_sock, 0, &paddrs); + sctp_freepaddrs(paddrs); + len = sprintf(buffer, "Client peer address count: %d", peer_count); + if (verbose) + printf("%s\n", buffer); + + + /* Get initial CLIENT primary address (that should be ADDR1). */ + get_primaddr(client_prim_addr1, client_sock); + + /* server waiting for write before sending BINDX_ADD */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + exit(1); + } + + /* Sleep a while as server pings us the new address */ + sleep(1); + /* then set an alarm and check number of peer addresses for CLIENT */ + signal(SIGALRM, getpaddrs_alarm); + alarm(2); + peer_count_err = false; + result = 0; + + while (result != peer_count + 1) { + result = sctp_getpaddrs(client_sock, 0, &paddrs); + if (result > 0) + sctp_freepaddrs(paddrs); + + if (peer_count_err) + break; + } + alarm(0); + peer_count = result; + + len = sprintf(buffer, "Client peer address count: %d", result); + if (verbose) + printf("%s\n", buffer); + + /* server waiting for write before send SCTP_SET_PEER_PRIMARY_ADDR */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + exit(1); + } + + /* Now get the new primary address from the client */ + signal(SIGALRM, getprimaddr_alarm); + alarm(2); + memcpy(client_prim_addr2, client_prim_addr1, INET6_ADDRSTRLEN); + + while (!strcmp(client_prim_addr1, client_prim_addr2)) + get_primaddr(client_prim_addr2, client_sock); + + alarm(0); + len = sprintf(buffer, + "Client initial SCTP_PRIMARY_ADDR: %s\nClient current SCTP_PRIMARY_ADDR: %s", + client_prim_addr1, client_prim_addr2); + if (verbose) + printf("%s\n", buffer); + + if (!no_bindx_rem) { + /* Let server send bindx_rem */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + exit(1); + } + + /* Then delete addr that checks ASCONF - SCTP_PARAM_DEL_IP */ + if (!peer_count_err) { + signal(SIGALRM, getprimaddr_alarm); + alarm(2); + result = 0; + while (result != peer_count - 1) { + result = sctp_getpaddrs(client_sock, + 0, &paddrs); + if (result > 0) + sctp_freepaddrs(paddrs); + + if (peer_count_err) + break; + } + alarm(0); + sprintf(buffer, "Client peer address count: %d", + result); + if (verbose) + printf("%s\n", buffer); + } + } + + /* server waiting for client peer address count */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + exit(1); + } + + /* Compare the client primary addresses, they should be different. */ + if (!strcmp(client_prim_addr1, client_prim_addr2)) { + len = sprintf(buffer, + "Client ADDR1: %s same as ADDR2: %s - SCTP_SET_PEER_PRIMARY_ADDR failed", + client_prim_addr1, client_prim_addr2); + fprintf(stderr, "%s\n", buffer); + + /* server waiting for write to finish */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + } + exit(1); + } + + len = sprintf(buffer, "Client primary address changed successfully\n"); + if (verbose) + printf("%s\n", buffer); + + /* server waiting for write to finish */ + result = write(client_sock, buffer, len); + if (result < 0) { + perror("write"); + close(client_sock); + exit(1); + } + + close(client_sock); + exit(0); +} diff --git a/tests/sctp/sctp_asconf_params_server.c b/tests/sctp/sctp_asconf_params_server.c new file mode 100644 index 0000000..f710097 --- /dev/null +++ b/tests/sctp/sctp_asconf_params_server.c @@ -0,0 +1,236 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s -v addr new_pri_addr port\n" + "\nWhere:\n\t" + "-v Print status information.\n\t" + "addr IPv4/IPv6 address for initial connection.\n\t" + "new_pri_addr IPv4/IPv6 address that the server will bindx\n\t" + " then set to the new SCTP_PRIMARY_ADDR.\n\t" + "port port.\n", progname); + fprintf(stderr, + "Notes:\n\t" + "1) addr and new_pri_addr MUST NOT be loopback addresses.\n\t" + "2) addr and new_pri_addr MUST be same type (IPv4 or IPv6).\n\t" + "3) IPv6 link-local addresses require the %% to\n\t" + " obtain scopeid. e.g. fe80::7629:afff:fe0f:8e5d%%wlp6s0\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, srv_sock, new_sock, result, on = 1; + struct addrinfo srv_hints, *srv_res; + struct addrinfo *new_pri_addr_res; + struct sockaddr *sa_ptr; + socklen_t sinlen; + struct sockaddr_storage sin; + struct sctp_setpeerprim setpeerprim; + bool verbose = false, is_ipv6 = false; + char buffer[128]; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 3) + usage(argv[0]); + + if (strchr(argv[optind], ':') && strchr(argv[optind + 1], ':')) { + is_ipv6 = true; + srv_hints.ai_family = AF_INET6; + } else if (strchr(argv[optind], '.') && + strchr(argv[optind + 1], '.')) { + is_ipv6 = false; + srv_hints.ai_family = AF_INET; + } else { + usage(argv[0]); + } + + memset(&srv_hints, 0, sizeof(struct addrinfo)); + srv_hints.ai_flags = AI_PASSIVE; + srv_hints.ai_socktype = SOCK_STREAM; + srv_hints.ai_protocol = IPPROTO_SCTP; + + /* Set up server side */ + result = getaddrinfo(argv[optind], argv[optind + 2], + &srv_hints, &srv_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - server: %s\n", + gai_strerror(result)); + exit(1); + } + if (is_ipv6 && verbose) + printf("Server scopeID: %d\n", + ((struct sockaddr_in6 *) + srv_res->ai_addr)->sin6_scope_id); + + srv_sock = socket(srv_res->ai_family, srv_res->ai_socktype, + srv_res->ai_protocol); + if (srv_sock < 0) { + perror("socket - server"); + exit(1); + } + + result = setsockopt(srv_sock, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof(on)); + if (result < 0) { + perror("setsockopt: SO_REUSEADDR"); + close(srv_sock); + exit(1); + } + + result = bind(srv_sock, srv_res->ai_addr, srv_res->ai_addrlen); + if (result < 0) { + perror("bind"); + close(srv_sock); + exit(1); + } + + listen(srv_sock, 1); + + new_sock = accept(srv_sock, (struct sockaddr *)&sin, &sinlen); + if (new_sock < 0) { + perror("accept"); + result = 1; + goto err2; + } + + /* This waits for a client message before continuing. */ + result = read(new_sock, &buffer, sizeof(buffer)); + if (result < 0) { + perror("read"); + exit(1); + } + buffer[result] = 0; + if (verbose) + printf("%s\n", buffer); + + /* Obtain address info for the BINDX_ADD and new SCTP_PRIMARY_ADDR. */ + result = getaddrinfo(argv[optind + 1], argv[optind + 2], + &srv_hints, &new_pri_addr_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - new SCTP_PRIMARY_ADDR: %s\n", + gai_strerror(result)); + close(srv_sock); + exit(1); + } + if (is_ipv6 && verbose) + printf("new_pri_addr scopeID: %d\n", + ((struct sockaddr_in6 *) + new_pri_addr_res->ai_addr)->sin6_scope_id); + + + /* Now call sctp_bindx to add ADDR2, this will cause an + * ASCONF - SCTP_PARAM_ADD_IP chunk to be sent to the CLIENT. + * This is non-blocking so there maybe a delay before the CLIENT + * receives the asconf chunk. + */ + if (verbose) + printf("Calling sctp_bindx ADD: %s\n", argv[optind + 1]); + + result = sctp_bindx(new_sock, + (struct sockaddr *)new_pri_addr_res->ai_addr, + 1, SCTP_BINDX_ADD_ADDR); + if (result < 0) { + if (errno == EACCES) { + perror("sctp_bindx ADD"); + } else { + perror("sctp_bindx ADD"); + result = 1; + goto err1; + } + } + + /* This waits for a client message before continuing. */ + result = read(new_sock, &buffer, sizeof(buffer)); + if (result < 0) { + perror("read"); + exit(1); + } + buffer[result] = 0; + if (verbose) + printf("%s\n", buffer); + + /* Now that the CLIENT has the new primary address ensure they use + * it by SCTP_SET_PEER_PRIMARY_ADDR. + */ + memset(&setpeerprim, 0, sizeof(struct sctp_setpeerprim)); + sa_ptr = (struct sockaddr *)&setpeerprim.sspp_addr; + if (is_ipv6) + memcpy(sa_ptr, new_pri_addr_res->ai_addr, + sizeof(struct sockaddr_in6)); + else + memcpy(sa_ptr, new_pri_addr_res->ai_addr, + sizeof(struct sockaddr_in)); + + if (verbose) + printf("Calling setsockopt SCTP_SET_PEER_PRIMARY_ADDR: %s\n", + argv[optind + 1]); + + result = setsockopt(new_sock, IPPROTO_SCTP, + SCTP_SET_PEER_PRIMARY_ADDR, + &setpeerprim, sizeof(struct sctp_setpeerprim)); + if (result < 0) { + perror("setsockopt: SCTP_SET_PEER_PRIMARY_ADDR"); + result = 1; + goto err1; + } + /* Sleep a sec to ensure client get info. */ + result = read(new_sock, &buffer, sizeof(buffer)); + if (result < 0) { + perror("read"); + exit(1); + } + buffer[result] = 0; + if (verbose) + printf("%s\n", buffer); + + /* Then delete addr that checks ASCONF - SCTP_PARAM_DEL_IP. */ + if (verbose) + printf("Calling sctp_bindx REM: %s\n", argv[optind]); + + result = sctp_bindx(new_sock, (struct sockaddr *)srv_res->ai_addr, + 1, SCTP_BINDX_REM_ADDR); + if (result < 0) { + perror("sctp_bindx - REM"); + result = 1; + goto err1; + } + + result = read(new_sock, &buffer, sizeof(buffer)); + if (result <= 0) { + if (errno != 0) + perror("read"); + result = 1; + goto err1; + } + buffer[result] = 0; + if (verbose) + printf("%s\n", buffer); + + result = read(new_sock, &buffer, sizeof(buffer)); + if (result < 0) { + perror("read"); + exit(1); + } + buffer[result] = 0; + if (verbose) + printf("%s\n", buffer); + + result = 0; + +err1: + close(new_sock); +err2: + close(srv_sock); + exit(result); +} diff --git a/tests/sctp/sctp_bind.c b/tests/sctp/sctp_bind.c new file mode 100644 index 0000000..e7c2a9b --- /dev/null +++ b/tests/sctp/sctp_bind.c @@ -0,0 +1,81 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] stream|seq port\n" + "\nWhere:\n\t" + "-v Print context information.\n\t" + "stream Use SCTP 1-to-1 style or:\n\t" + "seq use SCTP 1-to-Many style.\n\t" + "port Listening port.\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, sock, result, on = 1; + struct addrinfo hints, *res; + bool verbose = false; + char *context; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 2) + usage(argv[0]); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = IPPROTO_SCTP; + + if (!strcmp(argv[optind], "stream")) + hints.ai_socktype = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + hints.ai_socktype = SOCK_SEQPACKET; + else + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Process context: %s\n", context); + free(context); + } + + result = getaddrinfo(NULL, argv[optind + 1], &hints, &res); + if (result < 0) { + printf("getaddrinfo: %s\n", gai_strerror(result)); + exit(1); + } + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock < 0) { + perror("socket"); + exit(1); + } + + result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (result < 0) { + perror("setsockopt: SO_REUSEADDR"); + close(sock); + exit(1); + } + + result = bind(sock, res->ai_addr, res->ai_addrlen); + if (result < 0) { + perror("bind"); + close(sock); + exit(1); + } + + close(sock); + exit(0); +} diff --git a/tests/sctp/sctp_bindx.c b/tests/sctp/sctp_bindx.c new file mode 100644 index 0000000..7634bab --- /dev/null +++ b/tests/sctp/sctp_bindx.c @@ -0,0 +1,116 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-r] [-v] stream|seq port\n" + "\nWhere:\n\t" + "-r After two bindx ADDs, remove one with bindx REM.\n\t" + "-v Print context information.\n\t" + " The default is to add IPv4 and IPv6 loopback addrs.\n\t" + "stream Use SCTP 1-to-1 style or:\n\t" + "seq use SCTP 1-to-Many style.\n\t" + "port port.\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, type, sock, result; + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + unsigned short port; + bool rem = false; + bool verbose = false; + char *context; + + while ((opt = getopt(argc, argv, "rv")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + case 'r': + rem = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 2) + usage(argv[0]); + + if (!strcmp(argv[optind], "stream")) + type = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + type = SOCK_SEQPACKET; + else + usage(argv[0]); + + port = atoi(argv[optind + 1]); + if (!port) + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Process context: %s\n", context); + free(context); + } + + sock = socket(PF_INET6, type, IPPROTO_SCTP); + if (sock < 0) { + perror("socket"); + exit(1); + } + + if (verbose) + print_context(sock, "Server"); + + memset(&ipv4, 0, sizeof(struct sockaddr_in)); + ipv4.sin_family = AF_INET; + ipv4.sin_port = htons(port); + ipv4.sin_addr.s_addr = htonl(0x7f000001); + + result = sctp_bindx(sock, (struct sockaddr *)&ipv4, 1, + SCTP_BINDX_ADD_ADDR); + if (result < 0) { + perror("sctp_bindx ADD - ipv4"); + close(sock); + exit(1); + } + + if (verbose) + printf("sctp_bindx ADD - ipv4\n"); + + memset(&ipv6, 0, sizeof(struct sockaddr_in6)); + ipv6.sin6_family = AF_INET6; + ipv6.sin6_port = htons(port); + ipv6.sin6_addr = in6addr_loopback; + + result = sctp_bindx(sock, (struct sockaddr *)&ipv6, 1, + SCTP_BINDX_ADD_ADDR); + if (result < 0) { + perror("sctp_bindx ADD - ipv6"); + close(sock); + exit(1); + } + + if (verbose) + printf("sctp_bindx ADD - ipv6\n"); + + if (rem) { + result = sctp_bindx(sock, (struct sockaddr *)&ipv6, 1, + SCTP_BINDX_REM_ADDR); + if (result < 0) { + perror("sctp_bindx - REM"); + close(sock); + exit(1); + } + if (verbose) + printf("sctp_bindx REM - ipv6\n"); + } + + close(sock); + exit(0); +} diff --git a/tests/sctp/sctp_client.c b/tests/sctp/sctp_client.c new file mode 100644 index 0000000..595da75 --- /dev/null +++ b/tests/sctp/sctp_client.c @@ -0,0 +1,220 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-e expected_msg] [-v] [-n] [-x] stream|seq addr port\n" + "\nWhere:\n\t" + + "-e Optional expected message from server e.g. \"nopeer\".\n\t" + " If not present the client context will be used as a\n\t" + " comparison with the servers reply.\n\t" + "-n Do NOT call connect(3) or connectx(3).\n\t" + "-v Print context and ip options information.\n\t" + "-x Use sctp_connectx(3) instead of connect(3).\n\t" + "stream Use SCTP 1-to-1 style or:\n\t" + "seq use SCTP 1-to-Many style.\n\t" + "addr IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1).\n\t" + "port Port for accessing server.\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, sock, result, save_errno; + socklen_t opt_len; + struct addrinfo hints, *serverinfo; + char byte = 0x41, label[1024], *expected = NULL; + bool verbose = false, connectx = false, no_connects = false; + bool ipv4 = false, expect_ipopt = false; + char *context; + struct timeval tm; + + while ((opt = getopt(argc, argv, "e:vxmni")) != -1) { + switch (opt) { + case 'e': + expected = optarg; + break; + case 'i': + expect_ipopt = true; + break; + case 'v': + verbose = true; + break; + case 'n': + no_connects = true; + break; + case 'x': + connectx = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 3) + usage(argv[0]); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_protocol = IPPROTO_SCTP; + + if (!strcmp(argv[optind], "stream")) + hints.ai_socktype = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + hints.ai_socktype = SOCK_SEQPACKET; + else + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Client process context: %s\n", context); + free(context); + } + + result = getaddrinfo(argv[optind + 1], argv[optind + 2], &hints, + &serverinfo); + if (result < 0) { + fprintf(stderr, "Client getaddrinfo: %s\n", + gai_strerror(result)); + exit(2); + } + + if (serverinfo->ai_family == AF_INET) + ipv4 = true; + + sock = socket(serverinfo->ai_family, serverinfo->ai_socktype, + serverinfo->ai_protocol); + if (sock < 0) { + perror("Client socket"); + exit(3); + } + + /* + * These timeouts are set to test whether the peer { recv } completes + * or not when the permission is denied. These errors will be + * returned during testing: + * EINPROGRESS - Operation now in progress - SOCK_STREAM + * Uses SO_SNDTIMEO when using connect(2) or sctp_connectx(3) + * EAGAIN - Resource temporarily unavailable - SOCK_SEQPACKET + * Uses SO_RCVTIMEO when NO connects are called. + */ + tm.tv_sec = 2; + tm.tv_usec = 0; + result = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm)); + if (result < 0) { + perror("Client setsockopt: SO_SNDTIMEO"); + exit(4); + } + + result = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm)); + if (result < 0) { + perror("Client setsockopt: SO_RCVTIMEO"); + exit(5); + } + + if (!no_connects) { + if (connectx) + result = sctp_connectx(sock, serverinfo->ai_addr, + 1, NULL); + else + result = connect(sock, serverinfo->ai_addr, + serverinfo->ai_addrlen); + if (result < 0) { + save_errno = errno; + close(sock); + perror("Client connect"); + switch (save_errno) { + case EINPROGRESS: + exit(6); + break; + case ENOSPC: + exit(7); + break; + case EACCES: + exit(8); + break; + default: + exit(9); + } + } + if (verbose) { + print_context(sock, "Client connect"); + print_ip_option(sock, ipv4, "Client connect"); + } + } + + if (hints.ai_socktype == SOCK_STREAM) { + + result = write(sock, &byte, 1); + if (result < 0) { + perror("Client write"); + close(sock); + exit(10); + } + if (verbose) + print_context(sock, "Client STREAM write"); + + result = read(sock, label, sizeof(label)); + if (result < 0) { + perror("Client read"); + close(sock); + exit(11); + } + if (verbose) { + print_context(sock, "Client STREAM read"); + print_ip_option(sock, ipv4, "Client STREAM read"); + } + if (expect_ipopt) + expected = get_ip_option(sock, ipv4, &opt_len); + + } else { /* hints.ai_socktype == SOCK_SEQPACKET */ + + result = sctp_sendmsg(sock, &byte, 1, + serverinfo->ai_addr, + serverinfo->ai_addrlen, + 0, 0, 0, 0, 0); + if (result < 0) { + perror("Client sctp_sendmsg"); + close(sock); + exit(12); + } + + if (verbose) { + print_context(sock, "Client SEQPACKET sctp_sendmsg"); + print_ip_option(sock, ipv4, + "Client SEQPACKET sctp_sendmsg"); + } + + result = sctp_recvmsg(sock, label, sizeof(label), + NULL, 0, NULL, NULL); + if (result < 0) { + perror("Client sctp_recvmsg"); + close(sock); + exit(13); + } + if (expect_ipopt) + expected = get_ip_option(sock, ipv4, &opt_len); + } + + label[result] = 0; + close(sock); + + if (!expected && !expect_ipopt) { + result = getcon(&expected); + if (result < 0) { + perror("Client getcon"); + exit(14); + } + } + + if (strcmp(expected, label)) { + fprintf(stderr, "Client expected %s, got %s\n", + expected, label); + exit(15); + } else if (verbose) { + printf("Client received %s\n", label); + } + + exit(0); +} diff --git a/tests/sctp/sctp_common.c b/tests/sctp/sctp_common.c new file mode 100644 index 0000000..100ab22 --- /dev/null +++ b/tests/sctp/sctp_common.c @@ -0,0 +1,101 @@ +#include "sctp_common.h" + +void print_context(int fd, char *text) +{ + char *context; + + if (fgetfilecon(fd, &context) < 0) + context = strdup("unavailable"); + printf("%s fd context: %s\n", text, context); + free(context); + + if (getpeercon(fd, &context) < 0) + context = strdup("unavailable"); + printf("%s peer context: %s\n", text, context); + free(context); +} + +void print_addr_info(struct sockaddr *sin, char *text) +{ + struct sockaddr_in *addr4; + struct sockaddr_in6 *addr6; + char addr_str[INET6_ADDRSTRLEN + 1]; + + switch (sin->sa_family) { + case AF_INET: + addr4 = (struct sockaddr_in *)sin; + inet_ntop(sin->sa_family, + (void *)&addr4->sin_addr, + addr_str, INET6_ADDRSTRLEN + 1); + printf("%s IPv4 addr %s\n", text, addr_str); + break; + case AF_INET6: + addr6 = (struct sockaddr_in6 *)sin; + if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { + inet_ntop(AF_INET, + (void *)&addr6->sin6_addr.s6_addr32[3], + addr_str, INET6_ADDRSTRLEN + 1); + printf("%s IPv6->IPv4 MAPPED addr %s\n", + text, addr_str); + } else { + inet_ntop(sin->sa_family, + (void *)&addr6->sin6_addr, + addr_str, INET6_ADDRSTRLEN + 1); + printf("%s IPv6 addr %s\n", text, + addr_str); + } + break; + } +} + +char *get_ip_option(int fd, bool ipv4, socklen_t *opt_len) +{ + int result, i; + unsigned char ip_options[1024]; + socklen_t len = sizeof(ip_options); + char *ip_optbuf; + + if (ipv4) + result = getsockopt(fd, IPPROTO_IP, IP_OPTIONS, + ip_options, &len); + else + result = getsockopt(fd, IPPROTO_IPV6, IPV6_HOPOPTS, + ip_options, &len); + + if (result < 0) { + perror("get ip options error"); + return NULL; + } + + ip_optbuf = calloc(1, len * 2 + 1); + if (!ip_optbuf) { + perror("get ip options malloc error"); + return NULL; + } + + if (len > 0) { + for (i = 0; i < len; i++) + sprintf(&ip_optbuf[i * 2], "%02x", ip_options[i]); + + *opt_len = len; + return ip_optbuf; + } + + return NULL; +} + +void print_ip_option(int fd, bool ipv4, char *text) +{ + char *ip_options; + socklen_t len; + + ip_options = get_ip_option(fd, ipv4, &len); + + if (ip_options) { + printf("%s IP Options Family: %s Length: %d\n\tEntry: %s\n", + text, ipv4 ? "IPv4" : "IPv6", len, ip_options); + free(ip_options); + } else { + printf("%s No IP Options set\n", text); + } +} diff --git a/tests/sctp/sctp_common.h b/tests/sctp/sctp_common.h new file mode 100644 index 0000000..d5c1397 --- /dev/null +++ b/tests/sctp/sctp_common.h @@ -0,0 +1,27 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* For poll(2) POLLRDHUP - Detect client close(2) */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void print_context(int fd, char *text); +void print_addr_info(struct sockaddr *sin, char *text); +char *get_ip_option(int fd, bool ipv4, socklen_t *opt_len); +void print_ip_option(int fd, bool ipv4, char *text); diff --git a/tests/sctp/sctp_connectx.c b/tests/sctp/sctp_connectx.c new file mode 100644 index 0000000..18d133d --- /dev/null +++ b/tests/sctp/sctp_connectx.c @@ -0,0 +1,124 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] stream|seq addr port\n" + "\nWhere:\n\t" + "-v Print context information.\n\t" + "stream Use SCTP 1-to-1 style or:\n\t" + "seq use SCTP 1-to-Many style.\n\t" + "addr Servers IPv4 or IPv6 address.\n\t" + "port port.\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, type, srv_sock, client_sock, result, on = 1; + struct addrinfo srv_hints, client_hints, *srv_res, *client_res; + bool verbose = false; + char *context; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 3) + usage(argv[0]); + + if (!strcmp(argv[optind], "stream")) + type = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + type = SOCK_SEQPACKET; + else + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Process context: %s\n", context); + free(context); + } + + memset(&srv_hints, 0, sizeof(struct addrinfo)); + srv_hints.ai_flags = AI_PASSIVE; + srv_hints.ai_family = AF_INET6; + + srv_hints.ai_socktype = type; + srv_hints.ai_protocol = IPPROTO_SCTP; + + /* Set up server side */ + result = getaddrinfo(NULL, argv[optind + 2], &srv_hints, &srv_res); + if (result < 0) { + printf("getaddrinfo - server: %s\n", gai_strerror(result)); + exit(1); + } + + srv_sock = socket(srv_res->ai_family, srv_res->ai_socktype, + srv_res->ai_protocol); + if (srv_sock < 0) { + perror("socket - server"); + exit(1); + } + + if (verbose) + print_context(srv_sock, "Server"); + + result = setsockopt(srv_sock, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof(on)); + if (result < 0) { + perror("setsockopt: SO_REUSEADDR"); + close(srv_sock); + exit(1); + } + + result = bind(srv_sock, srv_res->ai_addr, srv_res->ai_addrlen); + if (result < 0) { + perror("bind"); + close(srv_sock); + exit(1); + } + + listen(srv_sock, 1); + + /* Set up client side */ + memset(&client_hints, 0, sizeof(struct addrinfo)); + client_hints.ai_socktype = type; + client_hints.ai_protocol = IPPROTO_SCTP; + result = getaddrinfo(argv[optind + 1], argv[optind + 2], + &client_hints, &client_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - client: %s\n", + gai_strerror(result)); + exit(1); + } + + client_sock = socket(client_res->ai_family, client_res->ai_socktype, + client_res->ai_protocol); + if (client_sock < 0) { + perror("socket - client"); + exit(1); + } + + if (verbose) + print_context(client_sock, "Client"); + + result = sctp_connectx(client_sock, client_res->ai_addr, 1, NULL); + if (result < 0) { + perror("connectx"); + close(srv_sock); + close(client_sock); + exit(1); + } + + close(srv_sock); + close(client_sock); + exit(0); +} diff --git a/tests/sctp/sctp_peeloff_server.c b/tests/sctp/sctp_peeloff_server.c new file mode 100644 index 0000000..eb198af --- /dev/null +++ b/tests/sctp/sctp_peeloff_server.c @@ -0,0 +1,260 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-4] [-i] [-n] [-v] port\n" + "\nWhere:\n\t" + "-4 Listen on IPv4 addresses only.\n\t" + "-i Send IP Options as msg (default is peer label).\n\t" + "-n No peer context will be available therefore send\n\t" + " \"nopeer\" message to client, otherwise the peer context\n\t" + " will be retrieved and sent to client.\n\t" + "-v Print context and ip options information.\n\t" + "port Listening port.\n", progname); + exit(1); +} + +static void set_subscr_events(int fd, int value) +{ + int result; + struct sctp_event_subscribe subscr_events; + + memset(&subscr_events, 0, sizeof(subscr_events)); + subscr_events.sctp_association_event = value; + /* subscr_events.sctp_data_io_event = value; */ + + result = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, + &subscr_events, sizeof(subscr_events)); + if (result < 0) { + perror("Server setsockopt: SCTP_EVENTS"); + close(fd); + exit(1); + } +} + +static sctp_assoc_t handle_event(void *buf) +{ + union sctp_notification *snp = buf; + struct sctp_assoc_change *sac; + + switch (snp->sn_header.sn_type) { + case SCTP_ASSOC_CHANGE: + sac = &snp->sn_assoc_change; + return sac->sac_assoc_id; + case SCTP_PEER_ADDR_CHANGE: + case SCTP_SEND_FAILED: + case SCTP_REMOTE_ERROR: + case SCTP_SHUTDOWN_EVENT: + case SCTP_PARTIAL_DELIVERY_EVENT: + case SCTP_ADAPTATION_INDICATION: + case SCTP_AUTHENTICATION_INDICATION: + case SCTP_SENDER_DRY_EVENT: + printf("Unrequested event: %x\n", snp->sn_header.sn_type); + break; + default: + printf("Unknown event: %x\n", snp->sn_header.sn_type); + break; + } + return -1; +} + +int main(int argc, char **argv) +{ + int opt, sock, result, peeloff_sk = 0, flags, on = 1; + sctp_assoc_t assoc_id; + socklen_t sinlen, opt_len; + struct sockaddr_storage sin; + struct addrinfo hints, *res; + char *peerlabel, *context, msglabel[256]; + bool nopeer = false, verbose = false, ipv4 = false, snd_opt = false; + unsigned short port; + + while ((opt = getopt(argc, argv, "4inv")) != -1) { + switch (opt) { + case '4': + ipv4 = true; + break; + case 'i': + snd_opt = true; + break; + case 'n': + nopeer = true; + break; + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 1) + usage(argv[0]); + + port = atoi(argv[optind]); + if (!port) + usage(argv[0]); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = IPPROTO_SCTP; + + if (ipv4) + hints.ai_family = AF_INET; + else + hints.ai_family = AF_INET6; + + /* sctp_peeloff(3) must be from 1 to Many style socket */ + hints.ai_socktype = SOCK_SEQPACKET; + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Server process context: %s\n", context); + free(context); + } + + result = getaddrinfo(NULL, argv[optind], &hints, &res); + if (result < 0) { + fprintf(stderr, "Server getaddrinfo: %s\n", + gai_strerror(result)); + exit(1); + } + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock < 0) { + perror("Server socket"); + exit(1); + } + + result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (result < 0) { + perror("Server setsockopt: SO_REUSEADDR"); + close(sock); + exit(1); + } + + result = bind(sock, res->ai_addr, res->ai_addrlen); + if (result < 0) { + perror("Server bind"); + close(sock); + exit(1); + } + + if (verbose) + print_context(sock, "Server LISTEN sock"); + + if (listen(sock, SOMAXCONN)) { + perror("Server listen"); + close(sock); + exit(1); + } + + do { + set_subscr_events(sock, 1); /* Get assoc_id for sctp_peeloff() */ + sinlen = sizeof(sin); + flags = 0; + + result = sctp_recvmsg(sock, msglabel, sizeof(msglabel), + (struct sockaddr *)&sin, &sinlen, + NULL, &flags); + if (result < 0) { + perror("Server sctp_recvmsg-1"); + close(sock); + exit(1); + } + + if (verbose) + print_addr_info((struct sockaddr *)&sin, + "Server SEQPACKET recvmsg"); + + if (flags & MSG_NOTIFICATION && flags & MSG_EOR) { + assoc_id = handle_event(msglabel); + if (assoc_id <= 0) { + printf("Server Invalid association ID: %d\n", + assoc_id); + close(sock); + exit(1); + } + /* No more notifications */ + set_subscr_events(sock, 0); + + peeloff_sk = sctp_peeloff(sock, assoc_id); + if (peeloff_sk < 0) { + perror("Server sctp_peeloff"); + close(sock); + exit(1); + } + if (verbose) { + printf("Server sctp_peeloff(3) on sk: %d with association ID: %d\n", + peeloff_sk, assoc_id); + print_context(peeloff_sk, "Server PEELOFF"); + } + + /* Now get the client msg on peeloff socket */ + result = sctp_recvmsg(peeloff_sk, msglabel, sizeof(msglabel), + (struct sockaddr *)&sin, &sinlen, + NULL, &flags); + if (result < 0) { + perror("Server sctp_recvmsg-2"); + close(peeloff_sk); + close(sock); + exit(1); + } + + if (verbose) + print_addr_info((struct sockaddr *)&sin, + "Server SEQPACKET peeloff recvmsg"); + } else { + printf("Invalid sctp_recvmsg response FLAGS: %x\n", + flags); + close(peeloff_sk); + close(sock); + exit(1); + } + + if (nopeer) { + peerlabel = strdup("nopeer"); + } else if (snd_opt) { + peerlabel = get_ip_option(sock, ipv4, &opt_len); + + if (!peerlabel) + peerlabel = strdup("no_ip_options"); + } else { + result = getpeercon(peeloff_sk, &peerlabel); + if (result < 0) { + perror("Server getpeercon"); + close(sock); + close(peeloff_sk); + exit(1); + } + } + + printf("Server PEELOFF %s: %s\n", + snd_opt ? "sock_opt" : "peer label", peerlabel); + + result = sctp_sendmsg(peeloff_sk, peerlabel, + strlen(peerlabel), + (struct sockaddr *)&sin, + sinlen, 0, 0, 0, 0, 0); + if (result < 0) { + perror("Server sctp_sendmsg"); + close(peeloff_sk); + close(sock); + exit(1); + } + + if (verbose) + printf("Server PEELOFF sent: %s\n", peerlabel); + + free(peerlabel); + + + + close(peeloff_sk); + } while (1); + + close(sock); + exit(0); +} diff --git a/tests/sctp/sctp_server.c b/tests/sctp/sctp_server.c new file mode 100644 index 0000000..a119f2d --- /dev/null +++ b/tests/sctp/sctp_server.c @@ -0,0 +1,335 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-4] [-b ipv4_addr] [-h addr] [-i] [-n] [-v] stream|seq port\n" + "\nWhere:\n\t" + "-4 Listen on IPv4 addresses only (used for CIPSO tests).\n\t" + "-b Call sctp_bindx(3) with the supplied IPv4 address.\n\t" + "-h IPv4 or IPv6 listen address. If IPv6 link-local address,\n\t" + " then requires the %% to obtain scopeid. e.g.\n\t" + " fe80::7629:afff:fe0f:8e5d%%wlp6s0\n\t" + "-i Send IP Options as msg (default is peer label).\n\t" + "-n No peer label or IP option will be available therefore\n\t" + " send \"nopeer\" message to client.\n\t" + "-v Print context and ip options information.\n\t" + "stream Use SCTP 1-to-1 style or:\n\t" + "seq use SCTP 1-to-Many style.\n\t" + "port Listening port.\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt, sock, newsock, result, flags, if_index = 0, on = 1; + socklen_t sinlen, opt_len; + struct sockaddr_storage sin; + struct addrinfo hints, *res; + struct sctp_sndrcvinfo sinfo; + struct pollfd poll_fd; + char getsockopt_peerlabel[1024]; + char byte, *peerlabel, msglabel[1024], if_name[30]; + bool nopeer = false, verbose = false, ipv4 = false, snd_opt = false; + char *context, *host_addr = NULL, *bindx_addr = NULL; + struct sockaddr_in ipv4_addr; + unsigned short port; + + while ((opt = getopt(argc, argv, "4b:h:inv")) != -1) { + switch (opt) { + case '4': + ipv4 = true; + break; + case 'b': + bindx_addr = optarg; + break; + case 'h': + host_addr = optarg; + break; + case 'i': + snd_opt = true; + break; + case 'n': + nopeer = true; + break; + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 2) + usage(argv[0]); + + port = atoi(argv[optind + 1]); + if (!port) + usage(argv[0]); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = IPPROTO_SCTP; + + if (ipv4) + hints.ai_family = AF_INET; + else + hints.ai_family = AF_INET6; + + if (!strcmp(argv[optind], "stream")) + hints.ai_socktype = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + hints.ai_socktype = SOCK_SEQPACKET; + else + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + printf("Server process context: %s\n", context); + free(context); + } + + if (host_addr) { + char *ptr; + + ptr = strpbrk(host_addr, "%"); + if (ptr) + strcpy(if_name, ptr + 1); + + if_index = if_nametoindex(if_name); + if (!if_index) { + perror("Server if_nametoindex"); + exit(1); + } + + result = getaddrinfo(host_addr, argv[optind + 1], + &hints, &res); + + } else { + result = getaddrinfo(NULL, argv[optind + 1], &hints, &res); + } + + if (result < 0) { + fprintf(stderr, "Server getaddrinfo: %s\n", + gai_strerror(result)); + exit(1); + } + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock < 0) { + perror("Server socket"); + exit(1); + } + + result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (result < 0) { + perror("Server setsockopt: SO_REUSEADDR"); + close(sock); + exit(1); + } + + /* Enables sctp_data_io_events for sctp_recvmsg(3) for assoc_id. */ + result = setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &on, sizeof(on)); + if (result < 0) { + perror("Server setsockopt: SCTP_EVENTS"); + close(sock); + exit(1); + } + + if (bindx_addr) { + memset(&ipv4_addr, 0, sizeof(struct sockaddr_in)); + ipv4_addr.sin_family = AF_INET; + ipv4_addr.sin_port = htons(port); + ipv4_addr.sin_addr.s_addr = inet_addr(bindx_addr); + + result = sctp_bindx(sock, (struct sockaddr *)&ipv4_addr, 1, + SCTP_BINDX_ADD_ADDR); + if (result < 0) { + perror("Server sctp_bindx ADD - ipv4"); + close(sock); + exit(1); + } + } else { + result = bind(sock, res->ai_addr, res->ai_addrlen); + if (result < 0) { + perror("Server bind"); + close(sock); + exit(1); + } + } + + if (verbose) { + print_context(sock, "Server LISTEN"); + print_ip_option(sock, ipv4, "Server LISTEN"); + } + + if (listen(sock, SOMAXCONN)) { + perror("Server listen"); + close(sock); + exit(1); + } + + if (hints.ai_socktype == SOCK_STREAM) { + if (verbose) + print_context(sock, "Server STREAM"); + + do { + socklen_t labellen = sizeof(getsockopt_peerlabel); + + sinlen = sizeof(sin); + + newsock = accept(sock, (struct sockaddr *)&sin, + &sinlen); + if (newsock < 0) { + perror("Server accept"); + close(sock); + exit(1); + } + + if (verbose) { + print_context(newsock, + "Server STREAM accept on newsock"); + print_addr_info((struct sockaddr *)&sin, + "Server connected to Client"); + print_ip_option(newsock, ipv4, + "Server STREAM accept on newsock"); + } + + if (nopeer) { + peerlabel = strdup("nopeer"); + } else if (snd_opt) { + peerlabel = get_ip_option(newsock, ipv4, + &opt_len); + if (!peerlabel) + peerlabel = strdup("no_ip_options"); + } else { + result = getpeercon(newsock, &peerlabel); + if (result < 0) { + perror("Server getpeercon"); + close(sock); + close(newsock); + exit(1); + } + + /* Also test the getsockopt version */ + result = getsockopt(newsock, SOL_SOCKET, + SO_PEERSEC, + getsockopt_peerlabel, + &labellen); + if (result < 0) { + perror("Server getsockopt: SO_PEERSEC"); + close(sock); + close(newsock); + exit(1); + } + if (verbose) + printf("Server STREAM SO_PEERSEC peer label: %s\n", + getsockopt_peerlabel); + } + printf("Server STREAM %s: %s\n", + snd_opt ? "sock_opt" : "peer label", peerlabel); + + result = read(newsock, &byte, 1); + if (result < 0) { + perror("Server read"); + close(sock); + close(newsock); + exit(1); + } + + result = write(newsock, peerlabel, strlen(peerlabel)); + if (result < 0) { + perror("Server write"); + close(sock); + close(newsock); + exit(1); + } + + if (verbose) + printf("Server STREAM sent: %s\n", peerlabel); + + free(peerlabel); + + /* Let the client close the connection first as this + * will stop OOTB chunks if newsock closed early. + */ + poll_fd.fd = newsock; + poll_fd.events = POLLRDHUP; + poll_fd.revents = 1; + result = poll(&poll_fd, 1, 1000); + if (verbose && result == 1) + printf("Server STREAM: Client closed connection\n"); + else if (verbose && result == 0) + printf("Server: poll(2) timed out - OKAY\n"); + else if (result < 0) + perror("Server - poll"); + + close(newsock); + } while (1); + } else { /* hints.ai_socktype == SOCK_SEQPACKET */ + if (verbose) + print_context(sock, "Server SEQPACKET sock"); + + do { + sinlen = sizeof(sin); + + result = sctp_recvmsg(sock, msglabel, sizeof(msglabel), + (struct sockaddr *)&sin, &sinlen, + &sinfo, &flags); + if (result < 0) { + perror("Server sctp_recvmsg"); + close(sock); + exit(1); + } + + if (verbose) { + print_context(sock, "Server SEQPACKET recvmsg"); + print_addr_info((struct sockaddr *)&sin, + "Server SEQPACKET recvmsg"); + print_ip_option(sock, ipv4, + "Server SEQPACKET recvmsg"); + } + + if (nopeer) { + peerlabel = strdup("nopeer"); + } else if (snd_opt) { + peerlabel = get_ip_option(sock, ipv4, &opt_len); + + if (!peerlabel) + peerlabel = strdup("no_ip_options"); + } else { + result = getpeercon(sock, &peerlabel); + if (result < 0) { + perror("Server getpeercon"); + close(sock); + exit(1); + } + } + printf("Server SEQPACKET %s: %s\n", + snd_opt ? "sock_opt" : "peer label", peerlabel); + + if (sin.ss_family == AF_INET6 && host_addr) + ((struct sockaddr_in6 *)&sin)->sin6_scope_id = if_index; + + result = sctp_sendmsg(sock, peerlabel, + strlen(peerlabel), + (struct sockaddr *)&sin, + sinlen, 0, 0, 0, 0, 0); + if (result < 0) { + perror("Server sctp_sendmsg"); + close(sock); + exit(1); + } + + if (verbose) + printf("Server SEQPACKET sent: %s\n", + peerlabel); + + free(peerlabel); + } while (1); + } + + close(sock); + exit(0); +} diff --git a/tests/sctp/sctp_set_params.c b/tests/sctp/sctp_set_params.c new file mode 100644 index 0000000..d4914bb --- /dev/null +++ b/tests/sctp/sctp_set_params.c @@ -0,0 +1,205 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] [-o aci|pap|pat] stream|seq addr port\n" + "\nWhere:\n\t" + "-v Print information.\n\t" + "-o Test setsockoption(3) using one of the following\n\t" + " options:\n\t\t" + " aci = SCTP_ASSOCINFO\n\t\t" + " pap = SCTP_PEER_ADDR_PARAMS\n\t\t" + " pat = SCTP_PEER_ADDR_THLDS\n\t\t" + "stream SCTP 1-to-1 style or:\n\t" + "seq SCTP 1-to-Many style.\n\t" + "addr Servers IPv4 or IPv6 address.\n\t" + "port port.\n", progname); + exit(1); +} + +/* Test set_param permission for SCTP_ASSOCINFO */ +static void sctp_associnfo(int sk, int option) +{ + int result; + socklen_t len; + struct sctp_assocparams assocparams; + + memset(&assocparams, 0, sizeof(struct sctp_assocparams)); + + len = sizeof(struct sctp_assocparams); + result = getsockopt(sk, IPPROTO_SCTP, option, &assocparams, &len); + if (result < 0) { + perror("getsockopt: SCTP_ASSOCINFO"); + close(sk); + exit(1); + } + + assocparams.sasoc_asocmaxrxt += 5; + assocparams.sasoc_cookie_life += 15; + + result = setsockopt(sk, IPPROTO_SCTP, option, &assocparams, len); + if (result < 0) { + perror("setsockopt: SCTP_ASSOCINFO"); + close(sk); + exit(1); + } +} + + +/* Test set_param permission for SCTP_PEER_ADDR_PARAMS */ +static void sctp_peer_addr_params(int sk, int option) +{ + int result; + struct sctp_paddrparams heartbeat; + + memset(&heartbeat, 0, sizeof(struct sctp_paddrparams)); + heartbeat.spp_flags = SPP_HB_ENABLE; + heartbeat.spp_hbinterval = 100; + heartbeat.spp_pathmaxrxt = 1; + + result = setsockopt(sk, IPPROTO_SCTP, option, + &heartbeat, sizeof(heartbeat)); + if (result < 0) { + perror("setsockopt: SCTP_PEER_ADDR_PARAMS"); + close(sk); + exit(1); + } +} + +int main(int argc, char **argv) +{ + int opt, type, srv_sock, client_sock, result, sockoption = 0; + struct addrinfo srv_hints, client_hints, *srv_res, *client_res; + bool verbose = false; + char *context; + + while ((opt = getopt(argc, argv, "o:v")) != -1) { + switch (opt) { + case 'o': + if (!strcmp(optarg, "aci")) + sockoption = SCTP_ASSOCINFO; + else if (!strcmp(optarg, "pap")) + sockoption = SCTP_PEER_ADDR_PARAMS; + else if (!strcmp(optarg, "pat")) { + printf("SCTP_PEER_ADDR_THLDS not currently supported by userspace\n"); + exit(1); + } else + usage(argv[0]); + break; + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 3) + usage(argv[0]); + + if (!strcmp(argv[optind], "stream")) + type = SOCK_STREAM; + else if (!strcmp(argv[optind], "seq")) + type = SOCK_SEQPACKET; + else + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + + printf("Process context: %s\n", context); + free(context); + } + + memset(&srv_hints, 0, sizeof(struct addrinfo)); + srv_hints.ai_flags = AI_PASSIVE; + srv_hints.ai_family = AF_INET6; + + srv_hints.ai_socktype = type; + srv_hints.ai_protocol = IPPROTO_SCTP; + + /* Set up server side */ + result = getaddrinfo(NULL, argv[optind + 2], &srv_hints, &srv_res); + if (result < 0) { + printf("getaddrinfo - server: %s\n", gai_strerror(result)); + exit(1); + } + + srv_sock = socket(srv_res->ai_family, srv_res->ai_socktype, + srv_res->ai_protocol); + if (srv_sock < 0) { + perror("socket - server"); + exit(1); + } + + if (verbose) + print_context(srv_sock, "Server"); + + if (bind(srv_sock, srv_res->ai_addr, srv_res->ai_addrlen) < 0) { + perror("bind"); + close(srv_sock); + exit(1); + } + + listen(srv_sock, 1); + + /* Set up client side */ + memset(&client_hints, 0, sizeof(struct addrinfo)); + client_hints.ai_socktype = type; + client_hints.ai_protocol = IPPROTO_SCTP; + result = getaddrinfo(argv[optind + 1], argv[optind + 2], + &client_hints, &client_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - client: %s\n", + gai_strerror(result)); + exit(1); + } + + client_sock = socket(client_res->ai_family, client_res->ai_socktype, + client_res->ai_protocol); + if (client_sock < 0) { + perror("socket - client"); + exit(1); + } + + if (verbose) + print_context(client_sock, "Client"); + + result = sctp_connectx(client_sock, client_res->ai_addr, 1, NULL); + if (result < 0) { + perror("connectx"); + close(client_sock); + exit(1); + } + + if (sockoption) { + switch (sockoption) { + case SCTP_ASSOCINFO: + if (verbose) + printf("Testing: SCTP_ASSOCINFO\n"); + sctp_associnfo(srv_sock, sockoption); + break; + case SCTP_PEER_ADDR_PARAMS: + if (verbose) + printf("Testing: SCTP_PEER_ADDR_PARAMS\n"); + sctp_peer_addr_params(client_sock, sockoption); + break; + } + } else { + + if (verbose) + printf("Testing: SCTP_ASSOCINFO\n"); + sctp_associnfo(srv_sock, SCTP_ASSOCINFO); + + if (verbose) + printf("Testing: SCTP_PEER_ADDR_PARAMS\n"); + sctp_peer_addr_params(client_sock, SCTP_PEER_ADDR_PARAMS); + + } + + close(srv_sock); + close(client_sock); + exit(0); +} diff --git a/tests/sctp/sctp_set_peer_addr.c b/tests/sctp/sctp_set_peer_addr.c new file mode 100644 index 0000000..61a3a44 --- /dev/null +++ b/tests/sctp/sctp_set_peer_addr.c @@ -0,0 +1,414 @@ +/* + * This test will allow the server side to add/remove bindx addresses and + * inform the client side via ASCONF chunks. It will also allow the server + * side to inform the client that the peer primary address is being updated. + * The code for checking these parameters are in net/sctp/sm_make_chunk.c + * sctp_process_asconf_param(). + * + * To enable the processing of these incoming ASCONF parameters for: + * SCTP_PARAM_SET_PRIMARY, SCTP_PARAM_ADD_IP and SCTP_PARAM_DEL_IP + * the following options must be enabled: + * echo 1 > /proc/sys/net/sctp/addip_enable + * echo 1 > /proc/sys/net/sctp/addip_noauth_enable + * + * If these are not enabled the SCTP_SET_PEER_PRIMARY_ADDR setsockopt + * fails with EPERM "Operation not permitted", however the bindx calls + * will complete but the client side will not be informed. + * + * NOTES: + * 1) SCTP_SET_PEER_PRIMARY_ADDR requires a non-loopback IP address. + * 2) Both addresses MUST be the same type (i.e. IPv4 or IPv6). + */ + +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s -v addr new_pri_addr port\n" + "\nWhere:\n\t" + "-v Print status information.\n\t" + "addr IPv4/IPv6 address for initial connection.\n\t" + "new_pri_addr IPv4/IPv6 address that the server will bindx\n\t" + " then set to the new SCTP_PRIMARY_ADDR.\n\t" + "port port.\n", progname); + fprintf(stderr, + "Notes:\n\t" + "1) addr and new_pri_addr MUST NOT be loopback addresses.\n\t" + "2) addr and new_pri_addr MUST be same type (IPv4 or IPv6).\n\t" + "3) IPv6 link-local addresses require the %% to\n\t" + " obtain scopeid. e.g. fe80::7629:afff:fe0f:8e5d%%wlp6s0\n"); + exit(1); +} + +static int peer_count, peer_count_err; + +static void getpaddrs_alarm(int sig) +{ + fprintf(stderr, "Get peer address count timer expired - carry on test\n"); + peer_count += 1; + peer_count_err = true; +} + +static void getprimaddr_alarm(int sig) +{ + fprintf(stderr, "Get primary address timer expired - end test.\n"); + exit(1); +} + +static void print_primaddr(char *msg, int socket) +{ + int result; + struct sctp_prim prim; + struct sockaddr_in *in_addr; + struct sockaddr_in6 *in6_addr; + struct sockaddr *paddr; + socklen_t prim_len; + char addr_buf[INET6_ADDRSTRLEN]; + const char *addr_ptr = NULL; + + memset(&prim, 0, sizeof(struct sctp_prim)); + + prim_len = sizeof(struct sctp_prim); + result = getsockopt(socket, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, + &prim, &prim_len); + if (result < 0) { + perror("getsockopt: SCTP_PRIMARY_ADDR"); + exit(1); + } + + paddr = (struct sockaddr *)&prim.ssp_addr; + if (paddr->sa_family == AF_INET) { + in_addr = (struct sockaddr_in *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET, &in_addr->sin_addr, addr_buf, + INET6_ADDRSTRLEN); + } else if (paddr->sa_family == AF_INET6) { + in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET6, &in6_addr->sin6_addr, addr_buf, + INET6_ADDRSTRLEN); + } + + if (!addr_ptr) { + perror("inet_ntop"); + exit(1); + } + + printf("%s SCTP_PRIMARY_ADDR: %s\n", msg, addr_ptr); +} + +static void get_primaddr(char *addr_buf, int socket) +{ + int result; + struct sctp_prim prim; + struct sockaddr_in *in_addr; + struct sockaddr_in6 *in6_addr; + struct sockaddr *paddr; + socklen_t prim_len; + const char *addr_ptr = NULL; + + memset(&prim, 0, sizeof(struct sctp_prim)); + prim_len = sizeof(struct sctp_prim); + result = getsockopt(socket, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, + &prim, &prim_len); + if (result < 0) { + perror("getsockopt: SCTP_PRIMARY_ADDR"); + exit(1); + } + + paddr = (struct sockaddr *)&prim.ssp_addr; + if (paddr->sa_family == AF_INET) { + in_addr = (struct sockaddr_in *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET, &in_addr->sin_addr, addr_buf, + INET6_ADDRSTRLEN); + } else if (paddr->sa_family == AF_INET6) { + in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr; + addr_ptr = inet_ntop(AF_INET6, &in6_addr->sin6_addr, addr_buf, + INET6_ADDRSTRLEN); + } + if (!addr_ptr) { + perror("inet_ntop"); + exit(1); + } +} + +int main(int argc, char **argv) +{ + int opt, srv_sock, client_sock, new_sock, result, on = 1; + struct addrinfo srv_hints, client_hints, *srv_res, *client_res; + struct addrinfo *new_pri_addr_res; + struct sockaddr *sa_ptr, *paddrs; + socklen_t sinlen; + struct sockaddr_storage sin; + struct sctp_setpeerprim setpeerprim; + bool verbose = false, is_ipv6 = false; + char client_prim_addr[INET6_ADDRSTRLEN]; + char client_prim_new_pri_addr[INET6_ADDRSTRLEN]; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 3) + usage(argv[0]); + + if (strchr(argv[optind], ':') && strchr(argv[optind + 1], ':')) { + is_ipv6 = true; + srv_hints.ai_family = AF_INET6; + } else if (strchr(argv[optind], '.') && + strchr(argv[optind + 1], '.')) { + is_ipv6 = false; + srv_hints.ai_family = AF_INET; + } else { + usage(argv[0]); + } + + memset(&srv_hints, 0, sizeof(struct addrinfo)); + srv_hints.ai_flags = AI_PASSIVE; + srv_hints.ai_socktype = SOCK_STREAM; + srv_hints.ai_protocol = IPPROTO_SCTP; + + /* Set up server side */ + result = getaddrinfo(argv[optind], argv[optind + 2], + &srv_hints, &srv_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - server: %s\n", + gai_strerror(result)); + exit(1); + } + + result = getaddrinfo(argv[optind], argv[optind + 2], + &srv_hints, &srv_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - server: %s\n", + gai_strerror(result)); + exit(1); + } + if (is_ipv6 && verbose) + printf("Server scopeID: %d\n", + ((struct sockaddr_in6 *) + srv_res->ai_addr)->sin6_scope_id); + + srv_sock = socket(srv_res->ai_family, srv_res->ai_socktype, + srv_res->ai_protocol); + if (srv_sock < 0) { + perror("socket - server"); + exit(1); + } + + result = setsockopt(srv_sock, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); + if (result < 0) { + perror("setsockopt: SO_REUSEADDR"); + close(srv_sock); + exit(1); + } + + result = bind(srv_sock, srv_res->ai_addr, srv_res->ai_addrlen); + if (result < 0) { + perror("bind"); + close(srv_sock); + exit(1); + } + + listen(srv_sock, 1); + + /* Set up client side and connect */ + memset(&client_hints, 0, sizeof(struct addrinfo)); + client_hints.ai_socktype = SOCK_STREAM; + client_hints.ai_protocol = IPPROTO_SCTP; + result = getaddrinfo(argv[optind], argv[optind + 2], + &client_hints, &client_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - client: %s\n", + gai_strerror(result)); + close(srv_sock); + exit(1); + } + if (is_ipv6 && verbose) + printf("Client scopeID: %d\n", + ((struct sockaddr_in6 *) + client_res->ai_addr)->sin6_scope_id); + + client_sock = socket(client_res->ai_family, client_res->ai_socktype, + client_res->ai_protocol); + if (client_sock < 0) { + perror("socket - client"); + close(srv_sock); + exit(1); + } + + result = connect(client_sock, client_res->ai_addr, + client_res->ai_addrlen); + if (result < 0) { + if (errno != EINPROGRESS) + perror("connect"); + else + fprintf(stderr, "connect timeout\n"); + result = 1; + goto err2; + } + + /* Obtain address info for the BINDX_ADD and new SCTP_PRIMARY_ADDR. */ + result = getaddrinfo(argv[optind + 1], argv[optind + 2], + &client_hints, &new_pri_addr_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - new SCTP_PRIMARY_ADDR: %s\n", + gai_strerror(result)); + close(srv_sock); + exit(1); + } + if (is_ipv6 && verbose) + printf("new_pri_addr scopeID: %d\n", + ((struct sockaddr_in6 *) + new_pri_addr_res->ai_addr)->sin6_scope_id); + + /* Get number of peer addresses on CLIENT (should be 1) for a check + * later as sctp_bindx SERVER -> CLIENT is non-blocking. + */ + peer_count = sctp_getpaddrs(client_sock, 0, &paddrs); + sctp_freepaddrs(paddrs); + if (verbose) + printf("Client peer address count: %d\n", peer_count); + + /* Client and server now set so accept new socket on server side. */ + new_sock = accept(srv_sock, (struct sockaddr *)&sin, &sinlen); + if (new_sock < 0) { + perror("accept"); + result = 1; + goto err2; + } + + /* Get initial CLIENT primary address (that should be ADDR1). */ + get_primaddr(client_prim_addr, client_sock); + + /* Now call sctp_bindx to add new_pri_addr, this will cause an + * ASCONF - SCTP_PARAM_ADD_IP chunk to be sent to the CLIENT. + * This is non-blocking so there maybe a delay before the CLIENT + * receives the asconf chunk. + */ + if (verbose) + printf("Calling sctp_bindx ADD: %s\n", argv[optind + 1]); + + result = sctp_bindx(new_sock, + (struct sockaddr *)new_pri_addr_res->ai_addr, + 1, SCTP_BINDX_ADD_ADDR); + if (result < 0) { + if (errno == EACCES) { + perror("sctp_bindx ADD"); + } else { + perror("sctp_bindx ADD"); + result = 1; + goto err1; + } + } + /* so set an alarm and check number of peer addresses for CLIENT. */ + signal(SIGALRM, getpaddrs_alarm); + alarm(2); + peer_count_err = false; + result = 0; + + while (result != peer_count + 1) { + result = sctp_getpaddrs(client_sock, 0, &paddrs); + sctp_freepaddrs(paddrs); + + if (peer_count_err) + break; + } + peer_count = result; + + if (verbose) + printf("Client peer address count: %d\n", result); + + /* Now that the CLIENT has the new primary address ensure they use + * it by SCTP_SET_PEER_PRIMARY_ADDR. + */ + memset(&setpeerprim, 0, sizeof(struct sctp_setpeerprim)); + sa_ptr = (struct sockaddr *)&setpeerprim.sspp_addr; + if (is_ipv6) + memcpy(sa_ptr, new_pri_addr_res->ai_addr, + sizeof(struct sockaddr_in6)); + else + memcpy(sa_ptr, new_pri_addr_res->ai_addr, + sizeof(struct sockaddr_in)); + + if (verbose) + printf("Calling setsockopt SCTP_SET_PEER_PRIMARY_ADDR: %s\n", + argv[optind + 1]); + + result = setsockopt(new_sock, IPPROTO_SCTP, + SCTP_SET_PEER_PRIMARY_ADDR, + &setpeerprim, sizeof(struct sctp_setpeerprim)); + if (result < 0) { + perror("setsockopt: SCTP_SET_PEER_PRIMARY_ADDR"); + result = 1; + goto err1; + } + + /* Now get the new primary address from the client */ + signal(SIGALRM, getprimaddr_alarm); + alarm(2); + memcpy(client_prim_new_pri_addr, client_prim_addr, INET6_ADDRSTRLEN); + + while (!strcmp(client_prim_addr, client_prim_new_pri_addr)) + get_primaddr(client_prim_new_pri_addr, client_sock); + + if (verbose) { + printf("Client initial SCTP_PRIMARY_ADDR: %s\n", + client_prim_addr); + print_primaddr("Server", new_sock); + printf("Client current SCTP_PRIMARY_ADDR: %s\n", + client_prim_new_pri_addr); + } + + /* Then delete addr1 that checks ASCONF - SCTP_PARAM_DEL_IP. */ + if (verbose) + printf("Calling sctp_bindx REM: %s\n", argv[optind]); + + result = sctp_bindx(new_sock, (struct sockaddr *)client_res->ai_addr, + 1, SCTP_BINDX_REM_ADDR); + if (result < 0) { + perror("sctp_bindx - REM"); + result = 1; + goto err1; + } + + if (!peer_count_err) { + alarm(2); + result = 0; + + while (result != peer_count - 1) { + result = sctp_getpaddrs(client_sock, 0, &paddrs); + sctp_freepaddrs(paddrs); + } + + if (verbose) + printf("Client peer address count: %d\n", result); + } + + /* Compare the client primary addresses, they should be different. */ + if (!strcmp(client_prim_addr, client_prim_new_pri_addr)) { + fprintf(stderr, + "Client addr: %s same as new_pri_addr: %s - SCTP_SET_PEER_PRIMARY_ADDR failed\n", + client_prim_addr, client_prim_new_pri_addr); + result = 1; + goto err1; + } + + if (verbose) + printf("Client primary address changed successfully.\n"); + + result = 0; + +err1: + close(new_sock); +err2: + close(srv_sock); + close(client_sock); + exit(result); +} diff --git a/tests/sctp/sctp_set_pri_addr.c b/tests/sctp/sctp_set_pri_addr.c new file mode 100644 index 0000000..5122001 --- /dev/null +++ b/tests/sctp/sctp_set_pri_addr.c @@ -0,0 +1,135 @@ +#include "sctp_common.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] addr port\n" + "\nWhere:\n\t" + "-v Print information.\n\t" + "addr Servers IPv4 or IPv6 address.\n\t" + "port port.\n", progname); + exit(1); +} + +static void sctp_primary_addr(int sk, int option) +{ + int result; + socklen_t len; + struct sctp_prim primaddr; + + memset(&primaddr, 0, sizeof(struct sctp_prim)); + + len = sizeof(struct sctp_prim); + result = getsockopt(sk, IPPROTO_SCTP, option, + &primaddr, &len); + if (result < 0) { + perror("getsockopt: SCTP_PRIMARY_ADDR"); + close(sk); + exit(1); + } + + result = setsockopt(sk, IPPROTO_SCTP, option, &primaddr, len); + if (result < 0) { + perror("setsockopt: SCTP_PRIMARY_ADDR"); + close(sk); + exit(1); + } +} + +int main(int argc, char **argv) +{ + int opt, srv_sock, client_sock, result; + struct addrinfo srv_hints, client_hints, *srv_res, *client_res; + bool verbose = false; + char *context; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 2) + usage(argv[0]); + + if (verbose) { + if (getcon(&context) < 0) + context = strdup("unavailable"); + + printf("Process context: %s\n", context); + free(context); + } + + memset(&srv_hints, 0, sizeof(struct addrinfo)); + srv_hints.ai_flags = AI_PASSIVE; + srv_hints.ai_family = AF_INET6; + + srv_hints.ai_socktype = SOCK_STREAM; + srv_hints.ai_protocol = IPPROTO_SCTP; + + /* Set up server side */ + result = getaddrinfo(NULL, argv[optind + 1], &srv_hints, &srv_res); + if (result < 0) { + printf("getaddrinfo - server: %s\n", gai_strerror(result)); + exit(1); + } + + srv_sock = socket(srv_res->ai_family, srv_res->ai_socktype, + srv_res->ai_protocol); + if (srv_sock < 0) { + perror("socket - server"); + exit(1); + } + + if (verbose) + print_context(srv_sock, "Server"); + + if (bind(srv_sock, srv_res->ai_addr, srv_res->ai_addrlen) < 0) { + perror("bind"); + close(srv_sock); + exit(1); + } + + listen(srv_sock, 1); + + /* Set up client side */ + memset(&client_hints, 0, sizeof(struct addrinfo)); + client_hints.ai_socktype = SOCK_STREAM; + client_hints.ai_protocol = IPPROTO_SCTP; + result = getaddrinfo(argv[optind], argv[optind + 1], &client_hints, + &client_res); + if (result < 0) { + fprintf(stderr, "getaddrinfo - client: %s\n", + gai_strerror(result)); + exit(1); + } + + client_sock = socket(client_res->ai_family, client_res->ai_socktype, + client_res->ai_protocol); + if (client_sock < 0) { + perror("socket - client"); + exit(1); + } + + if (verbose) + print_context(client_sock, "Client"); + + result = sctp_connectx(client_sock, client_res->ai_addr, 1, NULL); + if (result < 0) { + perror("connectx"); + close(client_sock); + exit(1); + } + + if (verbose) + printf("Testing: SCTP_PRIMARY_ADDR\n"); + sctp_primary_addr(client_sock, SCTP_PRIMARY_ADDR); + + close(srv_sock); + close(client_sock); + exit(0); +} diff --git a/tests/sctp/test b/tests/sctp/test new file mode 100755 index 0000000..d375cab --- /dev/null +++ b/tests/sctp/test @@ -0,0 +1,814 @@ +#!/usr/bin/perl +use Test::More; + +BEGIN { + $basedir = $0; + $basedir =~ s|(.*)/[^/]*|$1|; + + # allow SCTP info to be shown during tests + $v = $ARGV[0]; + if ($v) { + if ( $v ne "-v" ) { + plan skip_all => "Invalid option (use -v)"; + } + } + else { + $v = " "; + } + + # check if sctp enabled + if ( system("checksctp 2> /dev/null") != 0 ) { + plan skip_all => "SCTP not supported"; + } + else { + $test_count = 71; + + # asconf parameter tests require two local non-loopback addresses. + $ipaddress_list = `ip -o addr show up scope global`; + $test_asconf = 0; + $count = 0; + $ipaddress[0] = 0; + $ipaddress[1] = 0; + + for my $line ( split /\n/, $ipaddress_list ) { + if ( $line =~ /inet ([^ \/]+)/ && $count < 2 ) { + $ipaddress[$count] = $1; + } + $count++; + } + + if ( $ipaddress[1] ne 0 ) { + $test_count += 2; + $test_asconf = 1; + } + + # Determine if CALIPSO supported by netlabelctl(8) and kernel. + $test_calipso = 0; + $netlabelctl = `netlabelctl -V`; + $netlabelctl =~ s/\D//g; + $kvercur = `uname -r`; + chomp($kvercur); + $kvermincalipso = "4.8"; + + $rc = `$basedir/../kvercmp $kvercur $kvermincalipso`; + if ( $netlabelctl gt "021" && $rc > 0 ) { + $test_count += 13; + $test_calipso = 1; + } + + plan tests => $test_count; + } +} + +# +# NOTE: direction flow is given as Client->Server (STREAM->SEQ) +# + +# +########################## Test base configuration ########################## +# +print "# Testing base configuration.\n"; + +# Start the stream server. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v -n stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using connect(2). +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using sctp_connectx(3). +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -x -e nopeer stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server SEQ->STREAM with no client connect(2). +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -n -e nopeer seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server SEQ->STREAM. +$result = system + "runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer seq ::1 1035"; +ok( $result eq 0 ); + +######## This test requires setting a portcon statement in policy ########### +# Verify that the client cannot communicate with server when using port not allowed STREAM->STREAM. +# Note that the sctp_test policy only allows ports 1024-65535 +$result = system +"runcon -t test_sctp_client_t -- $basedir/sctp_client $v -e nopeer stream ::1 1023 2>&1"; +ok( $result >> 8 eq 8 ); + +# Kill the stream server. +kill TERM, $pid; + +######## This test requires setting a portcon statement in policy ########### +# Verify that the server cannot start when using port not allowed STREAM->STREAM. +# Note that the sctp_test policy only allows ports 1024-65535 +$result = + system "runcon -t test_sctp_server_t -- $basedir/sctp_bind $v stream 80 2>&1"; +ok($result); + +# +############################### CONNECTX ##################################### +# +print "# Testing connectx.\n"; + +$result = system +"runcon -t test_sctp_connectx_t $basedir/sctp_connectx $v stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +$result = + system + "runcon -t test_sctp_connectx_t $basedir/sctp_connectx $v seq ::1 1035"; +ok( $result eq 0 ); + +# +################################ BINDX ####################################### +# +print "# Testing bindx.\n"; + +$result = + system "runcon -t test_sctp_bindx_t $basedir/sctp_bindx $v -r stream 1035"; +ok( $result eq 0 ); + +$result = + system "runcon -t test_sctp_bindx_t $basedir/sctp_bindx $v -r seq 1035"; +ok( $result eq 0 ); + +# +######################### SET_PRI_ADDR SET_PEER_ADDR ######################## +# + +# These tests require two local non-loopback addresses. +if ($test_asconf) { + print "# Testing asconf parameter chunk processing.\n"; + + # To enable processing of incoming ASCONF parameters: + # SCTP_PARAM_SET_PRIMARY, SCTP_PARAM_ADD_IP and SCTP_PARAM_DEL_IP, + # need to set: + system("echo 1 > /proc/sys/net/sctp/addip_enable"); + system("echo 1 > /proc/sys/net/sctp/addip_noauth_enable"); + + # Verify ASCONF params. + $result = system +"runcon -t test_sctp_set_peer_addr_t $basedir/sctp_set_peer_addr $v $ipaddress[0] $ipaddress[1] 1035"; + ok( $result eq 0 ); + + # Start the asconf server. + if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_set_peer_addr_t $basedir/sctp_asconf_params_server $v $ipaddress[0] $ipaddress[1] 1035"; + } + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# This should fail connect permission attempting to send SCTP_PARAM_ADD_IP to client. + $result = system +"runcon -t test_sctp_client_t -- $basedir/sctp_asconf_params_client $v $ipaddress[0] 1035 2>&1"; + ok($result); + + # The server should automatically exit. + kill TERM, $pid; + + system("echo 0 > /proc/sys/net/sctp/addip_enable"); + system("echo 0 > /proc/sys/net/sctp/addip_noauth_enable"); +} + +# +######################## Test NetLabel Configurations ####################### +# +########################## Fallback peer Labeling ############################ +# + +# Load NetLabel configuration using "netlabel_sctp_peer_t" as the label. +print "# Testing NetLabel fallback peer labeling.\n"; +system "/bin/sh $basedir/fb-label-load"; + +# Start stream server. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server SEQ->STREAM. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start seq server. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 seq ::1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->SEQ. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 stream ::1 1035"; +ok( $result eq 0 ); + +# Verify that a client using connect(2) without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 seq ::1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Verify that a client using sctp_connectx(3) without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -x -e system_u:object_r:netlabel_sctp_peer_t:s0 seq ::1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Verify that a client not using any connect without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -n -e system_u:object_r:netlabel_sctp_peer_t:s0 seq ::1 1035 2>&1"; +ok( $result >> 8 eq 13 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/fb-label-flush"; + +# +#################### Test deny association permission ######################## +# +print "# Testing deny association.\n"; +system "/bin/sh $basedir/fb-deny-label-load"; + +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server STREAM->STREAM. +# This sets the servers initial peer context to netlabel_sctp_peer_t:s0 +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e system_u:object_r:netlabel_sctp_peer_t:s0 stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that the server is denied this association as the client will timeout on connect. +$result = system +"runcon -t test_sctp_client_t -- $basedir/sctp_client $v -e system_u:object_r:deny_assoc_sctp_peer_t:s0 stream ::1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/fb-deny-label-flush"; + +# +############################## CIPSO/IPv4 TAG 1 ############################### +# +print "# Testing CIPSO/IPv4 - TAG 1 using socket ip_option data\n"; +system "/bin/sh $basedir/cipso-load-t1"; + +# Start the stream server for IPv4 only. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c182.c192 $basedir/sctp_server $v -4 -i stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using sctp_connectx(3). +$result = system +"runcon -t test_sctp_client_t -l s0:c182.c192 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using connect(2). +$result = system +"runcon -t test_sctp_client_t -l s0:c182.c192 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c182,c187,c190 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level SEQ->STREAM +$result = system +"runcon -t test_sctp_client_t -l s0:c189,c192 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client cannot communicate with the server using invalid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c182.c193 -- $basedir/sctp_client $v stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start the seq server. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c20.c300 $basedir/sctp_server $v -i -4 seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server. SEQ->SEQ +$result = system +"runcon -t test_sctp_client_t -l s0:c27.c28 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c30 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using SEQ->SEQ with diff valid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c24,c26,c27.c29 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using SEQ->SEQ with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c19.c100 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# TAG 1 allows categories 0 to 239 to be sent, if greater then ENOSPC (No space left on device) +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c300 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 7 ); + +# Kill server. +kill TERM, $pid; + +print "# Testing CIPSO/IPv4 - TAG 1 PEELOFF using socket ip_option data\n"; + +# Test sctp_peeloff(3) using 1 to Many SOCK_SEQPACKET +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c0.c10 $basedir/sctp_peeloff_server $v -4 -i 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server using SEQ->SEQ->Peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ->peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using STREAM->SEQ->peeloff with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c11 -- $basedir/sctp_client $v -x -i stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/cipso-flush"; + +# +############################## CIPSO/IPv4 TAG 2 ############################### +# +print "# Testing CIPSO/IPv4 - TAG 2 using socket ip_option data\n"; +system "/bin/sh $basedir/cipso-load-t2"; + +# Start the stream server for IPv4 only. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_server $v -4 -i stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using sctp_connectx(3). +$result = system +"runcon -t test_sctp_client_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using connect(2). +$result = system +"runcon -t test_sctp_client_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c769,c788,c803,c842,c864 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level SEQ->STREAM +$result = system +"runcon -t test_sctp_client_t -l s0:c769,c788,c803 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client cannot communicate with the server using invalid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c1023 -- $basedir/sctp_client $v stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start the seq server. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c20.c335 $basedir/sctp_server $v -i -4 seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server. SEQ->SEQ +$result = system +"runcon -t test_sctp_client_t -l s0:c328.c333 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c34 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using SEQ->SEQ with diff valid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c30,c31,c335 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using SEQ->SEQ with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c19.c30 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# TAG 2 allows a maximum of 15 categories in exchange, if greater then ENOSPC (No space left on device) +$result = system +"runcon -t test_sctp_client_t -l s0:c200.c216 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 7 ); + +# Kill server. +kill TERM, $pid; + +print "# Testing CIPSO/IPv4 - TAG 2 PEELOFF using socket ip_option data\n"; + +# Test sctp_peeloff(3) using 1 to Many SOCK_SEQPACKET +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c0.c10 $basedir/sctp_peeloff_server $v -4 -i 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server using SEQ->SEQ->Peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ->peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using STREAM->SEQ->peeloff with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c11 -- $basedir/sctp_client $v -x -i stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/cipso-flush"; + +# +############################## CIPSO/IPv4 TAG 5 ############################### +# +print "# Testing CIPSO/IPv4 - TAG 5 using socket ip_option data\n"; +system "/bin/sh $basedir/cipso-load-t5"; + +# Start the stream server for IPv4 only. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_server $v -4 -i stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using sctp_connectx(3). +$result = system +"runcon -t test_sctp_client_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using connect(2). +$result = system +"runcon -t test_sctp_client_t -l s0:c782,c714,c769,c788,c803,c842,c864 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c769,c788,c803,c842,c864 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level SEQ->STREAM +$result = system +"runcon -t test_sctp_client_t -l s0:c769,c788,c803 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client cannot communicate with the server using invalid level STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t -l s0:c1023 -- $basedir/sctp_client $v stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start the seq server. +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c20.c50 $basedir/sctp_server $v -i -4 seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server. SEQ->SEQ +$result = system +"runcon -t test_sctp_client_t -l s0:c28.c48 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c50 $basedir/sctp_client $v -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using SEQ->SEQ with diff valid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c30,c31,c35,c40.c45 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using SEQ->SEQ with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c20.c51 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# TAG 2 allows a maximum of 7 ranges in exchange, if greater then ENOSPC (No space left on device) +$result = system +"runcon -t test_sctp_client_t -l s0:c20,c22,c24,c30.c33,c38,c42.c45,c48,c50 -- $basedir/sctp_client $v -i seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 7 ); + +# Kill server. +kill TERM, $pid; + +print "# Testing CIPSO/IPv4 - TAG 5 PEELOFF using socket ip_option data\n"; + +# Test sctp_peeloff(3) using 1 to Many SOCK_SEQPACKET +if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c0.c10 $basedir/sctp_peeloff_server $v -4 -i 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server using SEQ->SEQ->Peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -i seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ->peeloff with same level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -x -i stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using STREAM->SEQ->peeloff with invalid level. +$result = system +"runcon -t test_sctp_client_t -l s0:c0.c11 -- $basedir/sctp_client $v -x -i stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/cipso-flush"; + +# +################## CIPSO/IPv4 Full Labeling over Loopback #################### +# + +print "# Testing CIPSO/IPv4 full labeling over loopback.\n"; +system "/bin/sh $basedir/cipso-fl-load"; + +# Start the stream server for IPv4 only. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v -4 stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM. +$result = system + "runcon -t test_sctp_client_t $basedir/sctp_client $v stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify a client without peer { recv } for client/server process cannot communicate with server STREAM->STREAM. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start the seq server for IPv4 only. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v -4 seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server SEQ->STREAM. +$result = + system + "runcon -t test_sctp_client_t $basedir/sctp_client $v seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/cipso-fl-flush"; + +# +############################### CALIPSO/IPv6 ################################# +# + +if ($test_calipso) { + print "# Testing CALIPSO/IPv6 using socket ip_option data\n"; + system "/bin/sh $basedir/calipso-load"; + + # Start the stream server. + if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c0,c12,c24,c36,c28,c610,c712,c414,c516,c318,c820,c622,c924,c726,c128,c330,c832,c534,c936,c138,c740,c42,c44,c246,c648,c950,c152,c354,c856,c158,c960,c662,c634,c686,c368,c570,c782,c714,c769,c788,c803,c842,c864,c986,c788,c290,c392,c594,c896,c698,c1023 $basedir/sctp_server $v -i stream 1035"; + } + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using sctp_connectx(3). + $result = system +"runcon -t test_sctp_client_t -l s0:c0,c12,c24,c36,c28,c610,c712,c414,c516,c318,c820,c622,c924,c726,c128,c330,c832,c534,c936,c138,c740,c42,c44,c246,c648,c950,c152,c354,c856,c158,c960,c662,c634,c686,c368,c570,c782,c714,c769,c788,c803,c842,c864,c986,c788,c290,c392,c594,c896,c698,c1023 $basedir/sctp_client $v -x -i stream ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM with client using connect(2). + $result = system +"runcon -t test_sctp_client_t -l s0:c0,c12,c24,c36,c28,c610,c712,c414,c516,c318,c820,c622,c924,c726,c128,c330,c832,c534,c936,c138,c740,c42,c44,c246,c648,c950,c152,c354,c856,c158,c960,c662,c634,c686,c368,c570,c782,c714,c769,c788,c803,c842,c864,c986,c788,c290,c392,c594,c896,c698,c1023 $basedir/sctp_client $v -i stream ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level STREAM->STREAM. + $result = system +"runcon -t test_sctp_client_t -l s0:c924,c726,c128,c330,c832,c534,c936,c138,c740,c42 $basedir/sctp_client $v -i stream ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using different valid level SEQ->STREAM + $result = system +"runcon -t test_sctp_client_t -l s0:c924,c726,c128,c330,c832,c534,c936,c138,c740,c42 $basedir/sctp_client $v -i seq ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client cannot communicate with the server using invalid level STREAM->STREAM. + $result = system +"runcon -t test_sctp_client_t -l s0:c8.c12 -- $basedir/sctp_client $v -i stream ::1 1035 2>&1"; + ok( $result >> 8 eq 6 ); + + # Kill the stream server. + kill TERM, $pid; + + # Start the seq server. + if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c20.c50 $basedir/sctp_server $v -i seq 1035"; + } + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + + # Verify that authorized client can communicate with the server. SEQ->SEQ + $result = system +"runcon -t test_sctp_client_t -l s0:c28.c48 $basedir/sctp_client $v -i seq ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ. + $result = system +"runcon -t test_sctp_client_t -l s0:c20.c50 $basedir/sctp_client $v -i stream ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using SEQ->SEQ with diff valid level. + $result = system +"runcon -t test_sctp_client_t -l s0:c20.c30,c31,c35,c40.c45 $basedir/sctp_client $v -i seq ::1 1035"; + ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using SEQ->SEQ with invalid level. + $result = system +"runcon -t test_sctp_client_t -l s0:c20.c51 $basedir/sctp_client $v -i seq ::1 1035 2>&1"; + ok( $result >> 8 eq 6 ); + +# Verify that client cannot communicate with the server using SEQ->SEQ with invalid level. + $result = system +"runcon -t test_sctp_client_t -l s0:c19.c50 -- $basedir/sctp_client $v -i seq ::1 1035 2>&1"; + ok( $result >> 8 eq 6 ); + + # Kill server. + kill TERM, $pid; + + print "# Testing CALIPSO/IPv6 PEELOFF using socket ip_option data\n"; + + # Test sctp_peeloff(3) using 1 to Many SOCK_SEQPACKET + if ( ( $pid = fork() ) == 0 ) { + exec +"runcon -t test_sctp_server_t -l s0:c0.c10 $basedir/sctp_peeloff_server $v -i 1035"; + } + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize + +# Verify that authorized client can communicate with the server using SEQ->SEQ->Peeloff with same level. + $result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -i seq ::1 1035"; + ok( $result eq 0 ); + +# Verify that authorized client can communicate with the server using STREAM->SEQ->peeloff with same level. + $result = system +"runcon -t test_sctp_client_t -l s0:c0.c10 $basedir/sctp_client $v -x -i stream ::1 1035"; + ok( $result eq 0 ); + +# Verify that client cannot communicate with the server using STREAM->SEQ->peeloff with invalid level. + $result = system +"runcon -t test_sctp_client_t -l s0:c0.c11 -- $basedir/sctp_client $v -x -i stream ::1 1035 2>&1"; + ok( $result >> 8 eq 6 ); + + # Kill the seq server. + kill TERM, $pid; + + system "/bin/sh $basedir/calipso-flush"; +} + +# +##################### Test iptables configuration ############################ +# +print "# Testing iptables (IPv4/IPv6).\n"; +system "/bin/sh $basedir/iptables-load"; + +# Start the stream server. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v -n stream 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer stream 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e nopeer stream 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Verify that authorized client can communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer stream ::1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server STREAM->STREAM. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e nopeer stream ::1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the stream server. +kill TERM, $pid; + +# Start the seq server. +if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_sctp_server_t $basedir/sctp_server $v -n seq 1035"; +} +select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer seq 127.0.0.1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e nopeer seq 127.0.0.1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Verify that authorized client can communicate with the server SEQ->SEQ. +$result = system + "runcon -t test_sctp_client_t $basedir/sctp_client $v -e nopeer seq ::1 1035"; +ok( $result eq 0 ); + +# Verify that a client without peer { recv } permission cannot communicate with the server SEQ->SEQ. +$result = system +"runcon -t test_sctp_deny_peer_client_t -- $basedir/sctp_client $v -e nopeer seq ::1 1035 2>&1"; +ok( $result >> 8 eq 6 ); + +# Kill the seq server. +kill TERM, $pid; + +system "/bin/sh $basedir/iptables-flush"; + +exit;