log_msg_obj.c

00001 /*
00002  * lib/netfilter/log_msg_obj.c  Netfilter Log Object
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 #include <netlink-local.h>
00015 #include <netlink/netfilter/nfnl.h>
00016 #include <netlink/netfilter/netfilter.h>
00017 #include <netlink/netfilter/log_msg.h>
00018 
00019 /** @cond SKIP */
00020 #define LOG_MSG_ATTR_FAMILY             (1UL << 0)
00021 #define LOG_MSG_ATTR_HWPROTO            (1UL << 1)
00022 #define LOG_MSG_ATTR_HOOK               (1UL << 2)
00023 #define LOG_MSG_ATTR_MARK               (1UL << 3)
00024 #define LOG_MSG_ATTR_TIMESTAMP          (1UL << 4)
00025 #define LOG_MSG_ATTR_INDEV              (1UL << 5)
00026 #define LOG_MSG_ATTR_OUTDEV             (1UL << 6)
00027 #define LOG_MSG_ATTR_PHYSINDEV          (1UL << 7)
00028 #define LOG_MSG_ATTR_PHYSOUTDEV         (1UL << 8)
00029 #define LOG_MSG_ATTR_HWADDR             (1UL << 9)
00030 #define LOG_MSG_ATTR_PAYLOAD            (1UL << 10)
00031 #define LOG_MSG_ATTR_PREFIX             (1UL << 11)
00032 #define LOG_MSG_ATTR_UID                (1UL << 12)
00033 #define LOG_MSG_ATTR_GID                (1UL << 13)
00034 #define LOG_MSG_ATTR_SEQ                (1UL << 14)
00035 #define LOG_MSG_ATTR_SEQ_GLOBAL         (1UL << 15)
00036 /** @endcond */
00037 
00038 static void log_msg_free_data(struct nl_object *c)
00039 {
00040         struct nfnl_log_msg *msg = (struct nfnl_log_msg *) c;
00041 
00042         if (msg == NULL)
00043                 return;
00044 
00045         free(msg->log_msg_payload);
00046         free(msg->log_msg_prefix);
00047 }
00048 
00049 static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src)
00050 {
00051         struct nfnl_log_msg *dst = (struct nfnl_log_msg *) _dst;
00052         struct nfnl_log_msg *src = (struct nfnl_log_msg *) _src;
00053         int err;
00054 
00055         if (src->log_msg_payload) {
00056                 err = nfnl_log_msg_set_payload(dst, src->log_msg_payload,
00057                                                src->log_msg_payload_len);
00058                 if (err < 0)
00059                         goto errout;
00060         }
00061 
00062         if (src->log_msg_prefix) {
00063                 err = nfnl_log_msg_set_prefix(dst, src->log_msg_prefix);
00064                 if (err < 0)
00065                         goto errout;
00066         }
00067 
00068         return 0;
00069 errout:
00070         return err;
00071 }
00072 
00073 static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p)
00074 {
00075         struct nfnl_log_msg *msg = (struct nfnl_log_msg *) a;
00076         struct nl_cache *link_cache;
00077         char buf[64];
00078 
00079         link_cache = nl_cache_mngt_require("route/link");
00080 
00081         nl_new_line(p);
00082 
00083         if (msg->ce_mask & LOG_MSG_ATTR_PREFIX)
00084                 nl_dump(p, "%s", msg->log_msg_prefix);
00085 
00086         if (msg->ce_mask & LOG_MSG_ATTR_INDEV) {
00087                 if (link_cache)
00088                         nl_dump(p, "IN=%s ",
00089                                 rtnl_link_i2name(link_cache,
00090                                                  msg->log_msg_indev,
00091                                                  buf, sizeof(buf)));
00092                 else
00093                         nl_dump(p, "IN=%d ", msg->log_msg_indev);
00094         }
00095 
00096         if (msg->ce_mask & LOG_MSG_ATTR_PHYSINDEV) {
00097                 if (link_cache)
00098                         nl_dump(p, "PHYSIN=%s ",
00099                                 rtnl_link_i2name(link_cache,
00100                                                  msg->log_msg_physindev,
00101                                                  buf, sizeof(buf)));
00102                 else
00103                         nl_dump(p, "IN=%d ", msg->log_msg_physindev);
00104         }
00105 
00106         if (msg->ce_mask & LOG_MSG_ATTR_OUTDEV) {
00107                 if (link_cache)
00108                         nl_dump(p, "OUT=%s ",
00109                                 rtnl_link_i2name(link_cache,
00110                                                  msg->log_msg_outdev,
00111                                                  buf, sizeof(buf)));
00112                 else
00113                         nl_dump(p, "OUT=%d ", msg->log_msg_outdev);
00114         }
00115 
00116         if (msg->ce_mask & LOG_MSG_ATTR_PHYSOUTDEV) {
00117                 if (link_cache)
00118                         nl_dump(p, "PHYSOUT=%s ",
00119                                 rtnl_link_i2name(link_cache,
00120                                                  msg->log_msg_physoutdev,
00121                                                  buf, sizeof(buf)));
00122                 else
00123                         nl_dump(p, "PHYSOUT=%d ", msg->log_msg_physoutdev);
00124         }
00125 
00126         if (msg->ce_mask & LOG_MSG_ATTR_HWADDR) {
00127                 int i;
00128 
00129                 nl_dump(p, "MAC");
00130                 for (i = 0; i < msg->log_msg_hwaddr_len; i++)
00131                         nl_dump(p, "%c%02x", i?':':'=', msg->log_msg_hwaddr[i]);
00132                 nl_dump(p, " ");
00133         }
00134 
00135         /* FIXME: parse the payload to get iptables LOG compatible format */
00136 
00137         if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
00138                 nl_dump(p, "FAMILY=%s ",
00139                         nl_af2str(msg->log_msg_family, buf, sizeof(buf)));
00140 
00141         if (msg->ce_mask & LOG_MSG_ATTR_HWPROTO)
00142                 nl_dump(p, "HWPROTO=%s ",
00143                         nl_ether_proto2str(ntohs(msg->log_msg_hwproto),
00144                                            buf, sizeof(buf)));
00145 
00146         if (msg->ce_mask & LOG_MSG_ATTR_HOOK)
00147                 nl_dump(p, "HOOK=%s ",
00148                         nfnl_inet_hook2str(msg->log_msg_hook,
00149                                            buf, sizeof(buf)));
00150 
00151         if (msg->ce_mask & LOG_MSG_ATTR_MARK)
00152                 nl_dump(p, "MARK=%u ", msg->log_msg_mark);
00153 
00154         if (msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)
00155                 nl_dump(p, "PAYLOADLEN=%d ", msg->log_msg_payload_len);
00156 
00157         if (msg->ce_mask & LOG_MSG_ATTR_UID)
00158                 nl_dump(p, "UID=%u ", msg->log_msg_uid);
00159 
00160         if (msg->ce_mask & LOG_MSG_ATTR_GID)
00161                 nl_dump(p, "GID=%u ", msg->log_msg_gid);
00162 
00163         if (msg->ce_mask & LOG_MSG_ATTR_SEQ)
00164                 nl_dump(p, "SEQ=%d ", msg->log_msg_seq);
00165 
00166         if (msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL)
00167                 nl_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global);
00168 
00169         nl_dump(p, "\n");
00170 }
00171 
00172 /**
00173  * @name Allocation/Freeing
00174  * @{
00175  */
00176 
00177 struct nfnl_log_msg *nfnl_log_msg_alloc(void)
00178 {
00179         return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops);
00180 }
00181 
00182 void nfnl_log_msg_get(struct nfnl_log_msg *msg)
00183 {
00184         nl_object_get((struct nl_object *) msg);
00185 }
00186 
00187 void nfnl_log_msg_put(struct nfnl_log_msg *msg)
00188 {
00189         nl_object_put((struct nl_object *) msg);
00190 }
00191 
00192 /** @} */
00193 
00194 /**
00195  * @name Attributes
00196  * @{
00197  */
00198 
00199 void nfnl_log_msg_set_family(struct nfnl_log_msg *msg, uint8_t family)
00200 {
00201         msg->log_msg_family = family;
00202         msg->ce_mask |= LOG_MSG_ATTR_FAMILY;
00203 }
00204 
00205 uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *msg)
00206 {
00207         if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
00208                 return msg->log_msg_family;
00209         else
00210                 return AF_UNSPEC;
00211 }
00212 
00213 void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *msg, uint16_t hwproto)
00214 {
00215         msg->log_msg_hwproto = hwproto;
00216         msg->ce_mask |= LOG_MSG_ATTR_HWPROTO;
00217 }
00218 
00219 int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg)
00220 {
00221         return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO);
00222 }
00223 
00224 uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg)
00225 {
00226         return msg->log_msg_hwproto;
00227 }
00228 
00229 void nfnl_log_msg_set_hook(struct nfnl_log_msg *msg, uint8_t hook)
00230 {
00231         msg->log_msg_hook = hook;
00232         msg->ce_mask |= LOG_MSG_ATTR_HOOK;
00233 }
00234 
00235 int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg)
00236 {
00237         return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK);
00238 }
00239 
00240 uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg)
00241 {
00242         return msg->log_msg_hook;
00243 }
00244 
00245 void nfnl_log_msg_set_mark(struct nfnl_log_msg *msg, uint32_t mark)
00246 {
00247         msg->log_msg_mark = mark;
00248         msg->ce_mask |= LOG_MSG_ATTR_MARK;
00249 }
00250 
00251 int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg)
00252 {
00253         return !!(msg->ce_mask & LOG_MSG_ATTR_MARK);
00254 }
00255 
00256 uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg)
00257 {
00258         return msg->log_msg_mark;
00259 }
00260 
00261 void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *msg, struct timeval *tv)
00262 {
00263         msg->log_msg_timestamp.tv_sec = tv->tv_sec;
00264         msg->log_msg_timestamp.tv_usec = tv->tv_usec;
00265         msg->ce_mask |= LOG_MSG_ATTR_TIMESTAMP;
00266 }
00267 
00268 const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *msg)
00269 {
00270         if (!(msg->ce_mask & LOG_MSG_ATTR_TIMESTAMP))
00271                 return NULL;
00272         return &msg->log_msg_timestamp;
00273 }
00274 
00275 void nfnl_log_msg_set_indev(struct nfnl_log_msg *msg, uint32_t indev)
00276 {
00277         msg->log_msg_indev = indev;
00278         msg->ce_mask |= LOG_MSG_ATTR_INDEV;
00279 }
00280 
00281 uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg)
00282 {
00283         return msg->log_msg_indev;
00284 }
00285 
00286 void nfnl_log_msg_set_outdev(struct nfnl_log_msg *msg, uint32_t outdev)
00287 {
00288         msg->log_msg_outdev = outdev;
00289         msg->ce_mask |= LOG_MSG_ATTR_OUTDEV;
00290 }
00291 
00292 uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg)
00293 {
00294         return msg->log_msg_outdev;
00295 }
00296 
00297 void nfnl_log_msg_set_physindev(struct nfnl_log_msg *msg, uint32_t physindev)
00298 {
00299         msg->log_msg_physindev = physindev;
00300         msg->ce_mask |= LOG_MSG_ATTR_PHYSINDEV;
00301 }
00302 
00303 uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg)
00304 {
00305         return msg->log_msg_physindev;
00306 }
00307 
00308 void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *msg, uint32_t physoutdev)
00309 {
00310         msg->log_msg_physoutdev = physoutdev;
00311         msg->ce_mask |= LOG_MSG_ATTR_PHYSOUTDEV;
00312 }
00313 
00314 uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg)
00315 {
00316         return msg->log_msg_physoutdev;
00317 }
00318 
00319 void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *msg, uint8_t *hwaddr, int len)
00320 {
00321         if (len > sizeof(msg->log_msg_hwaddr))
00322                 len = sizeof(msg->log_msg_hwaddr);
00323         msg->log_msg_hwaddr_len = len;
00324         memcpy(msg->log_msg_hwaddr, hwaddr, len);
00325         msg->ce_mask |= LOG_MSG_ATTR_HWADDR;
00326 }
00327 
00328 const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len)
00329 {
00330         if (!(msg->ce_mask & LOG_MSG_ATTR_HWADDR)) {
00331                 *len = 0;
00332                 return NULL;
00333         }
00334 
00335         *len = msg->log_msg_hwaddr_len;
00336         return msg->log_msg_hwaddr;
00337 }
00338 
00339 int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len)
00340 {
00341         free(msg->log_msg_payload);
00342         msg->log_msg_payload = malloc(len);
00343         if (!msg->log_msg_payload)
00344                 return -NLE_NOMEM;
00345 
00346         memcpy(msg->log_msg_payload, payload, len);
00347         msg->log_msg_payload_len = len;
00348         msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD;
00349         return 0;
00350 }
00351 
00352 const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len)
00353 {
00354         if (!(msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)) {
00355                 *len = 0;
00356                 return NULL;
00357         }
00358 
00359         *len = msg->log_msg_payload_len;
00360         return msg->log_msg_payload;
00361 }
00362 
00363 int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix)
00364 {
00365         free(msg->log_msg_prefix);
00366         msg->log_msg_prefix = strdup(prefix);
00367         if (!msg->log_msg_prefix)
00368                 return -NLE_NOMEM;
00369 
00370         msg->ce_mask |= LOG_MSG_ATTR_PREFIX;
00371         return 0;
00372 }
00373 
00374 const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg)
00375 {
00376         return msg->log_msg_prefix;
00377 }
00378 
00379 void nfnl_log_msg_set_uid(struct nfnl_log_msg *msg, uint32_t uid)
00380 {
00381         msg->log_msg_uid = uid;
00382         msg->ce_mask |= LOG_MSG_ATTR_UID;
00383 }
00384 
00385 int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg)
00386 {
00387         return !!(msg->ce_mask & LOG_MSG_ATTR_UID);
00388 }
00389 
00390 uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg)
00391 {
00392         return msg->log_msg_uid;
00393 }
00394 
00395 void nfnl_log_msg_set_gid(struct nfnl_log_msg *msg, uint32_t gid)
00396 {
00397         msg->log_msg_gid = gid;
00398         msg->ce_mask |= LOG_MSG_ATTR_GID;
00399 }
00400 
00401 int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg)
00402 {
00403         return !!(msg->ce_mask & LOG_MSG_ATTR_GID);
00404 }
00405 
00406 uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg)
00407 {
00408         return msg->log_msg_gid;
00409 }
00410 
00411 
00412 void nfnl_log_msg_set_seq(struct nfnl_log_msg *msg, uint32_t seq)
00413 {
00414         msg->log_msg_seq = seq;
00415         msg->ce_mask |= LOG_MSG_ATTR_SEQ;
00416 }
00417 
00418 int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg)
00419 {
00420         return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ);
00421 }
00422 
00423 uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg)
00424 {
00425         return msg->log_msg_seq;
00426 }
00427 
00428 void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *msg, uint32_t seq_global)
00429 {
00430         msg->log_msg_seq_global = seq_global;
00431         msg->ce_mask |= LOG_MSG_ATTR_SEQ_GLOBAL;
00432 }
00433 
00434 int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *msg)
00435 {
00436         return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL);
00437 }
00438 
00439 uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg)
00440 {
00441         return msg->log_msg_seq_global;
00442 }
00443 
00444 /** @} */
00445 
00446 struct nl_object_ops log_msg_obj_ops = {
00447         .oo_name                = "netfilter/log_msg",
00448         .oo_size                = sizeof(struct nfnl_log_msg),
00449         .oo_free_data           = log_msg_free_data,
00450         .oo_clone               = log_msg_clone,
00451         .oo_dump = {
00452             [NL_DUMP_LINE]      = log_msg_dump,
00453             [NL_DUMP_DETAILS]   = log_msg_dump,
00454             [NL_DUMP_STATS]     = log_msg_dump,
00455         },
00456 };
00457 
00458 /** @} */