144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/netfilter/nfnl.c Netfilter Netlink 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Secure Computing Corporation 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup nfnl Netfilter Netlink 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Message Format 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * | Header | Pad | Payload | Pad | 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * | struct nlmsghdr | | | | 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * <-------- NFNL_HDRLEN ---------> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * +--------------------------+- - -+------------+ 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * | Netfilter Netlink Header | Pad | Attributes | 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * | struct nfgenmsg | | | 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * +--------------------------+- - -+------------+ 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * nfnlmsg_attrdata(nfg, hdrlen)-----^ 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Creating a new netfilter netlink message 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_msg *msg; 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Create a new empty netlink message 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf * msg = nlmsg_alloc(); 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Append the netlink and netfilter netlink message header 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO, 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * FAMILY, RES_ID); 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Append the attributes. 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * nla_put_u32(msg, 1, 0x10); 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Message is ready to be sent. 491155370f520cb64657e25153255cf7dc1424317fThomas Graf * nl_send_auto_complete(sk, msg); 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // All done? Free the message. 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * nlmsg_free(msg); 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 2) Sending of trivial messages 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // For trivial messages not requiring any subsys specific header or 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // attributes, nfnl_send_simple() may be used to send messages directly. 591155370f520cb64657e25153255cf7dc1424317fThomas Graf * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID); 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/nfnl.h> 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Socket Creating 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Create and connect netfilter netlink socket. 751155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Creates a NETLINK_NETFILTER netlink socket, binds the socket and 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * issues a connection attempt. 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see nl_connect() 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 841155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_connect(struct nl_sock *sk) 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 861155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_connect(sk, NETLINK_NETFILTER); 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Sending 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Send trivial netfilter netlink message 981155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id nfnetlink subsystem 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type nfnetlink message type 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags message flags 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family nfnetlink address family 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id nfnetlink resource id 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated netlink message or NULL. 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1071155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf int flags, uint8_t family, uint16_t res_id) 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfgenmsg hdr = { 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf .nfgen_family = family, 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf .version = NFNETLINK_V0, 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf .res_id = htons(res_id), 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf 1161155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags, 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf &hdr, sizeof(hdr)); 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Parsing 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter subsystem id from message 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh netlink messsage header 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 13144d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_subsys(struct nlmsghdr *nlh) 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNL_SUBSYS_ID(nlh->nlmsg_type); 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter message type from message 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh netlink messsage header 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 14044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_subtype(struct nlmsghdr *nlh) 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNL_MSG_TYPE(nlh->nlmsg_type); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter family from message 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh netlink messsage header 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 14944d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_family(struct nlmsghdr *nlh) 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfgenmsg *nfg = nlmsg_data(nlh); 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf return nfg->nfgen_family; 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter resource id from message 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh netlink messsage header 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 16044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint16_t nfnlmsg_res_id(struct nlmsghdr *nlh) 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfgenmsg *nfg = nlmsg_data(nlh); 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf return ntohs(nfg->res_id); 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Building 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf 17444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id) 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfgenmsg *nfg; 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO); 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nfg == NULL) 1808a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf nfg->nfgen_family = family; 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf nfg->version = NFNETLINK_V0; 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf nfg->res_id = htons(res_id); 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n", 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf msg, family, res_id); 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new netfilter netlink message 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id nfnetlink subsystem 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type nfnetlink message type 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags message flags 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family nfnetlink address family 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id nfnetlink resource id 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated netlink message or NULL. 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 20044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf uint8_t family, uint16_t res_id) 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags); 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (msg == NULL) 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nfnlmsg_append(msg, family, res_id) < 0) 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf return msg; 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf 21444d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add netlink and netfilter netlink headers to netlink message 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg msg netlink message 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg pid netlink process id 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg seq sequence number of message 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id nfnetlink subsystem 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type nfnetlink message type 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags message flags 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family nfnetlink address family 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id nfnetlink resource id 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 23044d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf uint8_t subsys_id, uint8_t type, int flags, uint8_t family, 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t res_id) 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlmsghdr *nlh; 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags); 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlh == NULL) 2388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf return nfnlmsg_append(msg, family, res_id); 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 246