Home | History | Annotate | Download | only in netfilter
      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-2012 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 Library (libnl-nf)
     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-private/netlink.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