summaryrefslogtreecommitdiffstats
path: root/src/plugins/nat/det44/det44_inlines.h
blob: e5e70bbaebcfdeb0e065fedb2df5288effd56d45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * det44.h - deterministic NAT definitions
 *
 * Copyright (c) 2020 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file
 * @brief Deterministic NAT (CGN) inlines
 */

#ifndef __included_det44_inlines_h__
#define __included_det44_inlines_h__

static_always_inline int
det44_is_interface_addr (vlib_node_runtime_t * node,
			 u32 sw_if_index0, u32 ip4_addr)
{
  det44_runtime_t *rt = (det44_runtime_t *) node->runtime_data;
  det44_main_t *dm = &det44_main;
  ip4_address_t *first_int_addr;

  if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
    {
      first_int_addr = ip4_interface_first_address (dm->ip4_main,
						    sw_if_index0, 0);
      rt->cached_sw_if_index = sw_if_index0;
      if (first_int_addr)
	rt->cached_ip4_address = first_int_addr->as_u32;
      else
	rt->cached_ip4_address = 0;
    }
  if (PREDICT_FALSE (rt->cached_ip4_address == ip4_addr))
    return 0;
  return 1;
}

/**
 * @brief Check if packet should be translated
 *
 * Packets aimed at outside interface and external address with active session
 * should be translated.
 *
 * @param node          NAT runtime data
 * @param sw_if_index0  index of the inside interface
 * @param ip0           IPv4 header
 * @param proto0        NAT protocol
 * @param rx_fib_index0 RX FIB index
 *
 * @returns 0 if packet should be translated otherwise 1
 */
static_always_inline int
det44_translate (vlib_node_runtime_t * node, u32 sw_if_index0,
		 ip4_header_t * ip0, u32 proto0, u32 rx_fib_index0)
{
  det44_main_t *dm = &det44_main;
  fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
  det44_fib_t *outside_fib;
  fib_prefix_t pfx = {
    .fp_proto = FIB_PROTOCOL_IP4,
    .fp_len = 32,
    .fp_addr = {
		.ip4.as_u32 = ip0->dst_address.as_u32,
		}
    ,
  };

  /* Don't NAT packet aimed at the interface address */
  if (PREDICT_FALSE (!det44_is_interface_addr (node, sw_if_index0,
					       ip0->dst_address.as_u32)))
    {
      return 1;
    }

  /* find out if there is outside feature enabled for this destination */
  fei = fib_table_lookup (rx_fib_index0, &pfx);
  if (FIB_NODE_INDEX_INVALID != fei)
    {
      u32 sw_if_index = fib_entry_get_resolving_interface (fei);
      if (sw_if_index == ~0)
	{
	  // TODO: go over use cases
	  vec_foreach (outside_fib, dm->outside_fibs)
	    {
	      fei = fib_table_lookup (outside_fib->fib_index, &pfx);
	      if (FIB_NODE_INDEX_INVALID != fei)
	        {
		  sw_if_index = fib_entry_get_resolving_interface (fei);
		  if (sw_if_index != ~0)
		    break;
	        }
	    }
	}
      if (sw_if_index != ~0)
	{
	  det44_interface_t *i;
          pool_foreach (i, dm->interfaces)  {
            /* NAT packet aimed at outside interface */
	    if ((det44_interface_is_outside (i)) && (sw_if_index == i->sw_if_index))
              return 0;
          }
	}
    }
  return 1;
}

#endif /* __included_det44_inlines_h__ */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */