l2vpn.c revision 1.11
1/* $OpenBSD: l2vpn.c,v 1.11 2016/05/23 18:33:56 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 <sys/socket.h> 24#include <arpa/inet.h> 25 26#include <err.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "ldpd.h" 32#include "lde.h" 33#include "ldpe.h" 34#include "control.h" 35#include "log.h" 36 37RB_PROTOTYPE(fec_tree, fec, entry, fec_compare) 38extern struct fec_tree ft; 39 40extern struct ldpd_conf *ldeconf; 41extern struct ldpd_conf *leconf; 42 43struct l2vpn * 44l2vpn_new(const char *name) 45{ 46 struct l2vpn *l2vpn; 47 48 if ((l2vpn = calloc(1, sizeof(*l2vpn))) == NULL) 49 fatal("l2vpn_new: calloc"); 50 51 strlcpy(l2vpn->name, name, sizeof(l2vpn->name)); 52 53 /* set default values */ 54 l2vpn->mtu = DEFAULT_L2VPN_MTU; 55 l2vpn->pw_type = DEFAULT_PW_TYPE; 56 57 LIST_INIT(&l2vpn->if_list); 58 LIST_INIT(&l2vpn->pw_list); 59 60 return (l2vpn); 61} 62 63struct l2vpn * 64l2vpn_find(struct ldpd_conf *xconf, const char *name) 65{ 66 struct l2vpn *l2vpn; 67 68 LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) 69 if (strcmp(l2vpn->name, name) == 0) 70 return (l2vpn); 71 72 return (NULL); 73} 74 75void 76l2vpn_del(struct l2vpn *l2vpn) 77{ 78 struct l2vpn_if *lif; 79 struct l2vpn_pw *pw; 80 81 while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { 82 LIST_REMOVE(lif, entry); 83 free(lif); 84 } 85 while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { 86 LIST_REMOVE(pw, entry); 87 l2vpn_pw_del(pw); 88 } 89 90 free(l2vpn); 91} 92 93void 94l2vpn_init(struct l2vpn *l2vpn) 95{ 96 struct l2vpn_pw *pw; 97 98 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 99 l2vpn_pw_init(pw); 100} 101 102struct l2vpn_if * 103l2vpn_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 119struct l2vpn_if * 120l2vpn_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 131struct l2vpn_pw * 132l2vpn_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 146struct l2vpn_pw * 147l2vpn_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 158void 159l2vpn_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, pw->lsr_id, 0, (void *)pw); 167} 168 169void 170l2vpn_pw_del(struct l2vpn_pw *pw) 171{ 172 struct fec fec; 173 174 l2vpn_pw_fec(pw, &fec); 175 lde_kernel_remove(&fec, pw->lsr_id); 176 free(pw); 177} 178 179void 180l2vpn_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 189void 190l2vpn_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 207int 208l2vpn_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 fec.type = FEC_TYPE_IPV4; 229 fec.u.ipv4.prefix = pw->lsr_id; 230 fec.u.ipv4.prefixlen = 32; 231 fn = (struct fec_node *)fec_find(&ft, &fec); 232 if (fn == NULL || fn->local_label == NO_LABEL) 233 return (0); 234 /* 235 * Need to ensure that there's a label binding for all nexthops. 236 * Otherwise, ECMP for this route could render the pseudowire unusable. 237 */ 238 LIST_FOREACH(fnh, &fn->nexthops, entry) 239 if (fnh->remote_label == NO_LABEL) 240 return (0); 241 242 return (1); 243} 244 245int 246l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) 247{ 248 struct l2vpn_pw *pw; 249 250 /* NOTE: thanks martini & friends for all this mess */ 251 252 pw = (struct l2vpn_pw *) fn->data; 253 if (pw == NULL) 254 /* 255 * pseudowire not configured, return and record 256 * the mapping later 257 */ 258 return (0); 259 260 /* RFC4447 - Section 6.2: control word negotiation */ 261 if (fec_find(&ln->sent_map, &fn->fec)) { 262 if ((map->flags & F_MAP_PW_CWORD) && 263 !(pw->flags & F_PW_CWORD_CONF)) { 264 /* ignore the received label mapping */ 265 return (1); 266 } else if (!(map->flags & F_MAP_PW_CWORD) && 267 (pw->flags & F_PW_CWORD_CONF)) { 268 /* TODO append a "Wrong C-bit" status code */ 269 lde_send_labelwithdraw(ln, fn, NO_LABEL); 270 271 pw->flags &= ~F_PW_CWORD; 272 lde_send_labelmapping(ln, fn, 1); 273 } 274 } else if (map->flags & F_MAP_PW_CWORD) { 275 if (pw->flags & F_PW_CWORD_CONF) 276 pw->flags |= F_PW_CWORD; 277 else 278 /* act as if no label mapping had been received */ 279 return (1); 280 } else 281 pw->flags &= ~F_PW_CWORD; 282 283 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */ 284 if (fec_find(&ln->recv_map, &fn->fec) == NULL && 285 !(map->flags & F_MAP_PW_STATUS)) 286 pw->flags &= ~F_PW_STATUSTLV; 287 288 return (0); 289} 290 291void 292l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec) 293{ 294 struct notify_msg nm; 295 296 memset(&nm, 0, sizeof(nm)); 297 nm.status = S_PW_STATUS; 298 299 nm.pw_status = status; 300 nm.flags |= F_NOTIF_PW_STATUS; 301 302 lde_fec2map(fec, &nm.fec); 303 nm.flags |= F_NOTIF_FEC; 304 305 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0, 306 &nm, sizeof(nm)); 307} 308 309void 310l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) 311{ 312 struct fec fec; 313 struct fec_node *fn; 314 struct fec_nh *fnh; 315 struct l2vpn_pw *pw; 316 317 /* TODO group wildcard */ 318 if (!(nm->fec.flags & F_MAP_PW_ID)) 319 return; 320 321 lde_map2fec(&nm->fec, ln->id, &fec); 322 fn = (struct fec_node *)fec_find(&ft, &fec); 323 if (fn == NULL) 324 /* unknown fec */ 325 return; 326 327 pw = (struct l2vpn_pw *) fn->data; 328 if (pw == NULL) 329 return; 330 331 fnh = fec_nh_find(fn, ln->id); 332 if (fnh == NULL) 333 return; 334 335 /* remote status didn't change */ 336 if (pw->remote_status == nm->pw_status) 337 return; 338 339 pw->remote_status = nm->pw_status; 340 341 if (l2vpn_pw_ok(pw, fnh)) 342 lde_send_change_klabel(fn, fnh); 343 else 344 lde_send_delete_klabel(fn, fnh); 345} 346 347void 348l2vpn_sync_pws(struct in_addr addr) 349{ 350 struct l2vpn *l2vpn; 351 struct l2vpn_pw *pw; 352 struct fec fec; 353 struct fec_node *fn; 354 struct fec_nh *fnh; 355 356 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { 357 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 358 if (pw->lsr_id.s_addr == addr.s_addr) { 359 l2vpn_pw_fec(pw, &fec); 360 fn = (struct fec_node *)fec_find(&ft, &fec); 361 if (fn == NULL) 362 continue; 363 fnh = fec_nh_find(fn, pw->lsr_id); 364 if (fnh == NULL) 365 continue; 366 367 if (l2vpn_pw_ok(pw, fnh)) 368 lde_send_change_klabel(fn, fnh); 369 else 370 lde_send_delete_klabel(fn, fnh); 371 } 372 } 373 } 374} 375 376void 377l2vpn_pw_ctl(pid_t pid) 378{ 379 struct l2vpn *l2vpn; 380 struct l2vpn_pw *pw; 381 static struct ctl_pw pwctl; 382 383 LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) 384 LIST_FOREACH(pw, &l2vpn->pw_list, entry) { 385 memset(&pwctl, 0, sizeof(pwctl)); 386 strlcpy(pwctl.ifname, pw->ifname, 387 sizeof(pwctl.ifname)); 388 pwctl.pwid = pw->pwid; 389 pwctl.lsr_id = pw->lsr_id; 390 pwctl.status = pw->flags & F_PW_STATUS_UP; 391 392 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0, 393 pid, &pwctl, sizeof(pwctl)); 394 } 395} 396 397void 398l2vpn_binding_ctl(pid_t pid) 399{ 400 struct fec *f; 401 struct fec_node *fn; 402 struct lde_map *me; 403 struct l2vpn_pw *pw; 404 static struct ctl_pw pwctl; 405 406 RB_FOREACH(f, fec_tree, &ft) { 407 if (f->type != FEC_TYPE_PWID) 408 continue; 409 410 fn = (struct fec_node *)f; 411 if (fn->local_label == NO_LABEL && 412 LIST_EMPTY(&fn->downstream)) 413 continue; 414 415 memset(&pwctl, 0, sizeof(pwctl)); 416 pwctl.type = f->u.pwid.type; 417 pwctl.pwid = f->u.pwid.pwid; 418 pwctl.lsr_id = f->u.pwid.lsr_id; 419 420 pw = (struct l2vpn_pw *) fn->data; 421 if (pw) { 422 pwctl.local_label = fn->local_label; 423 pwctl.local_gid = 0; 424 pwctl.local_ifmtu = pw->l2vpn->mtu; 425 } else 426 pwctl.local_label = NO_LABEL; 427 428 LIST_FOREACH(me, &fn->downstream, entry) 429 if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) 430 break; 431 432 if (me) { 433 pwctl.remote_label = me->map.label; 434 pwctl.remote_gid = me->map.fec.pwid.group_id; 435 if (me->map.flags & F_MAP_PW_IFMTU) 436 pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu; 437 438 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 439 0, pid, &pwctl, sizeof(pwctl)); 440 } else if (pw) { 441 pwctl.remote_label = NO_LABEL; 442 443 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING, 444 0, pid, &pwctl, sizeof(pwctl)); 445 } 446 } 447} 448 449/* ldpe */ 450 451void 452ldpe_l2vpn_init(struct l2vpn *l2vpn) 453{ 454 struct l2vpn_pw *pw; 455 456 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 457 ldpe_l2vpn_pw_init(pw); 458} 459 460void 461ldpe_l2vpn_exit(struct l2vpn *l2vpn) 462{ 463 struct l2vpn_pw *pw; 464 465 LIST_FOREACH(pw, &l2vpn->pw_list, entry) 466 ldpe_l2vpn_pw_exit(pw); 467} 468 469void 470ldpe_l2vpn_pw_init(struct l2vpn_pw *pw) 471{ 472 struct tnbr *tnbr; 473 474 tnbr = tnbr_find(leconf, pw->lsr_id); 475 if (!event_initialized(&tnbr->hello_timer)) 476 tnbr_update(tnbr); 477} 478 479void 480ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw) 481{ 482 struct tnbr *tnbr; 483 484 tnbr = tnbr_find(leconf, pw->lsr_id); 485 if (tnbr) { 486 tnbr->pw_count--; 487 tnbr_check(tnbr); 488 } 489} 490