2 * EIGRP General Sending and Receiving of EIGRP Packets.
3 * Copyright (C) 2013-2014
11 * This file is part of GNU Zebra.
13 * GNU Zebra is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2, or (at your option) any
18 * GNU Zebra is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; see the file COPYING; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
38 #include "sockunion.h"
45 #include "lib_errors.h"
47 #include "eigrpd/eigrp_structs.h"
48 #include "eigrpd/eigrpd.h"
49 #include "eigrpd/eigrp_interface.h"
50 #include "eigrpd/eigrp_neighbor.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_dump.h"
55 #include "eigrpd/eigrp_macros.h"
56 #include "eigrpd/eigrp_network.h"
57 #include "eigrpd/eigrp_topology.h"
58 #include "eigrpd/eigrp_fsm.h"
59 #include "eigrpd/eigrp_memory.h"
60 #include "eigrpd/eigrp_errors.h"
62 /* Packet Type String. */
63 const struct message eigrp_packet_type_str
[] = {
64 {EIGRP_OPC_UPDATE
, "Update"},
65 {EIGRP_OPC_REQUEST
, "Request"},
66 {EIGRP_OPC_QUERY
, "Query"},
67 {EIGRP_OPC_REPLY
, "Reply"},
68 {EIGRP_OPC_HELLO
, "Hello"},
69 {EIGRP_OPC_IPXSAP
, "IPX-SAP"},
70 {EIGRP_OPC_PROBE
, "Probe"},
71 {EIGRP_OPC_ACK
, "Ack"},
72 {EIGRP_OPC_SIAQUERY
, "SIAQuery"},
73 {EIGRP_OPC_SIAREPLY
, "SIAReply"},
77 static unsigned char zeropad
[16] = {0};
79 /* Forward function reference*/
80 static struct stream
*eigrp_recv_packet(int, struct interface
**,
82 static int eigrp_verify_header(struct stream
*, struct eigrp_interface
*,
83 struct ip
*, struct eigrp_header
*);
84 static int eigrp_check_network_mask(struct eigrp_interface
*, struct in_addr
);
86 static int eigrp_retrans_count_exceeded(struct eigrp_packet
*ep
,
87 struct eigrp_neighbor
*nbr
)
92 int eigrp_make_md5_digest(struct eigrp_interface
*ei
, struct stream
*s
,
95 struct key
*key
= NULL
;
96 struct keychain
*keychain
;
98 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
101 size_t backup_get
, backup_end
;
102 struct TLV_MD5_Authentication_Type
*auth_TLV
;
105 backup_end
= s
->endp
;
106 backup_get
= s
->getp
;
108 auth_TLV
= eigrp_authTLV_MD5_new();
110 stream_set_getp(s
, EIGRP_HEADER_LEN
);
111 stream_get(auth_TLV
, s
, EIGRP_AUTH_MD5_TLV_SIZE
);
112 stream_set_getp(s
, backup_get
);
114 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
116 key
= key_lookup_for_send(keychain
);
118 eigrp_authTLV_MD5_free(auth_TLV
);
119 return EIGRP_AUTH_TYPE_NONE
;
122 memset(&ctx
, 0, sizeof(ctx
));
125 /* Generate a digest. Each situation needs different handling */
126 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
127 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
128 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
129 if (strlen(key
->string
) < 16)
130 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
131 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
132 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
133 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
134 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
135 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
136 if (strlen(key
->string
) < 16)
137 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
138 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
140 ibuf
+ (EIGRP_HEADER_LEN
141 + EIGRP_AUTH_MD5_TLV_SIZE
),
144 + EIGRP_AUTH_MD5_TLV_SIZE
));
148 MD5Final(digest
, &ctx
);
150 /* Append md5 digest to the end of the stream. */
151 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
153 stream_set_endp(s
, EIGRP_HEADER_LEN
);
154 stream_put(s
, auth_TLV
, EIGRP_AUTH_MD5_TLV_SIZE
);
155 stream_set_endp(s
, backup_end
);
157 eigrp_authTLV_MD5_free(auth_TLV
);
158 return EIGRP_AUTH_TYPE_MD5_LEN
;
161 int eigrp_check_md5_digest(struct stream
*s
,
162 struct TLV_MD5_Authentication_Type
*authTLV
,
163 struct eigrp_neighbor
*nbr
, uint8_t flags
)
166 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
167 unsigned char orig
[EIGRP_AUTH_TYPE_MD5_LEN
];
168 struct key
*key
= NULL
;
169 struct keychain
*keychain
;
172 struct TLV_MD5_Authentication_Type
*auth_TLV
;
173 struct eigrp_header
*eigrph
;
175 if (ntohl(nbr
->crypt_seqnum
) > ntohl(authTLV
->key_sequence
)) {
177 "interface %s: eigrp_check_md5 bad sequence %d (expect %d)",
178 IF_NAME(nbr
->ei
), ntohl(authTLV
->key_sequence
),
179 ntohl(nbr
->crypt_seqnum
));
183 eigrph
= (struct eigrp_header
*)s
->data
;
184 eigrph
->checksum
= 0;
186 auth_TLV
= (struct TLV_MD5_Authentication_Type
*)(s
->data
188 memcpy(orig
, auth_TLV
->digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
189 memset(digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
190 memset(auth_TLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
193 backup_end
= s
->endp
;
195 keychain
= keychain_lookup(nbr
->ei
->params
.auth_keychain
);
197 key
= key_lookup_for_send(keychain
);
201 "Interface %s: Expected key value not found in config",
206 memset(&ctx
, 0, sizeof(ctx
));
209 /* Generate a digest. Each situation needs different handling */
210 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
211 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
212 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
213 if (strlen(key
->string
) < 16)
214 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
215 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
216 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
217 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
218 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
219 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
220 if (strlen(key
->string
) < 16)
221 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
222 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
224 ibuf
+ (EIGRP_HEADER_LEN
225 + EIGRP_AUTH_MD5_TLV_SIZE
),
228 + EIGRP_AUTH_MD5_TLV_SIZE
));
232 MD5Final(digest
, &ctx
);
234 /* compare the two */
235 if (memcmp(orig
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
) != 0) {
236 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
241 /* save neighbor's crypt_seqnum */
242 nbr
->crypt_seqnum
= authTLV
->key_sequence
;
247 int eigrp_make_sha256_digest(struct eigrp_interface
*ei
, struct stream
*s
,
250 struct key
*key
= NULL
;
251 struct keychain
*keychain
;
252 char source_ip
[PREFIX_STRLEN
];
254 unsigned char digest
[EIGRP_AUTH_TYPE_SHA256_LEN
];
255 unsigned char buffer
[1 + PLAINTEXT_LENGTH
+ 45 + 1] = {0};
259 size_t backup_get
, backup_end
;
260 struct TLV_SHA256_Authentication_Type
*auth_TLV
;
263 backup_end
= s
->endp
;
264 backup_get
= s
->getp
;
266 auth_TLV
= eigrp_authTLV_SHA256_new();
268 stream_set_getp(s
, EIGRP_HEADER_LEN
);
269 stream_get(auth_TLV
, s
, EIGRP_AUTH_SHA256_TLV_SIZE
);
270 stream_set_getp(s
, backup_get
);
272 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
274 key
= key_lookup_for_send(keychain
);
278 "Interface %s: Expected key value not found in config",
280 eigrp_authTLV_SHA256_free(auth_TLV
);
284 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
, source_ip
, PREFIX_STRLEN
);
286 memset(&ctx
, 0, sizeof(ctx
));
288 memcpy(buffer
+ 1, key
, strlen(key
->string
));
289 memcpy(buffer
+ 1 + strlen(key
->string
), source_ip
, strlen(source_ip
));
290 HMAC__SHA256_Init(&ctx
, buffer
,
291 1 + strlen(key
->string
) + strlen(source_ip
));
292 HMAC__SHA256_Update(&ctx
, ibuf
, strlen(ibuf
));
293 HMAC__SHA256_Final(digest
, &ctx
);
296 /* Put hmac-sha256 digest to it's place */
297 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_SHA256_LEN
);
299 stream_set_endp(s
, EIGRP_HEADER_LEN
);
300 stream_put(s
, auth_TLV
, EIGRP_AUTH_SHA256_TLV_SIZE
);
301 stream_set_endp(s
, backup_end
);
303 eigrp_authTLV_SHA256_free(auth_TLV
);
305 return EIGRP_AUTH_TYPE_SHA256_LEN
;
308 int eigrp_check_sha256_digest(struct stream
*s
,
309 struct TLV_SHA256_Authentication_Type
*authTLV
,
310 struct eigrp_neighbor
*nbr
, uint8_t flags
)
315 int eigrp_write(struct thread
*thread
)
317 struct eigrp
*eigrp
= THREAD_ARG(thread
);
318 struct eigrp_header
*eigrph
;
319 struct eigrp_interface
*ei
;
320 struct eigrp_packet
*ep
;
321 struct sockaddr_in sa_dst
;
329 struct listnode
*node
;
330 #ifdef WANT_EIGRP_WRITE_FRAGMENT
331 static uint16_t ipid
= 0;
332 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
333 #define EIGRP_WRITE_IPHL_SHIFT 2
335 eigrp
->t_write
= NULL
;
337 node
= listhead(eigrp
->oi_write_q
);
339 ei
= listgetdata(node
);
342 #ifdef WANT_EIGRP_WRITE_FRAGMENT
343 /* seed ipid static with low order bits of time */
345 ipid
= (time(NULL
) & 0xffff);
346 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
348 /* Get one packet from queue. */
349 ep
= eigrp_fifo_next(ei
->obuf
);
351 flog_err(EC_LIB_DEVELOPMENT
,
352 "%s: Interface %s no packet on queue?",
353 __PRETTY_FUNCTION__
, ei
->ifp
->name
);
356 if (ep
->length
< EIGRP_HEADER_LEN
) {
357 flog_err(EC_EIGRP_PACKET
, "%s: Packet just has a header?",
358 __PRETTY_FUNCTION__
);
359 eigrp_header_dump((struct eigrp_header
*)ep
->s
->data
);
360 eigrp_packet_delete(ei
);
364 if (ep
->dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
))
365 eigrp_if_ipmulticast(eigrp
, ei
->address
, ei
->ifp
->ifindex
);
367 memset(&iph
, 0, sizeof(struct ip
));
368 memset(&sa_dst
, 0, sizeof(sa_dst
));
371 * We build and schedule packets to go out
372 * in the future. In the mean time we may
373 * process some update packets from the
374 * neighbor, thus making it necessary
375 * to update the ack we are using for
376 * this outgoing packet.
378 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
379 seqno
= ntohl(eigrph
->sequence
);
380 ack
= ntohl(eigrph
->ack
);
381 if (ep
->nbr
&& (ack
!= ep
->nbr
->recv_sequence_number
)) {
382 eigrph
->ack
= htonl(ep
->nbr
->recv_sequence_number
);
383 ack
= ep
->nbr
->recv_sequence_number
;
384 eigrph
->checksum
= 0;
385 eigrp_packet_checksum(ei
, ep
->s
, ep
->length
);
388 sa_dst
.sin_family
= AF_INET
;
389 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
390 sa_dst
.sin_len
= sizeof(sa_dst
);
391 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
392 sa_dst
.sin_addr
= ep
->dst
;
393 sa_dst
.sin_port
= htons(0);
395 /* Set DONTROUTE flag if dst is unicast. */
396 if (!IN_MULTICAST(htonl(ep
->dst
.s_addr
)))
397 flags
= MSG_DONTROUTE
;
399 iph
.ip_hl
= sizeof(struct ip
) >> EIGRP_WRITE_IPHL_SHIFT
;
400 /* it'd be very strange for header to not be 4byte-word aligned but.. */
401 if (sizeof(struct ip
)
402 > (unsigned int)(iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
))
403 iph
.ip_hl
++; /* we presume sizeof struct ip cant overflow
406 iph
.ip_v
= IPVERSION
;
407 iph
.ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
408 iph
.ip_len
= (iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
) + ep
->length
;
410 #if defined(__DragonFly__)
412 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
414 iph
.ip_len
= htons(iph
.ip_len
);
418 iph
.ip_ttl
= EIGRP_IP_TTL
;
419 iph
.ip_p
= IPPROTO_EIGRPIGP
;
421 iph
.ip_src
.s_addr
= ei
->address
->u
.prefix4
.s_addr
;
422 iph
.ip_dst
.s_addr
= ep
->dst
.s_addr
;
424 memset(&msg
, 0, sizeof(msg
));
425 msg
.msg_name
= (caddr_t
)&sa_dst
;
426 msg
.msg_namelen
= sizeof(sa_dst
);
430 iov
[0].iov_base
= (char *)&iph
;
431 iov
[0].iov_len
= iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
;
432 iov
[1].iov_base
= stream_pnt(ep
->s
);
433 iov
[1].iov_len
= ep
->length
;
435 /* send final fragment (could be first) */
436 sockopt_iphdrincl_swab_htosys(&iph
);
437 ret
= sendmsg(eigrp
->fd
, &msg
, flags
);
438 sockopt_iphdrincl_swab_systoh(&iph
);
440 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)) {
441 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
443 "Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
444 lookup_msg(eigrp_packet_type_str
, eigrph
->opcode
, NULL
),
445 seqno
, ack
, inet_ntoa(ep
->dst
), IF_NAME(ei
), ret
);
450 "*** sendmsg in eigrp_write failed to %s, "
451 "id %d, off %d, len %d, interface %s, mtu %u: %s",
452 inet_ntoa(iph
.ip_dst
), iph
.ip_id
, iph
.ip_off
,
453 iph
.ip_len
, ei
->ifp
->name
, ei
->ifp
->mtu
,
454 safe_strerror(errno
));
456 /* Now delete packet from queue. */
457 eigrp_packet_delete(ei
);
460 if (eigrp_fifo_next(ei
->obuf
) == NULL
) {
462 list_delete_node(eigrp
->oi_write_q
, node
);
465 /* If packets still remain in queue, call write thread. */
466 if (!list_isempty(eigrp
->oi_write_q
)) {
467 eigrp
->t_write
= NULL
;
468 thread_add_write(master
, eigrp_write
, eigrp
, eigrp
->fd
,
475 /* Starting point of packet process function. */
476 int eigrp_read(struct thread
*thread
)
481 struct eigrp_interface
*ei
;
483 struct eigrp_header
*eigrph
;
484 struct interface
*ifp
;
485 struct eigrp_neighbor
*nbr
;
490 /* first of all get interface pointer. */
491 eigrp
= THREAD_ARG(thread
);
493 /* prepare for next packet. */
494 eigrp
->t_read
= NULL
;
495 thread_add_read(master
, eigrp_read
, eigrp
, eigrp
->fd
, &eigrp
->t_read
);
497 stream_reset(eigrp
->ibuf
);
498 if (!(ibuf
= eigrp_recv_packet(eigrp
->fd
, &ifp
, eigrp
->ibuf
))) {
499 /* This raw packet is known to be at least as big as its IP
504 /* Note that there should not be alignment problems with this assignment
505 because this is at the beginning of the stream data buffer. */
506 iph
= (struct ip
*)STREAM_DATA(ibuf
);
508 // Substract IPv4 header size from EIGRP Packet itself
510 length
= (iph
->ip_len
) - 20U;
513 /* IP Header dump. */
514 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
515 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
516 eigrp_ip_header_dump(iph
);
518 /* Note that sockopt_iphdrincl_swab_systoh was called in
519 * eigrp_recv_packet. */
522 /* Handle cases where the platform does not support retrieving
524 and also platforms (such as Solaris 8) that claim to support
526 retrieval but do not. */
527 c
= if_lookup_address((void *)&iph
->ip_src
, AF_INET
,
536 /* associate packet with eigrp interface */
539 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
541 after the checks below are passed. These checks in turn access the
542 fields of unverified "eigrph" structure for their own purposes and
543 must remain very accurate in doing this.
548 /* Self-originated packet should be discarded silently. */
549 if (eigrp_if_lookup_by_local_addr(eigrp
, NULL
, iph
->ip_src
)
550 || (IPV4_ADDR_SAME(&iph
->ip_src
, &ei
->address
->u
.prefix4
))) {
551 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
553 "eigrp_read[%s]: Dropping self-originated packet",
554 inet_ntoa(iph
->ip_src
));
558 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
559 by eigrp_recv_packet() to be correct). */
561 stream_forward_getp(ibuf
, (iph
->ip_hl
* 4));
562 eigrph
= (struct eigrp_header
*)stream_pnt(ibuf
);
564 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
565 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
566 eigrp_header_dump(eigrph
);
568 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
569 // stream_get_getp(ibuf)))
572 /* If incoming interface is passive one, ignore it. */
573 if (eigrp_if_is_passive(ei
)) {
574 char buf
[3][INET_ADDRSTRLEN
];
576 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
578 "ignoring packet from router %s sent to %s, "
579 "received on a passive interface, %s",
580 inet_ntop(AF_INET
, &eigrph
->vrid
, buf
[0],
582 inet_ntop(AF_INET
, &iph
->ip_dst
, buf
[1],
584 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
,
585 buf
[2], sizeof(buf
[2])));
587 if (iph
->ip_dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
)) {
588 eigrp_if_set_multicast(ei
);
593 /* else it must be a local eigrp interface, check it was received on
596 else if (ei
->ifp
!= ifp
) {
597 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
598 zlog_warn("Packet from [%s] received on wrong link %s",
599 inet_ntoa(iph
->ip_src
), ifp
->name
);
603 /* Verify more EIGRP header fields. */
604 ret
= eigrp_verify_header(ibuf
, ei
, iph
, eigrph
);
606 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
608 "eigrp_read[%s]: Header check failed, dropping.",
609 inet_ntoa(iph
->ip_src
));
613 /* calcualte the eigrp packet length, and move the pounter to the
614 start of the eigrp TLVs */
615 opcode
= eigrph
->opcode
;
617 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)) {
618 char src
[PREFIX_STRLEN
], dst
[PREFIX_STRLEN
];
620 strlcpy(src
, inet_ntoa(iph
->ip_src
), sizeof(src
));
621 strlcpy(dst
, inet_ntoa(iph
->ip_dst
), sizeof(dst
));
623 "Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
624 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
625 ntohl(eigrph
->sequence
), ntohl(eigrph
->ack
), length
,
626 IF_NAME(ei
), src
, dst
);
629 /* Read rest of the packet and call each sort of packet routine. */
630 stream_forward_getp(ibuf
, EIGRP_HEADER_LEN
);
632 /* New testing block of code for handling Acks */
633 if (ntohl(eigrph
->ack
) != 0) {
634 struct eigrp_packet
*ep
= NULL
;
636 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
638 // neighbor must be valid, eigrp_nbr_get creates if none existed
641 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
642 if ((ep
) && (ntohl(eigrph
->ack
) == ep
->sequence_number
)) {
643 ep
= eigrp_fifo_pop(nbr
->retrans_queue
);
644 eigrp_packet_free(ep
);
646 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
647 && (ntohl(eigrph
->ack
)
648 == nbr
->init_sequence_number
)) {
649 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_UP
);
650 zlog_info("Neighbor(%s) adjacency became full",
651 inet_ntoa(nbr
->src
));
652 nbr
->init_sequence_number
= 0;
653 nbr
->recv_sequence_number
=
654 ntohl(eigrph
->sequence
);
655 eigrp_update_send_EOT(nbr
);
657 eigrp_send_packet_reliably(nbr
);
659 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
661 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
662 ep
= eigrp_fifo_pop(nbr
->multicast_queue
);
663 eigrp_packet_free(ep
);
664 if (nbr
->multicast_queue
->count
> 0) {
665 eigrp_send_packet_reliably(nbr
);
673 case EIGRP_OPC_HELLO
:
674 eigrp_hello_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
676 case EIGRP_OPC_PROBE
:
677 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
680 case EIGRP_OPC_QUERY
:
681 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
683 case EIGRP_OPC_REPLY
:
684 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
686 case EIGRP_OPC_REQUEST
:
687 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
690 case EIGRP_OPC_SIAQUERY
:
691 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
693 case EIGRP_OPC_SIAREPLY
:
694 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
696 case EIGRP_OPC_UPDATE
:
697 eigrp_update_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
701 "interface %s: EIGRP packet header type %d unsupported",
702 IF_NAME(ei
), opcode
);
709 static struct stream
*eigrp_recv_packet(int fd
, struct interface
**ifp
,
715 unsigned int ifindex
= 0;
717 /* Header and data both require alignment. */
718 char buff
[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
721 memset(&msgh
, 0, sizeof(struct msghdr
));
724 msgh
.msg_control
= (caddr_t
)buff
;
725 msgh
.msg_controllen
= sizeof(buff
);
727 ret
= stream_recvmsg(ibuf
, fd
, &msgh
, 0, (EIGRP_PACKET_MAX_LEN
+ 1));
729 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno
));
732 if ((unsigned int)ret
< sizeof(*iph
)) /* ret must be > 0 now */
735 "eigrp_recv_packet: discarding runt packet of length %d "
736 "(ip header size is %u)",
737 ret
, (unsigned int)sizeof(*iph
));
741 /* Note that there should not be alignment problems with this assignment
742 because this is at the beginning of the stream data buffer. */
743 iph
= (struct ip
*)STREAM_DATA(ibuf
);
744 sockopt_iphdrincl_swab_systoh(iph
);
746 ip_len
= iph
->ip_len
;
748 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
750 * Kernel network code touches incoming IP header parameters,
751 * before protocol specific processing.
753 * 1) Convert byteorder to host representation.
754 * --> ip_len, ip_id, ip_off
756 * 2) Adjust ip_len to strip IP header size!
757 * --> If user process receives entire IP packet via RAW
758 * socket, it must consider adding IP header size to
759 * the "ip_len" field of "ip" structure.
761 * For more details, see <netinet/ip_input.c>.
763 ip_len
= ip_len
+ (iph
->ip_hl
<< 2);
766 #if defined(__DragonFly__)
768 * in DragonFly's raw socket, ip_len/ip_off are read
769 * in network byte order.
770 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
772 ip_len
= ntohs(iph
->ip_len
) + (iph
->ip_hl
<< 2);
775 ifindex
= getsockopt_ifindex(AF_INET
, &msgh
);
777 *ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
781 "eigrp_recv_packet read length mismatch: ip_len is %d, "
782 "but recvmsg returned %d",
790 struct eigrp_fifo
*eigrp_fifo_new(void)
792 struct eigrp_fifo
*new;
794 new = XCALLOC(MTYPE_EIGRP_FIFO
, sizeof(struct eigrp_fifo
));
798 /* Free eigrp packet fifo. */
799 void eigrp_fifo_free(struct eigrp_fifo
*fifo
)
801 struct eigrp_packet
*ep
;
802 struct eigrp_packet
*next
;
804 for (ep
= fifo
->head
; ep
; ep
= next
) {
806 eigrp_packet_free(ep
);
808 fifo
->head
= fifo
->tail
= NULL
;
811 XFREE(MTYPE_EIGRP_FIFO
, fifo
);
814 /* Free eigrp fifo entries without destroying fifo itself*/
815 void eigrp_fifo_reset(struct eigrp_fifo
*fifo
)
817 struct eigrp_packet
*ep
;
818 struct eigrp_packet
*next
;
820 for (ep
= fifo
->head
; ep
; ep
= next
) {
822 eigrp_packet_free(ep
);
824 fifo
->head
= fifo
->tail
= NULL
;
828 struct eigrp_packet
*eigrp_packet_new(size_t size
, struct eigrp_neighbor
*nbr
)
830 struct eigrp_packet
*new;
832 new = XCALLOC(MTYPE_EIGRP_PACKET
, sizeof(struct eigrp_packet
));
833 new->s
= stream_new(size
);
834 new->retrans_counter
= 0;
840 void eigrp_send_packet_reliably(struct eigrp_neighbor
*nbr
)
842 struct eigrp_packet
*ep
;
844 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
847 struct eigrp_packet
*duplicate
;
848 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
849 /* Add packet to the top of the interface output queue*/
850 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
852 /*Start retransmission timer*/
853 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
854 EIGRP_PACKET_RETRANS_TIME
,
855 &ep
->t_retrans_timer
);
857 /*Increment sequence number counter*/
858 nbr
->ei
->eigrp
->sequence_number
++;
860 /* Hook thread to write packet. */
861 if (nbr
->ei
->on_write_q
== 0) {
862 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
863 nbr
->ei
->on_write_q
= 1;
865 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
866 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
870 /* Calculate EIGRP checksum */
871 void eigrp_packet_checksum(struct eigrp_interface
*ei
, struct stream
*s
,
874 struct eigrp_header
*eigrph
;
876 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
878 /* Calculate checksum. */
879 eigrph
->checksum
= in_cksum(eigrph
, length
);
882 /* Make EIGRP header. */
883 void eigrp_packet_header_init(int type
, struct eigrp
*eigrp
, struct stream
*s
,
884 uint32_t flags
, uint32_t sequence
, uint32_t ack
)
886 struct eigrp_header
*eigrph
;
889 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
891 eigrph
->version
= (uint8_t)EIGRP_HEADER_VERSION
;
892 eigrph
->opcode
= (uint8_t)type
;
893 eigrph
->checksum
= 0;
895 eigrph
->vrid
= htons(eigrp
->vrid
);
896 eigrph
->ASNumber
= htons(eigrp
->AS
);
897 eigrph
->ack
= htonl(ack
);
898 eigrph
->sequence
= htonl(sequence
);
899 // if(flags == EIGRP_INIT_FLAG)
900 // eigrph->sequence = htonl(3);
901 eigrph
->flags
= htonl(flags
);
903 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
904 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
905 htonl(eigrph
->sequence
), htonl(eigrph
->ack
));
907 stream_forward_endp(s
, EIGRP_HEADER_LEN
);
910 /* Add new packet to head of fifo. */
911 void eigrp_fifo_push(struct eigrp_fifo
*fifo
, struct eigrp_packet
*ep
)
913 ep
->next
= fifo
->head
;
916 if (fifo
->tail
== NULL
)
919 if (fifo
->count
!= 0)
920 fifo
->head
->previous
= ep
;
927 /* Return last fifo entry. */
928 struct eigrp_packet
*eigrp_fifo_next(struct eigrp_fifo
*fifo
)
933 void eigrp_packet_delete(struct eigrp_interface
*ei
)
935 struct eigrp_packet
*ep
;
937 ep
= eigrp_fifo_pop(ei
->obuf
);
940 eigrp_packet_free(ep
);
943 void eigrp_packet_free(struct eigrp_packet
*ep
)
948 THREAD_OFF(ep
->t_retrans_timer
);
950 XFREE(MTYPE_EIGRP_PACKET
, ep
);
953 /* EIGRP Header verification. */
954 static int eigrp_verify_header(struct stream
*ibuf
, struct eigrp_interface
*ei
,
955 struct ip
*iph
, struct eigrp_header
*eigrph
)
957 /* Check network mask, Silently discarded. */
958 if (!eigrp_check_network_mask(ei
, iph
->ip_src
)) {
960 "interface %s: eigrp_read network address is not same [%s]",
961 IF_NAME(ei
), inet_ntoa(iph
->ip_src
));
965 // /* Check authentication. The function handles logging actions, where
967 // if (! eigrp_check_auth(ei, eigrph))
973 /* Unbound socket will accept any Raw IP packets if proto is matched.
974 To prevent it, compare src IP address and i/f address with masking
976 static int eigrp_check_network_mask(struct eigrp_interface
*ei
,
977 struct in_addr ip_src
)
979 struct in_addr mask
, me
, him
;
981 if (ei
->type
== EIGRP_IFTYPE_POINTOPOINT
)
984 masklen2ip(ei
->address
->prefixlen
, &mask
);
986 me
.s_addr
= ei
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
987 him
.s_addr
= ip_src
.s_addr
& mask
.s_addr
;
989 if (IPV4_ADDR_SAME(&me
, &him
))
995 int eigrp_unack_packet_retrans(struct thread
*thread
)
997 struct eigrp_neighbor
*nbr
;
998 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1000 struct eigrp_packet
*ep
;
1001 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
1004 struct eigrp_packet
*duplicate
;
1005 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1007 /* Add packet to the top of the interface output queue*/
1008 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1010 ep
->retrans_counter
++;
1011 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1012 return eigrp_retrans_count_exceeded(ep
, nbr
);
1014 /*Start retransmission timer*/
1015 ep
->t_retrans_timer
= NULL
;
1016 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
1017 EIGRP_PACKET_RETRANS_TIME
,
1018 &ep
->t_retrans_timer
);
1020 /* Hook thread to write packet. */
1021 if (nbr
->ei
->on_write_q
== 0) {
1022 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1023 nbr
->ei
->on_write_q
= 1;
1025 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1026 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1032 int eigrp_unack_multicast_packet_retrans(struct thread
*thread
)
1034 struct eigrp_neighbor
*nbr
;
1035 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1037 struct eigrp_packet
*ep
;
1038 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
1041 struct eigrp_packet
*duplicate
;
1042 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1043 /* Add packet to the top of the interface output queue*/
1044 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1046 ep
->retrans_counter
++;
1047 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1048 return eigrp_retrans_count_exceeded(ep
, nbr
);
1050 /*Start retransmission timer*/
1051 ep
->t_retrans_timer
= NULL
;
1052 thread_add_timer(master
, eigrp_unack_multicast_packet_retrans
,
1053 nbr
, EIGRP_PACKET_RETRANS_TIME
,
1054 &ep
->t_retrans_timer
);
1056 /* Hook thread to write packet. */
1057 if (nbr
->ei
->on_write_q
== 0) {
1058 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1059 nbr
->ei
->on_write_q
= 1;
1061 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1062 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1068 /* Get packet from tail of fifo. */
1069 struct eigrp_packet
*eigrp_fifo_pop(struct eigrp_fifo
*fifo
)
1071 struct eigrp_packet
*ep
= NULL
;
1076 fifo
->tail
= ep
->previous
;
1078 if (fifo
->tail
== NULL
)
1081 fifo
->tail
->next
= NULL
;
1089 struct eigrp_packet
*eigrp_packet_duplicate(struct eigrp_packet
*old
,
1090 struct eigrp_neighbor
*nbr
)
1092 struct eigrp_packet
*new;
1094 new = eigrp_packet_new(EIGRP_PACKET_MTU(nbr
->ei
->ifp
->mtu
), nbr
);
1095 new->length
= old
->length
;
1096 new->retrans_counter
= old
->retrans_counter
;
1097 new->dst
= old
->dst
;
1098 new->sequence_number
= old
->sequence_number
;
1099 stream_copy(new->s
, old
->s
);
1104 static struct TLV_IPv4_Internal_type
*eigrp_IPv4_InternalTLV_new()
1106 struct TLV_IPv4_Internal_type
*new;
1108 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV
,
1109 sizeof(struct TLV_IPv4_Internal_type
));
1114 struct TLV_IPv4_Internal_type
*eigrp_read_ipv4_tlv(struct stream
*s
)
1116 struct TLV_IPv4_Internal_type
*tlv
;
1118 tlv
= eigrp_IPv4_InternalTLV_new();
1120 tlv
->type
= stream_getw(s
);
1121 tlv
->length
= stream_getw(s
);
1122 tlv
->forward
.s_addr
= stream_getl(s
);
1123 tlv
->metric
.delay
= stream_getl(s
);
1124 tlv
->metric
.bandwidth
= stream_getl(s
);
1125 tlv
->metric
.mtu
[0] = stream_getc(s
);
1126 tlv
->metric
.mtu
[1] = stream_getc(s
);
1127 tlv
->metric
.mtu
[2] = stream_getc(s
);
1128 tlv
->metric
.hop_count
= stream_getc(s
);
1129 tlv
->metric
.reliability
= stream_getc(s
);
1130 tlv
->metric
.load
= stream_getc(s
);
1131 tlv
->metric
.tag
= stream_getc(s
);
1132 tlv
->metric
.flags
= stream_getc(s
);
1134 tlv
->prefix_length
= stream_getc(s
);
1136 if (tlv
->prefix_length
<= 8) {
1137 tlv
->destination_part
[0] = stream_getc(s
);
1138 tlv
->destination
.s_addr
= (tlv
->destination_part
[0]);
1139 } else if (tlv
->prefix_length
> 8 && tlv
->prefix_length
<= 16) {
1140 tlv
->destination_part
[0] = stream_getc(s
);
1141 tlv
->destination_part
[1] = stream_getc(s
);
1142 tlv
->destination
.s_addr
= ((tlv
->destination_part
[1] << 8)
1143 + tlv
->destination_part
[0]);
1144 } else if (tlv
->prefix_length
> 16 && tlv
->prefix_length
<= 24) {
1145 tlv
->destination_part
[0] = stream_getc(s
);
1146 tlv
->destination_part
[1] = stream_getc(s
);
1147 tlv
->destination_part
[2] = stream_getc(s
);
1148 tlv
->destination
.s_addr
= ((tlv
->destination_part
[2] << 16)
1149 + (tlv
->destination_part
[1] << 8)
1150 + tlv
->destination_part
[0]);
1151 } else if (tlv
->prefix_length
> 24 && tlv
->prefix_length
<= 32) {
1152 tlv
->destination_part
[0] = stream_getc(s
);
1153 tlv
->destination_part
[1] = stream_getc(s
);
1154 tlv
->destination_part
[2] = stream_getc(s
);
1155 tlv
->destination_part
[3] = stream_getc(s
);
1156 tlv
->destination
.s_addr
= ((tlv
->destination_part
[3] << 24)
1157 + (tlv
->destination_part
[2] << 16)
1158 + (tlv
->destination_part
[1] << 8)
1159 + tlv
->destination_part
[0]);
1164 uint16_t eigrp_add_internalTLV_to_stream(struct stream
*s
,
1165 struct eigrp_prefix_entry
*pe
)
1169 stream_putw(s
, EIGRP_TLV_IPv4_INT
);
1170 switch (pe
->destination
->prefixlen
) {
1180 length
= EIGRP_TLV_IPV4_SIZE_GRT_0_BIT
;
1181 stream_putw(s
, length
);
1191 length
= EIGRP_TLV_IPV4_SIZE_GRT_8_BIT
;
1192 stream_putw(s
, length
);
1202 length
= EIGRP_TLV_IPV4_SIZE_GRT_16_BIT
;
1203 stream_putw(s
, length
);
1213 length
= EIGRP_TLV_IPV4_SIZE_GRT_24_BIT
;
1214 stream_putw(s
, length
);
1217 flog_err(EC_LIB_DEVELOPMENT
, "%s: Unexpected prefix length: %d",
1218 __PRETTY_FUNCTION__
, pe
->destination
->prefixlen
);
1221 stream_putl(s
, 0x00000000);
1224 stream_putl(s
, pe
->reported_metric
.delay
);
1225 stream_putl(s
, pe
->reported_metric
.bandwidth
);
1226 stream_putc(s
, pe
->reported_metric
.mtu
[2]);
1227 stream_putc(s
, pe
->reported_metric
.mtu
[1]);
1228 stream_putc(s
, pe
->reported_metric
.mtu
[0]);
1229 stream_putc(s
, pe
->reported_metric
.hop_count
);
1230 stream_putc(s
, pe
->reported_metric
.reliability
);
1231 stream_putc(s
, pe
->reported_metric
.load
);
1232 stream_putc(s
, pe
->reported_metric
.tag
);
1233 stream_putc(s
, pe
->reported_metric
.flags
);
1235 stream_putc(s
, pe
->destination
->prefixlen
);
1237 stream_putc(s
, pe
->destination
->u
.prefix4
.s_addr
& 0xFF);
1238 if (pe
->destination
->prefixlen
> 8)
1239 stream_putc(s
, (pe
->destination
->u
.prefix4
.s_addr
>> 8) & 0xFF);
1240 if (pe
->destination
->prefixlen
> 16)
1242 (pe
->destination
->u
.prefix4
.s_addr
>> 16) & 0xFF);
1243 if (pe
->destination
->prefixlen
> 24)
1245 (pe
->destination
->u
.prefix4
.s_addr
>> 24) & 0xFF);
1250 uint16_t eigrp_add_authTLV_MD5_to_stream(struct stream
*s
,
1251 struct eigrp_interface
*ei
)
1254 struct keychain
*keychain
;
1255 struct TLV_MD5_Authentication_Type
*authTLV
;
1257 authTLV
= eigrp_authTLV_MD5_new();
1259 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1260 authTLV
->length
= htons(EIGRP_AUTH_MD5_TLV_SIZE
);
1261 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_MD5
);
1262 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_MD5_LEN
);
1263 authTLV
->key_sequence
= 0;
1264 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1266 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1268 key
= key_lookup_for_send(keychain
);
1270 free(ei
->params
.auth_keychain
);
1271 ei
->params
.auth_keychain
= NULL
;
1272 eigrp_authTLV_MD5_free(authTLV
);
1277 authTLV
->key_id
= htonl(key
->index
);
1278 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
1279 stream_put(s
, authTLV
,
1280 sizeof(struct TLV_MD5_Authentication_Type
));
1281 eigrp_authTLV_MD5_free(authTLV
);
1282 return EIGRP_AUTH_MD5_TLV_SIZE
;
1285 eigrp_authTLV_MD5_free(authTLV
);
1290 uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream
*s
,
1291 struct eigrp_interface
*ei
)
1294 struct keychain
*keychain
;
1295 struct TLV_SHA256_Authentication_Type
*authTLV
;
1297 authTLV
= eigrp_authTLV_SHA256_new();
1299 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1300 authTLV
->length
= htons(EIGRP_AUTH_SHA256_TLV_SIZE
);
1301 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_SHA256
);
1302 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_SHA256_LEN
);
1303 authTLV
->key_sequence
= 0;
1304 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1306 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1308 key
= key_lookup_for_send(keychain
);
1310 free(ei
->params
.auth_keychain
);
1311 ei
->params
.auth_keychain
= NULL
;
1312 eigrp_authTLV_SHA256_free(authTLV
);
1317 authTLV
->key_id
= 0;
1318 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_SHA256_LEN
);
1319 stream_put(s
, authTLV
,
1320 sizeof(struct TLV_SHA256_Authentication_Type
));
1321 eigrp_authTLV_SHA256_free(authTLV
);
1322 return EIGRP_AUTH_SHA256_TLV_SIZE
;
1325 eigrp_authTLV_SHA256_free(authTLV
);
1330 struct TLV_MD5_Authentication_Type
*eigrp_authTLV_MD5_new()
1332 struct TLV_MD5_Authentication_Type
*new;
1334 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV
,
1335 sizeof(struct TLV_MD5_Authentication_Type
));
1340 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type
*authTLV
)
1342 XFREE(MTYPE_EIGRP_AUTH_TLV
, authTLV
);
1345 struct TLV_SHA256_Authentication_Type
*eigrp_authTLV_SHA256_new()
1347 struct TLV_SHA256_Authentication_Type
*new;
1349 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV
,
1350 sizeof(struct TLV_SHA256_Authentication_Type
));
1355 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type
*authTLV
)
1357 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV
, authTLV
);
1360 void eigrp_IPv4_InternalTLV_free(
1361 struct TLV_IPv4_Internal_type
*IPv4_InternalTLV
)
1363 XFREE(MTYPE_EIGRP_IPV4_INT_TLV
, IPv4_InternalTLV
);
1366 struct TLV_Sequence_Type
*eigrp_SequenceTLV_new()
1368 struct TLV_Sequence_Type
*new;
1370 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV
, sizeof(struct TLV_Sequence_Type
));