Line data Source code
1 : /*
2 : * Copyright (c) 2021 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : #include "pnat.h"
16 : #include <vnet/vnet.h>
17 : #include <pnat/pnat.api_enum.h>
18 : #include <pnat/pnat.api_types.h>
19 : #include <vlibmemory/api.h>
20 : #include <vnet/fib/fib_table.h>
21 : #include <vnet/ip/ip.h>
22 : #include <vnet/ip/ip_types_api.h>
23 : #include <vnet/ip/reass/ip4_sv_reass.h>
24 : #include <vnet/ip/reass/ip6_full_reass.h>
25 : #include <vnet/ip/reass/ip6_sv_reass.h>
26 : #include <vpp/app/version.h>
27 :
28 : /*
29 : * This file contains the API handlers for the pnat.api
30 : */
31 :
32 : #define REPLY_MSG_ID_BASE pm->msg_id_base
33 : #include <vlibapi/api_helper_macros.h>
34 :
35 9 : static void vl_api_pnat_binding_add_t_handler(vl_api_pnat_binding_add_t *mp) {
36 9 : pnat_main_t *pm = &pnat_main;
37 : vl_api_pnat_binding_add_reply_t *rmp;
38 : u32 binding_index;
39 :
40 : // for backward compatibility
41 9 : if (mp->match.proto == 0)
42 2 : mp->match.mask |= PNAT_PROTO;
43 :
44 9 : int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
45 9 : REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_REPLY,
46 : ({ rmp->binding_index = binding_index; }));
47 : }
48 :
49 : static void
50 2 : vl_api_pnat_binding_add_v2_t_handler(vl_api_pnat_binding_add_t *mp) {
51 2 : pnat_main_t *pm = &pnat_main;
52 : vl_api_pnat_binding_add_reply_t *rmp;
53 : u32 binding_index;
54 2 : int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
55 2 : REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_V2_REPLY,
56 : ({ rmp->binding_index = binding_index; }));
57 : }
58 :
59 : static void
60 11 : vl_api_pnat_binding_attach_t_handler(vl_api_pnat_binding_attach_t *mp) {
61 11 : pnat_main_t *pm = &pnat_main;
62 : vl_api_pnat_binding_attach_reply_t *rmp;
63 : int rv;
64 :
65 11 : VALIDATE_SW_IF_INDEX_END(mp);
66 :
67 : rv =
68 11 : pnat_binding_attach(mp->sw_if_index, mp->attachment, mp->binding_index);
69 :
70 11 : bad_sw_if_index:
71 11 : REPLY_MACRO_END(VL_API_PNAT_BINDING_ATTACH_REPLY);
72 : }
73 :
74 : static void
75 11 : vl_api_pnat_binding_detach_t_handler(vl_api_pnat_binding_detach_t *mp) {
76 11 : pnat_main_t *pm = &pnat_main;
77 : vl_api_pnat_binding_detach_reply_t *rmp;
78 : int rv;
79 :
80 11 : VALIDATE_SW_IF_INDEX_END(mp);
81 :
82 : rv =
83 11 : pnat_binding_detach(mp->sw_if_index, mp->attachment, mp->binding_index);
84 :
85 11 : bad_sw_if_index:
86 11 : REPLY_MACRO_END(VL_API_PNAT_BINDING_DETACH_REPLY);
87 : }
88 :
89 11 : static void vl_api_pnat_binding_del_t_handler(vl_api_pnat_binding_del_t *mp) {
90 11 : pnat_main_t *pm = &pnat_main;
91 : vl_api_pnat_binding_del_reply_t *rmp;
92 11 : int rv = pnat_binding_del(mp->binding_index);
93 11 : REPLY_MACRO_END(VL_API_PNAT_BINDING_DEL_REPLY);
94 : }
95 :
96 : /*
97 : * Workaround for a bug in vppapigen that doesn't register the endian handler
98 : * for _details messages. When that's fixed it should be possible to use
99 : * REPLY_MACRO_DETAILS4_END and not have to care about endian-ness in the
100 : * handler itself.
101 : */
102 : #define vl_endianfun
103 : #include <pnat/pnat.api.h>
104 : #undef vl_endianfun
105 2 : static void send_bindings_details(u32 index, vl_api_registration_t *rp,
106 : u32 context) {
107 2 : pnat_main_t *pm = &pnat_main;
108 : vl_api_pnat_bindings_details_t *rmp;
109 2 : pnat_translation_t *t = pool_elt_at_index(pm->translations, index);
110 :
111 : /* Make sure every field is initiated (or don't skip the clib_memset()) */
112 :
113 2 : REPLY_MACRO_DETAILS4(VL_API_PNAT_BINDINGS_DETAILS, rp, context, ({
114 : rmp->match = t->match;
115 : rmp->rewrite = t->rewrite;
116 :
117 : /* Endian hack until apigen registers _details
118 : * endian functions */
119 : vl_api_pnat_bindings_details_t_endian(rmp);
120 : rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
121 : rmp->context = htonl(rmp->context);
122 : }));
123 2 : }
124 :
125 1 : static void vl_api_pnat_bindings_get_t_handler(vl_api_pnat_bindings_get_t *mp) {
126 1 : pnat_main_t *pm = &pnat_main;
127 : vl_api_pnat_bindings_get_reply_t *rmp;
128 :
129 1 : i32 rv = 0;
130 :
131 1 : if (pool_elts(pm->translations) == 0) {
132 0 : REPLY_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY);
133 0 : return;
134 : }
135 :
136 : /*
137 : * "cursor" comes from the get call, and allows client to continue a dump
138 : */
139 3 : REPLY_AND_DETAILS_MACRO(VL_API_PNAT_BINDINGS_GET_REPLY, pm->translations, ({
140 : send_bindings_details(cursor, rp, mp->context);
141 : }));
142 : }
143 :
144 2 : static void send_interfaces_details(u32 index, vl_api_registration_t *rp,
145 : u32 context) {
146 2 : pnat_main_t *pm = &pnat_main;
147 : vl_api_pnat_interfaces_details_t *rmp;
148 2 : pnat_interface_t *i = pool_elt_at_index(pm->interfaces, index);
149 :
150 : /* Make sure every field is initiated (or don't skip the clib_memset()) */
151 :
152 2 : REPLY_MACRO_DETAILS4(
153 : VL_API_PNAT_INTERFACES_DETAILS, rp, context, ({
154 : rmp->sw_if_index = i->sw_if_index;
155 : clib_memcpy(rmp->enabled, i->enabled, sizeof(rmp->enabled));
156 : clib_memcpy(rmp->lookup_mask, i->lookup_mask,
157 : sizeof(rmp->lookup_mask));
158 :
159 : /* Endian hack until apigen registers _details
160 : * endian functions */
161 : vl_api_pnat_interfaces_details_t_endian(rmp);
162 : rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
163 : rmp->context = htonl(rmp->context);
164 : }));
165 2 : }
166 :
167 : static void
168 1 : vl_api_pnat_interfaces_get_t_handler(vl_api_pnat_interfaces_get_t *mp) {
169 1 : pnat_main_t *pm = &pnat_main;
170 : vl_api_pnat_interfaces_get_reply_t *rmp;
171 :
172 1 : i32 rv = 0;
173 :
174 1 : if (pool_elts(pm->interfaces) == 0) {
175 0 : REPLY_MACRO(VL_API_PNAT_INTERFACES_GET_REPLY);
176 0 : return;
177 : }
178 :
179 : /*
180 : * "cursor" comes from the get call, and allows client to continue a dump
181 : */
182 3 : REPLY_AND_DETAILS_MACRO(
183 : VL_API_PNAT_INTERFACES_GET_REPLY, pm->interfaces,
184 : ({ send_interfaces_details(cursor, rp, mp->context); }));
185 : }
186 :
187 : /* API definitions */
188 : #include <vnet/format_fns.h>
189 : #include <pnat/pnat.api.c>
190 :
191 : /* Set up the API message handling tables */
192 559 : clib_error_t *pnat_plugin_api_hookup(vlib_main_t *vm) {
193 559 : pnat_main_t *pm = &pnat_main;
194 :
195 559 : pm->msg_id_base = setup_message_id_table();
196 :
197 559 : return 0;
198 : }
199 :
200 : /*
201 : * Register the plugin and hook up the API
202 : */
203 : #include <vnet/plugin/plugin.h>
204 : VLIB_PLUGIN_REGISTER() = {
205 : .version = VPP_BUILD_VER,
206 : .description = "Policy 1:1 NAT",
207 : };
208 :
209 559 : clib_error_t *pnat_init(vlib_main_t *vm) {
210 559 : pnat_main_t *pm = &pnat_main;
211 559 : memset(pm, 0, sizeof(*pm));
212 :
213 559 : return pnat_plugin_api_hookup(vm);
214 : }
215 :
216 1119 : VLIB_INIT_FUNCTION(pnat_init);
|