1 /* 2 * Copyright (c) 2017, 2018 Chen Jingpiao <chenjingpiao (at) gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "tests.h" 29 30 #ifdef HAVE_LINUX_NETFILTER_NFNETLINK_H 31 32 # include <stdio.h> 33 # include <string.h> 34 # include <unistd.h> 35 # include <netinet/in.h> 36 # include <arpa/inet.h> 37 # include <sys/socket.h> 38 # include "test_netlink.h" 39 # include <linux/netfilter/nfnetlink.h> 40 # ifdef HAVE_LINUX_NETFILTER_NF_TABLES_H 41 # include <linux/netfilter/nf_tables.h> 42 # endif 43 44 # ifndef NFNETLINK_V0 45 # define NFNETLINK_V0 0 46 # endif 47 # ifndef NFNL_SUBSYS_NFTABLES 48 # define NFNL_SUBSYS_NFTABLES 10 49 # endif 50 # ifndef NFT_MSG_NEWTABLE 51 # define NFT_MSG_NEWTABLE 0 52 # endif 53 54 static void 55 test_nlmsg_type(const int fd) 56 { 57 long rc; 58 struct nlmsghdr nlh = { 59 .nlmsg_len = sizeof(nlh), 60 .nlmsg_flags = NLM_F_REQUEST, 61 }; 62 63 # ifdef NFNL_MSG_BATCH_BEGIN 64 nlh.nlmsg_type = NFNL_MSG_BATCH_BEGIN; 65 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); 66 printf("sendto(%d, {len=%u, type=NFNL_MSG_BATCH_BEGIN" 67 ", flags=NLM_F_REQUEST, seq=0, pid=0}" 68 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", 69 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); 70 # endif 71 72 nlh.nlmsg_type = NFNL_SUBSYS_CTNETLINK << 8 | 0xff; 73 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); 74 printf("sendto(%d, {len=%u" 75 ", type=NFNL_SUBSYS_CTNETLINK<<8|0xff /* IPCTNL_MSG_CT_??? */" 76 ", flags=NLM_F_REQUEST, seq=0, pid=0}" 77 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", 78 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); 79 80 nlh.nlmsg_type = 0xffff; 81 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); 82 printf("sendto(%d, {len=%u, type=0xff /* NFNL_SUBSYS_??? */<<8|0xff" 83 ", flags=NLM_F_REQUEST, seq=0, pid=0}" 84 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", 85 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); 86 } 87 88 static void 89 test_nlmsg_done(const int fd) 90 { 91 const int num = 0xabcdefad; 92 void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(num)); 93 94 TEST_NETLINK(fd, nlh0, NLMSG_DONE, NLM_F_REQUEST, 95 sizeof(num), &num, sizeof(num), 96 printf("%d", num)); 97 } 98 99 static void 100 test_nfgenmsg(const int fd) 101 { 102 static const struct nlattr nla = { 103 .nla_len = sizeof(nla), 104 .nla_type = 0x0bcd 105 }; 106 107 struct nfgenmsg msg = { 108 .nfgen_family = AF_UNIX, 109 .version = NFNETLINK_V0, 110 .res_id = NFNL_SUBSYS_NFTABLES 111 }; 112 char str_buf[NLMSG_ALIGN(sizeof(msg)) + 4]; 113 char nla_buf[NLMSG_ALIGN(sizeof(msg)) + sizeof(nla)]; 114 115 void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, 116 MAX(sizeof(str_buf), sizeof(nla_buf))); 117 118 TEST_NETLINK_OBJECT_EX_(fd, nlh0, 119 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE, 120 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE", 121 NLM_F_REQUEST, "NLM_F_REQUEST", 122 msg, print_quoted_hex, 123 printf("{nfgen_family=AF_UNIX"); 124 printf(", version=NFNETLINK_V0"); 125 printf(", res_id="); 126 if (htons(NFNL_SUBSYS_NFTABLES) == NFNL_SUBSYS_NFTABLES) 127 printf("htons(NFNL_SUBSYS_NFTABLES)"); 128 else 129 printf("NFNL_SUBSYS_NFTABLES"); 130 ); 131 132 msg.res_id = htons(NFNL_SUBSYS_NFTABLES); 133 TEST_NETLINK_(fd, nlh0, 134 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE, 135 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE", 136 NLM_F_REQUEST, "NLM_F_REQUEST", 137 sizeof(msg), &msg, sizeof(msg), 138 printf("{nfgen_family=AF_UNIX"); 139 printf(", version=NFNETLINK_V0"); 140 printf(", res_id=htons(NFNL_SUBSYS_NFTABLES)")); 141 142 msg.res_id = htons(0xabcd); 143 TEST_NETLINK_(fd, nlh0, 144 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE, 145 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE", 146 NLM_F_REQUEST, "NLM_F_REQUEST", 147 sizeof(msg), &msg, sizeof(msg), 148 printf("{nfgen_family=AF_UNIX"); 149 printf(", version=NFNETLINK_V0"); 150 printf(", res_id=htons(%d)", 0xabcd)); 151 152 # ifdef NFNL_MSG_BATCH_BEGIN 153 msg.res_id = htons(NFNL_SUBSYS_NFTABLES); 154 TEST_NETLINK(fd, nlh0, 155 NFNL_MSG_BATCH_BEGIN, NLM_F_REQUEST, 156 sizeof(msg), &msg, sizeof(msg), 157 printf("{nfgen_family=AF_UNIX"); 158 printf(", version=NFNETLINK_V0"); 159 printf(", res_id=htons(%d)", NFNL_SUBSYS_NFTABLES)); 160 161 msg.res_id = htons(0xabcd); 162 memcpy(str_buf, &msg, sizeof(msg)); 163 memcpy(str_buf + NLMSG_ALIGN(sizeof(msg)), "1234", 4); 164 165 TEST_NETLINK(fd, nlh0, 166 NFNL_MSG_BATCH_BEGIN, NLM_F_REQUEST, 167 sizeof(str_buf), str_buf, sizeof(str_buf), 168 printf("{nfgen_family=AF_UNIX"); 169 printf(", version=NFNETLINK_V0"); 170 printf(", res_id=htons(%d)" 171 ", \"\\x31\\x32\\x33\\x34\"", 0xabcd)); 172 # endif /* NFNL_MSG_BATCH_BEGIN */ 173 174 msg.res_id = htons(NFNL_SUBSYS_NFTABLES); 175 memcpy(nla_buf, &msg, sizeof(msg)); 176 memcpy(nla_buf + NLMSG_ALIGN(sizeof(msg)), &nla, sizeof(nla)); 177 178 TEST_NETLINK_(fd, nlh0, 179 NFNL_SUBSYS_NFTABLES << 8 | 0xff, 180 "NFNL_SUBSYS_NFTABLES<<8|0xff /* NFT_MSG_??? */", 181 NLM_F_REQUEST, "NLM_F_REQUEST", 182 sizeof(nla_buf), nla_buf, sizeof(nla_buf), 183 printf("{nfgen_family=AF_UNIX"); 184 printf(", version=NFNETLINK_V0"); 185 printf(", res_id=htons(NFNL_SUBSYS_NFTABLES)" 186 ", {nla_len=%d, nla_type=%#x}", 187 nla.nla_len, nla.nla_type)); 188 } 189 190 int main(void) 191 { 192 skip_if_unavailable("/proc/self/fd/"); 193 194 int fd = create_nl_socket(NETLINK_NETFILTER); 195 196 test_nlmsg_type(fd); 197 test_nlmsg_done(fd); 198 test_nfgenmsg(fd); 199 200 printf("+++ exited with 0 +++\n"); 201 202 return 0; 203 } 204 205 #else 206 207 SKIP_MAIN_UNDEFINED("HAVE_LINUX_NETFILTER_NFNETLINK_H") 208 209 #endif 210