1 /* NHRP virtual connection
2 * Copyright (c) 2014-2015 Timo Teräs
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.
20 DEFINE_MTYPE_STATIC(NHRPD
, NHRP_VC
, "NHRP virtual connection")
25 struct list_head childlist_entry
;
28 static struct hash
*nhrp_vc_hash
;
29 static struct list_head childlist_head
[512];
31 static unsigned int nhrp_vc_key(void *peer_data
)
33 struct nhrp_vc
*vc
= peer_data
;
34 return jhash_2words(sockunion_hash(&vc
->local
.nbma
),
35 sockunion_hash(&vc
->remote
.nbma
), 0);
38 static int nhrp_vc_cmp(const void *cache_data
, const void *key_data
)
40 const struct nhrp_vc
*a
= cache_data
;
41 const struct nhrp_vc
*b
= key_data
;
42 return sockunion_same(&a
->local
.nbma
, &b
->local
.nbma
)
43 && sockunion_same(&a
->remote
.nbma
, &b
->remote
.nbma
);
46 static void *nhrp_vc_alloc(void *data
)
48 struct nhrp_vc
*vc
, *key
= data
;
50 vc
= XMALLOC(MTYPE_NHRP_VC
, sizeof(struct nhrp_vc
));
52 *vc
= (struct nhrp_vc
){
53 .local
.nbma
= key
->local
.nbma
,
54 .remote
.nbma
= key
->remote
.nbma
,
56 NOTIFIER_LIST_INITIALIZER(&vc
->notifier_list
),
63 static void nhrp_vc_free(void *data
)
65 XFREE(MTYPE_NHRP_VC
, data
);
68 struct nhrp_vc
*nhrp_vc_get(const union sockunion
*src
,
69 const union sockunion
*dst
, int create
)
72 key
.local
.nbma
= *src
;
73 key
.remote
.nbma
= *dst
;
74 return hash_get(nhrp_vc_hash
, &key
, create
? nhrp_vc_alloc
: 0);
77 static void nhrp_vc_check_delete(struct nhrp_vc
*vc
)
79 if (vc
->updating
|| vc
->ipsec
|| notifier_active(&vc
->notifier_list
))
81 hash_release(nhrp_vc_hash
, vc
);
85 static void nhrp_vc_update(struct nhrp_vc
*vc
, long cmd
)
88 notifier_call(&vc
->notifier_list
, cmd
);
90 nhrp_vc_check_delete(vc
);
93 static void nhrp_vc_ipsec_reset(struct nhrp_vc
*vc
)
96 vc
->local
.certlen
= 0;
98 vc
->remote
.certlen
= 0;
101 int nhrp_vc_ipsec_updown(uint32_t child_id
, struct nhrp_vc
*vc
)
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;
108 list_for_each_entry(lsa
, &childlist_head
[child_hash
], childlist_entry
)
110 if (lsa
->id
== child_id
) {
120 sa
= XMALLOC(MTYPE_NHRP_VC
, sizeof(struct child_sa
));
124 *sa
= (struct child_sa
){
127 LIST_INITIALIZER(sa
->childlist_entry
),
130 list_add_tail(&sa
->childlist_entry
,
131 &childlist_head
[child_hash
]);
138 /* Attach first to new VC */
140 nhrp_vc_update(vc
, NOTIFY_VC_IPSEC_CHANGED
);
143 /* Notify old VC of migration */
144 sa
->vc
->abort_migration
= 0;
145 debugf(NHRP_DEBUG_COMMON
, "IPsec NBMA change of %s to %s",
146 sockunion2str(&sa
->vc
->remote
.nbma
, buf
[0],
148 sockunion2str(&vc
->remote
.nbma
, buf
[1], sizeof buf
[1]));
149 nhrp_vc_update(sa
->vc
, NOTIFY_VC_IPSEC_UPDATE_NBMA
);
150 abort_migration
= sa
->vc
->abort_migration
;
153 /* Deattach old VC */
156 nhrp_vc_ipsec_reset(sa
->vc
);
157 nhrp_vc_update(sa
->vc
, NOTIFY_VC_IPSEC_CHANGED
);
163 list_del(&sa
->childlist_entry
);
164 XFREE(MTYPE_NHRP_VC
, sa
);
167 return abort_migration
;
170 void nhrp_vc_notify_add(struct nhrp_vc
*vc
, struct notifier_block
*n
,
171 notifier_fn_t action
)
173 notifier_add(n
, &vc
->notifier_list
, action
);
176 void nhrp_vc_notify_del(struct nhrp_vc
*vc
, struct notifier_block
*n
)
179 nhrp_vc_check_delete(vc
);
183 struct nhrp_vc_iterator_ctx
{
184 void (*cb
)(struct nhrp_vc
*, void *);
188 static void nhrp_vc_iterator(struct hash_backet
*b
, void *ctx
)
190 struct nhrp_vc_iterator_ctx
*ic
= ctx
;
191 ic
->cb(b
->data
, ic
->ctx
);
194 void nhrp_vc_foreach(void (*cb
)(struct nhrp_vc
*, void *), void *ctx
)
196 struct nhrp_vc_iterator_ctx ic
= {
197 .cb
= cb
, .ctx
= ctx
,
199 hash_iterate(nhrp_vc_hash
, nhrp_vc_iterator
, &ic
);
202 void nhrp_vc_init(void)
206 nhrp_vc_hash
= hash_create(nhrp_vc_key
, nhrp_vc_cmp
, "NHRP VC hash");
207 for (i
= 0; i
< ZEBRA_NUM_OF(childlist_head
); i
++)
208 list_init(&childlist_head
[i
]);
211 void nhrp_vc_reset(void)
213 struct child_sa
*sa
, *n
;
216 for (i
= 0; i
< ZEBRA_NUM_OF(childlist_head
); i
++) {
217 list_for_each_entry_safe(sa
, n
, &childlist_head
[i
],
219 nhrp_vc_ipsec_updown(sa
->id
, 0);
223 void nhrp_vc_terminate(void)
226 hash_clean(nhrp_vc_hash
, nhrp_vc_free
);