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