]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/nhrp_vc.c
Merge pull request #12908 from opensourcerouting/fix/memory_leak_path_attributes
[mirror_frr.git] / nhrpd / nhrp_vc.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
2fb975da
TT
2/* NHRP virtual connection
3 * Copyright (c) 2014-2015 Timo Teräs
2fb975da
TT
4 */
5
6#include "zebra.h"
7#include "memory.h"
8#include "stream.h"
9#include "hash.h"
10#include "thread.h"
11#include "jhash.h"
12
13#include "nhrpd.h"
14#include "os.h"
15
bf8d3d6a 16DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection");
819dc8bb 17
b4f3d41b
DL
18PREDECL_DLIST(childlist);
19
2fb975da
TT
20struct child_sa {
21 uint32_t id;
22 struct nhrp_vc *vc;
b4f3d41b 23 struct childlist_item childlist_entry;
2fb975da
TT
24};
25
b4f3d41b
DL
26DECLARE_DLIST(childlist, struct child_sa, childlist_entry);
27
2fb975da 28static struct hash *nhrp_vc_hash;
b4f3d41b 29static struct childlist_head childlist_head[512];
2fb975da 30
d8b87afe 31static unsigned int nhrp_vc_key(const void *peer_data)
2fb975da 32{
d8b87afe 33 const struct nhrp_vc *vc = peer_data;
996c9314
LB
34 return jhash_2words(sockunion_hash(&vc->local.nbma),
35 sockunion_hash(&vc->remote.nbma), 0);
2fb975da
TT
36}
37
74df8d6d 38static bool nhrp_vc_cmp(const void *cache_data, const void *key_data)
2fb975da
TT
39{
40 const struct nhrp_vc *a = cache_data;
41 const struct nhrp_vc *b = key_data;
74df8d6d 42
996c9314
LB
43 return sockunion_same(&a->local.nbma, &b->local.nbma)
44 && sockunion_same(&a->remote.nbma, &b->remote.nbma);
2fb975da
TT
45}
46
47static void *nhrp_vc_alloc(void *data)
48{
49 struct nhrp_vc *vc, *key = data;
50
51 vc = XMALLOC(MTYPE_NHRP_VC, sizeof(struct nhrp_vc));
0ce1ca80
DS
52
53 *vc = (struct nhrp_vc){
54 .local.nbma = key->local.nbma,
55 .remote.nbma = key->remote.nbma,
56 .notifier_list =
57 NOTIFIER_LIST_INITIALIZER(&vc->notifier_list),
58 };
2fb975da
TT
59
60 return vc;
61}
62
63static void nhrp_vc_free(void *data)
64{
65 XFREE(MTYPE_NHRP_VC, data);
66}
67
996c9314
LB
68struct nhrp_vc *nhrp_vc_get(const union sockunion *src,
69 const union sockunion *dst, int create)
2fb975da
TT
70{
71 struct nhrp_vc key;
72 key.local.nbma = *src;
73 key.remote.nbma = *dst;
74 return hash_get(nhrp_vc_hash, &key, create ? nhrp_vc_alloc : 0);
75}
76
77static void nhrp_vc_check_delete(struct nhrp_vc *vc)
78{
79 if (vc->updating || vc->ipsec || notifier_active(&vc->notifier_list))
80 return;
81 hash_release(nhrp_vc_hash, vc);
82 nhrp_vc_free(vc);
83}
84
85static void nhrp_vc_update(struct nhrp_vc *vc, long cmd)
86{
87 vc->updating = 1;
88 notifier_call(&vc->notifier_list, cmd);
89 vc->updating = 0;
90 nhrp_vc_check_delete(vc);
91}
92
93static void nhrp_vc_ipsec_reset(struct nhrp_vc *vc)
94{
95 vc->local.id[0] = 0;
96 vc->local.certlen = 0;
97 vc->remote.id[0] = 0;
98 vc->remote.certlen = 0;
99}
100
101int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
102{
2fb975da 103 struct child_sa *sa = NULL, *lsa;
7e3a1ec7 104 uint32_t child_hash = child_id % array_size(childlist_head);
2fb975da
TT
105 int abort_migration = 0;
106
b4f3d41b 107 frr_each (childlist, &childlist_head[child_hash], lsa) {
2fb975da
TT
108 if (lsa->id == child_id) {
109 sa = lsa;
110 break;
111 }
112 }
113
114 if (!sa) {
996c9314
LB
115 if (!vc)
116 return 0;
2fb975da
TT
117
118 sa = XMALLOC(MTYPE_NHRP_VC, sizeof(struct child_sa));
2fb975da 119
996c9314 120 *sa = (struct child_sa){
2fb975da 121 .id = child_id,
2fb975da
TT
122 .vc = NULL,
123 };
b4f3d41b 124 childlist_add_tail(&childlist_head[child_hash], sa);
2fb975da
TT
125 }
126
127 if (sa->vc == vc)
128 return 0;
129
130 if (vc) {
131 /* Attach first to new VC */
132 vc->ipsec++;
133 nhrp_vc_update(vc, NOTIFY_VC_IPSEC_CHANGED);
134 }
135 if (sa->vc && vc) {
136 /* Notify old VC of migration */
137 sa->vc->abort_migration = 0;
b6c48481
DS
138 debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %pSU to %pSU",
139 &sa->vc->remote.nbma, &vc->remote.nbma);
2fb975da
TT
140 nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_UPDATE_NBMA);
141 abort_migration = sa->vc->abort_migration;
142 }
143 if (sa->vc) {
144 /* Deattach old VC */
145 sa->vc->ipsec--;
996c9314
LB
146 if (!sa->vc->ipsec)
147 nhrp_vc_ipsec_reset(sa->vc);
2fb975da
TT
148 nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_CHANGED);
149 }
150
151 /* Update */
152 sa->vc = vc;
153 if (!vc) {
b4f3d41b 154 childlist_del(&childlist_head[child_hash], sa);
2fb975da
TT
155 XFREE(MTYPE_NHRP_VC, sa);
156 }
157
158 return abort_migration;
159}
160
996c9314
LB
161void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n,
162 notifier_fn_t action)
2fb975da
TT
163{
164 notifier_add(n, &vc->notifier_list, action);
165}
166
167void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
168{
865bf787 169 notifier_del(n, &vc->notifier_list);
2fb975da
TT
170 nhrp_vc_check_delete(vc);
171}
172
173
174struct nhrp_vc_iterator_ctx {
175 void (*cb)(struct nhrp_vc *, void *);
176 void *ctx;
177};
178
e3b78da8 179static void nhrp_vc_iterator(struct hash_bucket *b, void *ctx)
2fb975da
TT
180{
181 struct nhrp_vc_iterator_ctx *ic = ctx;
182 ic->cb(b->data, ic->ctx);
183}
184
185void nhrp_vc_foreach(void (*cb)(struct nhrp_vc *, void *), void *ctx)
186{
187 struct nhrp_vc_iterator_ctx ic = {
996c9314 188 .cb = cb, .ctx = ctx,
2fb975da
TT
189 };
190 hash_iterate(nhrp_vc_hash, nhrp_vc_iterator, &ic);
191}
192
193void nhrp_vc_init(void)
194{
195 size_t i;
196
996c9314 197 nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash");
7e3a1ec7 198 for (i = 0; i < array_size(childlist_head); i++)
b4f3d41b 199 childlist_init(&childlist_head[i]);
2fb975da
TT
200}
201
202void nhrp_vc_reset(void)
203{
b4f3d41b 204 struct child_sa *sa;
2fb975da
TT
205 size_t i;
206
7e3a1ec7 207 for (i = 0; i < array_size(childlist_head); i++) {
b4f3d41b 208 frr_each_safe (childlist, &childlist_head[i], sa)
2fb975da
TT
209 nhrp_vc_ipsec_updown(sa->id, 0);
210 }
211}
212
213void nhrp_vc_terminate(void)
214{
215 nhrp_vc_reset();
216 hash_clean(nhrp_vc_hash, nhrp_vc_free);
217}