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