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