1/* $NetBSD: mpls_interface.c,v 1.12 2013/07/24 09:05:53 kefren Exp $ */ 2 3/*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Mihai Chelaru <kefren@NetBSD.org> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <arpa/inet.h> 33#include <netinet/in.h> 34#include <netmpls/mpls.h> 35#include <net/route.h> 36 37#include <sys/param.h> 38 39#include <assert.h> 40#include <stdio.h> 41#include <string.h> 42#include <stdlib.h> 43#include <unistd.h> 44 45#include "ldp.h" 46#include "ldp_peer.h" 47#include "ldp_errors.h" 48#include "tlv_stack.h" 49#include "label.h" 50#include "mpls_interface.h" 51#include "mpls_routes.h" 52 53extern int no_default_route; 54 55int 56mpls_add_label(struct label *lab) 57{ 58 char p_str[20]; 59 union sockunion *so_dest, *so_nexthop, *so_tag, so_ifa; 60 uint8_t prefixlen; 61 uint32_t oldbinding; 62 struct peer_map *pm; 63 64 assert(lab != NULL); 65 66 oldbinding = lab->binding; 67 prefixlen = from_union_to_cidr(&lab->so_pref); 68 69 strlcpy(p_str, satos(lab->p->address), sizeof(p_str)); 70 warnp("Trying to add %s/%d as label %d (oldlocal %d) to peer %s\n", 71 satos(&lab->so_dest.sa), prefixlen, lab->label, lab->binding,p_str); 72 73 /* Check if we should accept default route */ 74 if (prefixlen == 0 && no_default_route != 0) 75 return LDP_E_BAD_AF; 76 77 /* double check if there is a label mapping for this */ 78 if ((pm = ldp_test_mapping(&lab->so_dest.sa, prefixlen, 79 &lab->so_gate.sa)) == NULL || pm->peer != lab->p) { 80 if (pm != NULL) 81 free(pm); 82 return LDP_E_NOENT; 83 } 84 free(pm); 85 86 if (lab->so_gate.sa.sa_family != AF_INET && 87 lab->so_gate.sa.sa_family != AF_INET6) { 88 warnp("mpls_add_label: so_gate is not IP or IPv6\n"); 89 return LDP_E_BAD_AF; 90 } 91 92 /* Check if the address is bounded to the peer */ 93 if (check_ifaddr(lab->p, &lab->so_gate.sa) == NULL) { 94 warnp("Failed at next-hop check\n"); 95 return LDP_E_ROUTE_ERROR; 96 } 97 98 /* if binding is implicit null we need to generate a new one */ 99 if (lab->binding == MPLS_LABEL_IMPLNULL) { 100 lab->binding = get_free_local_label(); 101 if (!lab->binding) { 102 fatalp("Label pool depleted\n"); 103 return LDP_E_TOO_MANY_LABELS; 104 } 105 announce_label_change(lab); 106 } 107 108 warnp("[mpls_add_label] Adding %s/%d as local binding %d (%d), label %d" 109 " to peer %s\n", satos(&lab->so_dest.sa), prefixlen, lab->binding, 110 oldbinding, lab->label, p_str); 111 112 /* Add switching route */ 113 if ((so_dest = make_mpls_union(lab->binding)) == NULL) 114 return LDP_E_MEMORY; 115 if ((so_tag = make_mpls_union(lab->label)) == NULL) { 116 free(so_dest); 117 fatalp("Out of memory\n"); 118 return LDP_E_MEMORY; 119 } 120 if ((so_nexthop = malloc(lab->so_gate.sa.sa_len)) == NULL) { 121 free(so_dest); 122 free(so_tag); 123 fatalp("Out of memory\n"); 124 return LDP_E_MEMORY; 125 } 126 memcpy(so_nexthop, &lab->so_gate, lab->so_gate.sa.sa_len); 127 128 if (add_route(so_dest, NULL, so_nexthop, NULL, so_tag, FREESO, 129 oldbinding == MPLS_LABEL_IMPLNULL ? RTM_ADD : RTM_CHANGE) 130 != LDP_E_OK) { 131 fatalp("[mpls_add_label] MPLS route error\n"); 132 return LDP_E_ROUTE_ERROR; 133 } 134 135 /* Now, let's add tag to IP route and point it to mpls interface */ 136 137 if (getsockname(lab->p->socket, &so_ifa.sa, 138 & (socklen_t) { sizeof(union sockunion) } )) { 139 fatalp("[mpls_add_label]: getsockname\n"); 140 return LDP_E_ROUTE_ERROR; 141 } 142 143 if ((so_tag = make_mpls_union(lab->label)) == NULL) { 144 fatalp("Out of memory\n"); 145 return LDP_E_MEMORY; 146 } 147 148 if (add_route(&lab->so_dest, lab->host ? NULL : &lab->so_pref, 149 &lab->so_gate, &so_ifa, so_tag, NO_FREESO, RTM_CHANGE) != LDP_E_OK){ 150 free(so_tag); 151 fatalp("[mpls_add_label]: INET route failure\n"); 152 return LDP_E_ROUTE_ERROR; 153 } 154 free(so_tag); 155 156 warnp("[mpls_add_label]: SUCCESS\n"); 157 158 return LDP_E_OK; 159} 160 161int 162mpls_add_ldp_peer(const struct ldp_peer * p) 163{ 164 return LDP_E_OK; 165} 166 167int 168mpls_delete_ldp_peer(const struct ldp_peer * p) 169{ 170 171 /* Reput all the routes also to IPv4 */ 172 label_reattach_all_peer_labels(p, REATT_INET_CHANGE); 173 174 return LDP_E_OK; 175} 176 177int 178mpls_start_ldp() 179{ 180 ldp_peer_init(); 181 label_init(); 182 183 return LDP_E_OK; 184} 185