Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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