l2vpn.c revision 1.17
1/* $OpenBSD: l2vpn.c,v 1.17 2016/06/18 01:25:53 renato Exp $ */ 2 3/* 4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 6 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 7 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22#include <sys/types.h> 23#include <stdlib.h> 24#include <string.h> 25#include <limits.h> 26 27#include "ldpd.h" 28#include "ldpe.h" 29#include "lde.h" 30#include "log.h" 31 32static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *); 33 34struct l2vpn * 35l2vpn_new(const char *name) 36{ 37 struct l2vpn *l2vpn; 38 39 if ((l2vpn = calloc(1, sizeof(*l2vpn))) == NULL) 40 fatal("l2vpn_new: calloc"); 41 42 strlcpy(l2vpn->name, name, sizeof(l2vpn->name)); 43 44 /* set default values */ 45 l2vpn->mtu = DEFAULT_L2VPN_MTU; 46 l2vpn->pw_type = DEFAULT_PW_TYPE; 47 48 LIST_INIT(&l2vpn->if_list); 49 LIST_INIT(&l2vpn->pw_list); 50 51 return (l2vpn); 52} 53 54struct l2vpn * 55l2vpn_find(struct ldpd_conf *xconf, const char *name) 56{ 57 struct l2vpn *l2vpn; 58 59 LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) 60 if (strcmp(l2vpn->name, name) == 0) 61 return (l2vpn); 62 63 return (NULL); 64} 65 66void 67l2vpn_del(struct l2vpn *l2vpn) 68{ 69 struct l2vpn_if *lif; 70 struct l2vpn_pw *pw; 71 72 while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { 73 LIST_REMOVE(lif, entry); 74 free(lif); 75 } 76 while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { 77 l2vpn_pw_exit(pw); 78 LIST_REMOVE(pw, entry); 79 free(pw); 80 } 81 82 free(l2vpn); 83} 84 85void 86l2vpn_init(struct l2vpn *l2vpn) 87{ 88 struct l2vpn_pw *pw; 89 90 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 91 l2vpn_pw_init(pw); 92} 93 94struct l2vpn_if * 95l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) 96{ 97 struct l2vpn_if *lif; 98 99 if ((lif = calloc(1, sizeof(*lif))) == NULL) 100 fatal("l2vpn_if_new: calloc"); 101 102 lif->l2vpn = l2vpn; 103 strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); 104 lif->ifindex = kif->ifindex; 105 lif->flags = kif->flags; 106 lif->link_state = kif->link_state; 107 108 return (lif); 109} 110 111struct l2vpn_if * 112l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) 113{ 114 struct l2vpn_if *lif; 115 116 LIST_FOREACH(lif, &l2vpn->if_list, entry) 117 if (lif->ifindex == ifindex) 118 return (lif); 119 120 return (NULL); 121} 122 123struct l2vpn_pw * 124l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) 125{ 126 struct l2vpn_pw *pw; 127 128 if ((pw = calloc(1, sizeof(*pw))) == NULL) 129 fatal("l2vpn_pw_new: calloc"); 130 131 pw->l2vpn = l2vpn; 132 strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); 133 pw->ifindex = kif->ifindex; 134 135 return (pw); 136} 137 138struct l2vpn_pw * 139l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) 140{ 141 struct l2vpn_pw *pw; 142 143 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 144 if (pw->ifindex == ifindex) 145 return (pw); 146 147 return (NULL); 148} 149 150void 151l2vpn_pw_init(struct l2vpn_pw *pw) 152{ 153 struct fec fec; 154 155 l2vpn_pw_reset(pw); 156 157 l2vpn_pw_fec(pw, &fec); 158 lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 159 0, (void *)pw); 160} 161 162void 163l2vpn_pw_exit(struct l2vpn_pw *pw) 164{ 165 struct fec fec; 166 167 l2vpn_pw_fec(pw, &fec); 168 lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0); 169} 170 171static void 172l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec) 173{ 174 memset(fec, 0, sizeof(*fec)); 175 fec->type = FEC_TYPE_PWID; 176 fec->u.pwid.type = pw->l2vpn->pw_type; 177 fec->u.pwid.pwid = pw->pwid; 178 fec->u.pwid.lsr_id = pw->lsr_id; 179} 180 181void 182l2vpn_pw_reset(struct l2vpn_pw *pw) 183{ 184 pw->remote_group = 0; 185 pw->remote_mtu = 0; 186 pw->remote_status = 0; 187 188 if (pw->flags & F_PW_CWORD_CONF) 189 pw->flags |= F_PW_CWORD; 190 else 191 pw->flags &= ~F_PW_CWORD; 192 193 if (pw->flags & F_PW_STATUSTLV_CONF) 194 pw->flags |= F_PW_STATUSTLV; 195 else 196 pw->flags &= ~F_PW_STATUSTLV; 197} 198 199int 200l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) 201{ 202 struct fec fec; 203 struct fec_node *fn; 204 205 /* check for a remote label */ 206 if (fnh->remote_label == NO_LABEL) 207 return (0); 208 209 /* MTUs must match */ 210 if (pw->l2vpn->mtu != pw->remote_mtu) 211 return (0); 212 213 /* check pw status if applicable */ 214 if ((pw->flags & F_PW_STATUSTLV) && 215 pw->remote_status != PW_FORWARDING) 216 return (0); 217 218 /* check for a working lsp to the nexthop */ 219 memset(&fec, 0, sizeof(fec)); 220 switch (pw->af) { 221 case AF_INET: 222 fec.type = FEC_TYPE_IPV4; 223 fec.u.ipv4.prefix = pw->addr.v4; 224 fec.u.ipv4.prefixlen = 32; 225 break; 226 case AF_INET6: 227 fec.type = FEC_TYPE_IPV6; 228 fec.u.ipv6.prefix = pw->addr.v6; 229 fec.u.ipv6.prefixlen = 128; 230 break; 231 default: 232 fatalx("l2vpn_pw_ok: unknown af"); 233 } 234 235 fn = (struct fec_node *)fec_find(&ft, &fec); 236 if (fn == NULL || fn->local_label == NO_LABEL) 237 return (0); 238 /* 239 * Need to ensure that there's a label binding for all nexthops. 240 * Otherwise, ECMP for this route could render the pseudowire unusable. 241 */ 242 LIST_FOREACH(fnh, &fn->nexthops, entry) 243 if (fnh->remote_label == NO_LABEL) 244 return (0); 245 246 return (1); 247} 248 249int 250l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) 251{ 252 struct l2vpn_pw *pw; 253 254 /* NOTE: thanks martini & friends for all this mess */ 255 256 pw = (struct l2vpn_pw *) fn->data; 257 if (pw == NULL) 258 /* 259 * pseudowire not configured, return and record 260 * the mapping later 261 */ 262 return (0); 263 264 /* RFC4447 - Section 6.2: control word negotiation */ 265 if (fec_find(&ln->sent_map, &fn->fec)) { 266 if ((map->flags & F_MAP_PW_CWORD) && 267 !(pw->flags & F_PW_CWORD_CONF)) { 268 /* ignore the received label mapping */ 269 return (1); 270 } else if (!(map->flags & F_MAP_PW_CWORD) && 271 (pw->flags & F_PW_CWORD_CONF)) { 272 /* TODO append a "Wrong C-bit" status code */ 273 lde_send_labelwithdraw(ln, fn, NO_LABEL); 274 275 pw->flags &= ~F_PW_CWORD; 276 lde_send_labelmapping(ln, fn, 1); 277 } 278 } else if (map->flags & F_MAP_PW_CWORD) { 279 if (pw->flags & F_PW_CWORD_CONF) 280 pw->flags |= F_PW_CWORD; 281 else 282 /* act as if no label mapping had been received */ 283 return (1); 284 } else 285 pw->flags &= ~F_PW_CWORD; 286 287 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */ 288 if (fec_find(&ln->recv_map, &fn->fec) == NULL && 289 !(map->flags & F_MAP_PW_STATUS)) 290 pw->flags &= ~F_PW_STATUSTLV; 291 292 return (0); 293} 294 295void 296l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec) 297{ 298 struct notify_msg nm; 299 300 memset(&nm, 0, sizeof(nm)); 301 nm.status = S_PW_STATUS; 302 303 nm.pw_status = status; 304 nm.flags |= F_NOTIF_PW_STATUS; 305 306 lde_fec2map(fec, &nm.fec); 307 nm.flags |= F_NOTIF_FEC; 308 309 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0, 310 &nm, sizeof(nm)); 311} 312 313void 314l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) 315{ 316 struct fec fec; 317 struct fec_node *fn; 318 struct fec_nh *fnh; 319 struct l2vpn_pw *pw; 320 321 /* TODO group wildcard */ 322 if (!(nm->fec.flags & F_MAP_PW_ID)) 323 return; 324 325 lde_map2fec(&nm->fec, ln->id, &fec); 326 fn = (struct fec_node *)fec_find(&ft, &fec); 327 if (fn == NULL) 328 /* unknown fec */ 329 return; 330 331 pw = (struct l2vpn_pw *) fn->data; 332 if (pw == NULL) 333 return; 334 335 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0); 336 if (fnh == NULL) 337 return; 338 339 /* remote status didn't change */ 340 if (pw->remote_status == nm->pw_status) 341 return; 342 343 pw->remote_status = nm->pw_status; 344 345 if (l2vpn_pw_ok(pw, fnh)) 346 lde_send_change_klabel(fn, fnh); 347 else 348 lde_send_delete_klabel(fn, fnh); 349} 350 351void 352l2vpn_sync_pws(int af, union ldpd_addr *addr) 353{ 354 struct l2vpn *l2vpn; 355 struct l2vpn_pw *pw; 356 struct fec fec; 357 struct fec_node *fn; 358 struct fec_nh *fnh; 359 360 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { 361 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 362 if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) 363 continue; 364 365 l2vpn_pw_fec(pw, &fec); 366 fn = (struct fec_node *)fec_find(&ft, &fec); 367 if (fn == NULL) 368 continue; 369 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *) 370 &pw->lsr_id, 0); 371 if (fnh == NULL) 372 continue; 373 374 if (l2vpn_pw_ok(pw, fnh)) 375 lde_send_change_klabel(fn, fnh); 376 else 377 lde_send_delete_klabel(fn, fnh); 378 } 379 } 380} 381 382void 383l2vpn_pw_ctl(pid_t pid) 384{ 385 struct l2vpn *l2vpn; 386 struct l2vpn_pw *pw; 387 static struct ctl_pw pwctl; 388 389 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) 390 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 391 memset(&pwctl, 0, sizeof(pwctl)); 392 strlcpy(pwctl.ifname, pw->ifname, 393 sizeof(pwctl.ifname)); 394 pwctl.pwid = pw->pwid; 395 pwctl.lsr_id = pw->lsr_id; 396 pwctl.status = pw->flags & F_PW_STATUS_UP; 397 398 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0, 399 pid, &pwctl, sizeof(pwctl)); 400 } 401} 402 403void 404l2vpn_binding_ctl(pid_t pid) 405{ 406 struct fec *f; 407 struct fec_node *fn; 408 struct lde_map *me; 409 struct l2vpn_pw *pw; 410 static struct ctl_pw pwctl; 411 412 RB_FOREACH(f, fec_tree, &ft) { 413 if (f->type != FEC_TYPE_PWID) 414 continue; 415 416 fn = (struct fec_node *)f; 417 if (fn->local_label == NO_LABEL && 418 LIST_EMPTY(&fn->downstream)) 419 continue; 420 421 memset(&pwctl, 0, sizeof(pwctl)); 422 pwctl.type = f->u.pwid.type; 423 pwctl.pwid = f->u.pwid.pwid; 424 pwctl.lsr_id = f->u.pwid.lsr_id; 425 426 pw = (struct l2vpn_pw *) fn->data; 427 if (pw) { 428 pwctl.local_label = fn->local_label; 429 pwctl.local_gid = 0; 430 pwctl.local_ifmtu = pw->l2vpn->mtu; 431 } else 432 pwctl.local_label = NO_LABEL; 433 434 LIST_FOREACH(me, &fn->downstream, entry) 435 if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) 436 break; 437 438 if (me) { 439 pwctl.remote_label = me->map.label; 440 pwctl.remote_gid = me->map.fec.pwid.group_id; 441 if (me->map.flags & F_MAP_PW_IFMTU) 442 pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu; 443 444 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 445 0, pid, &pwctl, sizeof(pwctl)); 446 } else if (pw) { 447 pwctl.remote_label = NO_LABEL; 448 449 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 450 0, pid, &pwctl, sizeof(pwctl)); 451 } 452 } 453} 454 455/* ldpe */ 456 457void 458ldpe_l2vpn_init(struct l2vpn *l2vpn) 459{ 460 struct l2vpn_pw *pw; 461 462 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 463 ldpe_l2vpn_pw_init(pw); 464} 465 466void 467ldpe_l2vpn_exit(struct l2vpn *l2vpn) 468{ 469 struct l2vpn_pw *pw; 470 471 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 472 ldpe_l2vpn_pw_exit(pw); 473} 474 475void 476ldpe_l2vpn_pw_init(struct l2vpn_pw *pw) 477{ 478 struct tnbr *tnbr; 479 480 tnbr = tnbr_find(leconf, pw->af, &pw->addr); 481 if (tnbr == NULL) { 482 tnbr = tnbr_new(leconf, pw->af, &pw->addr); 483 tnbr_update(tnbr); 484 LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); 485 } 486 487 tnbr->pw_count++; 488} 489 490void 491ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw) 492{ 493 struct tnbr *tnbr; 494 495 tnbr = tnbr_find(leconf, pw->af, &pw->addr); 496 if (tnbr) { 497 tnbr->pw_count--; 498 tnbr_check(tnbr); 499 } 500} 501