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