Home | History | Annotate | Line # | Download | only in ldpd
tlv_stack.c revision 1.4.8.1
      1  1.4.8.1       tls /* $NetBSD: tlv_stack.c,v 1.4.8.1 2012/11/20 03:03:02 tls 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 
     34      1.1    kefren #include <netmpls/mpls.h>
     35      1.1    kefren 
     36      1.1    kefren #include <stdio.h>
     37      1.1    kefren #include <string.h>
     38      1.1    kefren #include <stdlib.h>
     39      1.1    kefren 
     40      1.1    kefren #include "ldp.h"
     41      1.1    kefren #include "ldp_errors.h"
     42      1.1    kefren #include "ldp_peer.h"
     43      1.1    kefren #include "tlv.h"
     44      1.1    kefren #include "socketops.h"
     45      1.1    kefren #include "pdu.h"
     46      1.1    kefren #include "label.h"
     47      1.1    kefren #include "mpls_interface.h"
     48      1.1    kefren #include "tlv_stack.h"
     49      1.1    kefren 
     50      1.1    kefren uint8_t ldp_ceil8(int);
     51      1.1    kefren 
     52      1.1    kefren uint8_t
     53      1.1    kefren ldp_ceil8(int x)
     54      1.1    kefren {
     55      1.1    kefren 	if (x % 8 == 0)
     56      1.1    kefren 		return x / 8;
     57      1.1    kefren 	return x / 8 + 1;
     58      1.1    kefren }
     59      1.1    kefren 
     60      1.1    kefren int
     61      1.1    kefren map_label(struct ldp_peer * p, struct fec_tlv * f, struct label_tlv * l)
     62      1.1    kefren {
     63      1.1    kefren 	int             n;
     64      1.1    kefren 	struct prefix_tlv *pref;
     65      1.1    kefren 	struct in_addr  inatmp;
     66      1.1    kefren 
     67      1.1    kefren 	if (ntohs(f->type) != TLV_FEC) {
     68      1.1    kefren 		debugp("Invalid FEC TLV !\n");
     69      1.1    kefren 		return LDP_E_BAD_FEC;
     70      1.1    kefren 	}
     71      1.1    kefren 	if (ntohs(l->type) != TLV_GENERIC_LABEL) {
     72      1.1    kefren 		debugp("Invalid LABEL TLV! (0x%.4X)\n", ntohs(l->type));
     73      1.1    kefren 		return LDP_E_BAD_LABEL;
     74      1.1    kefren 	}
     75      1.1    kefren 	/*
     76      1.1    kefren 	 * Actually address field length is given only in length field in
     77      1.1    kefren 	 * bits !
     78      1.1    kefren 	 */
     79      1.1    kefren 
     80      1.1    kefren 	n = ntohs(f->length);
     81      1.1    kefren 	if (!n)
     82      1.1    kefren 		return LDP_E_BAD_FEC;
     83      1.1    kefren 
     84      1.1    kefren 	debugp("Label %u for:\n", ntohl(l->label));
     85      1.1    kefren 
     86      1.1    kefren 	pref = (struct prefix_tlv *) & f[1];
     87      1.1    kefren 
     88      1.1    kefren 	/*
     89      1.1    kefren 	 * Section 3.4.1
     90      1.1    kefren 	 * Note that this version of LDP supports the use of multiple FEC
     91      1.1    kefren 	 * Elements per FEC for the Label Mapping message only.  The use of
     92      1.1    kefren 	 * multiple FEC Elements in other messages is not permitted in this
     93      1.1    kefren 	 * version, and is a subject for future study.
     94      1.1    kefren 	 */
     95      1.1    kefren 
     96      1.1    kefren 	for (; n > 0; pref = (struct prefix_tlv *) ((unsigned char *) pref +
     97      1.1    kefren 			ldp_ceil8(pref->prelen) + TLV_TYPE_LENGTH)) {
     98      1.1    kefren 		n -= ldp_ceil8(pref->prelen) + TLV_TYPE_LENGTH;
     99      1.1    kefren 		if (ntohs(pref->af) != LDP_AF_INET) {
    100      1.1    kefren 			debugp("BAD ADDRESS FAMILY (%d) ! (prefix type %d, "
    101      1.1    kefren 			    "length %d)\n", ntohs(pref->af), pref->type,
    102      1.1    kefren 			    pref->prelen);
    103      1.1    kefren 			return LDP_E_BAD_AF;
    104      1.1    kefren 		}
    105      1.1    kefren 		switch(pref->type) {
    106      1.1    kefren 		    case FEC_PREFIX:
    107      1.1    kefren 		    case FEC_HOST:
    108      1.1    kefren 			memset(&inatmp, 0, sizeof(struct in_addr));
    109      1.1    kefren 			memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
    110      1.1    kefren 			debugp("Prefix/Host add: %s/%d\n", inet_ntoa(inatmp),
    111      1.1    kefren 			    pref->prelen);
    112      1.3    kefren 
    113      1.1    kefren 			ldp_peer_add_mapping(p, &inatmp, pref->prelen,
    114      1.1    kefren 			    ntohl(l->label));
    115      1.4    kefren 
    116      1.4    kefren 			/* Try to change RIB only if label is installed */
    117      1.4    kefren 			if (label_get_by_prefix(&inatmp, pref->prelen) != NULL)
    118      1.4    kefren 				mpls_add_label(p, NULL, &inatmp, pref->prelen,
    119      1.4    kefren 				    ntohl(l->label), 1);
    120      1.1    kefren 			break;
    121      1.1    kefren 		    case FEC_WILDCARD:
    122      1.1    kefren 			fatalp("LDP: Wildcard add from peer %s\n",
    123      1.1    kefren 			    inet_ntoa(p->address));
    124      1.1    kefren 			return LDP_E_BAD_FEC;
    125      1.1    kefren 		    default:
    126      1.1    kefren 			fatalp("Unknown FEC type %d\n", pref->type);
    127      1.1    kefren 			return LDP_E_BAD_FEC;
    128      1.1    kefren 		}
    129      1.1    kefren 	}
    130      1.1    kefren 
    131      1.1    kefren 	return LDP_E_OK;
    132      1.1    kefren }
    133      1.1    kefren 
    134      1.1    kefren int
    135      1.1    kefren withdraw_label(struct ldp_peer * p, struct fec_tlv * f)
    136      1.1    kefren {
    137      1.1    kefren 	int             n;
    138      1.1    kefren 	struct prefix_tlv *pref;
    139      1.1    kefren 	struct in_addr  inatmp;
    140      1.1    kefren 	struct label *lab;
    141      1.1    kefren 
    142      1.1    kefren 	if (ntohs(f->type) != TLV_FEC) {
    143      1.1    kefren 		debugp("Invalid FEC TLV !\n");
    144      1.1    kefren 		return LDP_E_BAD_FEC;
    145      1.1    kefren 	}
    146      1.1    kefren 	n = ntohs(f->length);
    147      1.1    kefren 	if (!n)
    148      1.1    kefren 		return LDP_E_BAD_FEC;
    149      1.1    kefren 
    150      1.1    kefren 	pref = (struct prefix_tlv *) & f[1];
    151      1.1    kefren 	if (ntohs(pref->af) != LDP_AF_INET) {
    152      1.1    kefren 		debugp("BAD ADDRESS FAMILY (%d)! (prefix type %d, length %d)\n",
    153      1.1    kefren 		    ntohs(pref->af), pref->type, pref->prelen);
    154      1.1    kefren 		return LDP_E_BAD_AF;
    155      1.1    kefren 	}
    156      1.1    kefren 	switch(pref->type) {
    157      1.1    kefren 	    case FEC_PREFIX:
    158      1.1    kefren 	    case FEC_HOST:
    159      1.1    kefren 		memset(&inatmp, 0, sizeof(struct in_addr));
    160      1.1    kefren 		memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
    161      1.1    kefren 		debugp("Prefix/Host withdraw: %s/%d\n", inet_ntoa(inatmp),
    162      1.1    kefren 		    pref->prelen);
    163      1.1    kefren 
    164      1.1    kefren 		/* Delete mapping */
    165      1.1    kefren 		ldp_peer_delete_mapping(p, &inatmp, pref->prelen);
    166      1.1    kefren 
    167      1.1    kefren 		/* Get label, see if we're pointing to this peer
    168      1.1    kefren 		 * if so, send withdraw, reattach IP route and announce
    169      1.1    kefren 		 * POP Label
    170      1.1    kefren 		 */
    171      1.1    kefren 		lab = label_get_by_prefix(&inatmp, pref->prelen);
    172      1.1    kefren 		if ((lab) && (lab->p == p)) {
    173      1.1    kefren 			change_local_label(lab, MPLS_LABEL_IMPLNULL);
    174      1.1    kefren 			label_reattach_route(lab, LDP_READD_CHANGE);
    175      1.1    kefren 		}
    176      1.1    kefren 		break;
    177      1.1    kefren 	    case FEC_WILDCARD:
    178      1.1    kefren 		fatalp("LDP neighbour %s: Wildcard withdraw !!!\n",
    179      1.1    kefren 		    inet_ntoa(p->address));
    180      1.1    kefren 		ldp_peer_delete_mapping(p, NULL, 0);
    181      1.1    kefren 		label_reattach_all_peer_labels(p, LDP_READD_CHANGE);
    182      1.1    kefren 		break;
    183      1.1    kefren 	    default:
    184      1.1    kefren 		fatalp("Unknown FEC type %d\n", pref->type);
    185      1.1    kefren 		return LDP_E_BAD_FEC;
    186      1.1    kefren 	}
    187      1.1    kefren 
    188      1.1    kefren 	return LDP_E_OK;
    189      1.1    kefren }
    190      1.1    kefren 
    191      1.1    kefren 
    192      1.1    kefren /*
    193      1.1    kefren  * In case of label redraw, reuse the same buffer to send label release
    194      1.1    kefren  * Simply replace type and message id
    195      1.1    kefren  */
    196      1.1    kefren void
    197      1.1    kefren prepare_release(struct tlv * v)
    198      1.1    kefren {
    199      1.1    kefren 	struct label_map_tlv *t;
    200      1.1    kefren 
    201      1.1    kefren 	t = (struct label_map_tlv *) v;
    202      1.1    kefren 
    203      1.1    kefren 	t->type = htons(LDP_LABEL_RELEASE);
    204      1.1    kefren 	t->messageid = htonl(get_message_id());
    205      1.1    kefren }
    206      1.1    kefren 
    207      1.1    kefren /* Sends a label mapping */
    208      1.1    kefren void
    209      1.1    kefren send_label_tlv(struct ldp_peer * peer, struct in_addr * addr,
    210      1.1    kefren     uint8_t prefixlen, uint32_t label, struct label_request_tlv *lrt)
    211      1.1    kefren {
    212      1.1    kefren 	struct label_map_tlv *lmt;
    213      1.1    kefren 	struct fec_tlv *fec;
    214      1.1    kefren 	struct prefix_tlv *p;
    215      1.1    kefren 	struct label_tlv *l;
    216      1.1    kefren 
    217      1.1    kefren 	/*
    218      1.1    kefren 	 * Ok, so we have label map tlv that contains fec tlvs and label tlv
    219      1.1    kefren 	 * but fec tlv contains prefix or host tlvs and prefix or host tlvs
    220      1.1    kefren 	 * contains the network. After that we may have optional parameters
    221      1.1    kefren 	 * Got it ?
    222      1.1    kefren 	 */
    223      1.1    kefren 
    224      1.2  christos 	lmt = malloc(
    225      1.1    kefren 		sizeof(struct label_map_tlv) +
    226      1.1    kefren 		sizeof(struct fec_tlv) +
    227      1.1    kefren 		sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    228      1.1    kefren 			ldp_ceil8(prefixlen) +
    229      1.1    kefren 		sizeof(struct label_tlv) +
    230      1.1    kefren 	 /* Label request optional parameter  */
    231      1.1    kefren 	 	(lrt != NULL ? sizeof(struct label_request_tlv) : 0) );
    232      1.1    kefren 
    233      1.1    kefren 	if (!lmt) {
    234      1.1    kefren 		fatalp("send_label_tlv: malloc problem\n");
    235      1.1    kefren 		return;
    236      1.2  christos 	}
    237      1.1    kefren 
    238      1.1    kefren 	lmt->type = htons(LDP_LABEL_MAPPING);
    239      1.1    kefren 	lmt->length = htons(sizeof(struct label_map_tlv) - TLV_TYPE_LENGTH
    240      1.1    kefren 	    + sizeof(struct fec_tlv)
    241      1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    242      1.1    kefren 		ldp_ceil8(prefixlen)
    243      1.1    kefren 	    + sizeof(struct label_tlv) +
    244      1.1    kefren 	    + (lrt != NULL ? sizeof(struct label_request_tlv) : 0));
    245      1.1    kefren 	lmt->messageid = htonl(get_message_id());
    246      1.1    kefren 
    247      1.1    kefren 	/* FEC TLV */
    248      1.1    kefren 	fec = (struct fec_tlv *) & lmt[1];
    249      1.1    kefren 	fec->type = htons(TLV_FEC);
    250      1.1    kefren 	fec->length = htons(sizeof(struct fec_tlv) - TLV_TYPE_LENGTH
    251      1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    252      1.1    kefren 		ldp_ceil8(prefixlen));
    253      1.1    kefren 
    254      1.1    kefren 	/* Now let's do the even a dirtier job: PREFIX TLV */
    255      1.1    kefren 	p = (struct prefix_tlv *) & fec[1];
    256  1.4.8.1       tls 	/*
    257  1.4.8.1       tls 	 * RFC5036 obsoletes FEC_HOST
    258      1.1    kefren 	 *
    259      1.1    kefren 	 * if (prefixlen == 32) p->type = FEC_HOST; else
    260      1.1    kefren 	 */
    261      1.1    kefren 	p->type = FEC_PREFIX;
    262      1.1    kefren 	p->af = htons(LDP_AF_INET);
    263      1.1    kefren 	p->prelen = prefixlen;
    264      1.1    kefren 	memcpy(&p->prefix, addr, ldp_ceil8(prefixlen));
    265      1.1    kefren 
    266      1.1    kefren 	/* LABEL TLV */
    267      1.1    kefren 	l = (struct label_tlv *) ((unsigned char *) p +
    268      1.1    kefren 		sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    269      1.1    kefren 		ldp_ceil8(prefixlen));
    270      1.1    kefren 	l->type = htons(TLV_GENERIC_LABEL);
    271      1.1    kefren 	l->length = htons(sizeof(l->label));
    272      1.1    kefren 	l->label = htonl(label);
    273      1.1    kefren 
    274      1.1    kefren 	/* Label request optional parameter */
    275      1.1    kefren 	if (lrt)
    276      1.1    kefren 		memcpy(((char*)l) + TLV_TYPE_LENGTH + ntohs(l->length),
    277      1.1    kefren 			lrt, htons(lrt->length) + TLV_TYPE_LENGTH);
    278      1.1    kefren 
    279      1.1    kefren 	/* Wow, seems we're ready */
    280      1.1    kefren 	send_tlv(peer, (struct tlv *) lmt);
    281      1.1    kefren 	free(lmt);
    282      1.1    kefren }
    283      1.1    kefren 
    284      1.1    kefren void
    285      1.1    kefren send_label_tlv_to_all(struct in_addr * addr, uint8_t prefixlen, uint32_t label)
    286      1.1    kefren {
    287      1.1    kefren 	struct ldp_peer *p;
    288      1.1    kefren 	SLIST_FOREACH(p, &ldp_peer_head, peers)
    289      1.1    kefren 		send_label_tlv(p, addr, prefixlen, label, NULL);
    290      1.1    kefren }
    291      1.1    kefren 
    292      1.1    kefren /*
    293      1.1    kefren  * Send all local labels to a peer
    294      1.1    kefren  */
    295      1.1    kefren void
    296      1.1    kefren send_all_bindings(struct ldp_peer * peer)
    297      1.1    kefren {
    298      1.1    kefren 	struct label *l;
    299      1.1    kefren 
    300      1.1    kefren 	SLIST_FOREACH(l, &label_head, labels)
    301      1.1    kefren 	   send_label_tlv(peer, &((struct sockaddr_in*)(&l->so_dest))->sin_addr,
    302      1.1    kefren 		from_union_to_cidr(&l->so_pref), l->binding, NULL);
    303      1.1    kefren 
    304      1.1    kefren }
    305      1.1    kefren 
    306      1.1    kefren /* Sends a label WITHDRAW */
    307      1.1    kefren void
    308      1.1    kefren send_withdraw_tlv(struct ldp_peer * peer, struct in_addr * addr,
    309      1.1    kefren     uint8_t prefixlen)
    310      1.1    kefren {
    311      1.1    kefren 	struct label_map_tlv *lmt;
    312      1.1    kefren 	struct fec_tlv *fec;
    313      1.1    kefren 	struct prefix_tlv *p;
    314      1.1    kefren 
    315      1.1    kefren 	/*
    316      1.1    kefren 	 * Ok, so we have label map tlv that contains fec tlvs but fec tlv
    317      1.1    kefren 	 * contains prefix or host tlvs and prefix or host tlvs contains the
    318      1.1    kefren 	 * network. Yes, we don't have to announce label here
    319      1.1    kefren 	 */
    320      1.1    kefren 
    321      1.2  christos 	lmt = malloc(sizeof(struct label_map_tlv)
    322      1.1    kefren 	      + sizeof(struct fec_tlv)
    323      1.1    kefren 	      + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    324      1.1    kefren 			ldp_ceil8(prefixlen));
    325      1.1    kefren 
    326      1.1    kefren 	if (!lmt) {
    327      1.1    kefren 		fatalp("send_withdraw_tlv: malloc problem\n");
    328      1.1    kefren 		return;
    329      1.1    kefren 		}
    330      1.1    kefren 
    331      1.1    kefren 	lmt->type = htons(LDP_LABEL_WITHDRAW);
    332      1.1    kefren 	lmt->length = htons(sizeof(struct label_map_tlv) - TLV_TYPE_LENGTH
    333      1.1    kefren 	    + sizeof(struct fec_tlv)
    334      1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    335      1.1    kefren 		ldp_ceil8(prefixlen));
    336      1.1    kefren 	lmt->messageid = htonl(get_message_id());
    337      1.1    kefren 
    338      1.1    kefren 	/* FEC TLV */
    339      1.1    kefren 	fec = (struct fec_tlv *) & lmt[1];
    340      1.1    kefren 	fec->type = htons(TLV_FEC);
    341      1.1    kefren 	fec->length = htons(sizeof(struct fec_tlv) - TLV_TYPE_LENGTH
    342      1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    343      1.1    kefren 		ldp_ceil8(prefixlen));
    344      1.1    kefren 
    345      1.1    kefren 	/* Now the even dirtier job: PREFIX TLV */
    346      1.1    kefren 	p = (struct prefix_tlv *) & fec[1];
    347  1.4.8.1       tls 	/*
    348  1.4.8.1       tls 	 * RFC5036 obsoletes FEC_HOST
    349      1.1    kefren 	 *
    350      1.1    kefren 	 * if (prefixlen == 32) p->type = FEC_HOST; else
    351      1.1    kefren 	 */
    352      1.1    kefren 	p->type = FEC_PREFIX;
    353      1.1    kefren 	p->af = htons(LDP_AF_INET);
    354      1.1    kefren 	p->prelen = prefixlen;
    355      1.1    kefren 	memcpy(&p->prefix, addr, ldp_ceil8(prefixlen));
    356      1.1    kefren 
    357      1.1    kefren 	/* Wow, seems we're ready */
    358      1.1    kefren 	send_tlv(peer, (struct tlv *) lmt);
    359      1.1    kefren 	free(lmt);
    360      1.1    kefren }
    361      1.1    kefren 
    362      1.1    kefren void
    363      1.1    kefren send_withdraw_tlv_to_all(struct in_addr * addr, uint8_t prefixlen)
    364      1.1    kefren {
    365      1.1    kefren 	struct ldp_peer *p;
    366      1.1    kefren 	SLIST_FOREACH(p, &ldp_peer_head, peers)
    367      1.1    kefren 		send_withdraw_tlv(p, addr, prefixlen);
    368      1.1    kefren }
    369      1.1    kefren 
    370      1.1    kefren int
    371      1.1    kefren request_respond(struct ldp_peer *p, struct label_map_tlv *lmt,
    372      1.1    kefren     struct fec_tlv *fec)
    373      1.1    kefren {
    374      1.1    kefren 	struct prefix_tlv *pref;
    375      1.1    kefren 	struct in_addr inatmp;
    376      1.1    kefren 	struct label *lab;
    377      1.1    kefren 	struct label_request_tlv lrm;
    378      1.1    kefren 
    379      1.1    kefren 	if (ntohs(fec->type) != TLV_FEC || fec->length == 0) {
    380      1.1    kefren 		debugp("Invalid FEC TLV !\n");
    381      1.1    kefren 		return LDP_E_BAD_FEC;
    382      1.1    kefren 	}
    383      1.1    kefren 	pref = (struct prefix_tlv *) (fec + 1);
    384      1.1    kefren 
    385      1.1    kefren 	if (ntohs(pref->af) != LDP_AF_INET) {
    386      1.1    kefren 		debugp("request_respond: Bad address family\n");
    387      1.1    kefren 		return LDP_E_BAD_AF;
    388      1.1    kefren 	}
    389      1.1    kefren 
    390      1.1    kefren 	switch (pref->type) {
    391      1.1    kefren 		case FEC_PREFIX:
    392      1.1    kefren 		case FEC_HOST:
    393      1.1    kefren 
    394      1.1    kefren 		memset(&inatmp, 0, sizeof(struct in_addr));
    395      1.1    kefren 		memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
    396      1.1    kefren 		debugp("Prefix/Host request: %s/%d\n", inet_ntoa(inatmp),
    397      1.1    kefren 			pref->prelen);
    398      1.1    kefren 
    399      1.1    kefren 		lab = label_get_by_prefix(&inatmp, pref->prelen);
    400      1.1    kefren 		if (!lab)
    401      1.1    kefren 			return LDP_E_NO_SUCH_ROUTE;
    402      1.1    kefren 		lrm.type = htons(TLV_LABEL_REQUEST);
    403      1.1    kefren 		lrm.length = htons(sizeof(uint32_t));
    404      1.1    kefren 		lrm.messageid = lmt->messageid;
    405      1.1    kefren 		send_label_tlv(p, &inatmp, pref->prelen, lab->binding, &lrm);
    406      1.1    kefren 		break;
    407      1.1    kefren 
    408      1.1    kefren 		case FEC_WILDCARD:
    409      1.1    kefren 		/*
    410      1.1    kefren 		 * Section 3.4.1
    411      1.1    kefren 		 * To be used only in the Label Withdraw and Label Release
    412      1.1    kefren 		 */
    413      1.1    kefren 		/* Fallthrough */
    414      1.1    kefren 		default:
    415      1.1    kefren 
    416      1.1    kefren 		fatalp("Invalid FEC type\n");
    417      1.1    kefren 		return LDP_E_BAD_FEC;
    418      1.1    kefren 	}
    419      1.1    kefren 	return LDP_E_OK;
    420      1.1    kefren }
    421