nhrp_nhs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /* NHRP NHC nexthop server functions (registration)
  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. #include "zebra.h"
  10. #include "zbuf.h"
  11. #include "memory.h"
  12. #include "thread.h"
  13. #include "nhrpd.h"
  14. #include "nhrp_protocol.h"
  15. static int nhrp_nhs_resolve(struct thread *t);
  16. static int nhrp_reg_send_req(struct thread *t);
  17. static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
  18. {
  19. struct nhrp_packet_parser *p = arg;
  20. struct nhrp_registration *r = container_of(reqid, struct nhrp_registration, reqid);
  21. struct nhrp_nhs *nhs = r->nhs;
  22. struct interface *ifp = nhs->ifp;
  23. struct nhrp_interface *nifp = ifp->info;
  24. struct nhrp_extension_header *ext;
  25. struct nhrp_cie_header *cie;
  26. struct nhrp_cache *c;
  27. struct zbuf extpl;
  28. union sockunion cie_nbma, cie_proto, *proto;
  29. char buf[64];
  30. int ok = 0, holdtime;
  31. nhrp_reqid_free(&nhrp_packet_reqid, &r->reqid);
  32. if (p->hdr->type != NHRP_PACKET_REGISTRATION_REPLY) {
  33. debugf(NHRP_DEBUG_COMMON, "NHS: Registration failed");
  34. return;
  35. }
  36. debugf(NHRP_DEBUG_COMMON, "NHS: Reg.reply received");
  37. ok = 1;
  38. while ((cie = nhrp_cie_pull(&p->payload, p->hdr, &cie_nbma, &cie_proto)) != NULL) {
  39. proto = sockunion_family(&cie_proto) != AF_UNSPEC ? &cie_proto : &p->src_proto;
  40. debugf(NHRP_DEBUG_COMMON, "NHS: CIE registration: %s: %d",
  41. sockunion2str(proto, buf, sizeof(buf)),
  42. cie->code);
  43. if (!((cie->code == NHRP_CODE_SUCCESS) ||
  44. (cie->code == NHRP_CODE_ADMINISTRATIVELY_PROHIBITED && nhs->hub)))
  45. ok = 0;
  46. }
  47. if (!ok)
  48. return;
  49. /* Parse extensions */
  50. sockunion_family(&nifp->nat_nbma) = AF_UNSPEC;
  51. while ((ext = nhrp_ext_pull(&p->extensions, &extpl)) != NULL) {
  52. switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) {
  53. case NHRP_EXTENSION_NAT_ADDRESS:
  54. /* NHS adds second CIE if NAT is detected */
  55. if (nhrp_cie_pull(&extpl, p->hdr, &cie_nbma, &cie_proto) &&
  56. nhrp_cie_pull(&extpl, p->hdr, &cie_nbma, &cie_proto)) {
  57. nifp->nat_nbma = cie_nbma;
  58. debugf(NHRP_DEBUG_IF, "%s: NAT detected, real NBMA address: %s",
  59. ifp->name, sockunion2str(&nifp->nbma, buf, sizeof(buf)));
  60. }
  61. break;
  62. }
  63. }
  64. /* Success - schedule next registration, and route NHS */
  65. r->timeout = 2;
  66. holdtime = nifp->afi[nhs->afi].holdtime;
  67. THREAD_OFF(r->t_register);
  68. /* RFC 2332 5.2.3 - Registration is recommend to be renewed
  69. * every one third of holdtime */
  70. THREAD_TIMER_ON(master, r->t_register, nhrp_reg_send_req, r, holdtime / 3);
  71. r->proto_addr = p->dst_proto;
  72. c = nhrp_cache_get(ifp, &p->dst_proto, 1);
  73. if (c) nhrp_cache_update_binding(c, NHRP_CACHE_NHS, holdtime, nhrp_peer_ref(r->peer), 0, NULL);
  74. }
  75. static int nhrp_reg_timeout(struct thread *t)
  76. {
  77. struct nhrp_registration *r = THREAD_ARG(t);
  78. struct nhrp_cache *c;
  79. r->t_register = NULL;
  80. if (r->timeout >= 16 && sockunion_family(&r->proto_addr) != AF_UNSPEC) {
  81. nhrp_reqid_free(&nhrp_packet_reqid, &r->reqid);
  82. c = nhrp_cache_get(r->nhs->ifp, &r->proto_addr, 0);
  83. if (c) nhrp_cache_update_binding(c, NHRP_CACHE_NHS, -1, NULL, 0, NULL);
  84. sockunion_family(&r->proto_addr) = AF_UNSPEC;
  85. }
  86. r->timeout <<= 1;
  87. if (r->timeout > 64) r->timeout = 2;
  88. THREAD_TIMER_MSEC_ON(master, r->t_register, nhrp_reg_send_req, r, 10);
  89. return 0;
  90. }
  91. static void nhrp_reg_peer_notify(struct notifier_block *n, unsigned long cmd)
  92. {
  93. struct nhrp_registration *r = container_of(n, struct nhrp_registration, peer_notifier);
  94. char buf[SU_ADDRSTRLEN];
  95. switch (cmd) {
  96. case NOTIFY_PEER_UP:
  97. case NOTIFY_PEER_DOWN:
  98. case NOTIFY_PEER_IFCONFIG_CHANGED:
  99. case NOTIFY_PEER_MTU_CHANGED:
  100. debugf(NHRP_DEBUG_COMMON, "NHS: Flush timer for %s",
  101. sockunion2str(&r->peer->vc->remote.nbma, buf, sizeof buf));
  102. THREAD_TIMER_OFF(r->t_register);
  103. THREAD_TIMER_MSEC_ON(master, r->t_register, nhrp_reg_send_req, r, 10);
  104. break;
  105. }
  106. }
  107. static int nhrp_reg_send_req(struct thread *t)
  108. {
  109. struct nhrp_registration *r = THREAD_ARG(t);
  110. struct nhrp_nhs *nhs = r->nhs;
  111. char buf1[SU_ADDRSTRLEN], buf2[SU_ADDRSTRLEN];
  112. struct interface *ifp = nhs->ifp;
  113. struct nhrp_interface *nifp = ifp->info;
  114. struct nhrp_afi_data *if_ad = &nifp->afi[nhs->afi];
  115. union sockunion *dst_proto;
  116. struct zbuf *zb;
  117. struct nhrp_packet_header *hdr;
  118. struct nhrp_extension_header *ext;
  119. struct nhrp_cie_header *cie;
  120. r->t_register = NULL;
  121. if (!nhrp_peer_check(r->peer, 2)) {
  122. debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %s",
  123. sockunion2str(&r->peer->vc->remote.nbma, buf1, sizeof buf1));
  124. THREAD_TIMER_ON(master, r->t_register, nhrp_reg_send_req, r, 120);
  125. return 0;
  126. }
  127. THREAD_TIMER_ON(master, r->t_register, nhrp_reg_timeout, r, r->timeout);
  128. /* RFC2332 5.2.3 NHC uses it's own address as dst if NHS is unknown */
  129. dst_proto = &nhs->proto_addr;
  130. if (sockunion_family(dst_proto) == AF_UNSPEC)
  131. dst_proto = &if_ad->addr;
  132. sockunion2str(&if_ad->addr, buf1, sizeof(buf1));
  133. sockunion2str(dst_proto, buf2, sizeof(buf2));
  134. debugf(NHRP_DEBUG_COMMON, "NHS: Register %s -> %s (timeout %d)", buf1, buf2, r->timeout);
  135. /* No protocol address configured for tunnel interface */
  136. if (sockunion_family(&if_ad->addr) == AF_UNSPEC)
  137. return 0;
  138. zb = zbuf_alloc(1400);
  139. hdr = nhrp_packet_push(zb, NHRP_PACKET_REGISTRATION_REQUEST, &nifp->nbma, &if_ad->addr, dst_proto);
  140. hdr->hop_count = 1;
  141. if (!(if_ad->flags & NHRP_IFF_REG_NO_UNIQUE))
  142. hdr->flags |= htons(NHRP_FLAG_REGISTRATION_UNIQUE);
  143. hdr->u.request_id = htonl(nhrp_reqid_alloc(&nhrp_packet_reqid, &r->reqid, nhrp_reg_reply));
  144. /* FIXME: push CIE for each local protocol address */
  145. cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
  146. cie->prefix_length = 0xff;
  147. cie->holding_time = htons(if_ad->holdtime);
  148. cie->mtu = htons(if_ad->mtu);
  149. nhrp_ext_request(zb, hdr, ifp);
  150. /* Cisco NAT detection extension */
  151. hdr->flags |= htons(NHRP_FLAG_REGISTRATION_NAT);
  152. ext = nhrp_ext_push(zb, hdr, NHRP_EXTENSION_NAT_ADDRESS);
  153. cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &nifp->nbma, &if_ad->addr);
  154. cie->prefix_length = 8 * sockunion_get_addrlen(&if_ad->addr);
  155. nhrp_ext_complete(zb, ext);
  156. nhrp_packet_complete(zb, hdr);
  157. nhrp_peer_send(r->peer, zb);
  158. zbuf_free(zb);
  159. return 0;
  160. }
  161. static void nhrp_reg_delete(struct nhrp_registration *r)
  162. {
  163. nhrp_peer_notify_del(r->peer, &r->peer_notifier);
  164. nhrp_peer_unref(r->peer);
  165. list_del(&r->reglist_entry);
  166. THREAD_OFF(r->t_register);
  167. XFREE(MTYPE_NHRP_REGISTRATION, r);
  168. }
  169. static struct nhrp_registration *nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr)
  170. {
  171. struct nhrp_registration *r;
  172. list_for_each_entry(r, &nhs->reglist_head, reglist_entry)
  173. if (sockunion_same(&r->peer->vc->remote.nbma, nbma_addr))
  174. return r;
  175. return NULL;
  176. }
  177. static void nhrp_nhs_resolve_cb(struct resolver_query *q, int n, union sockunion *addrs)
  178. {
  179. struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve);
  180. struct nhrp_interface *nifp = nhs->ifp->info;
  181. struct nhrp_registration *reg, *regn;
  182. int i;
  183. nhs->t_resolve = NULL;
  184. if (n < 0) {
  185. /* Failed, retry in a moment */
  186. THREAD_TIMER_ON(master, nhs->t_resolve, nhrp_nhs_resolve, nhs, 5);
  187. return;
  188. }
  189. THREAD_TIMER_ON(master, nhs->t_resolve, nhrp_nhs_resolve, nhs, 2*60*60);
  190. list_for_each_entry(reg, &nhs->reglist_head, reglist_entry)
  191. reg->mark = 1;
  192. nhs->hub = 0;
  193. for (i = 0; i < n; i++) {
  194. if (sockunion_same(&addrs[i], &nifp->nbma)) {
  195. nhs->hub = 1;
  196. continue;
  197. }
  198. reg = nhrp_reg_by_nbma(nhs, &addrs[i]);
  199. if (reg) {
  200. reg->mark = 0;
  201. continue;
  202. }
  203. reg = XCALLOC(MTYPE_NHRP_REGISTRATION, sizeof(*reg));
  204. reg->peer = nhrp_peer_get(nhs->ifp, &addrs[i]);
  205. reg->nhs = nhs;
  206. reg->timeout = 1;
  207. list_init(&reg->reglist_entry);
  208. list_add_tail(&reg->reglist_entry, &nhs->reglist_head);
  209. nhrp_peer_notify_add(reg->peer, &reg->peer_notifier, nhrp_reg_peer_notify);
  210. THREAD_TIMER_MSEC_ON(master, reg->t_register, nhrp_reg_send_req, reg, 50);
  211. }
  212. list_for_each_entry_safe(reg, regn, &nhs->reglist_head, reglist_entry) {
  213. if (reg->mark)
  214. nhrp_reg_delete(reg);
  215. }
  216. }
  217. static int nhrp_nhs_resolve(struct thread *t)
  218. {
  219. struct nhrp_nhs *nhs = THREAD_ARG(t);
  220. resolver_resolve(&nhs->dns_resolve, AF_INET, nhs->nbma_fqdn, nhrp_nhs_resolve_cb);
  221. return 0;
  222. }
  223. int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn)
  224. {
  225. struct nhrp_interface *nifp = ifp->info;
  226. struct nhrp_nhs *nhs;
  227. if (sockunion_family(proto_addr) != AF_UNSPEC &&
  228. sockunion_family(proto_addr) != afi2family(afi))
  229. return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
  230. list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) {
  231. if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC &&
  232. sockunion_family(proto_addr) != AF_UNSPEC &&
  233. sockunion_same(&nhs->proto_addr, proto_addr))
  234. return NHRP_ERR_ENTRY_EXISTS;
  235. if (strcmp(nhs->nbma_fqdn, nbma_fqdn) == 0)
  236. return NHRP_ERR_ENTRY_EXISTS;
  237. }
  238. nhs = XMALLOC(MTYPE_NHRP_NHS, sizeof(struct nhrp_nhs));
  239. if (!nhs) return NHRP_ERR_NO_MEMORY;
  240. *nhs = (struct nhrp_nhs) {
  241. .afi = afi,
  242. .ifp = ifp,
  243. .proto_addr = *proto_addr,
  244. .nbma_fqdn = strdup(nbma_fqdn),
  245. .reglist_head = LIST_INITIALIZER(nhs->reglist_head),
  246. };
  247. list_add_tail(&nhs->nhslist_entry, &nifp->afi[afi].nhslist_head);
  248. THREAD_TIMER_MSEC_ON(master, nhs->t_resolve, nhrp_nhs_resolve, nhs, 1000);
  249. return NHRP_OK;
  250. }
  251. int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn)
  252. {
  253. struct nhrp_interface *nifp = ifp->info;
  254. struct nhrp_nhs *nhs, *nnhs;
  255. int ret = NHRP_ERR_ENTRY_NOT_FOUND;
  256. if (sockunion_family(proto_addr) != AF_UNSPEC &&
  257. sockunion_family(proto_addr) != afi2family(afi))
  258. return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
  259. list_for_each_entry_safe(nhs, nnhs, &nifp->afi[afi].nhslist_head, nhslist_entry) {
  260. if (!sockunion_same(&nhs->proto_addr, proto_addr))
  261. continue;
  262. if (strcmp(nhs->nbma_fqdn, nbma_fqdn) != 0)
  263. continue;
  264. nhrp_nhs_free(nhs);
  265. ret = NHRP_OK;
  266. }
  267. return ret;
  268. }
  269. int nhrp_nhs_free(struct nhrp_nhs *nhs)
  270. {
  271. struct nhrp_registration *r, *rn;
  272. list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry)
  273. nhrp_reg_delete(r);
  274. THREAD_OFF(nhs->t_resolve);
  275. list_del(&nhs->nhslist_entry);
  276. free((void*) nhs->nbma_fqdn);
  277. XFREE(MTYPE_NHRP_NHS, nhs);
  278. return 0;
  279. }
  280. void nhrp_nhs_terminate(void)
  281. {
  282. struct interface *ifp;
  283. struct nhrp_interface *nifp;
  284. struct nhrp_nhs *nhs, *tmp;
  285. struct listnode *node;
  286. afi_t afi;
  287. for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
  288. nifp = ifp->info;
  289. for (afi = 0; afi < AFI_MAX; afi++) {
  290. list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head, nhslist_entry)
  291. nhrp_nhs_free(nhs);
  292. }
  293. }
  294. }
  295. void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx)
  296. {
  297. struct nhrp_interface *nifp = ifp->info;
  298. struct nhrp_nhs *nhs;
  299. struct nhrp_registration *reg;
  300. list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) {
  301. if (!list_empty(&nhs->reglist_head)) {
  302. list_for_each_entry(reg, &nhs->reglist_head, reglist_entry)
  303. cb(nhs, reg, ctx);
  304. } else
  305. cb(nhs, 0, ctx);
  306. }
  307. }