1 /*
2 * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10 #include "internal/internal.h"
11
__parse_message(const struct nlmsghdr * nlh)12 static int __parse_message(const struct nlmsghdr *nlh)
13 {
14 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
15 uint16_t flags = nlh->nlmsg_flags;
16 int ret = NFCT_T_UNKNOWN;
17
18 switch(type) {
19 case IPCTNL_MSG_CT_NEW: /* same value for IPCTNL_MSG_EXP_NEW. */
20 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
21 ret = NFCT_T_NEW;
22 else
23 ret = NFCT_T_UPDATE;
24 break;
25 case IPCTNL_MSG_CT_DELETE: /* same value for IPCTNL_MSG_EXP_DELETE. */
26 ret = NFCT_T_DESTROY;
27 break;
28 }
29 return ret;
30 }
31
__callback(struct nlmsghdr * nlh,struct nfattr * nfa[],void * data)32 int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data)
33 {
34 int ret = NFNL_CB_STOP;
35 unsigned int type;
36 struct nf_conntrack *ct = NULL;
37 struct nf_expect *exp = NULL;
38 struct __data_container *container = data;
39 uint8_t subsys = NFNL_SUBSYS_ID(nlh->nlmsg_type);
40
41 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
42 errno = EINVAL;
43 return NFNL_CB_FAILURE;
44 }
45 type = __parse_message(nlh);
46 if (!(type & container->type))
47 return NFNL_CB_CONTINUE;
48
49 switch(subsys) {
50 case NFNL_SUBSYS_CTNETLINK:
51 ct = nfct_new();
52 if (ct == NULL)
53 return NFNL_CB_FAILURE;
54
55 __parse_conntrack(nlh, nfa, ct);
56
57 if (container->h->cb) {
58 ret = container->h->cb(type, ct, container->data);
59 } else if (container->h->cb2) {
60 ret = container->h->cb2(nlh, type, ct,
61 container->data);
62 }
63 break;
64 case NFNL_SUBSYS_CTNETLINK_EXP:
65 exp = nfexp_new();
66 if (exp == NULL)
67 return NFNL_CB_FAILURE;
68
69 __parse_expect(nlh, nfa, exp);
70
71 if (container->h->expect_cb) {
72 ret = container->h->expect_cb(type, exp,
73 container->data);
74 } else if (container->h->expect_cb2) {
75 ret = container->h->expect_cb2(nlh, type, exp,
76 container->data);
77 }
78 break;
79 default:
80 errno = ENOTSUP;
81 ret = NFNL_CB_FAILURE;
82 break;
83 }
84
85 if (ret == NFCT_CB_STOLEN)
86 return NFNL_CB_CONTINUE;
87
88 if (ct)
89 nfct_destroy(ct);
90 if (exp)
91 nfexp_destroy(exp);
92
93 return ret;
94 }
95