1 /* $OpenBSD: l2vpn.c,v 1.21 2016/07/01 23:36:38 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 32 static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *); 33 34 struct l2vpn * 35 l2vpn_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 54 struct l2vpn * 55 l2vpn_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 66 void 67 l2vpn_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 LIST_REMOVE(pw, entry); 78 free(pw); 79 } 80 81 free(l2vpn); 82 } 83 84 void 85 l2vpn_init(struct l2vpn *l2vpn) 86 { 87 struct l2vpn_pw *pw; 88 89 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 90 l2vpn_pw_init(pw); 91 } 92 93 void 94 l2vpn_exit(struct l2vpn *l2vpn) 95 { 96 struct l2vpn_pw *pw; 97 98 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 99 l2vpn_pw_exit(pw); 100 } 101 102 struct l2vpn_if * 103 l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) 104 { 105 struct l2vpn_if *lif; 106 107 if ((lif = calloc(1, sizeof(*lif))) == NULL) 108 fatal("l2vpn_if_new: calloc"); 109 110 lif->l2vpn = l2vpn; 111 strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); 112 lif->ifindex = kif->ifindex; 113 lif->flags = kif->flags; 114 lif->link_state = kif->link_state; 115 116 return (lif); 117 } 118 119 struct l2vpn_if * 120 l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) 121 { 122 struct l2vpn_if *lif; 123 124 LIST_FOREACH(lif, &l2vpn->if_list, entry) 125 if (lif->ifindex == ifindex) 126 return (lif); 127 128 return (NULL); 129 } 130 131 struct l2vpn_pw * 132 l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) 133 { 134 struct l2vpn_pw *pw; 135 136 if ((pw = calloc(1, sizeof(*pw))) == NULL) 137 fatal("l2vpn_pw_new: calloc"); 138 139 pw->l2vpn = l2vpn; 140 strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); 141 pw->ifindex = kif->ifindex; 142 143 return (pw); 144 } 145 146 struct l2vpn_pw * 147 l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) 148 { 149 struct l2vpn_pw *pw; 150 151 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 152 if (pw->ifindex == ifindex) 153 return (pw); 154 155 return (NULL); 156 } 157 158 void 159 l2vpn_pw_init(struct l2vpn_pw *pw) 160 { 161 struct fec fec; 162 163 l2vpn_pw_reset(pw); 164 165 l2vpn_pw_fec(pw, &fec); 166 lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 167 0, (void *)pw); 168 } 169 170 void 171 l2vpn_pw_exit(struct l2vpn_pw *pw) 172 { 173 struct fec fec; 174 175 l2vpn_pw_fec(pw, &fec); 176 lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0); 177 } 178 179 static void 180 l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec) 181 { 182 memset(fec, 0, sizeof(*fec)); 183 fec->type = FEC_TYPE_PWID; 184 fec->u.pwid.type = pw->l2vpn->pw_type; 185 fec->u.pwid.pwid = pw->pwid; 186 fec->u.pwid.lsr_id = pw->lsr_id; 187 } 188 189 void 190 l2vpn_pw_reset(struct l2vpn_pw *pw) 191 { 192 pw->remote_group = 0; 193 pw->remote_mtu = 0; 194 pw->remote_status = 0; 195 196 if (pw->flags & F_PW_CWORD_CONF) 197 pw->flags |= F_PW_CWORD; 198 else 199 pw->flags &= ~F_PW_CWORD; 200 201 if (pw->flags & F_PW_STATUSTLV_CONF) 202 pw->flags |= F_PW_STATUSTLV; 203 else 204 pw->flags &= ~F_PW_STATUSTLV; 205 } 206 207 int 208 l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) 209 { 210 struct fec fec; 211 struct fec_node *fn; 212 213 /* check for a remote label */ 214 if (fnh->remote_label == NO_LABEL) 215 return (0); 216 217 /* MTUs must match */ 218 if (pw->l2vpn->mtu != pw->remote_mtu) 219 return (0); 220 221 /* check pw status if applicable */ 222 if ((pw->flags & F_PW_STATUSTLV) && 223 pw->remote_status != PW_FORWARDING) 224 return (0); 225 226 /* check for a working lsp to the nexthop */ 227 memset(&fec, 0, sizeof(fec)); 228 switch (pw->af) { 229 case AF_INET: 230 fec.type = FEC_TYPE_IPV4; 231 fec.u.ipv4.prefix = pw->addr.v4; 232 fec.u.ipv4.prefixlen = 32; 233 break; 234 case AF_INET6: 235 fec.type = FEC_TYPE_IPV6; 236 fec.u.ipv6.prefix = pw->addr.v6; 237 fec.u.ipv6.prefixlen = 128; 238 break; 239 default: 240 fatalx("l2vpn_pw_ok: unknown af"); 241 } 242 243 fn = (struct fec_node *)fec_find(&ft, &fec); 244 if (fn == NULL || fn->local_label == NO_LABEL) 245 return (0); 246 /* 247 * Need to ensure that there's a label binding for all nexthops. 248 * Otherwise, ECMP for this route could render the pseudowire unusable. 249 */ 250 LIST_FOREACH(fnh, &fn->nexthops, entry) 251 if (fnh->remote_label == NO_LABEL) 252 return (0); 253 254 return (1); 255 } 256 257 int 258 l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) 259 { 260 struct l2vpn_pw *pw; 261 struct status_tlv st; 262 263 /* NOTE: thanks martini & friends for all this mess */ 264 265 pw = (struct l2vpn_pw *) fn->data; 266 if (pw == NULL) 267 /* 268 * pseudowire not configured, return and record 269 * the mapping later 270 */ 271 return (0); 272 273 /* RFC4447 - Section 6.2: control word negotiation */ 274 if (fec_find(&ln->sent_map, &fn->fec)) { 275 if ((map->flags & F_MAP_PW_CWORD) && 276 !(pw->flags & F_PW_CWORD_CONF)) { 277 /* ignore the received label mapping */ 278 return (1); 279 } else if (!(map->flags & F_MAP_PW_CWORD) && 280 (pw->flags & F_PW_CWORD_CONF)) { 281 /* append a "Wrong C-bit" status code */ 282 st.status_code = S_WRONG_CBIT; 283 st.msg_id = map->msg_id; 284 st.msg_type = htons(MSG_TYPE_LABELMAPPING); 285 lde_send_labelwithdraw(ln, fn, NO_LABEL, &st); 286 287 pw->flags &= ~F_PW_CWORD; 288 lde_send_labelmapping(ln, fn, 1); 289 } 290 } else if (map->flags & F_MAP_PW_CWORD) { 291 if (pw->flags & F_PW_CWORD_CONF) 292 pw->flags |= F_PW_CWORD; 293 else 294 /* act as if no label mapping had been received */ 295 return (1); 296 } else 297 pw->flags &= ~F_PW_CWORD; 298 299 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */ 300 if (fec_find(&ln->recv_map, &fn->fec) == NULL && 301 !(map->flags & F_MAP_PW_STATUS)) 302 pw->flags &= ~F_PW_STATUSTLV; 303 304 return (0); 305 } 306 307 void 308 l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec) 309 { 310 struct notify_msg nm; 311 312 memset(&nm, 0, sizeof(nm)); 313 nm.status_code = S_PW_STATUS; 314 nm.pw_status = status; 315 nm.flags |= F_NOTIF_PW_STATUS; 316 lde_fec2map(fec, &nm.fec); 317 nm.flags |= F_NOTIF_FEC; 318 319 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0, 320 &nm, sizeof(nm)); 321 } 322 323 void 324 l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) 325 { 326 struct fec fec; 327 struct fec_node *fn; 328 struct fec_nh *fnh; 329 struct l2vpn_pw *pw; 330 331 /* TODO group wildcard */ 332 if (!(nm->fec.flags & F_MAP_PW_ID)) 333 return; 334 335 lde_map2fec(&nm->fec, ln->id, &fec); 336 fn = (struct fec_node *)fec_find(&ft, &fec); 337 if (fn == NULL) 338 /* unknown fec */ 339 return; 340 341 pw = (struct l2vpn_pw *) fn->data; 342 if (pw == NULL) 343 return; 344 345 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0); 346 if (fnh == NULL) 347 return; 348 349 /* remote status didn't change */ 350 if (pw->remote_status == nm->pw_status) 351 return; 352 353 pw->remote_status = nm->pw_status; 354 355 if (l2vpn_pw_ok(pw, fnh)) 356 lde_send_change_klabel(fn, fnh); 357 else 358 lde_send_delete_klabel(fn, fnh); 359 } 360 361 void 362 l2vpn_sync_pws(int af, union ldpd_addr *addr) 363 { 364 struct l2vpn *l2vpn; 365 struct l2vpn_pw *pw; 366 struct fec fec; 367 struct fec_node *fn; 368 struct fec_nh *fnh; 369 370 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { 371 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 372 if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) 373 continue; 374 375 l2vpn_pw_fec(pw, &fec); 376 fn = (struct fec_node *)fec_find(&ft, &fec); 377 if (fn == NULL) 378 continue; 379 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *) 380 &pw->lsr_id, 0); 381 if (fnh == NULL) 382 continue; 383 384 if (l2vpn_pw_ok(pw, fnh)) 385 lde_send_change_klabel(fn, fnh); 386 else 387 lde_send_delete_klabel(fn, fnh); 388 } 389 } 390 } 391 392 void 393 l2vpn_pw_ctl(pid_t pid) 394 { 395 struct l2vpn *l2vpn; 396 struct l2vpn_pw *pw; 397 static struct ctl_pw pwctl; 398 399 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) 400 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 401 memset(&pwctl, 0, sizeof(pwctl)); 402 strlcpy(pwctl.ifname, pw->ifname, 403 sizeof(pwctl.ifname)); 404 pwctl.pwid = pw->pwid; 405 pwctl.lsr_id = pw->lsr_id; 406 pwctl.status = pw->flags & F_PW_STATUS_UP; 407 408 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0, 409 pid, &pwctl, sizeof(pwctl)); 410 } 411 } 412 413 void 414 l2vpn_binding_ctl(pid_t pid) 415 { 416 struct fec *f; 417 struct fec_node *fn; 418 struct lde_map *me; 419 struct l2vpn_pw *pw; 420 static struct ctl_pw pwctl; 421 422 RB_FOREACH(f, fec_tree, &ft) { 423 if (f->type != FEC_TYPE_PWID) 424 continue; 425 426 fn = (struct fec_node *)f; 427 if (fn->local_label == NO_LABEL && 428 LIST_EMPTY(&fn->downstream)) 429 continue; 430 431 memset(&pwctl, 0, sizeof(pwctl)); 432 pwctl.type = f->u.pwid.type; 433 pwctl.pwid = f->u.pwid.pwid; 434 pwctl.lsr_id = f->u.pwid.lsr_id; 435 436 pw = (struct l2vpn_pw *) fn->data; 437 if (pw) { 438 pwctl.local_label = fn->local_label; 439 pwctl.local_gid = 0; 440 pwctl.local_ifmtu = pw->l2vpn->mtu; 441 } else 442 pwctl.local_label = NO_LABEL; 443 444 LIST_FOREACH(me, &fn->downstream, entry) 445 if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) 446 break; 447 448 if (me) { 449 pwctl.remote_label = me->map.label; 450 pwctl.remote_gid = me->map.fec.pwid.group_id; 451 if (me->map.flags & F_MAP_PW_IFMTU) 452 pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu; 453 454 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 455 0, pid, &pwctl, sizeof(pwctl)); 456 } else if (pw) { 457 pwctl.remote_label = NO_LABEL; 458 459 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 460 0, pid, &pwctl, sizeof(pwctl)); 461 } 462 } 463 } 464 465 /* ldpe */ 466 467 void 468 ldpe_l2vpn_init(struct l2vpn *l2vpn) 469 { 470 struct l2vpn_pw *pw; 471 472 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 473 ldpe_l2vpn_pw_init(pw); 474 } 475 476 void 477 ldpe_l2vpn_exit(struct l2vpn *l2vpn) 478 { 479 struct l2vpn_pw *pw; 480 481 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 482 ldpe_l2vpn_pw_exit(pw); 483 } 484 485 void 486 ldpe_l2vpn_pw_init(struct l2vpn_pw *pw) 487 { 488 struct tnbr *tnbr; 489 490 tnbr = tnbr_find(leconf, pw->af, &pw->addr); 491 if (tnbr == NULL) { 492 tnbr = tnbr_new(leconf, pw->af, &pw->addr); 493 tnbr_update(tnbr); 494 LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); 495 } 496 497 tnbr->pw_count++; 498 } 499 500 void 501 ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw) 502 { 503 struct tnbr *tnbr; 504 505 tnbr = tnbr_find(leconf, pw->af, &pw->addr); 506 if (tnbr) { 507 tnbr->pw_count--; 508 tnbr_check(tnbr); 509 } 510 } 511