]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/nhrp_vc.c
Merge pull request #2809 from opensourcerouting/routemap-rpki-fix
[mirror_frr.git] / nhrpd / nhrp_vc.c
CommitLineData
2fb975da
TT
1/* NHRP virtual connection
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "zebra.h"
11#include "memory.h"
12#include "stream.h"
13#include "hash.h"
14#include "thread.h"
15#include "jhash.h"
16
17#include "nhrpd.h"
18#include "os.h"
19
819dc8bb
DL
20DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection")
21
2fb975da
TT
22struct child_sa {
23 uint32_t id;
24 struct nhrp_vc *vc;
25 struct list_head childlist_entry;
26};
27
28static struct hash *nhrp_vc_hash;
29static struct list_head childlist_head[512];
30
31static unsigned int nhrp_vc_key(void *peer_data)
32{
33 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
38static int nhrp_vc_cmp(const void *cache_data, const void *key_data)
39{
40 const struct nhrp_vc *a = cache_data;
41 const struct nhrp_vc *b = key_data;
996c9314
LB
42 return sockunion_same(&a->local.nbma, &b->local.nbma)
43 && sockunion_same(&a->remote.nbma, &b->remote.nbma);
2fb975da
TT
44}
45
46static void *nhrp_vc_alloc(void *data)
47{
48 struct nhrp_vc *vc, *key = data;
49
50 vc = XMALLOC(MTYPE_NHRP_VC, sizeof(struct nhrp_vc));
51 if (vc) {
996c9314 52 *vc = (struct nhrp_vc){
2fb975da
TT
53 .local.nbma = key->local.nbma,
54 .remote.nbma = key->remote.nbma,
996c9314
LB
55 .notifier_list =
56 NOTIFIER_LIST_INITIALIZER(&vc->notifier_list),
2fb975da
TT
57 };
58 }
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{
103 char buf[2][SU_ADDRSTRLEN];
104 struct child_sa *sa = NULL, *lsa;
105 uint32_t child_hash = child_id % ZEBRA_NUM_OF(childlist_head);
106 int abort_migration = 0;
107
996c9314
LB
108 list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry)
109 {
2fb975da
TT
110 if (lsa->id == child_id) {
111 sa = lsa;
112 break;
113 }
114 }
115
116 if (!sa) {
996c9314
LB
117 if (!vc)
118 return 0;
2fb975da
TT
119
120 sa = XMALLOC(MTYPE_NHRP_VC, sizeof(struct child_sa));
996c9314
LB
121 if (!sa)
122 return 0;
2fb975da 123
996c9314 124 *sa = (struct child_sa){
2fb975da 125 .id = child_id,
996c9314
LB
126 .childlist_entry =
127 LIST_INITIALIZER(sa->childlist_entry),
2fb975da
TT
128 .vc = NULL,
129 };
996c9314
LB
130 list_add_tail(&sa->childlist_entry,
131 &childlist_head[child_hash]);
2fb975da
TT
132 }
133
134 if (sa->vc == vc)
135 return 0;
136
137 if (vc) {
138 /* Attach first to new VC */
139 vc->ipsec++;
140 nhrp_vc_update(vc, NOTIFY_VC_IPSEC_CHANGED);
141 }
142 if (sa->vc && vc) {
143 /* Notify old VC of migration */
144 sa->vc->abort_migration = 0;
145 debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %s to %s",
996c9314
LB
146 sockunion2str(&sa->vc->remote.nbma, buf[0],
147 sizeof buf[0]),
148 sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]));
2fb975da
TT
149 nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_UPDATE_NBMA);
150 abort_migration = sa->vc->abort_migration;
151 }
152 if (sa->vc) {
153 /* Deattach old VC */
154 sa->vc->ipsec--;
996c9314
LB
155 if (!sa->vc->ipsec)
156 nhrp_vc_ipsec_reset(sa->vc);
2fb975da
TT
157 nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_CHANGED);
158 }
159
160 /* Update */
161 sa->vc = vc;
162 if (!vc) {
163 list_del(&sa->childlist_entry);
164 XFREE(MTYPE_NHRP_VC, sa);
165 }
166
167 return abort_migration;
168}
169
996c9314
LB
170void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n,
171 notifier_fn_t action)
2fb975da
TT
172{
173 notifier_add(n, &vc->notifier_list, action);
174}
175
176void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
177{
178 notifier_del(n);
179 nhrp_vc_check_delete(vc);
180}
181
182
183struct nhrp_vc_iterator_ctx {
184 void (*cb)(struct nhrp_vc *, void *);
185 void *ctx;
186};
187
188static void nhrp_vc_iterator(struct hash_backet *b, void *ctx)
189{
190 struct nhrp_vc_iterator_ctx *ic = ctx;
191 ic->cb(b->data, ic->ctx);
192}
193
194void nhrp_vc_foreach(void (*cb)(struct nhrp_vc *, void *), void *ctx)
195{
196 struct nhrp_vc_iterator_ctx ic = {
996c9314 197 .cb = cb, .ctx = ctx,
2fb975da
TT
198 };
199 hash_iterate(nhrp_vc_hash, nhrp_vc_iterator, &ic);
200}
201
202void nhrp_vc_init(void)
203{
204 size_t i;
205
996c9314 206 nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash");
2fb975da
TT
207 for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++)
208 list_init(&childlist_head[i]);
209}
210
211void nhrp_vc_reset(void)
212{
213 struct child_sa *sa, *n;
214 size_t i;
215
216 for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++) {
996c9314
LB
217 list_for_each_entry_safe(sa, n, &childlist_head[i],
218 childlist_entry)
2fb975da
TT
219 nhrp_vc_ipsec_updown(sa->id, 0);
220 }
221}
222
223void nhrp_vc_terminate(void)
224{
225 nhrp_vc_reset();
226 hash_clean(nhrp_vc_hash, nhrp_vc_free);
227}