00001 /* 00002 * lib/netfilter/nfnl.c Netfilter Netlink 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> 00011 * Copyright (c) 2007 Secure Computing Corporation 00012 */ 00013 00014 /** 00015 * @ingroup nlfam 00016 * @defgroup nfnl Netfilter Netlink 00017 * 00018 * @par Message Format 00019 * @code 00020 * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> 00021 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 00022 * | Header | Pad | Payload | Pad | 00023 * | struct nlmsghdr | | | | 00024 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 00025 * @endcode 00026 * @code 00027 * <-------- NFNL_HDRLEN ---------> 00028 * +--------------------------+- - -+------------+ 00029 * | Netfilter Netlink Header | Pad | Attributes | 00030 * | struct nfgenmsg | | | 00031 * +--------------------------+- - -+------------+ 00032 * nfnlmsg_attrdata(nfg, hdrlen)-----^ 00033 * @endcode 00034 * 00035 * @par 1) Creating a new netfilter netlink message 00036 * @code 00037 * struct nl_msg *msg; 00038 * 00039 * // Create a new empty netlink message 00040 * msg = nlmsg_alloc(); 00041 * 00042 * // Append the netlink and netfilter netlink message header 00043 * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO, 00044 * FAMILY, RES_ID); 00045 * 00046 * // Append the attributes. 00047 * nla_put_u32(msg, 1, 0x10); 00048 * 00049 * // Message is ready to be sent. 00050 * nl_send_auto_complete(nl_handle, msg); 00051 * 00052 * // All done? Free the message. 00053 * nlmsg_free(msg); 00054 * @endcode 00055 * 00056 * @par 2) Sending of trivial messages 00057 * @code 00058 * // For trivial messages not requiring any subsys specific header or 00059 * // attributes, nfnl_send_simple() may be used to send messages directly. 00060 * nfnl_send_simple(nl_handle, SUBSYS, TYPE, 0, FAMILY, RES_ID); 00061 * @endcode 00062 * @{ 00063 */ 00064 00065 #include <netlink-local.h> 00066 #include <netlink/netlink.h> 00067 #include <netlink/netfilter/nfnl.h> 00068 00069 /** 00070 * @name Socket Creating 00071 * @{ 00072 */ 00073 00074 /** 00075 * Create and connect netfilter netlink socket. 00076 * @arg handle Netlink handle. 00077 * 00078 * Creates a NETLINK_NETFILTER netlink socket, binds the socket and 00079 * issues a connection attempt. 00080 * 00081 * @see nl_connect() 00082 * 00083 * @return 0 on success or a negative error code. 00084 */ 00085 int nfnl_connect(struct nl_handle *handle) 00086 { 00087 return nl_connect(handle, NETLINK_NETFILTER); 00088 } 00089 00090 /** @} */ 00091 00092 /** 00093 * @name Sending 00094 * @{ 00095 */ 00096 00097 /** 00098 * Send trivial netfilter netlink message 00099 * @arg handle Netlink handle. 00100 * @arg subsys_id nfnetlink subsystem 00101 * @arg type nfnetlink message type 00102 * @arg flags message flags 00103 * @arg family nfnetlink address family 00104 * @arg res_id nfnetlink resource id 00105 * 00106 * @return Newly allocated netlink message or NULL. 00107 */ 00108 int nfnl_send_simple(struct nl_handle *handle, uint8_t subsys_id, uint8_t type, 00109 int flags, uint8_t family, uint16_t res_id) 00110 { 00111 struct nfgenmsg hdr = { 00112 .nfgen_family = family, 00113 .version = NFNETLINK_V0, 00114 .res_id = htons(res_id), 00115 }; 00116 00117 return nl_send_simple(handle, NFNLMSG_TYPE(subsys_id, type), flags, 00118 &hdr, sizeof(hdr)); 00119 } 00120 00121 /** @} */ 00122 00123 /** 00124 * @name Message Parsing 00125 * @{ 00126 */ 00127 00128 /** 00129 * Get netfilter subsystem id from message 00130 * @arg nlh netlink messsage header 00131 */ 00132 uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh) 00133 { 00134 return NFNL_SUBSYS_ID(nlh->nlmsg_type); 00135 } 00136 00137 /** 00138 * Get netfilter message type from message 00139 * @arg nlh netlink messsage header 00140 */ 00141 uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh) 00142 { 00143 return NFNL_MSG_TYPE(nlh->nlmsg_type); 00144 } 00145 00146 /** 00147 * Get netfilter family from message 00148 * @arg nlh netlink messsage header 00149 */ 00150 uint8_t nfnlmsg_family(struct nlmsghdr *nlh) 00151 { 00152 struct nfgenmsg *nfg = nlmsg_data(nlh); 00153 00154 return nfg->nfgen_family; 00155 } 00156 00157 /** 00158 * Get netfilter resource id from message 00159 * @arg nlh netlink messsage header 00160 */ 00161 uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh) 00162 { 00163 struct nfgenmsg *nfg = nlmsg_data(nlh); 00164 00165 return ntohs(nfg->res_id); 00166 } 00167 00168 /** @} */ 00169 00170 /** 00171 * @name Message Building 00172 * @{ 00173 */ 00174 00175 static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id) 00176 { 00177 struct nfgenmsg *nfg; 00178 00179 nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO); 00180 if (nfg == NULL) 00181 return nl_errno(ENOMEM); 00182 00183 nfg->nfgen_family = family; 00184 nfg->version = NFNETLINK_V0; 00185 nfg->res_id = htons(res_id); 00186 NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n", 00187 msg, family, res_id); 00188 return 0; 00189 } 00190 00191 /** 00192 * Allocate a new netfilter netlink message 00193 * @arg subsys_id nfnetlink subsystem 00194 * @arg type nfnetlink message type 00195 * @arg flags message flags 00196 * @arg family nfnetlink address family 00197 * @arg res_id nfnetlink resource id 00198 * 00199 * @return Newly allocated netlink message or NULL. 00200 */ 00201 struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, 00202 uint8_t family, uint16_t res_id) 00203 { 00204 struct nl_msg *msg; 00205 00206 msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags); 00207 if (msg == NULL) 00208 return NULL; 00209 00210 if (nfnlmsg_append(msg, family, res_id) < 0) 00211 goto nla_put_failure; 00212 00213 return msg; 00214 00215 nla_put_failure: 00216 nlmsg_free(msg); 00217 return NULL; 00218 } 00219 00220 /** 00221 * Add netlink and netfilter netlink headers to netlink message 00222 * @arg msg netlink message 00223 * @arg pid netlink process id 00224 * @arg seq sequence number of message 00225 * @arg subsys_id nfnetlink subsystem 00226 * @arg type nfnetlink message type 00227 * @arg flags message flags 00228 * @arg family nfnetlink address family 00229 * @arg res_id nfnetlink resource id 00230 */ 00231 int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, 00232 uint8_t subsys_id, uint8_t type, int flags, uint8_t family, 00233 uint16_t res_id) 00234 { 00235 struct nlmsghdr *nlh; 00236 00237 nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags); 00238 if (nlh == NULL) 00239 return nl_get_errno(); 00240 00241 return nfnlmsg_append(msg, family, res_id); 00242 } 00243 00244 /** @} */ 00245 00246 /** @} */