libnl 1.1
lib/netfilter/log.c
00001 /*
00002  * lib/netfilter/log.c  Netfilter Log
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 nfnl
00016  * @defgroup log Log
00017  * @brief
00018  * @{
00019  */
00020 
00021 #include <sys/types.h>
00022 #include <linux/netfilter/nfnetlink_log.h>
00023 
00024 #include <netlink-local.h>
00025 #include <netlink/attr.h>
00026 #include <netlink/netfilter/nfnl.h>
00027 #include <netlink/netfilter/log.h>
00028 
00029 static struct nl_cache_ops nfnl_log_ops;
00030 
00031 #if __BYTE_ORDER == __BIG_ENDIAN
00032 static uint64_t ntohll(uint64_t x)
00033 {
00034         return x;
00035 }
00036 #elif __BYTE_ORDER == __LITTLE_ENDIAN
00037 static uint64_t ntohll(uint64_t x)
00038 {
00039         return __bswap_64(x);
00040 }
00041 #endif
00042 
00043 static struct nla_policy log_policy[NFULA_MAX+1] = {
00044         [NFULA_PACKET_HDR]              = {
00045                 .minlen = sizeof(struct nfulnl_msg_packet_hdr)
00046         },
00047         [NFULA_MARK]                    = { .type = NLA_U32 },
00048         [NFULA_TIMESTAMP]               = {
00049                 .minlen = sizeof(struct nfulnl_msg_packet_timestamp)
00050         },
00051         [NFULA_IFINDEX_INDEV]           = { .type = NLA_U32 },
00052         [NFULA_IFINDEX_OUTDEV]          = { .type = NLA_U32 },
00053         [NFULA_IFINDEX_PHYSINDEV]       = { .type = NLA_U32 },
00054         [NFULA_IFINDEX_PHYSOUTDEV]      = { .type = NLA_U32 },
00055         [NFULA_HWADDR]                  = {
00056                 .minlen = sizeof(struct nfulnl_msg_packet_hw)
00057         },
00058         //[NFULA_PAYLOAD]
00059         [NFULA_PREFIX]                  = { .type = NLA_STRING, },
00060         [NFULA_UID]                     = { .type = NLA_U32 },
00061         [NFULA_SEQ]                     = { .type = NLA_U32 },
00062         [NFULA_SEQ_GLOBAL]              = { .type = NLA_U32 },
00063 };
00064 
00065 struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *nlh)
00066 {
00067         struct nfnl_log *log;
00068         struct nlattr *tb[NFULA_MAX+1];
00069         struct nlattr *attr;
00070         int err;
00071 
00072         log = nfnl_log_alloc();
00073         if (!log)
00074                 return NULL;
00075 
00076         log->ce_msgtype = nlh->nlmsg_type;
00077 
00078         err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
00079                           log_policy);
00080         if (err < 0)
00081                 goto errout;
00082 
00083         nfnl_log_set_family(log, nfnlmsg_family(nlh));
00084 
00085         attr = tb[NFULA_PACKET_HDR];
00086         if (attr) {
00087                 struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
00088 
00089                 nfnl_log_set_hwproto(log, hdr->hw_protocol);
00090                 nfnl_log_set_hook(log, hdr->hook);
00091         }
00092 
00093         attr = tb[NFULA_MARK];
00094         if (attr)
00095                 nfnl_log_set_mark(log, ntohl(nla_get_u32(attr)));
00096 
00097         attr = tb[NFULA_TIMESTAMP];
00098         if (attr) {
00099                 struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr);
00100                 struct timeval tv;
00101 
00102                 tv.tv_sec = ntohll(timestamp->sec);
00103                 tv.tv_usec = ntohll(timestamp->usec);
00104                 nfnl_log_set_timestamp(log, &tv);
00105         }
00106 
00107         attr = tb[NFULA_IFINDEX_INDEV];
00108         if (attr)
00109                 nfnl_log_set_indev(log, ntohl(nla_get_u32(attr)));
00110 
00111         attr = tb[NFULA_IFINDEX_OUTDEV];
00112         if (attr)
00113                 nfnl_log_set_outdev(log, ntohl(nla_get_u32(attr)));
00114 
00115         attr = tb[NFULA_IFINDEX_PHYSINDEV];
00116         if (attr)
00117                 nfnl_log_set_physindev(log, ntohl(nla_get_u32(attr)));
00118 
00119         attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
00120         if (attr)
00121                 nfnl_log_set_physoutdev(log, ntohl(nla_get_u32(attr)));
00122 
00123         attr = tb[NFULA_HWADDR];
00124         if (attr) {
00125                 struct nfulnl_msg_packet_hw *hw = nla_data(attr);
00126 
00127                 nfnl_log_set_hwaddr(log, hw->hw_addr, ntohs(hw->hw_addrlen));
00128         }
00129 
00130         attr = tb[NFULA_PAYLOAD];
00131         if (attr) {
00132                 err = nfnl_log_set_payload(log, nla_data(attr), nla_len(attr));
00133                 if (err < 0)
00134                         goto errout;
00135         }
00136 
00137         attr = tb[NFULA_PREFIX];
00138         if (attr) {
00139                 err = nfnl_log_set_prefix(log, nla_data(attr));
00140                 if (err < 0)
00141                         goto errout;
00142         }
00143 
00144         attr = tb[NFULA_UID];
00145         if (attr)
00146                 nfnl_log_set_uid(log, ntohl(nla_get_u32(attr)));
00147 
00148         attr = tb[NFULA_SEQ];
00149         if (attr)
00150                 nfnl_log_set_seq(log, ntohl(nla_get_u32(attr)));
00151 
00152         attr = tb[NFULA_SEQ_GLOBAL];
00153         if (attr)
00154                 nfnl_log_set_seq_global(log, ntohl(nla_get_u32(attr)));
00155 
00156         return log;
00157 
00158 errout:
00159         nfnl_log_put(log);
00160         return NULL;
00161 }
00162 
00163 static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00164                          struct nlmsghdr *nlh, struct nl_parser_param *pp)
00165 {
00166         struct nfnl_log *log;
00167         int err;
00168 
00169         log = nfnlmsg_log_parse(nlh);
00170         if (log == NULL)
00171                 goto errout_errno;
00172 
00173         err = pp->pp_cb((struct nl_object *) log, pp);
00174         if (err < 0)
00175                 goto errout;
00176 
00177         err = P_ACCEPT;
00178 
00179 errout:
00180         nfnl_log_put(log);
00181         return err;
00182 
00183 errout_errno:
00184         err = nl_get_errno();
00185         goto errout;
00186 }
00187 
00188 /**
00189  * @name Log Commands
00190  * @{
00191  */
00192 
00193 static struct nl_msg *build_log_cmd_msg(uint8_t family, uint16_t queuenum,
00194                                         uint8_t command)
00195 {
00196         struct nl_msg *msg;
00197         struct nfulnl_msg_config_cmd cmd;
00198 
00199         msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
00200                                    family, queuenum);
00201         if (msg == NULL)
00202                 return NULL;
00203 
00204         cmd.command = command;
00205         if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
00206                 goto nla_put_failure;
00207 
00208         return msg;
00209 
00210 nla_put_failure:
00211         nlmsg_free(msg);
00212         return NULL;
00213 }
00214 
00215 static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg)
00216 {
00217         int err;
00218 
00219         err = nl_send_auto_complete(handle, msg);
00220         nlmsg_free(msg);
00221         if (err < 0)
00222                 return err;
00223 
00224         return nl_wait_for_ack(handle);
00225 }
00226 
00227 struct nl_msg *nfnl_log_build_bind(uint16_t queuenum)
00228 {
00229         return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_BIND);
00230 }
00231 
00232 int nfnl_log_bind(struct nl_handle *nlh, uint16_t queuenum)
00233 {
00234         struct nl_msg *msg;
00235 
00236         msg = nfnl_log_build_bind(queuenum);
00237         if (!msg)
00238                 return nl_get_errno();
00239 
00240         return send_log_msg(nlh, msg);
00241 }
00242 
00243 struct nl_msg *nfnl_log_build_unbind(uint16_t queuenum)
00244 {
00245         return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_UNBIND);
00246 }
00247 
00248 int nfnl_log_unbind(struct nl_handle *nlh, uint16_t queuenum)
00249 {
00250         struct nl_msg *msg;
00251 
00252         msg = nfnl_log_build_bind(queuenum);
00253         if (!msg)
00254                 return nl_get_errno();
00255 
00256         return send_log_msg(nlh, msg);
00257 }
00258 
00259 struct nl_msg *nfnl_log_build_pf_bind(uint8_t pf)
00260 {
00261         return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_BIND);
00262 }
00263 
00264 int nfnl_log_pf_bind(struct nl_handle *nlh, uint8_t pf)
00265 {
00266         struct nl_msg *msg;
00267 
00268         msg = nfnl_log_build_pf_bind(pf);
00269         if (!msg)
00270                 return nl_get_errno();
00271 
00272         return send_log_msg(nlh, msg);
00273 }
00274 
00275 struct nl_msg *nfnl_log_build_pf_unbind(uint8_t pf)
00276 {
00277         return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_UNBIND);
00278 }
00279 
00280 int nfnl_log_pf_unbind(struct nl_handle *nlh, uint8_t pf)
00281 {
00282         struct nl_msg *msg;
00283 
00284         msg = nfnl_log_build_pf_unbind(pf);
00285         if (!msg)
00286                 return nl_get_errno();
00287 
00288         return send_log_msg(nlh, msg);
00289 }
00290 
00291 struct nl_msg *nfnl_log_build_mode(uint16_t queuenum, uint8_t copy_mode,
00292                                    uint32_t copy_range)
00293 {
00294         struct nl_msg *msg;
00295         struct nfulnl_msg_config_mode mode;
00296 
00297         msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
00298                         0, queuenum);
00299         if (msg == NULL)
00300                 return NULL;
00301 
00302         mode.copy_mode = copy_mode;
00303         mode.copy_range = htonl(copy_range);
00304         if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
00305                 goto nla_put_failure;
00306 
00307         return msg;
00308 
00309 nla_put_failure:
00310         nlmsg_free(msg);
00311         return NULL;
00312 }
00313 
00314 int nfnl_log_set_mode(struct nl_handle *nlh, uint16_t queuenum,
00315                       uint8_t copy_mode, uint32_t copy_range)
00316 {
00317         struct nl_msg *msg;
00318 
00319         msg = nfnl_log_build_mode(queuenum, copy_mode, copy_range);
00320         if (!msg)
00321                 return nl_get_errno();
00322         return send_log_msg(nlh, msg);
00323 }
00324 
00325 /** @} */
00326 
00327 #define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
00328 static struct nl_cache_ops nfnl_log_ops = {
00329         .co_name                = "netfilter/log",
00330         .co_hdrsize             = NFNL_HDRLEN,
00331         .co_msgtypes            = {
00332                 { NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" },
00333                 END_OF_MSGTYPES_LIST,
00334         },
00335         .co_protocol            = NETLINK_NETFILTER,
00336         .co_msg_parser          = log_msg_parser,
00337         .co_obj_ops             = &log_obj_ops,
00338 };
00339 
00340 static void __init log_init(void)
00341 {
00342         nl_cache_mngt_register(&nfnl_log_ops);
00343 }
00344 
00345 static void __exit log_exit(void)
00346 {
00347         nl_cache_mngt_unregister(&nfnl_log_ops);
00348 }
00349 
00350 /** @} */