libnetfilter_conntrack 1.0.9
nfct-mnl-set-label.c
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <time.h>
5
6#include <libmnl/libmnl.h>
7#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
8
10 struct mnl_socket *nl;
11 unsigned int seq;
12 int bit;
13};
14
15static void set_label(struct nf_conntrack *ct, struct callback_args *cbargs)
16{
17 struct nfct_bitmask *b = (void *) nfct_get_attr(ct, ATTR_CONNLABELS);
18 int bit = cbargs->bit;
19 char buf[MNL_SOCKET_BUFFER_SIZE];
20 struct nlmsghdr *nlh;
21 struct nfgenmsg *nfh;
22 int ret;
23
24 if (b) {
25 if (bit < 0)
26 b = nfct_bitmask_new(0);
27 else if (nfct_bitmask_test_bit(b, bit))
28 return;
29 } else {
30 b = nfct_bitmask_new(0);
31 }
32
33 if (!b)
34 return;
35 if (bit >= 0)
36 nfct_bitmask_set_bit(b, bit);
37 nfct_set_attr(ct, ATTR_CONNLABELS, b);
38
39 if (bit >= 0) {
40 b = nfct_bitmask_new(bit);
41 if (b) {
42 nfct_bitmask_set_bit(b, bit);
43 nfct_set_attr(ct, ATTR_CONNLABELS_MASK, b);
44 }
45 }
46
47 cbargs->seq++;
48
49 nlh = mnl_nlmsg_put_header(buf);
50 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
51 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
52 nlh->nlmsg_seq = cbargs->seq;
53
54 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
55 nfh->nfgen_family = nfct_get_attr_u8(ct, ATTR_L3PROTO);
56 nfh->version = NFNETLINK_V0;
57 nfh->res_id = 0;
58
59 ret = nfct_nlmsg_build(nlh, ct);
60 if (ret == -1) {
61 perror("nfct_nlmsg_build");
62 exit(EXIT_FAILURE);
63 }
64
65 if (mnl_socket_sendto(cbargs->nl, nlh, nlh->nlmsg_len) < 0)
66 perror("mnl_socket_sendto");
67}
68
69static int data_cb(const struct nlmsghdr *nlh, void *data)
70{
71 struct nf_conntrack *ct;
72 char buf[4096];
73
74 ct = nfct_new();
75 if (ct == NULL)
76 return MNL_CB_OK;
77
78 nfct_nlmsg_parse(nlh, ct);
79
80 nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
81 printf("%s\n", buf);
82
83 set_label(ct, data);
84
85 nfct_destroy(ct);
86
87 return MNL_CB_OK;
88}
89
90static void show_labels(struct nfct_labelmap *l)
91{
92 unsigned int i = 0;
93 const char *name;
94
95 if (l) {
96 fputs("usage: program label, configured labels are:\n", stderr);
97 while ((name = nfct_labelmap_get_name(l, i))) {
98 if (*name)
99 fprintf(stderr, "%s -> bit %d\n", name, i);
100 i++;
101 }
102 } else {
103 fputs("no labels configured, usage: program bit\n", stderr);
104 }
105 exit(1);
106}
107
108static struct mnl_socket *sock_nl_create(void)
109{
110 struct mnl_socket *nl;
111
112 nl = mnl_socket_open(NETLINK_NETFILTER);
113 if (nl == NULL) {
114 perror("mnl_socket_open");
115 exit(EXIT_FAILURE);
116 }
117
118 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
119 perror("mnl_socket_bind");
120 exit(EXIT_FAILURE);
121 }
122
123 return nl;
124}
125
126int main(int argc, char *argv[])
127{
128 struct mnl_socket *nl;
129 struct nlmsghdr *nlh;
130 struct nfgenmsg *nfh;
131 char buf[MNL_SOCKET_BUFFER_SIZE];
132 unsigned int seq, portid;
133 struct callback_args cbargs;
134 int ret;
135 struct nfct_labelmap *l = nfct_labelmap_new(NULL);
136
137 if (argc < 2)
138 show_labels(l);
139
140 cbargs.bit = l ? nfct_labelmap_get_bit(l, argv[1]) : -1;
141
142 if (cbargs.bit < 0) {
143 cbargs.bit = atoi(argv[1]);
144 if (cbargs.bit == 0 && argv[1][0] != '0')
145 show_labels(l);
146 }
147
148 if (cbargs.bit < 0)
149 puts("will clear all labels");
150 else
151 printf("will set label bit %d\n", cbargs.bit);
152
153 nl = sock_nl_create();
154 portid = mnl_socket_get_portid(nl);
155
156 nlh = mnl_nlmsg_put_header(buf);
157 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
158 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
159 nlh->nlmsg_seq = seq = time(NULL);
160
161 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
162 nfh->nfgen_family = AF_UNSPEC;
163 nfh->version = NFNETLINK_V0;
164 nfh->res_id = 0;
165
166
167 ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
168 if (ret == -1) {
169 perror("mnl_socket_sendto");
170 exit(EXIT_FAILURE);
171 }
172
173 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
174
175
176 cbargs.nl = sock_nl_create();
177 cbargs.seq = seq;
178
179 while (ret > 0) {
180 ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &cbargs);
181 if (ret <= MNL_CB_STOP)
182 break;
183 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
184 }
185 if (ret == -1) {
186 perror("mnl_socket_recvfrom");
187 exit(EXIT_FAILURE);
188 }
189
190 if (l)
192 mnl_socket_close(nl);
193
194 return 0;
195}
void nfct_destroy(struct nf_conntrack *ct)
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_snprintf(char *buf, unsigned int size, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int out_type, const unsigned int out_flags)
uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
struct nf_conntrack * nfct_new(void)
void nfct_labelmap_destroy(struct nfct_labelmap *map)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
struct nfct_labelmap * nfct_labelmap_new(const char *mapfile)
int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)