libnftnl 1.2.6
rt.c
1/*
2 * Copyright (c) 2016 Anders K. Pedersen <akp@cohaesio.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <stdio.h>
11#include <stdint.h>
12#include <string.h>
13#include <arpa/inet.h>
14#include <errno.h>
15#include <linux/netfilter/nf_tables.h>
16
17#include "internal.h"
18#include <libmnl/libmnl.h>
19#include <libnftnl/expr.h>
20#include <libnftnl/rule.h>
21
23 enum nft_rt_keys key;
24 enum nft_registers dreg;
25};
26
27static int
28nftnl_expr_rt_set(struct nftnl_expr *e, uint16_t type,
29 const void *data, uint32_t data_len)
30{
31 struct nftnl_expr_rt *rt = nftnl_expr_data(e);
32
33 switch (type) {
34 case NFTNL_EXPR_RT_KEY:
35 memcpy(&rt->key, data, sizeof(rt->key));
36 break;
37 case NFTNL_EXPR_RT_DREG:
38 memcpy(&rt->dreg, data, sizeof(rt->dreg));
39 break;
40 default:
41 return -1;
42 }
43 return 0;
44}
45
46static const void *
47nftnl_expr_rt_get(const struct nftnl_expr *e, uint16_t type,
48 uint32_t *data_len)
49{
50 struct nftnl_expr_rt *rt = nftnl_expr_data(e);
51
52 switch (type) {
53 case NFTNL_EXPR_RT_KEY:
54 *data_len = sizeof(rt->key);
55 return &rt->key;
56 case NFTNL_EXPR_RT_DREG:
57 *data_len = sizeof(rt->dreg);
58 return &rt->dreg;
59 }
60 return NULL;
61}
62
63static int nftnl_expr_rt_cb(const struct nlattr *attr, void *data)
64{
65 const struct nlattr **tb = data;
66 int type = mnl_attr_get_type(attr);
67
68 if (mnl_attr_type_valid(attr, NFTA_RT_MAX) < 0)
69 return MNL_CB_OK;
70
71 switch (type) {
72 case NFTA_RT_KEY:
73 case NFTA_RT_DREG:
74 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
75 abi_breakage();
76 break;
77 }
78
79 tb[type] = attr;
80 return MNL_CB_OK;
81}
82
83static void
84nftnl_expr_rt_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
85{
86 struct nftnl_expr_rt *rt = nftnl_expr_data(e);
87
88 if (e->flags & (1 << NFTNL_EXPR_RT_KEY))
89 mnl_attr_put_u32(nlh, NFTA_RT_KEY, htonl(rt->key));
90 if (e->flags & (1 << NFTNL_EXPR_RT_DREG))
91 mnl_attr_put_u32(nlh, NFTA_RT_DREG, htonl(rt->dreg));
92}
93
94static int
95nftnl_expr_rt_parse(struct nftnl_expr *e, struct nlattr *attr)
96{
97 struct nftnl_expr_rt *rt = nftnl_expr_data(e);
98 struct nlattr *tb[NFTA_RT_MAX+1] = {};
99
100 if (mnl_attr_parse_nested(attr, nftnl_expr_rt_cb, tb) < 0)
101 return -1;
102
103 if (tb[NFTA_RT_KEY]) {
104 rt->key = ntohl(mnl_attr_get_u32(tb[NFTA_RT_KEY]));
105 e->flags |= (1 << NFTNL_EXPR_RT_KEY);
106 }
107 if (tb[NFTA_RT_DREG]) {
108 rt->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_RT_DREG]));
109 e->flags |= (1 << NFTNL_EXPR_RT_DREG);
110 }
111
112 return 0;
113}
114
115static const char *rt_key2str_array[NFT_RT_MAX + 1] = {
116 [NFT_RT_CLASSID] = "classid",
117 [NFT_RT_NEXTHOP4] = "nexthop4",
118 [NFT_RT_NEXTHOP6] = "nexthop6",
119 [NFT_RT_TCPMSS] = "tcpmss",
120 [NFT_RT_XFRM] = "ipsec",
121};
122
123static const char *rt_key2str(uint8_t key)
124{
125 if (key <= NFT_RT_MAX)
126 return rt_key2str_array[key];
127
128 return "unknown";
129}
130
131static inline int str2rt_key(const char *str)
132{
133 int i;
134
135 for (i = 0; i < NFT_RT_MAX; i++) {
136 if (strcmp(str, rt_key2str_array[i]) == 0)
137 return i;
138 }
139
140 errno = EINVAL;
141 return -1;
142}
143
144static int
145nftnl_expr_rt_snprintf(char *buf, size_t len,
146 uint32_t flags, const struct nftnl_expr *e)
147{
148 struct nftnl_expr_rt *rt = nftnl_expr_data(e);
149
150 if (e->flags & (1 << NFTNL_EXPR_RT_DREG)) {
151 return snprintf(buf, len, "load %s => reg %u ",
152 rt_key2str(rt->key), rt->dreg);
153 }
154 return 0;
155}
156
157struct expr_ops expr_ops_rt = {
158 .name = "rt",
159 .alloc_len = sizeof(struct nftnl_expr_rt),
160 .max_attr = NFTA_RT_MAX,
161 .set = nftnl_expr_rt_set,
162 .get = nftnl_expr_rt_get,
163 .parse = nftnl_expr_rt_parse,
164 .build = nftnl_expr_rt_build,
165 .output = nftnl_expr_rt_snprintf,
166};