1 /* 2 * lib/netfilter/nfnl.c Netfilter Netlink 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf (at) suug.ch> 10 * Copyright (c) 2007 Philip Craig <philipc (at) snapgear.com> 11 * Copyright (c) 2007 Secure Computing Corporation 12 */ 13 14 /** 15 * @defgroup nfnl Netfilter Netlink 16 * 17 * @par Message Format 18 * @code 19 * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> 20 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 21 * | Header | Pad | Payload | Pad | 22 * | struct nlmsghdr | | | | 23 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 24 * @endcode 25 * @code 26 * <-------- NFNL_HDRLEN ---------> 27 * +--------------------------+- - -+------------+ 28 * | Netfilter Netlink Header | Pad | Attributes | 29 * | struct nfgenmsg | | | 30 * +--------------------------+- - -+------------+ 31 * nfnlmsg_attrdata(nfg, hdrlen)-----^ 32 * @endcode 33 * 34 * @par 1) Creating a new netfilter netlink message 35 * @code 36 * struct nl_msg *msg; 37 * 38 * // Create a new empty netlink message 39 * msg = nlmsg_alloc(); 40 * 41 * // Append the netlink and netfilter netlink message header 42 * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO, 43 * FAMILY, RES_ID); 44 * 45 * // Append the attributes. 46 * nla_put_u32(msg, 1, 0x10); 47 * 48 * // Message is ready to be sent. 49 * nl_send_auto_complete(sk, msg); 50 * 51 * // All done? Free the message. 52 * nlmsg_free(msg); 53 * @endcode 54 * 55 * @par 2) Sending of trivial messages 56 * @code 57 * // For trivial messages not requiring any subsys specific header or 58 * // attributes, nfnl_send_simple() may be used to send messages directly. 59 * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID); 60 * @endcode 61 * @{ 62 */ 63 64 #include <netlink-local.h> 65 #include <netlink/netlink.h> 66 #include <netlink/netfilter/nfnl.h> 67 68 /** 69 * @name Socket Creating 70 * @{ 71 */ 72 73 /** 74 * Create and connect netfilter netlink socket. 75 * @arg sk Netlink socket. 76 * 77 * Creates a NETLINK_NETFILTER netlink socket, binds the socket and 78 * issues a connection attempt. 79 * 80 * @see nl_connect() 81 * 82 * @return 0 on success or a negative error code. 83 */ 84 int nfnl_connect(struct nl_sock *sk) 85 { 86 return nl_connect(sk, NETLINK_NETFILTER); 87 } 88 89 /** @} */ 90 91 /** 92 * @name Sending 93 * @{ 94 */ 95 96 /** 97 * Send trivial netfilter netlink message 98 * @arg sk Netlink socket. 99 * @arg subsys_id nfnetlink subsystem 100 * @arg type nfnetlink message type 101 * @arg flags message flags 102 * @arg family nfnetlink address family 103 * @arg res_id nfnetlink resource id 104 * 105 * @return Newly allocated netlink message or NULL. 106 */ 107 int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, 108 int flags, uint8_t family, uint16_t res_id) 109 { 110 struct nfgenmsg hdr = { 111 .nfgen_family = family, 112 .version = NFNETLINK_V0, 113 .res_id = htons(res_id), 114 }; 115 116 return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags, 117 &hdr, sizeof(hdr)); 118 } 119 120 /** @} */ 121 122 /** 123 * @name Message Parsing 124 * @{ 125 */ 126 127 /** 128 * Get netfilter subsystem id from message 129 * @arg nlh netlink messsage header 130 */ 131 uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh) 132 { 133 return NFNL_SUBSYS_ID(nlh->nlmsg_type); 134 } 135 136 /** 137 * Get netfilter message type from message 138 * @arg nlh netlink messsage header 139 */ 140 uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh) 141 { 142 return NFNL_MSG_TYPE(nlh->nlmsg_type); 143 } 144 145 /** 146 * Get netfilter family from message 147 * @arg nlh netlink messsage header 148 */ 149 uint8_t nfnlmsg_family(struct nlmsghdr *nlh) 150 { 151 struct nfgenmsg *nfg = nlmsg_data(nlh); 152 153 return nfg->nfgen_family; 154 } 155 156 /** 157 * Get netfilter resource id from message 158 * @arg nlh netlink messsage header 159 */ 160 uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh) 161 { 162 struct nfgenmsg *nfg = nlmsg_data(nlh); 163 164 return ntohs(nfg->res_id); 165 } 166 167 /** @} */ 168 169 /** 170 * @name Message Building 171 * @{ 172 */ 173 174 static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id) 175 { 176 struct nfgenmsg *nfg; 177 178 nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO); 179 if (nfg == NULL) 180 return -NLE_NOMEM; 181 182 nfg->nfgen_family = family; 183 nfg->version = NFNETLINK_V0; 184 nfg->res_id = htons(res_id); 185 NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n", 186 msg, family, res_id); 187 return 0; 188 } 189 190 /** 191 * Allocate a new netfilter netlink message 192 * @arg subsys_id nfnetlink subsystem 193 * @arg type nfnetlink message type 194 * @arg flags message flags 195 * @arg family nfnetlink address family 196 * @arg res_id nfnetlink resource id 197 * 198 * @return Newly allocated netlink message or NULL. 199 */ 200 struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, 201 uint8_t family, uint16_t res_id) 202 { 203 struct nl_msg *msg; 204 205 msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags); 206 if (msg == NULL) 207 return NULL; 208 209 if (nfnlmsg_append(msg, family, res_id) < 0) 210 goto nla_put_failure; 211 212 return msg; 213 214 nla_put_failure: 215 nlmsg_free(msg); 216 return NULL; 217 } 218 219 /** 220 * Add netlink and netfilter netlink headers to netlink message 221 * @arg msg netlink message 222 * @arg pid netlink process id 223 * @arg seq sequence number of message 224 * @arg subsys_id nfnetlink subsystem 225 * @arg type nfnetlink message type 226 * @arg flags message flags 227 * @arg family nfnetlink address family 228 * @arg res_id nfnetlink resource id 229 */ 230 int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, 231 uint8_t subsys_id, uint8_t type, int flags, uint8_t family, 232 uint16_t res_id) 233 { 234 struct nlmsghdr *nlh; 235 236 nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags); 237 if (nlh == NULL) 238 return -NLE_MSGSIZE; 239 240 return nfnlmsg_append(msg, family, res_id); 241 } 242 243 /** @} */ 244 245 /** @} */ 246