libnl 1.1
lib/netfilter/nfnl.c
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 /** @} */