Bug Summary

File:src/usr.sbin/ldpd/labelmapping.c
Warning:line 79, column 7
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name labelmapping.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ldpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/ldpd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/ldpd/labelmapping.c
1/* $OpenBSD: labelmapping.c,v 1.69 2023/07/03 11:51:27 claudio Exp $ */
2
3/*
4 * Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <arpa/inet.h>
23#include <netmpls/mpls.h>
24#include <limits.h>
25#include <stddef.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "ldpd.h"
30#include "ldpe.h"
31#include "log.h"
32
33static void enqueue_pdu(struct nbr *, struct ibuf *, uint16_t);
34static int gen_label_tlv(struct ibuf *, uint32_t);
35static int tlv_decode_label(struct nbr *, struct ldp_msg *, char *,
36 uint16_t, uint32_t *);
37static int gen_reqid_tlv(struct ibuf *, uint32_t);
38static void log_msg_mapping(int, uint16_t, struct nbr *, struct map *);
39
40static void
41enqueue_pdu(struct nbr *nbr, struct ibuf *buf, uint16_t size)
42{
43 if (ibuf_set_n16(buf, offsetof(struct ldp_hdr, length)__builtin_offsetof(struct ldp_hdr, length), size) == -1)
44 fatal(__func__);
45 evbuf_enqueue(&nbr->tcp->wbuf, buf);
46}
47
48/* Generic function that handles all Label Message types */
49void
50send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
51{
52 struct ibuf *buf = NULL((void *)0);
53 struct mapping_entry *me;
54 uint16_t msg_size, size = 0;
55 int first = 1;
56 int err = 0;
57
58 /* nothing to send */
59 if (TAILQ_EMPTY(mh)(((mh)->tqh_first) == ((void *)0)))
1
Assuming field 'tqh_first' is not equal to null
2
Taking false branch
60 return;
61
62 while ((me = TAILQ_FIRST(mh)((mh)->tqh_first)) != NULL((void *)0)) {
3
Loop condition is true. Entering loop body
29
Loop condition is true. Entering loop body
63 /* generate pdu */
64 if (first
3.1
'first' is 1
29.1
'first' is 0
) {
4
Taking true branch
30
Taking false branch
65 if ((buf = ibuf_open(nbr->max_pdu_len +
5
Assuming the condition is false
6
Taking false branch
66 LDP_HDR_DEAD_LEN4)) == NULL((void *)0))
67 fatal(__func__);
68
69 /* real size will be set up later */
70 err |= gen_ldp_hdr(buf, 0);
71
72 size = LDP_HDR_PDU_LEN6;
73 first = 0;
74 }
75
76 /* calculate size */
77 msg_size = LDP_MSG_SIZE8;
78 msg_size += len_fec_tlv(&me->map);
79 if (me->map.label != NO_LABEL0xffffffffU)
7
Assuming field 'label' is equal to NO_LABEL
8
Taking false branch
31
Use of memory after it is freed
80 msg_size += LABEL_TLV_SIZE8;
81 if (me->map.flags & F_MAP_REQ_ID0x01)
9
Assuming the condition is false
10
Taking false branch
82 msg_size += REQID_TLV_SIZE8;
83 if (me->map.flags & F_MAP_STATUS0x02)
11
Assuming the condition is true
12
Taking true branch
84 msg_size += STATUS_SIZE14;
85
86 /* maximum pdu length exceeded, we need a new ldp pdu */
87 if (size + msg_size > nbr->max_pdu_len) {
13
Assuming the condition is false
14
Taking false branch
88 enqueue_pdu(nbr, buf, size);
89 first = 1;
90 continue;
91 }
92
93 size += msg_size;
94
95 /* append message and tlvs */
96 err |= gen_msg_hdr(buf, type, msg_size);
97 err |= gen_fec_tlv(buf, &me->map);
98 if (me->map.label != NO_LABEL0xffffffffU)
15
Assuming field 'label' is equal to NO_LABEL
16
Taking false branch
99 err |= gen_label_tlv(buf, me->map.label);
100 if (me->map.flags & F_MAP_REQ_ID0x01)
17
Assuming the condition is false
18
Taking false branch
101 err |= gen_reqid_tlv(buf, me->map.requestid);
102 if (me->map.flags & F_MAP_PW_STATUS0x20)
19
Assuming the condition is false
20
Taking false branch
103 err |= gen_pw_status_tlv(buf, me->map.pw_status);
104 if (me->map.flags & F_MAP_STATUS0x02)
21
Assuming the condition is false
22
Taking false branch
105 err |= gen_status_tlv(buf, me->map.st.status_code,
106 me->map.st.msg_id, me->map.st.msg_type);
107 if (err) {
23
Assuming 'err' is 0
24
Taking false branch
108 ibuf_free(buf);
109 mapping_list_clr(mh);
110 return;
111 }
112
113 log_msg_mapping(1, type, nbr, &me->map);
114
115 TAILQ_REMOVE(mh, me, entry)do { if (((me)->entry.tqe_next) != ((void *)0)) (me)->entry
.tqe_next->entry.tqe_prev = (me)->entry.tqe_prev; else (
mh)->tqh_last = (me)->entry.tqe_prev; *(me)->entry.tqe_prev
= (me)->entry.tqe_next; ; ; } while (0)
;
25
Assuming field 'tqe_next' is equal to null
26
Taking false branch
27
Loop condition is false. Exiting loop
116 free(me);
28
Memory is released
117 }
118
119 enqueue_pdu(nbr, buf, size);
120
121 nbr_fsm(nbr, NBR_EVT_PDU_SENT);
122}
123
124/* Generic function that handles all Label Message types */
125int
126recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
127{
128 struct ldp_msg msg;
129 struct tlv ft;
130 uint32_t label = NO_LABEL0xffffffffU, reqid = 0;
131 uint32_t pw_status = 0;
132 uint8_t flags = 0;
133 int feclen, lbllen, tlen;
134 struct mapping_entry *me;
135 struct mapping_head mh;
136 struct map map;
137
138 memcpy(&msg, buf, sizeof(msg));
139 buf += LDP_MSG_SIZE8;
140 len -= LDP_MSG_SIZE8;
141
142 /* FEC TLV */
143 if (len < sizeof(ft)) {
144 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg.id, msg.type);
145 return (-1);
146 }
147
148 memcpy(&ft, buf, sizeof(ft));
149 if (ntohs(ft.type)(__uint16_t)(__builtin_constant_p(ft.type) ? (__uint16_t)(((__uint16_t
)(ft.type) & 0xffU) << 8 | ((__uint16_t)(ft.type) &
0xff00U) >> 8) : __swap16md(ft.type))
!= TLV_TYPE_FEC0x0100) {
150 send_notification(nbr->tcp, S_MISS_MSG0x00000016, msg.id, msg.type);
151 return (-1);
152 }
153 feclen = ntohs(ft.length)(__uint16_t)(__builtin_constant_p(ft.length) ? (__uint16_t)((
(__uint16_t)(ft.length) & 0xffU) << 8 | ((__uint16_t
)(ft.length) & 0xff00U) >> 8) : __swap16md(ft.length
))
;
154 if (feclen > len - TLV_HDR_SIZE4) {
155 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg.id, msg.type);
156 return (-1);
157 }
158
159 buf += TLV_HDR_SIZE4; /* just advance to the end of the fec header */
160 len -= TLV_HDR_SIZE4;
161
162 TAILQ_INIT(&mh)do { (&mh)->tqh_first = ((void *)0); (&mh)->tqh_last
= &(&mh)->tqh_first; } while (0)
;
163 do {
164 memset(&map, 0, sizeof(map));
165 map.msg_id = msg.id;
166
167 if ((tlen = tlv_decode_fec_elm(nbr, &msg, buf, feclen,
168 &map)) == -1)
169 goto err;
170 if (map.type == MAP_TYPE_PWID0x80 &&
171 !(map.flags & F_MAP_PW_ID0x08) &&
172 type != MSG_TYPE_LABELWITHDRAW0x0402 &&
173 type != MSG_TYPE_LABELRELEASE0x0403) {
174 send_notification(nbr->tcp, S_MISS_MSG0x00000016, msg.id,
175 msg.type);
176 return (-1);
177 }
178
179 /*
180 * The Wildcard FEC Element can be used only in the
181 * Label Withdraw and Label Release messages.
182 */
183 if (map.type == MAP_TYPE_WILDCARD0x01) {
184 switch (type) {
185 case MSG_TYPE_LABELMAPPING0x0400:
186 case MSG_TYPE_LABELREQUEST0x0401:
187 case MSG_TYPE_LABELABORTREQ0x0404:
188 session_shutdown(nbr, S_UNKNOWN_FEC0x0000000C, msg.id,
189 msg.type);
190 goto err;
191 default:
192 break;
193 }
194 }
195
196 /*
197 * RFC 5561 - Section 4:
198 * "An LDP implementation that supports the Typed Wildcard
199 * FEC Element MUST support its use in Label Request, Label
200 * Withdraw, and Label Release messages".
201 */
202 if (map.type == MAP_TYPE_TYPED_WCARD0x05) {
203 switch (type) {
204 case MSG_TYPE_LABELMAPPING0x0400:
205 case MSG_TYPE_LABELABORTREQ0x0404:
206 session_shutdown(nbr, S_UNKNOWN_FEC0x0000000C, msg.id,
207 msg.type);
208 goto err;
209 default:
210 break;
211 }
212 }
213
214 /*
215 * LDP supports the use of multiple FEC Elements per
216 * FEC for the Label Mapping message only.
217 */
218 if (type != MSG_TYPE_LABELMAPPING0x0400 &&
219 tlen != feclen) {
220 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg.id, msg.type);
221 goto err;
222 }
223
224 mapping_list_add(&mh, &map);
225
226 buf += tlen;
227 len -= tlen;
228 feclen -= tlen;
229 } while (feclen > 0);
230
231 /* Mandatory Label TLV */
232 if (type == MSG_TYPE_LABELMAPPING0x0400) {
233 lbllen = tlv_decode_label(nbr, &msg, buf, len, &label);
234 if (lbllen == -1)
235 goto err;
236
237 buf += lbllen;
238 len -= lbllen;
239 }
240
241 /* Optional Parameters */
242 while (len > 0) {
243 struct tlv tlv;
244 uint16_t tlv_type;
245 uint16_t tlv_len;
246 uint32_t reqbuf, labelbuf, statusbuf;
247
248 if (len < sizeof(tlv)) {
249 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg.id, msg.type);
250 goto err;
251 }
252
253 memcpy(&tlv, buf, TLV_HDR_SIZE4);
254 tlv_type = ntohs(tlv.type)(__uint16_t)(__builtin_constant_p(tlv.type) ? (__uint16_t)(((
__uint16_t)(tlv.type) & 0xffU) << 8 | ((__uint16_t)
(tlv.type) & 0xff00U) >> 8) : __swap16md(tlv.type))
;
255 tlv_len = ntohs(tlv.length)(__uint16_t)(__builtin_constant_p(tlv.length) ? (__uint16_t)(
((__uint16_t)(tlv.length) & 0xffU) << 8 | ((__uint16_t
)(tlv.length) & 0xff00U) >> 8) : __swap16md(tlv.length
))
;
256 if (tlv_len + TLV_HDR_SIZE4 > len) {
257 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg.id, msg.type);
258 goto err;
259 }
260 buf += TLV_HDR_SIZE4;
261 len -= TLV_HDR_SIZE4;
262
263 switch (tlv_type) {
264 case TLV_TYPE_LABELREQUEST0x0600:
265 switch (type) {
266 case MSG_TYPE_LABELMAPPING0x0400:
267 case MSG_TYPE_LABELREQUEST0x0401:
268 if (tlv_len != REQID_TLV_LEN4) {
269 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007,
270 msg.id, msg.type);
271 goto err;
272 }
273
274 flags |= F_MAP_REQ_ID0x01;
275 memcpy(&reqbuf, buf, sizeof(reqbuf));
276 reqid = ntohl(reqbuf)(__uint32_t)(__builtin_constant_p(reqbuf) ? (__uint32_t)(((__uint32_t
)(reqbuf) & 0xff) << 24 | ((__uint32_t)(reqbuf) &
0xff00) << 8 | ((__uint32_t)(reqbuf) & 0xff0000) >>
8 | ((__uint32_t)(reqbuf) & 0xff000000) >> 24) : __swap32md
(reqbuf))
;
277 break;
278 default:
279 /* ignore */
280 break;
281 }
282 break;
283 case TLV_TYPE_HOPCOUNT0x0103:
284 case TLV_TYPE_PATHVECTOR0x0104:
285 /* ignore */
286 break;
287 case TLV_TYPE_GENERICLABEL0x0200:
288 switch (type) {
289 case MSG_TYPE_LABELWITHDRAW0x0402:
290 case MSG_TYPE_LABELRELEASE0x0403:
291 if (tlv_len != LABEL_TLV_LEN4) {
292 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007,
293 msg.id, msg.type);
294 goto err;
295 }
296
297 memcpy(&labelbuf, buf, sizeof(labelbuf));
298 label = ntohl(labelbuf)(__uint32_t)(__builtin_constant_p(labelbuf) ? (__uint32_t)(((
__uint32_t)(labelbuf) & 0xff) << 24 | ((__uint32_t)
(labelbuf) & 0xff00) << 8 | ((__uint32_t)(labelbuf)
& 0xff0000) >> 8 | ((__uint32_t)(labelbuf) & 0xff000000
) >> 24) : __swap32md(labelbuf))
;
299 break;
300 default:
301 /* ignore */
302 break;
303 }
304 break;
305 case TLV_TYPE_ATMLABEL0x0201:
306 case TLV_TYPE_FRLABEL0x0202:
307 switch (type) {
308 case MSG_TYPE_LABELWITHDRAW0x0402:
309 case MSG_TYPE_LABELRELEASE0x0403:
310 /* unsupported */
311 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg.id,
312 msg.type);
313 goto err;
314 break;
315 default:
316 /* ignore */
317 break;
318 }
319 break;
320 case TLV_TYPE_STATUS0x0300:
321 if (tlv_len != STATUS_TLV_LEN10) {
322 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg.id,
323 msg.type);
324 goto err;
325 }
326 /* ignore */
327 break;
328 case TLV_TYPE_PW_STATUS0x896A:
329 switch (type) {
330 case MSG_TYPE_LABELMAPPING0x0400:
331 if (tlv_len != PW_STATUS_TLV_LEN4) {
332 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007,
333 msg.id, msg.type);
334 goto err;
335 }
336
337 flags |= F_MAP_PW_STATUS0x20;
338 memcpy(&statusbuf, buf, sizeof(statusbuf));
339 pw_status = ntohl(statusbuf)(__uint32_t)(__builtin_constant_p(statusbuf) ? (__uint32_t)((
(__uint32_t)(statusbuf) & 0xff) << 24 | ((__uint32_t
)(statusbuf) & 0xff00) << 8 | ((__uint32_t)(statusbuf
) & 0xff0000) >> 8 | ((__uint32_t)(statusbuf) &
0xff000000) >> 24) : __swap32md(statusbuf))
;
340 break;
341 default:
342 /* ignore */
343 break;
344 }
345 break;
346 default:
347 if (!(ntohs(tlv.type)(__uint16_t)(__builtin_constant_p(tlv.type) ? (__uint16_t)(((
__uint16_t)(tlv.type) & 0xffU) << 8 | ((__uint16_t)
(tlv.type) & 0xff00U) >> 8) : __swap16md(tlv.type))
& UNKNOWN_FLAG0x8000))
348 send_notification_rtlvs(nbr, S_UNKNOWN_TLV0x00000006,
349 msg.id, msg.type, tlv_type, tlv_len, buf);
350 /* ignore unknown tlv */
351 break;
352 }
353 buf += tlv_len;
354 len -= tlv_len;
355 }
356
357 /* notify lde about the received message. */
358 while ((me = TAILQ_FIRST(&mh)((&mh)->tqh_first)) != NULL((void *)0)) {
359 int imsg_type = IMSG_NONE;
360
361 me->map.flags |= flags;
362 switch (me->map.type) {
363 case MAP_TYPE_PREFIX0x02:
364 switch (me->map.fec.prefix.af) {
365 case AF_INET2:
366 if (label == MPLS_LABEL_IPV6NULL2) {
367 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008,
368 msg.id, msg.type);
369 goto err;
370 }
371 if (!nbr->v4_enabled)
372 goto next;
373 break;
374 case AF_INET624:
375 if (label == MPLS_LABEL_IPV4NULL0) {
376 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008,
377 msg.id, msg.type);
378 goto err;
379 }
380 if (!nbr->v6_enabled)
381 goto next;
382 break;
383 default:
384 fatalx("recv_labelmessage: unknown af");
385 }
386 break;
387 case MAP_TYPE_PWID0x80:
388 if (label <= MPLS_LABEL_RESERVED_MAX15) {
389 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg.id,
390 msg.type);
391 goto err;
392 }
393 if (me->map.flags & F_MAP_PW_STATUS0x20)
394 me->map.pw_status = pw_status;
395 break;
396 default:
397 break;
398 }
399 me->map.label = label;
400 if (me->map.flags & F_MAP_REQ_ID0x01)
401 me->map.requestid = reqid;
402
403 log_msg_mapping(0, type, nbr, &me->map);
404
405 switch (type) {
406 case MSG_TYPE_LABELMAPPING0x0400:
407 imsg_type = IMSG_LABEL_MAPPING;
408 break;
409 case MSG_TYPE_LABELREQUEST0x0401:
410 imsg_type = IMSG_LABEL_REQUEST;
411 break;
412 case MSG_TYPE_LABELWITHDRAW0x0402:
413 imsg_type = IMSG_LABEL_WITHDRAW;
414 break;
415 case MSG_TYPE_LABELRELEASE0x0403:
416 imsg_type = IMSG_LABEL_RELEASE;
417 break;
418 case MSG_TYPE_LABELABORTREQ0x0404:
419 imsg_type = IMSG_LABEL_ABORT;
420 break;
421 default:
422 break;
423 }
424
425 ldpe_imsg_compose_lde(imsg_type, nbr->peerid, 0, &me->map,
426 sizeof(struct map));
427
428 next:
429 TAILQ_REMOVE(&mh, me, entry)do { if (((me)->entry.tqe_next) != ((void *)0)) (me)->entry
.tqe_next->entry.tqe_prev = (me)->entry.tqe_prev; else (
&mh)->tqh_last = (me)->entry.tqe_prev; *(me)->entry
.tqe_prev = (me)->entry.tqe_next; ; ; } while (0)
;
430 free(me);
431 }
432
433 return (0);
434
435 err:
436 mapping_list_clr(&mh);
437
438 return (-1);
439}
440
441/* Other TLV related functions */
442static int
443gen_label_tlv(struct ibuf *buf, uint32_t label)
444{
445 struct label_tlv lt;
446
447 lt.type = htons(TLV_TYPE_GENERICLABEL)(__uint16_t)(__builtin_constant_p(0x0200) ? (__uint16_t)(((__uint16_t
)(0x0200) & 0xffU) << 8 | ((__uint16_t)(0x0200) &
0xff00U) >> 8) : __swap16md(0x0200))
;
448 lt.length = htons(LABEL_TLV_LEN)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t
)(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U
) >> 8) : __swap16md(4))
;
449 lt.label = htonl(label)(__uint32_t)(__builtin_constant_p(label) ? (__uint32_t)(((__uint32_t
)(label) & 0xff) << 24 | ((__uint32_t)(label) &
0xff00) << 8 | ((__uint32_t)(label) & 0xff0000) >>
8 | ((__uint32_t)(label) & 0xff000000) >> 24) : __swap32md
(label))
;
450
451 return (ibuf_add(buf, &lt, sizeof(lt)));
452}
453
454static int
455tlv_decode_label(struct nbr *nbr, struct ldp_msg *msg, char *buf,
456 uint16_t len, uint32_t *label)
457{
458 struct label_tlv lt;
459
460 if (len < sizeof(lt)) {
461 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id, msg->type);
462 return (-1);
463 }
464 memcpy(&lt, buf, sizeof(lt));
465
466 if (!(ntohs(lt.type)(__uint16_t)(__builtin_constant_p(lt.type) ? (__uint16_t)(((__uint16_t
)(lt.type) & 0xffU) << 8 | ((__uint16_t)(lt.type) &
0xff00U) >> 8) : __swap16md(lt.type))
& TLV_TYPE_GENERICLABEL0x0200)) {
467 send_notification(nbr->tcp, S_MISS_MSG0x00000016, msg->id, msg->type);
468 return (-1);
469 }
470
471 switch (htons(lt.type)(__uint16_t)(__builtin_constant_p(lt.type) ? (__uint16_t)(((__uint16_t
)(lt.type) & 0xffU) << 8 | ((__uint16_t)(lt.type) &
0xff00U) >> 8) : __swap16md(lt.type))
) {
472 case TLV_TYPE_GENERICLABEL0x0200:
473 if (ntohs(lt.length)(__uint16_t)(__builtin_constant_p(lt.length) ? (__uint16_t)((
(__uint16_t)(lt.length) & 0xffU) << 8 | ((__uint16_t
)(lt.length) & 0xff00U) >> 8) : __swap16md(lt.length
))
!= sizeof(lt) - TLV_HDR_SIZE4) {
474 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
475 msg->type);
476 return (-1);
477 }
478
479 *label = ntohl(lt.label)(__uint32_t)(__builtin_constant_p(lt.label) ? (__uint32_t)(((
__uint32_t)(lt.label) & 0xff) << 24 | ((__uint32_t)
(lt.label) & 0xff00) << 8 | ((__uint32_t)(lt.label)
& 0xff0000) >> 8 | ((__uint32_t)(lt.label) & 0xff000000
) >> 24) : __swap32md(lt.label))
;
480 if (*label > MPLS_LABEL_MAX((1 << 20) - 1) ||
481 (*label <= MPLS_LABEL_RESERVED_MAX15 &&
482 *label != MPLS_LABEL_IPV4NULL0 &&
483 *label != MPLS_LABEL_IPV6NULL2 &&
484 *label != MPLS_LABEL_IMPLNULL3)) {
485 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg->id,
486 msg->type);
487 return (-1);
488 }
489 break;
490 case TLV_TYPE_ATMLABEL0x0201:
491 case TLV_TYPE_FRLABEL0x0202:
492 default:
493 /* unsupported */
494 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg->id, msg->type);
495 return (-1);
496 }
497
498 return (sizeof(lt));
499}
500
501static int
502gen_reqid_tlv(struct ibuf *buf, uint32_t reqid)
503{
504 struct reqid_tlv rt;
505
506 rt.type = htons(TLV_TYPE_LABELREQUEST)(__uint16_t)(__builtin_constant_p(0x0600) ? (__uint16_t)(((__uint16_t
)(0x0600) & 0xffU) << 8 | ((__uint16_t)(0x0600) &
0xff00U) >> 8) : __swap16md(0x0600))
;
507 rt.length = htons(REQID_TLV_LEN)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t
)(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U
) >> 8) : __swap16md(4))
;
508 rt.reqid = htonl(reqid)(__uint32_t)(__builtin_constant_p(reqid) ? (__uint32_t)(((__uint32_t
)(reqid) & 0xff) << 24 | ((__uint32_t)(reqid) &
0xff00) << 8 | ((__uint32_t)(reqid) & 0xff0000) >>
8 | ((__uint32_t)(reqid) & 0xff000000) >> 24) : __swap32md
(reqid))
;
509
510 return (ibuf_add(buf, &rt, sizeof(rt)));
511}
512
513int
514gen_pw_status_tlv(struct ibuf *buf, uint32_t status)
515{
516 struct pw_status_tlv st;
517
518 st.type = htons(TLV_TYPE_PW_STATUS)(__uint16_t)(__builtin_constant_p(0x896A) ? (__uint16_t)(((__uint16_t
)(0x896A) & 0xffU) << 8 | ((__uint16_t)(0x896A) &
0xff00U) >> 8) : __swap16md(0x896A))
;
519 st.length = htons(PW_STATUS_TLV_LEN)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t
)(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U
) >> 8) : __swap16md(4))
;
520 st.value = htonl(status)(__uint32_t)(__builtin_constant_p(status) ? (__uint32_t)(((__uint32_t
)(status) & 0xff) << 24 | ((__uint32_t)(status) &
0xff00) << 8 | ((__uint32_t)(status) & 0xff0000) >>
8 | ((__uint32_t)(status) & 0xff000000) >> 24) : __swap32md
(status))
;
521
522 return (ibuf_add(buf, &st, sizeof(st)));
523}
524
525uint16_t
526len_fec_tlv(struct map *map)
527{
528 uint16_t len = TLV_HDR_SIZE4;
529
530 switch (map->type) {
531 case MAP_TYPE_WILDCARD0x01:
532 len += FEC_ELM_WCARD_LEN1;
533 break;
534 case MAP_TYPE_PREFIX0x02:
535 len += FEC_ELM_PREFIX_MIN_LEN4 +
536 PREFIX_SIZE(map->fec.prefix.prefixlen)(((map->fec.prefix.prefixlen) + 7) / 8);
537 break;
538 case MAP_TYPE_PWID0x80:
539 len += FEC_PWID_ELM_MIN_LEN8;
540 if (map->flags & F_MAP_PW_ID0x08)
541 len += PW_STATUS_TLV_LEN4;
542 if (map->flags & F_MAP_PW_IFMTU0x10)
543 len += FEC_SUBTLV_IFMTU_SIZE4;
544 if (map->flags & F_MAP_PW_STATUS0x20)
545 len += PW_STATUS_TLV_SIZE8;
546 break;
547 case MAP_TYPE_TYPED_WCARD0x05:
548 len += FEC_ELM_TWCARD_MIN_LEN3;
549 switch (map->fec.twcard.type) {
550 case MAP_TYPE_PREFIX0x02:
551 case MAP_TYPE_PWID0x80:
552 len += sizeof(uint16_t);
553 break;
554 default:
555 fatalx("len_fec_tlv: unexpected fec type");
556 }
557 break;
558 default:
559 fatalx("len_fec_tlv: unexpected fec type");
560 }
561
562 return (len);
563}
564
565int
566gen_fec_tlv(struct ibuf *buf, struct map *map)
567{
568 struct tlv ft;
569 uint16_t family, len, pw_type, ifmtu;
570 uint8_t pw_len = 0, twcard_len;
571 uint32_t group_id, pwid;
572 int err = 0;
573
574 ft.type = htons(TLV_TYPE_FEC)(__uint16_t)(__builtin_constant_p(0x0100) ? (__uint16_t)(((__uint16_t
)(0x0100) & 0xffU) << 8 | ((__uint16_t)(0x0100) &
0xff00U) >> 8) : __swap16md(0x0100))
;
575
576 switch (map->type) {
577 case MAP_TYPE_WILDCARD0x01:
578 ft.length = htons(sizeof(uint8_t))(__uint16_t)(__builtin_constant_p(sizeof(uint8_t)) ? (__uint16_t
)(((__uint16_t)(sizeof(uint8_t)) & 0xffU) << 8 | ((
__uint16_t)(sizeof(uint8_t)) & 0xff00U) >> 8) : __swap16md
(sizeof(uint8_t)))
;
579 err |= ibuf_add(buf, &ft, sizeof(ft));
580 err |= ibuf_add(buf, &map->type, sizeof(map->type));
581 break;
582 case MAP_TYPE_PREFIX0x02:
583 len = PREFIX_SIZE(map->fec.prefix.prefixlen)(((map->fec.prefix.prefixlen) + 7) / 8);
584 ft.length = htons(sizeof(map->type) + sizeof(family) +(__uint16_t)(__builtin_constant_p(sizeof(map->type) + sizeof
(family) + sizeof(map->fec.prefix.prefixlen) + len) ? (__uint16_t
)(((__uint16_t)(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len) & 0xffU) << 8
| ((__uint16_t)(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len) & 0xff00U) >>
8) : __swap16md(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len))
585 sizeof(map->fec.prefix.prefixlen) + len)(__uint16_t)(__builtin_constant_p(sizeof(map->type) + sizeof
(family) + sizeof(map->fec.prefix.prefixlen) + len) ? (__uint16_t
)(((__uint16_t)(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len) & 0xffU) << 8
| ((__uint16_t)(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len) & 0xff00U) >>
8) : __swap16md(sizeof(map->type) + sizeof(family) + sizeof
(map->fec.prefix.prefixlen) + len))
;
586 err |= ibuf_add(buf, &ft, sizeof(ft));
587 err |= ibuf_add(buf, &map->type, sizeof(map->type));
588 switch (map->fec.prefix.af) {
589 case AF_INET2:
590 family = htons(AF_IPV4)(__uint16_t)(__builtin_constant_p(0x1) ? (__uint16_t)(((__uint16_t
)(0x1) & 0xffU) << 8 | ((__uint16_t)(0x1) & 0xff00U
) >> 8) : __swap16md(0x1))
;
591 break;
592 case AF_INET624:
593 family = htons(AF_IPV6)(__uint16_t)(__builtin_constant_p(0x2) ? (__uint16_t)(((__uint16_t
)(0x2) & 0xffU) << 8 | ((__uint16_t)(0x2) & 0xff00U
) >> 8) : __swap16md(0x2))
;
594 break;
595 default:
596 fatalx("gen_fec_tlv: unknown af");
597 break;
598 }
599 err |= ibuf_add(buf, &family, sizeof(family));
600 err |= ibuf_add(buf, &map->fec.prefix.prefixlen,
601 sizeof(map->fec.prefix.prefixlen));
602 if (len)
603 err |= ibuf_add(buf, &map->fec.prefix.prefix, len);
604 break;
605 case MAP_TYPE_PWID0x80:
606 if (map->flags & F_MAP_PW_ID0x08)
607 pw_len += FEC_PWID_SIZE4;
608 if (map->flags & F_MAP_PW_IFMTU0x10)
609 pw_len += FEC_SUBTLV_IFMTU_SIZE4;
610
611 len = FEC_PWID_ELM_MIN_LEN8 + pw_len;
612
613 ft.length = htons(len)(__uint16_t)(__builtin_constant_p(len) ? (__uint16_t)(((__uint16_t
)(len) & 0xffU) << 8 | ((__uint16_t)(len) & 0xff00U
) >> 8) : __swap16md(len))
;
614 err |= ibuf_add(buf, &ft, sizeof(ft));
615
616 err |= ibuf_add(buf, &map->type, sizeof(uint8_t));
617 pw_type = map->fec.pwid.type;
618 if (map->flags & F_MAP_PW_CWORD0x04)
619 pw_type |= CONTROL_WORD_FLAG0x8000;
620 pw_type = htons(pw_type)(__uint16_t)(__builtin_constant_p(pw_type) ? (__uint16_t)(((__uint16_t
)(pw_type) & 0xffU) << 8 | ((__uint16_t)(pw_type) &
0xff00U) >> 8) : __swap16md(pw_type))
;
621 err |= ibuf_add(buf, &pw_type, sizeof(uint16_t));
622 err |= ibuf_add(buf, &pw_len, sizeof(uint8_t));
623 group_id = htonl(map->fec.pwid.group_id)(__uint32_t)(__builtin_constant_p(map->fec.pwid.group_id) ?
(__uint32_t)(((__uint32_t)(map->fec.pwid.group_id) & 0xff
) << 24 | ((__uint32_t)(map->fec.pwid.group_id) &
0xff00) << 8 | ((__uint32_t)(map->fec.pwid.group_id
) & 0xff0000) >> 8 | ((__uint32_t)(map->fec.pwid
.group_id) & 0xff000000) >> 24) : __swap32md(map->
fec.pwid.group_id))
;
624 err |= ibuf_add(buf, &group_id, sizeof(uint32_t));
625 if (map->flags & F_MAP_PW_ID0x08) {
626 pwid = htonl(map->fec.pwid.pwid)(__uint32_t)(__builtin_constant_p(map->fec.pwid.pwid) ? (__uint32_t
)(((__uint32_t)(map->fec.pwid.pwid) & 0xff) << 24
| ((__uint32_t)(map->fec.pwid.pwid) & 0xff00) <<
8 | ((__uint32_t)(map->fec.pwid.pwid) & 0xff0000) >>
8 | ((__uint32_t)(map->fec.pwid.pwid) & 0xff000000) >>
24) : __swap32md(map->fec.pwid.pwid))
;
627 err |= ibuf_add(buf, &pwid, sizeof(uint32_t));
628 }
629 if (map->flags & F_MAP_PW_IFMTU0x10) {
630 struct subtlv stlv;
631
632 stlv.type = SUBTLV_IFMTU0x01;
633 stlv.length = FEC_SUBTLV_IFMTU_SIZE4;
634 err |= ibuf_add(buf, &stlv, sizeof(uint16_t));
635
636 ifmtu = htons(map->fec.pwid.ifmtu)(__uint16_t)(__builtin_constant_p(map->fec.pwid.ifmtu) ? (
__uint16_t)(((__uint16_t)(map->fec.pwid.ifmtu) & 0xffU
) << 8 | ((__uint16_t)(map->fec.pwid.ifmtu) & 0xff00U
) >> 8) : __swap16md(map->fec.pwid.ifmtu))
;
637 err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t));
638 }
639 break;
640 case MAP_TYPE_TYPED_WCARD0x05:
641 len = FEC_ELM_TWCARD_MIN_LEN3;
642 switch (map->fec.twcard.type) {
643 case MAP_TYPE_PREFIX0x02:
644 case MAP_TYPE_PWID0x80:
645 len += sizeof(uint16_t);
646 break;
647 default:
648 fatalx("gen_fec_tlv: unexpected fec type");
649 }
650 ft.length = htons(len)(__uint16_t)(__builtin_constant_p(len) ? (__uint16_t)(((__uint16_t
)(len) & 0xffU) << 8 | ((__uint16_t)(len) & 0xff00U
) >> 8) : __swap16md(len))
;
651 err |= ibuf_add(buf, &ft, sizeof(ft));
652 err |= ibuf_add(buf, &map->type, sizeof(uint8_t));
653 err |= ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t));
654
655 switch (map->fec.twcard.type) {
656 case MAP_TYPE_PREFIX0x02:
657 twcard_len = sizeof(uint16_t);
658 err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
659
660 switch (map->fec.twcard.u.prefix_af) {
661 case AF_INET2:
662 family = htons(AF_IPV4)(__uint16_t)(__builtin_constant_p(0x1) ? (__uint16_t)(((__uint16_t
)(0x1) & 0xffU) << 8 | ((__uint16_t)(0x1) & 0xff00U
) >> 8) : __swap16md(0x1))
;
663 break;
664 case AF_INET624:
665 family = htons(AF_IPV6)(__uint16_t)(__builtin_constant_p(0x2) ? (__uint16_t)(((__uint16_t
)(0x2) & 0xffU) << 8 | ((__uint16_t)(0x2) & 0xff00U
) >> 8) : __swap16md(0x2))
;
666 break;
667 default:
668 fatalx("gen_fec_tlv: unknown af");
669 break;
670 }
671
672 err |= ibuf_add(buf, &family, sizeof(uint16_t));
673 break;
674 case MAP_TYPE_PWID0x80:
675 twcard_len = sizeof(uint16_t);
676 err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
677 pw_type = htons(map->fec.twcard.u.pw_type)(__uint16_t)(__builtin_constant_p(map->fec.twcard.u.pw_type
) ? (__uint16_t)(((__uint16_t)(map->fec.twcard.u.pw_type) &
0xffU) << 8 | ((__uint16_t)(map->fec.twcard.u.pw_type
) & 0xff00U) >> 8) : __swap16md(map->fec.twcard.
u.pw_type))
;
678 err |= ibuf_add(buf, &pw_type, sizeof(uint16_t));
679 break;
680 default:
681 fatalx("gen_fec_tlv: unexpected fec type");
682 }
683 break;
684 default:
685 break;
686 }
687
688 return (err);
689}
690
691int
692tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
693 uint16_t len, struct map *map)
694{
695 uint16_t off = 0;
696 uint8_t pw_len, twcard_len;
697
698 map->type = *buf;
699 off += sizeof(uint8_t);
700
701 switch (map->type) {
702 case MAP_TYPE_WILDCARD0x01:
703 if (len == FEC_ELM_WCARD_LEN1)
704 return (off);
705 else {
706 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg->id,
707 msg->type);
708 return (-1);
709 }
710 break;
711 case MAP_TYPE_PREFIX0x02:
712 if (len < FEC_ELM_PREFIX_MIN_LEN4) {
713 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
714 msg->type);
715 return (-1);
716 }
717
718 /* Address Family */
719 memcpy(&map->fec.prefix.af, buf + off,
720 sizeof(map->fec.prefix.af));
721 off += sizeof(map->fec.prefix.af);
722 map->fec.prefix.af = ntohs(map->fec.prefix.af)(__uint16_t)(__builtin_constant_p(map->fec.prefix.af) ? (__uint16_t
)(((__uint16_t)(map->fec.prefix.af) & 0xffU) << 8
| ((__uint16_t)(map->fec.prefix.af) & 0xff00U) >>
8) : __swap16md(map->fec.prefix.af))
;
723 switch (map->fec.prefix.af) {
724 case AF_IPV40x1:
725 map->fec.prefix.af = AF_INET2;
726 break;
727 case AF_IPV60x2:
728 map->fec.prefix.af = AF_INET624;
729 break;
730 default:
731 send_notification(nbr->tcp, S_UNSUP_ADDR0x00000017, msg->id,
732 msg->type);
733 return (-1);
734 }
735
736 /* Prefix Length */
737 map->fec.prefix.prefixlen = buf[off];
738 off += sizeof(uint8_t);
739 if (len < off + PREFIX_SIZE(map->fec.prefix.prefixlen)(((map->fec.prefix.prefixlen) + 7) / 8)) {
740 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
741 msg->type);
742 return (-1);
743 }
744
745 /* Prefix */
746 memset(&map->fec.prefix.prefix, 0,
747 sizeof(map->fec.prefix.prefix));
748 memcpy(&map->fec.prefix.prefix, buf + off,
749 PREFIX_SIZE(map->fec.prefix.prefixlen)(((map->fec.prefix.prefixlen) + 7) / 8));
750
751 /* Just in case... */
752 ldp_applymask(map->fec.prefix.af, &map->fec.prefix.prefix,
753 &map->fec.prefix.prefix, map->fec.prefix.prefixlen);
754
755 return (off + PREFIX_SIZE(map->fec.prefix.prefixlen)(((map->fec.prefix.prefixlen) + 7) / 8));
756 case MAP_TYPE_PWID0x80:
757 if (len < FEC_PWID_ELM_MIN_LEN8) {
758 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
759 msg->type);
760 return (-1);
761 }
762
763 /* PW type */
764 memcpy(&map->fec.pwid.type, buf + off, sizeof(uint16_t));
765 map->fec.pwid.type = ntohs(map->fec.pwid.type)(__uint16_t)(__builtin_constant_p(map->fec.pwid.type) ? (__uint16_t
)(((__uint16_t)(map->fec.pwid.type) & 0xffU) << 8
| ((__uint16_t)(map->fec.pwid.type) & 0xff00U) >>
8) : __swap16md(map->fec.pwid.type))
;
766 if (map->fec.pwid.type & CONTROL_WORD_FLAG0x8000) {
767 map->flags |= F_MAP_PW_CWORD0x04;
768 map->fec.pwid.type &= ~CONTROL_WORD_FLAG0x8000;
769 }
770 off += sizeof(uint16_t);
771
772 /* PW info Length */
773 pw_len = buf[off];
774 off += sizeof(uint8_t);
775
776 if (len != FEC_PWID_ELM_MIN_LEN8 + pw_len) {
777 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
778 msg->type);
779 return (-1);
780 }
781
782 /* Group ID */
783 memcpy(&map->fec.pwid.group_id, buf + off, sizeof(uint32_t));
784 map->fec.pwid.group_id = ntohl(map->fec.pwid.group_id)(__uint32_t)(__builtin_constant_p(map->fec.pwid.group_id) ?
(__uint32_t)(((__uint32_t)(map->fec.pwid.group_id) & 0xff
) << 24 | ((__uint32_t)(map->fec.pwid.group_id) &
0xff00) << 8 | ((__uint32_t)(map->fec.pwid.group_id
) & 0xff0000) >> 8 | ((__uint32_t)(map->fec.pwid
.group_id) & 0xff000000) >> 24) : __swap32md(map->
fec.pwid.group_id))
;
785 off += sizeof(uint32_t);
786
787 /* PW ID */
788 if (pw_len == 0)
789 return (off);
790
791 if (pw_len < sizeof(uint32_t)) {
792 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
793 msg->type);
794 return (-1);
795 }
796
797 memcpy(&map->fec.pwid.pwid, buf + off, sizeof(uint32_t));
798 map->fec.pwid.pwid = ntohl(map->fec.pwid.pwid)(__uint32_t)(__builtin_constant_p(map->fec.pwid.pwid) ? (__uint32_t
)(((__uint32_t)(map->fec.pwid.pwid) & 0xff) << 24
| ((__uint32_t)(map->fec.pwid.pwid) & 0xff00) <<
8 | ((__uint32_t)(map->fec.pwid.pwid) & 0xff0000) >>
8 | ((__uint32_t)(map->fec.pwid.pwid) & 0xff000000) >>
24) : __swap32md(map->fec.pwid.pwid))
;
799 map->flags |= F_MAP_PW_ID0x08;
800 off += sizeof(uint32_t);
801 pw_len -= sizeof(uint32_t);
802
803 /* Optional Interface Parameter Sub-TLVs */
804 while (pw_len > 0) {
805 struct subtlv stlv;
806
807 if (pw_len < sizeof(stlv)) {
808 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
809 msg->type);
810 return (-1);
811 }
812
813 memcpy(&stlv, buf + off, sizeof(stlv));
814 if (stlv.length > pw_len) {
815 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
816 msg->type);
817 return (-1);
818 }
819
820 switch (stlv.type) {
821 case SUBTLV_IFMTU0x01:
822 if (stlv.length != FEC_SUBTLV_IFMTU_SIZE4) {
823 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007,
824 msg->id, msg->type);
825 return (-1);
826 }
827 memcpy(&map->fec.pwid.ifmtu, buf + off +
828 SUBTLV_HDR_SIZE2, sizeof(uint16_t));
829 map->fec.pwid.ifmtu = ntohs(map->fec.pwid.ifmtu)(__uint16_t)(__builtin_constant_p(map->fec.pwid.ifmtu) ? (
__uint16_t)(((__uint16_t)(map->fec.pwid.ifmtu) & 0xffU
) << 8 | ((__uint16_t)(map->fec.pwid.ifmtu) & 0xff00U
) >> 8) : __swap16md(map->fec.pwid.ifmtu))
;
830 map->flags |= F_MAP_PW_IFMTU0x10;
831 break;
832 default:
833 /* ignore */
834 break;
835 }
836 off += stlv.length;
837 pw_len -= stlv.length;
838 }
839
840 return (off);
841 case MAP_TYPE_TYPED_WCARD0x05:
842 if (len < FEC_ELM_TWCARD_MIN_LEN3) {
843 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
844 msg->type);
845 return (-1);
846 }
847
848 memcpy(&map->fec.twcard.type, buf + off, sizeof(uint8_t));
849 off += sizeof(uint8_t);
850 memcpy(&twcard_len, buf + off, sizeof(uint8_t));
851 off += sizeof(uint8_t);
852 if (len != FEC_ELM_TWCARD_MIN_LEN3 + twcard_len) {
853 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
854 msg->type);
855 return (-1);
856 }
857
858 switch (map->fec.twcard.type) {
859 case MAP_TYPE_PREFIX0x02:
860 if (twcard_len != sizeof(uint16_t)) {
861 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
862 msg->type);
863 return (-1);
864 }
865
866 memcpy(&map->fec.twcard.u.prefix_af, buf + off,
867 sizeof(uint16_t));
868 map->fec.twcard.u.prefix_af =
869 ntohs(map->fec.twcard.u.prefix_af)(__uint16_t)(__builtin_constant_p(map->fec.twcard.u.prefix_af
) ? (__uint16_t)(((__uint16_t)(map->fec.twcard.u.prefix_af
) & 0xffU) << 8 | ((__uint16_t)(map->fec.twcard.
u.prefix_af) & 0xff00U) >> 8) : __swap16md(map->
fec.twcard.u.prefix_af))
;
870 off += sizeof(uint16_t);
871
872 switch (map->fec.twcard.u.prefix_af) {
873 case AF_IPV40x1:
874 map->fec.twcard.u.prefix_af = AF_INET2;
875 break;
876 case AF_IPV60x2:
877 map->fec.twcard.u.prefix_af = AF_INET624;
878 break;
879 default:
880 session_shutdown(nbr, S_BAD_TLV_VAL0x80000008, msg->id,
881 msg->type);
882 return (-1);
883 }
884 break;
885 case MAP_TYPE_PWID0x80:
886 if (twcard_len != sizeof(uint16_t)) {
887 session_shutdown(nbr, S_BAD_TLV_LEN0x80000007, msg->id,
888 msg->type);
889 return (-1);
890 }
891
892 memcpy(&map->fec.twcard.u.pw_type, buf + off,
893 sizeof(uint16_t));
894 map->fec.twcard.u.pw_type =
895 ntohs(map->fec.twcard.u.pw_type)(__uint16_t)(__builtin_constant_p(map->fec.twcard.u.pw_type
) ? (__uint16_t)(((__uint16_t)(map->fec.twcard.u.pw_type) &
0xffU) << 8 | ((__uint16_t)(map->fec.twcard.u.pw_type
) & 0xff00U) >> 8) : __swap16md(map->fec.twcard.
u.pw_type))
;
896 /* ignore the reserved bit as per RFC 6667 */
897 map->fec.twcard.u.pw_type &= ~PW_TWCARD_RESERVED_BIT0x8000;
898 off += sizeof(uint16_t);
899 break;
900 default:
901 send_notification(nbr->tcp, S_UNKNOWN_FEC0x0000000C, msg->id,
902 msg->type);
903 return (-1);
904 }
905
906 return (off);
907 default:
908 send_notification(nbr->tcp, S_UNKNOWN_FEC0x0000000C, msg->id, msg->type);
909 break;
910 }
911
912 return (-1);
913}
914
915static void
916log_msg_mapping(int out, uint16_t msg_type, struct nbr *nbr, struct map *map)
917{
918 log_debug("msg-%s: %s: lsr-id %s, fec %s, label %s",
919 (out) ? "out" : "in", msg_name(msg_type), inet_ntoa(nbr->id),
920 log_map(map), log_label(map->label));
921}