1 /* NHRP NHC nexthop server functions (registration)
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.
15 #include "nhrp_protocol.h"
17 DEFINE_MTYPE_STATIC(NHRPD
, NHRP_NHS
, "NHRP next hop server")
18 DEFINE_MTYPE_STATIC(NHRPD
, NHRP_REGISTRATION
, "NHRP registration entries")
20 static int nhrp_nhs_resolve(struct thread
*t
);
21 static int nhrp_reg_send_req(struct thread
*t
);
23 static void nhrp_reg_reply(struct nhrp_reqid
*reqid
, void *arg
)
25 struct nhrp_packet_parser
*p
= arg
;
26 struct nhrp_registration
*r
=
27 container_of(reqid
, struct nhrp_registration
, reqid
);
28 struct nhrp_nhs
*nhs
= r
->nhs
;
29 struct interface
*ifp
= nhs
->ifp
;
30 struct nhrp_interface
*nifp
= ifp
->info
;
31 struct nhrp_extension_header
*ext
;
32 struct nhrp_cie_header
*cie
;
35 union sockunion cie_nbma
, cie_proto
, *proto
;
37 unsigned short mtu
= 0;
39 nhrp_reqid_free(&nhrp_packet_reqid
, &r
->reqid
);
41 if (p
->hdr
->type
!= NHRP_PACKET_REGISTRATION_REPLY
) {
42 debugf(NHRP_DEBUG_COMMON
, "NHS: Registration failed");
46 debugf(NHRP_DEBUG_COMMON
, "NHS: Reg.reply received");
49 while ((cie
= nhrp_cie_pull(&p
->payload
, p
->hdr
, &cie_nbma
, &cie_proto
))
51 proto
= sockunion_family(&cie_proto
) != AF_UNSPEC
54 debugf(NHRP_DEBUG_COMMON
, "NHS: CIE registration: %pSU: %d",
56 if (!((cie
->code
== NHRP_CODE_SUCCESS
)
57 || (cie
->code
== NHRP_CODE_ADMINISTRATIVELY_PROHIBITED
60 mtu
= ntohs(cie
->mtu
);
61 debugf(NHRP_DEBUG_COMMON
, "NHS: CIE MTU: %d", mtu
);
67 /* Parse extensions */
68 sockunion_family(&nifp
->nat_nbma
) = AF_UNSPEC
;
69 while ((ext
= nhrp_ext_pull(&p
->extensions
, &extpl
)) != NULL
) {
70 switch (htons(ext
->type
) & ~NHRP_EXTENSION_FLAG_COMPULSORY
) {
71 case NHRP_EXTENSION_NAT_ADDRESS
:
72 /* NHS adds second CIE if NAT is detected */
73 if (nhrp_cie_pull(&extpl
, p
->hdr
, &cie_nbma
, &cie_proto
)
74 && nhrp_cie_pull(&extpl
, p
->hdr
, &cie_nbma
,
76 nifp
->nat_nbma
= cie_nbma
;
78 "%s: NAT detected, real NBMA address: %pSU",
79 ifp
->name
, &nifp
->nbma
);
85 /* Success - schedule next registration, and route NHS */
87 holdtime
= nifp
->afi
[nhs
->afi
].holdtime
;
88 THREAD_OFF(r
->t_register
);
90 /* RFC 2332 5.2.3 - Registration is recommend to be renewed
91 * every one third of holdtime */
92 thread_add_timer(master
, nhrp_reg_send_req
, r
, holdtime
/ 3,
95 r
->proto_addr
= p
->dst_proto
;
96 c
= nhrp_cache_get(ifp
, &p
->dst_proto
, 1);
98 nhrp_cache_update_binding(c
, NHRP_CACHE_NHS
, holdtime
,
99 nhrp_peer_ref(r
->peer
), mtu
, NULL
);
102 static int nhrp_reg_timeout(struct thread
*t
)
104 struct nhrp_registration
*r
= THREAD_ARG(t
);
105 struct nhrp_cache
*c
;
107 r
->t_register
= NULL
;
109 if (r
->timeout
>= 16 && sockunion_family(&r
->proto_addr
) != AF_UNSPEC
) {
110 nhrp_reqid_free(&nhrp_packet_reqid
, &r
->reqid
);
111 c
= nhrp_cache_get(r
->nhs
->ifp
, &r
->proto_addr
, 0);
113 nhrp_cache_update_binding(c
, NHRP_CACHE_NHS
, -1, NULL
,
115 sockunion_family(&r
->proto_addr
) = AF_UNSPEC
;
121 //Remove the ipsec connection if it is there, it can get re-established later
122 if(r
->peer
&& r
->peer
->vc
&& r
->peer
->vc
->ike_uniqueid
)
124 debugf(NHRP_DEBUG_COMMON
, "Terminating IPSec Connection for %d\n", r
->peer
->vc
->ike_uniqueid
);
125 vici_terminate_vc(r
->peer
->vc
->ike_uniqueid
);
129 thread_add_timer_msec(master
, nhrp_reg_send_req
, r
, 10, &r
->t_register
);
134 static void nhrp_reg_peer_notify(struct notifier_block
*n
, unsigned long cmd
)
136 struct nhrp_registration
*r
=
137 container_of(n
, struct nhrp_registration
, peer_notifier
);
141 case NOTIFY_PEER_DOWN
:
142 case NOTIFY_PEER_IFCONFIG_CHANGED
:
143 case NOTIFY_PEER_MTU_CHANGED
:
144 debugf(NHRP_DEBUG_COMMON
, "NHS: Flush timer for %pSU",
145 &r
->peer
->vc
->remote
.nbma
);
146 THREAD_OFF(r
->t_register
);
147 thread_add_timer_msec(master
, nhrp_reg_send_req
, r
, 10,
153 static int nhrp_reg_send_req(struct thread
*t
)
155 struct nhrp_registration
*r
= THREAD_ARG(t
);
156 struct nhrp_nhs
*nhs
= r
->nhs
;
157 char buf1
[SU_ADDRSTRLEN
], buf2
[SU_ADDRSTRLEN
];
158 struct interface
*ifp
= nhs
->ifp
;
159 struct nhrp_interface
*nifp
= ifp
->info
;
160 struct nhrp_afi_data
*if_ad
= &nifp
->afi
[nhs
->afi
];
161 union sockunion
*dst_proto
;
163 struct nhrp_packet_header
*hdr
;
164 struct nhrp_extension_header
*ext
;
165 struct nhrp_cie_header
*cie
;
167 r
->t_register
= NULL
;
168 if (!nhrp_peer_check(r
->peer
, 2)) {
169 debugf(NHRP_DEBUG_COMMON
, "NHS: Waiting link for %pSU",
170 &r
->peer
->vc
->remote
.nbma
);
171 thread_add_timer(master
, nhrp_reg_send_req
, r
, 120,
176 thread_add_timer(master
, nhrp_reg_timeout
, r
, r
->timeout
,
179 /* RFC2332 5.2.3 NHC uses it's own address as dst if NHS is unknown */
180 dst_proto
= &nhs
->proto_addr
;
181 if (sockunion_family(dst_proto
) == AF_UNSPEC
)
182 dst_proto
= &if_ad
->addr
;
184 sockunion2str(&if_ad
->addr
, buf1
, sizeof(buf1
));
185 sockunion2str(dst_proto
, buf2
, sizeof(buf2
));
186 debugf(NHRP_DEBUG_COMMON
, "NHS: Register %s -> %s (timeout %d)", buf1
,
189 /* No protocol address configured for tunnel interface */
190 if (sockunion_family(&if_ad
->addr
) == AF_UNSPEC
)
193 zb
= zbuf_alloc(1400);
194 hdr
= nhrp_packet_push(zb
, NHRP_PACKET_REGISTRATION_REQUEST
,
195 &nifp
->nbma
, &if_ad
->addr
, dst_proto
);
197 if (!(if_ad
->flags
& NHRP_IFF_REG_NO_UNIQUE
))
198 hdr
->flags
|= htons(NHRP_FLAG_REGISTRATION_UNIQUE
);
200 hdr
->u
.request_id
= htonl(nhrp_reqid_alloc(&nhrp_packet_reqid
,
201 &r
->reqid
, nhrp_reg_reply
));
203 /* FIXME: push CIE for each local protocol address */
204 cie
= nhrp_cie_push(zb
, NHRP_CODE_SUCCESS
, NULL
, NULL
);
205 /* RFC2332 5.2.1 if unique is set then prefix length must be 0xff */
206 cie
->prefix_length
= (if_ad
->flags
& NHRP_IFF_REG_NO_UNIQUE
) ? 8 * sockunion_get_addrlen(dst_proto
) : 0xff;
207 cie
->holding_time
= htons(if_ad
->holdtime
);
208 cie
->mtu
= htons(if_ad
->mtu
);
210 nhrp_ext_request(zb
, hdr
, ifp
);
212 /* Cisco NAT detection extension */
213 hdr
->flags
|= htons(NHRP_FLAG_REGISTRATION_NAT
);
214 ext
= nhrp_ext_push(zb
, hdr
, NHRP_EXTENSION_NAT_ADDRESS
);
215 cie
= nhrp_cie_push(zb
, NHRP_CODE_SUCCESS
, &nifp
->nbma
, &if_ad
->addr
);
216 cie
->prefix_length
= 8 * sockunion_get_addrlen(&if_ad
->addr
);
217 nhrp_ext_complete(zb
, ext
);
219 nhrp_packet_complete(zb
, hdr
);
220 nhrp_peer_send(r
->peer
, zb
);
226 static void nhrp_reg_delete(struct nhrp_registration
*r
)
228 nhrp_peer_notify_del(r
->peer
, &r
->peer_notifier
);
229 nhrp_peer_unref(r
->peer
);
230 list_del(&r
->reglist_entry
);
231 THREAD_OFF(r
->t_register
);
232 XFREE(MTYPE_NHRP_REGISTRATION
, r
);
235 static struct nhrp_registration
*
236 nhrp_reg_by_nbma(struct nhrp_nhs
*nhs
, const union sockunion
*nbma_addr
)
238 struct nhrp_registration
*r
;
241 r
, &nhs
->reglist_head
,
242 reglist_entry
) if (sockunion_same(&r
->peer
->vc
->remote
.nbma
,
243 nbma_addr
)) return r
;
247 static void nhrp_nhs_resolve_cb(struct resolver_query
*q
, const char *errstr
,
248 int n
, union sockunion
*addrs
)
250 struct nhrp_nhs
*nhs
= container_of(q
, struct nhrp_nhs
, dns_resolve
);
251 struct nhrp_interface
*nifp
= nhs
->ifp
->info
;
252 struct nhrp_registration
*reg
, *regn
;
255 nhs
->t_resolve
= NULL
;
257 /* Failed, retry in a moment */
258 thread_add_timer(master
, nhrp_nhs_resolve
, nhs
, 5,
263 thread_add_timer(master
, nhrp_nhs_resolve
, nhs
, 2 * 60 * 60,
266 list_for_each_entry(reg
, &nhs
->reglist_head
, reglist_entry
) reg
->mark
=
270 for (i
= 0; i
< n
; i
++) {
271 if (sockunion_same(&addrs
[i
], &nifp
->nbma
)) {
276 reg
= nhrp_reg_by_nbma(nhs
, &addrs
[i
]);
282 reg
= XCALLOC(MTYPE_NHRP_REGISTRATION
, sizeof(*reg
));
283 reg
->peer
= nhrp_peer_get(nhs
->ifp
, &addrs
[i
]);
286 list_init(®
->reglist_entry
);
287 list_add_tail(®
->reglist_entry
, &nhs
->reglist_head
);
288 nhrp_peer_notify_add(reg
->peer
, ®
->peer_notifier
,
289 nhrp_reg_peer_notify
);
290 thread_add_timer_msec(master
, nhrp_reg_send_req
, reg
, 50,
294 list_for_each_entry_safe(reg
, regn
, &nhs
->reglist_head
, reglist_entry
)
297 nhrp_reg_delete(reg
);
301 static int nhrp_nhs_resolve(struct thread
*t
)
303 struct nhrp_nhs
*nhs
= THREAD_ARG(t
);
305 resolver_resolve(&nhs
->dns_resolve
, AF_INET
, nhs
->nbma_fqdn
,
306 nhrp_nhs_resolve_cb
);
311 int nhrp_nhs_add(struct interface
*ifp
, afi_t afi
, union sockunion
*proto_addr
,
312 const char *nbma_fqdn
)
314 struct nhrp_interface
*nifp
= ifp
->info
;
315 struct nhrp_nhs
*nhs
;
317 if (sockunion_family(proto_addr
) != AF_UNSPEC
318 && sockunion_family(proto_addr
) != afi2family(afi
))
319 return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH
;
321 list_for_each_entry(nhs
, &nifp
->afi
[afi
].nhslist_head
, nhslist_entry
)
323 if (sockunion_family(&nhs
->proto_addr
) != AF_UNSPEC
324 && sockunion_family(proto_addr
) != AF_UNSPEC
325 && sockunion_same(&nhs
->proto_addr
, proto_addr
))
326 return NHRP_ERR_ENTRY_EXISTS
;
328 if (strcmp(nhs
->nbma_fqdn
, nbma_fqdn
) == 0)
329 return NHRP_ERR_ENTRY_EXISTS
;
332 nhs
= XMALLOC(MTYPE_NHRP_NHS
, sizeof(struct nhrp_nhs
));
334 *nhs
= (struct nhrp_nhs
){
337 .proto_addr
= *proto_addr
,
338 .nbma_fqdn
= strdup(nbma_fqdn
),
339 .reglist_head
= LIST_INITIALIZER(nhs
->reglist_head
),
341 list_add_tail(&nhs
->nhslist_entry
, &nifp
->afi
[afi
].nhslist_head
);
342 thread_add_timer_msec(master
, nhrp_nhs_resolve
, nhs
, 1000,
348 int nhrp_nhs_del(struct interface
*ifp
, afi_t afi
, union sockunion
*proto_addr
,
349 const char *nbma_fqdn
)
351 struct nhrp_interface
*nifp
= ifp
->info
;
352 struct nhrp_nhs
*nhs
, *nnhs
;
353 int ret
= NHRP_ERR_ENTRY_NOT_FOUND
;
355 if (sockunion_family(proto_addr
) != AF_UNSPEC
356 && sockunion_family(proto_addr
) != afi2family(afi
))
357 return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH
;
359 list_for_each_entry_safe(nhs
, nnhs
, &nifp
->afi
[afi
].nhslist_head
,
362 if (!sockunion_same(&nhs
->proto_addr
, proto_addr
))
364 if (strcmp(nhs
->nbma_fqdn
, nbma_fqdn
) != 0)
374 int nhrp_nhs_free(struct nhrp_nhs
*nhs
)
376 struct nhrp_registration
*r
, *rn
;
378 list_for_each_entry_safe(r
, rn
, &nhs
->reglist_head
, reglist_entry
)
380 THREAD_OFF(nhs
->t_resolve
);
381 list_del(&nhs
->nhslist_entry
);
382 free((void *)nhs
->nbma_fqdn
);
383 XFREE(MTYPE_NHRP_NHS
, nhs
);
387 void nhrp_nhs_interface_del(struct interface
*ifp
)
389 struct nhrp_interface
*nifp
= ifp
->info
;
390 struct nhrp_nhs
*nhs
, *tmp
;
393 for (afi
= 0; afi
< AFI_MAX
; afi
++) {
394 debugf(NHRP_DEBUG_COMMON
, "Cleaning up nhs entries (%d)",
395 !list_empty(&nifp
->afi
[afi
].nhslist_head
));
397 list_for_each_entry_safe(nhs
, tmp
, &nifp
->afi
[afi
].nhslist_head
,
405 void nhrp_nhs_terminate(void)
407 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
408 struct interface
*ifp
;
409 struct nhrp_interface
*nifp
;
410 struct nhrp_nhs
*nhs
, *tmp
;
413 FOR_ALL_INTERFACES (vrf
, ifp
) {
415 for (afi
= 0; afi
< AFI_MAX
; afi
++) {
416 list_for_each_entry_safe(
417 nhs
, tmp
, &nifp
->afi
[afi
].nhslist_head
,
418 nhslist_entry
) nhrp_nhs_free(nhs
);
423 void nhrp_nhs_foreach(struct interface
*ifp
, afi_t afi
,
424 void (*cb
)(struct nhrp_nhs
*, struct nhrp_registration
*,
428 struct nhrp_interface
*nifp
= ifp
->info
;
429 struct nhrp_nhs
*nhs
;
430 struct nhrp_registration
*reg
;
432 list_for_each_entry(nhs
, &nifp
->afi
[afi
].nhslist_head
, nhslist_entry
)
434 if (!list_empty(&nhs
->reglist_head
)) {
435 list_for_each_entry(reg
, &nhs
->reglist_head
,
436 reglist_entry
) cb(nhs
, reg
, ctx
);