Home | History | Annotate | Line # | Download | only in ldpd
tlv_stack.c revision 1.3
      1  1.3    kefren /* $NetBSD: tlv_stack.c,v 1.3 2011/02/10 12:44:41 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 
     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.3    kefren 			/* don't bother if we don't have a label/route */
    114  1.3    kefren 			if (label_get_by_prefix(&inatmp, pref->prelen) == NULL)
    115  1.3    kefren 				break;
    116  1.3    kefren 
    117  1.1    kefren 			ldp_peer_add_mapping(p, &inatmp, pref->prelen,
    118  1.1    kefren 			    ntohl(l->label));
    119  1.1    kefren 			mpls_add_label(p, NULL, &inatmp, pref->prelen,
    120  1.1    kefren 			    ntohl(l->label), 1);
    121  1.1    kefren 			break;
    122  1.1    kefren 		    case FEC_WILDCARD:
    123  1.1    kefren 			fatalp("LDP: Wildcard add from peer %s\n",
    124  1.1    kefren 			    inet_ntoa(p->address));
    125  1.1    kefren 			return LDP_E_BAD_FEC;
    126  1.1    kefren 		    default:
    127  1.1    kefren 			fatalp("Unknown FEC type %d\n", pref->type);
    128  1.1    kefren 			return LDP_E_BAD_FEC;
    129  1.1    kefren 		}
    130  1.1    kefren 	}
    131  1.1    kefren 
    132  1.1    kefren 	return LDP_E_OK;
    133  1.1    kefren }
    134  1.1    kefren 
    135  1.1    kefren int
    136  1.1    kefren withdraw_label(struct ldp_peer * p, struct fec_tlv * f)
    137  1.1    kefren {
    138  1.1    kefren 	int             n;
    139  1.1    kefren 	struct prefix_tlv *pref;
    140  1.1    kefren 	struct in_addr  inatmp;
    141  1.1    kefren 	struct label *lab;
    142  1.1    kefren 
    143  1.1    kefren 	if (ntohs(f->type) != TLV_FEC) {
    144  1.1    kefren 		debugp("Invalid FEC TLV !\n");
    145  1.1    kefren 		return LDP_E_BAD_FEC;
    146  1.1    kefren 	}
    147  1.1    kefren 	n = ntohs(f->length);
    148  1.1    kefren 	if (!n)
    149  1.1    kefren 		return LDP_E_BAD_FEC;
    150  1.1    kefren 
    151  1.1    kefren 	pref = (struct prefix_tlv *) & f[1];
    152  1.1    kefren 	if (ntohs(pref->af) != LDP_AF_INET) {
    153  1.1    kefren 		debugp("BAD ADDRESS FAMILY (%d)! (prefix type %d, length %d)\n",
    154  1.1    kefren 		    ntohs(pref->af), pref->type, pref->prelen);
    155  1.1    kefren 		return LDP_E_BAD_AF;
    156  1.1    kefren 	}
    157  1.1    kefren 	switch(pref->type) {
    158  1.1    kefren 	    case FEC_PREFIX:
    159  1.1    kefren 	    case FEC_HOST:
    160  1.1    kefren 		memset(&inatmp, 0, sizeof(struct in_addr));
    161  1.1    kefren 		memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
    162  1.1    kefren 		debugp("Prefix/Host withdraw: %s/%d\n", inet_ntoa(inatmp),
    163  1.1    kefren 		    pref->prelen);
    164  1.1    kefren 
    165  1.1    kefren 		/* Delete mapping */
    166  1.1    kefren 		ldp_peer_delete_mapping(p, &inatmp, pref->prelen);
    167  1.1    kefren 
    168  1.1    kefren 		/* Get label, see if we're pointing to this peer
    169  1.1    kefren 		 * if so, send withdraw, reattach IP route and announce
    170  1.1    kefren 		 * POP Label
    171  1.1    kefren 		 */
    172  1.1    kefren 		lab = label_get_by_prefix(&inatmp, pref->prelen);
    173  1.1    kefren 		if ((lab) && (lab->p == p)) {
    174  1.1    kefren 			change_local_label(lab, MPLS_LABEL_IMPLNULL);
    175  1.1    kefren 			label_reattach_route(lab, LDP_READD_CHANGE);
    176  1.1    kefren 		}
    177  1.1    kefren 		break;
    178  1.1    kefren 	    case FEC_WILDCARD:
    179  1.1    kefren 		fatalp("LDP neighbour %s: Wildcard withdraw !!!\n",
    180  1.1    kefren 		    inet_ntoa(p->address));
    181  1.1    kefren 		ldp_peer_delete_mapping(p, NULL, 0);
    182  1.1    kefren 		label_reattach_all_peer_labels(p, LDP_READD_CHANGE);
    183  1.1    kefren 		break;
    184  1.1    kefren 	    default:
    185  1.1    kefren 		fatalp("Unknown FEC type %d\n", pref->type);
    186  1.1    kefren 		return LDP_E_BAD_FEC;
    187  1.1    kefren 	}
    188  1.1    kefren 
    189  1.1    kefren 	return LDP_E_OK;
    190  1.1    kefren }
    191  1.1    kefren 
    192  1.1    kefren 
    193  1.1    kefren /*
    194  1.1    kefren  * In case of label redraw, reuse the same buffer to send label release
    195  1.1    kefren  * Simply replace type and message id
    196  1.1    kefren  */
    197  1.1    kefren void
    198  1.1    kefren prepare_release(struct tlv * v)
    199  1.1    kefren {
    200  1.1    kefren 	struct label_map_tlv *t;
    201  1.1    kefren 
    202  1.1    kefren 	t = (struct label_map_tlv *) v;
    203  1.1    kefren 
    204  1.1    kefren 	t->type = htons(LDP_LABEL_RELEASE);
    205  1.1    kefren 	t->messageid = htonl(get_message_id());
    206  1.1    kefren }
    207  1.1    kefren 
    208  1.1    kefren /* Sends a label mapping */
    209  1.1    kefren void
    210  1.1    kefren send_label_tlv(struct ldp_peer * peer, struct in_addr * addr,
    211  1.1    kefren     uint8_t prefixlen, uint32_t label, struct label_request_tlv *lrt)
    212  1.1    kefren {
    213  1.1    kefren 	struct label_map_tlv *lmt;
    214  1.1    kefren 	struct fec_tlv *fec;
    215  1.1    kefren 	struct prefix_tlv *p;
    216  1.1    kefren 	struct label_tlv *l;
    217  1.1    kefren 
    218  1.1    kefren 	/*
    219  1.1    kefren 	 * Ok, so we have label map tlv that contains fec tlvs and label tlv
    220  1.1    kefren 	 * but fec tlv contains prefix or host tlvs and prefix or host tlvs
    221  1.1    kefren 	 * contains the network. After that we may have optional parameters
    222  1.1    kefren 	 * Got it ?
    223  1.1    kefren 	 */
    224  1.1    kefren 
    225  1.2  christos 	lmt = malloc(
    226  1.1    kefren 		sizeof(struct label_map_tlv) +
    227  1.1    kefren 		sizeof(struct fec_tlv) +
    228  1.1    kefren 		sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    229  1.1    kefren 			ldp_ceil8(prefixlen) +
    230  1.1    kefren 		sizeof(struct label_tlv) +
    231  1.1    kefren 	 /* Label request optional parameter  */
    232  1.1    kefren 	 	(lrt != NULL ? sizeof(struct label_request_tlv) : 0) );
    233  1.1    kefren 
    234  1.1    kefren 	if (!lmt) {
    235  1.1    kefren 		fatalp("send_label_tlv: malloc problem\n");
    236  1.1    kefren 		return;
    237  1.2  christos 	}
    238  1.1    kefren 
    239  1.1    kefren 	lmt->type = htons(LDP_LABEL_MAPPING);
    240  1.1    kefren 	lmt->length = htons(sizeof(struct label_map_tlv) - TLV_TYPE_LENGTH
    241  1.1    kefren 	    + sizeof(struct fec_tlv)
    242  1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    243  1.1    kefren 		ldp_ceil8(prefixlen)
    244  1.1    kefren 	    + sizeof(struct label_tlv) +
    245  1.1    kefren 	    + (lrt != NULL ? sizeof(struct label_request_tlv) : 0));
    246  1.1    kefren 	lmt->messageid = htonl(get_message_id());
    247  1.1    kefren 
    248  1.1    kefren 	/* FEC TLV */
    249  1.1    kefren 	fec = (struct fec_tlv *) & lmt[1];
    250  1.1    kefren 	fec->type = htons(TLV_FEC);
    251  1.1    kefren 	fec->length = htons(sizeof(struct fec_tlv) - TLV_TYPE_LENGTH
    252  1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    253  1.1    kefren 		ldp_ceil8(prefixlen));
    254  1.1    kefren 
    255  1.1    kefren 	/* Now let's do the even a dirtier job: PREFIX TLV */
    256  1.1    kefren 	p = (struct prefix_tlv *) & fec[1];
    257  1.1    kefren 	/* Cisco and Juniper don't support FEC type HOST
    258  1.1    kefren 	 * so everything is FEC_PREFIX..
    259  1.1    kefren 	 *
    260  1.1    kefren 	 * if (prefixlen == 32) p->type = FEC_HOST; else
    261  1.1    kefren 	 */
    262  1.1    kefren 	p->type = FEC_PREFIX;
    263  1.1    kefren 	p->af = htons(LDP_AF_INET);
    264  1.1    kefren 	p->prelen = prefixlen;
    265  1.1    kefren 	memcpy(&p->prefix, addr, ldp_ceil8(prefixlen));
    266  1.1    kefren 
    267  1.1    kefren 	/* LABEL TLV */
    268  1.1    kefren 	l = (struct label_tlv *) ((unsigned char *) p +
    269  1.1    kefren 		sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    270  1.1    kefren 		ldp_ceil8(prefixlen));
    271  1.1    kefren 	l->type = htons(TLV_GENERIC_LABEL);
    272  1.1    kefren 	l->length = htons(sizeof(l->label));
    273  1.1    kefren 	l->label = htonl(label);
    274  1.1    kefren 
    275  1.1    kefren 	/* Label request optional parameter */
    276  1.1    kefren 	if (lrt)
    277  1.1    kefren 		memcpy(((char*)l) + TLV_TYPE_LENGTH + ntohs(l->length),
    278  1.1    kefren 			lrt, htons(lrt->length) + TLV_TYPE_LENGTH);
    279  1.1    kefren 
    280  1.1    kefren 	/* Wow, seems we're ready */
    281  1.1    kefren 	send_tlv(peer, (struct tlv *) lmt);
    282  1.1    kefren 	free(lmt);
    283  1.1    kefren }
    284  1.1    kefren 
    285  1.1    kefren void
    286  1.1    kefren send_label_tlv_to_all(struct in_addr * addr, uint8_t prefixlen, uint32_t label)
    287  1.1    kefren {
    288  1.1    kefren 	struct ldp_peer *p;
    289  1.1    kefren 	SLIST_FOREACH(p, &ldp_peer_head, peers)
    290  1.1    kefren 		send_label_tlv(p, addr, prefixlen, label, NULL);
    291  1.1    kefren }
    292  1.1    kefren 
    293  1.1    kefren /*
    294  1.1    kefren  * Send all local labels to a peer
    295  1.1    kefren  */
    296  1.1    kefren void
    297  1.1    kefren send_all_bindings(struct ldp_peer * peer)
    298  1.1    kefren {
    299  1.1    kefren 	struct label *l;
    300  1.1    kefren 
    301  1.1    kefren 	SLIST_FOREACH(l, &label_head, labels)
    302  1.1    kefren 	   send_label_tlv(peer, &((struct sockaddr_in*)(&l->so_dest))->sin_addr,
    303  1.1    kefren 		from_union_to_cidr(&l->so_pref), l->binding, NULL);
    304  1.1    kefren 
    305  1.1    kefren }
    306  1.1    kefren 
    307  1.1    kefren /* Sends a label WITHDRAW */
    308  1.1    kefren void
    309  1.1    kefren send_withdraw_tlv(struct ldp_peer * peer, struct in_addr * addr,
    310  1.1    kefren     uint8_t prefixlen)
    311  1.1    kefren {
    312  1.1    kefren 	struct label_map_tlv *lmt;
    313  1.1    kefren 	struct fec_tlv *fec;
    314  1.1    kefren 	struct prefix_tlv *p;
    315  1.1    kefren 
    316  1.1    kefren 	/*
    317  1.1    kefren 	 * Ok, so we have label map tlv that contains fec tlvs but fec tlv
    318  1.1    kefren 	 * contains prefix or host tlvs and prefix or host tlvs contains the
    319  1.1    kefren 	 * network. Yes, we don't have to announce label here
    320  1.1    kefren 	 */
    321  1.1    kefren 
    322  1.2  christos 	lmt = malloc(sizeof(struct label_map_tlv)
    323  1.1    kefren 	      + sizeof(struct fec_tlv)
    324  1.1    kefren 	      + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    325  1.1    kefren 			ldp_ceil8(prefixlen));
    326  1.1    kefren 
    327  1.1    kefren 	if (!lmt) {
    328  1.1    kefren 		fatalp("send_withdraw_tlv: malloc problem\n");
    329  1.1    kefren 		return;
    330  1.1    kefren 		}
    331  1.1    kefren 
    332  1.1    kefren 	lmt->type = htons(LDP_LABEL_WITHDRAW);
    333  1.1    kefren 	lmt->length = htons(sizeof(struct label_map_tlv) - TLV_TYPE_LENGTH
    334  1.1    kefren 	    + sizeof(struct fec_tlv)
    335  1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    336  1.1    kefren 		ldp_ceil8(prefixlen));
    337  1.1    kefren 	lmt->messageid = htonl(get_message_id());
    338  1.1    kefren 
    339  1.1    kefren 	/* FEC TLV */
    340  1.1    kefren 	fec = (struct fec_tlv *) & lmt[1];
    341  1.1    kefren 	fec->type = htons(TLV_FEC);
    342  1.1    kefren 	fec->length = htons(sizeof(struct fec_tlv) - TLV_TYPE_LENGTH
    343  1.1    kefren 	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
    344  1.1    kefren 		ldp_ceil8(prefixlen));
    345  1.1    kefren 
    346  1.1    kefren 	/* Now the even dirtier job: PREFIX TLV */
    347  1.1    kefren 	p = (struct prefix_tlv *) & fec[1];
    348  1.1    kefren 	/* See above comment
    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