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"
46 #include "eigrpd/eigrp_structs.h"
47 #include "eigrpd/eigrpd.h"
48 #include "eigrpd/eigrp_interface.h"
49 #include "eigrpd/eigrp_neighbor.h"
50 #include "eigrpd/eigrp_packet.h"
51 #include "eigrpd/eigrp_zebra.h"
52 #include "eigrpd/eigrp_vty.h"
53 #include "eigrpd/eigrp_dump.h"
54 #include "eigrpd/eigrp_macros.h"
55 #include "eigrpd/eigrp_network.h"
56 #include "eigrpd/eigrp_topology.h"
57 #include "eigrpd/eigrp_fsm.h"
58 #include "eigrpd/eigrp_memory.h"
60 /* Packet Type String. */
61 const struct message eigrp_packet_type_str
[] = {
62 {EIGRP_OPC_UPDATE
, "Update"},
63 {EIGRP_OPC_REQUEST
, "Request"},
64 {EIGRP_OPC_QUERY
, "Query"},
65 {EIGRP_OPC_REPLY
, "Reply"},
66 {EIGRP_OPC_HELLO
, "Hello"},
67 {EIGRP_OPC_IPXSAP
, "IPX-SAP"},
68 {EIGRP_OPC_PROBE
, "Probe"},
69 {EIGRP_OPC_ACK
, "Ack"},
70 {EIGRP_OPC_SIAQUERY
, "SIAQuery"},
71 {EIGRP_OPC_SIAREPLY
, "SIAReply"},
75 static unsigned char zeropad
[16] = {0};
77 /* Forward function reference*/
78 static struct stream
*eigrp_recv_packet(int, struct interface
**,
80 static int eigrp_verify_header(struct stream
*, struct eigrp_interface
*,
81 struct ip
*, struct eigrp_header
*);
82 static int eigrp_check_network_mask(struct eigrp_interface
*, struct in_addr
);
84 static int eigrp_retrans_count_exceeded(struct eigrp_packet
*ep
,
85 struct eigrp_neighbor
*nbr
)
90 int eigrp_make_md5_digest(struct eigrp_interface
*ei
, struct stream
*s
,
93 struct key
*key
= NULL
;
94 struct keychain
*keychain
;
96 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
99 size_t backup_get
, backup_end
;
100 struct TLV_MD5_Authentication_Type
*auth_TLV
;
103 backup_end
= s
->endp
;
104 backup_get
= s
->getp
;
106 auth_TLV
= eigrp_authTLV_MD5_new();
108 stream_set_getp(s
, EIGRP_HEADER_LEN
);
109 stream_get(auth_TLV
, s
, EIGRP_AUTH_MD5_TLV_SIZE
);
110 stream_set_getp(s
, backup_get
);
112 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
114 key
= key_lookup_for_send(keychain
);
116 eigrp_authTLV_MD5_free(auth_TLV
);
117 return EIGRP_AUTH_TYPE_NONE
;
120 memset(&ctx
, 0, sizeof(ctx
));
123 /* Generate a digest. Each situation needs different handling */
124 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
125 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
126 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
127 if (strlen(key
->string
) < 16)
128 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
129 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
130 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
131 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
132 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
133 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
134 if (strlen(key
->string
) < 16)
135 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
136 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
138 ibuf
+ (EIGRP_HEADER_LEN
139 + EIGRP_AUTH_MD5_TLV_SIZE
),
142 + EIGRP_AUTH_MD5_TLV_SIZE
));
146 MD5Final(digest
, &ctx
);
148 /* Append md5 digest to the end of the stream. */
149 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
151 stream_set_endp(s
, EIGRP_HEADER_LEN
);
152 stream_put(s
, auth_TLV
, EIGRP_AUTH_MD5_TLV_SIZE
);
153 stream_set_endp(s
, backup_end
);
155 eigrp_authTLV_MD5_free(auth_TLV
);
156 return EIGRP_AUTH_TYPE_MD5_LEN
;
159 int eigrp_check_md5_digest(struct stream
*s
,
160 struct TLV_MD5_Authentication_Type
*authTLV
,
161 struct eigrp_neighbor
*nbr
, uint8_t flags
)
164 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
165 unsigned char orig
[EIGRP_AUTH_TYPE_MD5_LEN
];
166 struct key
*key
= NULL
;
167 struct keychain
*keychain
;
170 struct TLV_MD5_Authentication_Type
*auth_TLV
;
171 struct eigrp_header
*eigrph
;
173 if (ntohl(nbr
->crypt_seqnum
) > ntohl(authTLV
->key_sequence
)) {
175 "interface %s: eigrp_check_md5 bad sequence %d (expect %d)",
176 IF_NAME(nbr
->ei
), ntohl(authTLV
->key_sequence
),
177 ntohl(nbr
->crypt_seqnum
));
181 eigrph
= (struct eigrp_header
*)s
->data
;
182 eigrph
->checksum
= 0;
184 auth_TLV
= (struct TLV_MD5_Authentication_Type
*)(s
->data
186 memcpy(orig
, auth_TLV
->digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
187 memset(digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
188 memset(auth_TLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
191 backup_end
= s
->endp
;
193 keychain
= keychain_lookup(nbr
->ei
->params
.auth_keychain
);
195 key
= key_lookup_for_send(keychain
);
199 "Interface %s: Expected key value not found in config",
204 memset(&ctx
, 0, sizeof(ctx
));
207 /* Generate a digest. Each situation needs different handling */
208 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
209 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
210 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
211 if (strlen(key
->string
) < 16)
212 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
213 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
214 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
215 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
216 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
217 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
218 if (strlen(key
->string
) < 16)
219 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
220 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
222 ibuf
+ (EIGRP_HEADER_LEN
223 + EIGRP_AUTH_MD5_TLV_SIZE
),
226 + EIGRP_AUTH_MD5_TLV_SIZE
));
230 MD5Final(digest
, &ctx
);
232 /* compare the two */
233 if (memcmp(orig
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
) != 0) {
234 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
239 /* save neighbor's crypt_seqnum */
240 nbr
->crypt_seqnum
= authTLV
->key_sequence
;
245 int eigrp_make_sha256_digest(struct eigrp_interface
*ei
, struct stream
*s
,
248 struct key
*key
= NULL
;
249 struct keychain
*keychain
;
250 char source_ip
[PREFIX_STRLEN
];
252 unsigned char digest
[EIGRP_AUTH_TYPE_SHA256_LEN
];
253 unsigned char buffer
[1 + PLAINTEXT_LENGTH
+ 45 + 1] = {0};
257 size_t backup_get
, backup_end
;
258 struct TLV_SHA256_Authentication_Type
*auth_TLV
;
261 backup_end
= s
->endp
;
262 backup_get
= s
->getp
;
264 auth_TLV
= eigrp_authTLV_SHA256_new();
266 stream_set_getp(s
, EIGRP_HEADER_LEN
);
267 stream_get(auth_TLV
, s
, EIGRP_AUTH_SHA256_TLV_SIZE
);
268 stream_set_getp(s
, backup_get
);
270 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
272 key
= key_lookup_for_send(keychain
);
276 "Interface %s: Expected key value not found in config",
278 eigrp_authTLV_SHA256_free(auth_TLV
);
282 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
, source_ip
, PREFIX_STRLEN
);
284 memset(&ctx
, 0, sizeof(ctx
));
286 memcpy(buffer
+ 1, key
, strlen(key
->string
));
287 memcpy(buffer
+ 1 + strlen(key
->string
), source_ip
, strlen(source_ip
));
288 HMAC__SHA256_Init(&ctx
, buffer
,
289 1 + strlen(key
->string
) + strlen(source_ip
));
290 HMAC__SHA256_Update(&ctx
, ibuf
, strlen(ibuf
));
291 HMAC__SHA256_Final(digest
, &ctx
);
294 /* Put hmac-sha256 digest to it's place */
295 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_SHA256_LEN
);
297 stream_set_endp(s
, EIGRP_HEADER_LEN
);
298 stream_put(s
, auth_TLV
, EIGRP_AUTH_SHA256_TLV_SIZE
);
299 stream_set_endp(s
, backup_end
);
301 eigrp_authTLV_SHA256_free(auth_TLV
);
303 return EIGRP_AUTH_TYPE_SHA256_LEN
;
306 int eigrp_check_sha256_digest(struct stream
*s
,
307 struct TLV_SHA256_Authentication_Type
*authTLV
,
308 struct eigrp_neighbor
*nbr
, uint8_t flags
)
313 int eigrp_write(struct thread
*thread
)
315 struct eigrp
*eigrp
= THREAD_ARG(thread
);
316 struct eigrp_header
*eigrph
;
317 struct eigrp_interface
*ei
;
318 struct eigrp_packet
*ep
;
319 struct sockaddr_in sa_dst
;
327 struct listnode
*node
;
328 #ifdef WANT_EIGRP_WRITE_FRAGMENT
329 static uint16_t ipid
= 0;
330 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
331 #define EIGRP_WRITE_IPHL_SHIFT 2
333 eigrp
->t_write
= NULL
;
335 node
= listhead(eigrp
->oi_write_q
);
337 ei
= listgetdata(node
);
340 #ifdef WANT_EIGRP_WRITE_FRAGMENT
341 /* seed ipid static with low order bits of time */
343 ipid
= (time(NULL
) & 0xffff);
344 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
346 /* Get one packet from queue. */
347 ep
= eigrp_fifo_next(ei
->obuf
);
349 zlog_err("%s: Interface %s no packet on queue?",
350 __PRETTY_FUNCTION__
, ei
->ifp
->name
);
353 if (ep
->length
< EIGRP_HEADER_LEN
) {
354 zlog_err("%s: Packet just has a header?", __PRETTY_FUNCTION__
);
355 eigrp_header_dump((struct eigrp_header
*)ep
->s
->data
);
356 eigrp_packet_delete(ei
);
360 if (ep
->dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
))
361 eigrp_if_ipmulticast(eigrp
, ei
->address
, ei
->ifp
->ifindex
);
363 memset(&iph
, 0, sizeof(struct ip
));
364 memset(&sa_dst
, 0, sizeof(sa_dst
));
367 * We build and schedule packets to go out
368 * in the future. In the mean time we may
369 * process some update packets from the
370 * neighbor, thus making it necessary
371 * to update the ack we are using for
372 * this outgoing packet.
374 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
375 seqno
= ntohl(eigrph
->sequence
);
376 ack
= ntohl(eigrph
->ack
);
377 if (ep
->nbr
&& (ack
!= ep
->nbr
->recv_sequence_number
)) {
378 eigrph
->ack
= htonl(ep
->nbr
->recv_sequence_number
);
379 ack
= ep
->nbr
->recv_sequence_number
;
380 eigrph
->checksum
= 0;
381 eigrp_packet_checksum(ei
, ep
->s
, ep
->length
);
384 sa_dst
.sin_family
= AF_INET
;
385 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
386 sa_dst
.sin_len
= sizeof(sa_dst
);
387 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
388 sa_dst
.sin_addr
= ep
->dst
;
389 sa_dst
.sin_port
= htons(0);
391 /* Set DONTROUTE flag if dst is unicast. */
392 if (!IN_MULTICAST(htonl(ep
->dst
.s_addr
)))
393 flags
= MSG_DONTROUTE
;
395 iph
.ip_hl
= sizeof(struct ip
) >> EIGRP_WRITE_IPHL_SHIFT
;
396 /* it'd be very strange for header to not be 4byte-word aligned but.. */
397 if (sizeof(struct ip
)
398 > (unsigned int)(iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
))
399 iph
.ip_hl
++; /* we presume sizeof struct ip cant overflow
402 iph
.ip_v
= IPVERSION
;
403 iph
.ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
404 iph
.ip_len
= (iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
) + ep
->length
;
406 #if defined(__DragonFly__)
408 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
410 iph
.ip_len
= htons(iph
.ip_len
);
414 iph
.ip_ttl
= EIGRP_IP_TTL
;
415 iph
.ip_p
= IPPROTO_EIGRPIGP
;
417 iph
.ip_src
.s_addr
= ei
->address
->u
.prefix4
.s_addr
;
418 iph
.ip_dst
.s_addr
= ep
->dst
.s_addr
;
420 memset(&msg
, 0, sizeof(msg
));
421 msg
.msg_name
= (caddr_t
)&sa_dst
;
422 msg
.msg_namelen
= sizeof(sa_dst
);
426 iov
[0].iov_base
= (char *)&iph
;
427 iov
[0].iov_len
= iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
;
428 iov
[1].iov_base
= stream_pnt(ep
->s
);
429 iov
[1].iov_len
= ep
->length
;
431 /* send final fragment (could be first) */
432 sockopt_iphdrincl_swab_htosys(&iph
);
433 ret
= sendmsg(eigrp
->fd
, &msg
, flags
);
434 sockopt_iphdrincl_swab_systoh(&iph
);
436 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)) {
437 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
439 "Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
440 lookup_msg(eigrp_packet_type_str
, eigrph
->opcode
, NULL
),
441 seqno
, ack
, inet_ntoa(ep
->dst
), IF_NAME(ei
), ret
);
446 "*** sendmsg in eigrp_write failed to %s, "
447 "id %d, off %d, len %d, interface %s, mtu %u: %s",
448 inet_ntoa(iph
.ip_dst
), iph
.ip_id
, iph
.ip_off
,
449 iph
.ip_len
, ei
->ifp
->name
, ei
->ifp
->mtu
,
450 safe_strerror(errno
));
452 /* Now delete packet from queue. */
453 eigrp_packet_delete(ei
);
456 if (eigrp_fifo_next(ei
->obuf
) == NULL
) {
458 list_delete_node(eigrp
->oi_write_q
, node
);
461 /* If packets still remain in queue, call write thread. */
462 if (!list_isempty(eigrp
->oi_write_q
)) {
463 eigrp
->t_write
= NULL
;
464 thread_add_write(master
, eigrp_write
, eigrp
, eigrp
->fd
,
471 /* Starting point of packet process function. */
472 int eigrp_read(struct thread
*thread
)
477 struct eigrp_interface
*ei
;
479 struct eigrp_header
*eigrph
;
480 struct interface
*ifp
;
481 struct eigrp_neighbor
*nbr
;
486 /* first of all get interface pointer. */
487 eigrp
= THREAD_ARG(thread
);
489 /* prepare for next packet. */
490 eigrp
->t_read
= NULL
;
491 thread_add_read(master
, eigrp_read
, eigrp
, eigrp
->fd
, &eigrp
->t_read
);
493 stream_reset(eigrp
->ibuf
);
494 if (!(ibuf
= eigrp_recv_packet(eigrp
->fd
, &ifp
, eigrp
->ibuf
))) {
495 /* This raw packet is known to be at least as big as its IP
500 /* Note that there should not be alignment problems with this assignment
501 because this is at the beginning of the stream data buffer. */
502 iph
= (struct ip
*)STREAM_DATA(ibuf
);
504 // Substract IPv4 header size from EIGRP Packet itself
506 length
= (iph
->ip_len
) - 20U;
509 /* IP Header dump. */
510 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
511 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
512 eigrp_ip_header_dump(iph
);
514 /* Note that sockopt_iphdrincl_swab_systoh was called in
515 * eigrp_recv_packet. */
518 /* Handle cases where the platform does not support retrieving
520 and also platforms (such as Solaris 8) that claim to support
522 retrieval but do not. */
523 c
= if_lookup_address((void *)&iph
->ip_src
, AF_INET
,
532 /* associate packet with eigrp interface */
535 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
537 after the checks below are passed. These checks in turn access the
538 fields of unverified "eigrph" structure for their own purposes and
539 must remain very accurate in doing this.
544 /* Self-originated packet should be discarded silently. */
545 if (eigrp_if_lookup_by_local_addr(eigrp
, NULL
, iph
->ip_src
)
546 || (IPV4_ADDR_SAME(&iph
->ip_src
, &ei
->address
->u
.prefix4
))) {
547 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
549 "eigrp_read[%s]: Dropping self-originated packet",
550 inet_ntoa(iph
->ip_src
));
554 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
555 by eigrp_recv_packet() to be correct). */
557 stream_forward_getp(ibuf
, (iph
->ip_hl
* 4));
558 eigrph
= (struct eigrp_header
*)stream_pnt(ibuf
);
560 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
561 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
562 eigrp_header_dump(eigrph
);
564 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
565 // stream_get_getp(ibuf)))
568 /* If incoming interface is passive one, ignore it. */
569 if (eigrp_if_is_passive(ei
)) {
570 char buf
[3][INET_ADDRSTRLEN
];
572 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
574 "ignoring packet from router %s sent to %s, "
575 "received on a passive interface, %s",
576 inet_ntop(AF_INET
, &eigrph
->vrid
, buf
[0],
578 inet_ntop(AF_INET
, &iph
->ip_dst
, buf
[1],
580 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
,
581 buf
[2], sizeof(buf
[2])));
583 if (iph
->ip_dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
)) {
584 eigrp_if_set_multicast(ei
);
589 /* else it must be a local eigrp interface, check it was received on
592 else if (ei
->ifp
!= ifp
) {
593 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
594 zlog_warn("Packet from [%s] received on wrong link %s",
595 inet_ntoa(iph
->ip_src
), ifp
->name
);
599 /* Verify more EIGRP header fields. */
600 ret
= eigrp_verify_header(ibuf
, ei
, iph
, eigrph
);
602 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
604 "eigrp_read[%s]: Header check failed, dropping.",
605 inet_ntoa(iph
->ip_src
));
609 /* calcualte the eigrp packet length, and move the pounter to the
610 start of the eigrp TLVs */
611 opcode
= eigrph
->opcode
;
613 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)) {
614 char src
[PREFIX_STRLEN
], dst
[PREFIX_STRLEN
];
616 strlcpy(src
, inet_ntoa(iph
->ip_src
), sizeof(src
));
617 strlcpy(dst
, inet_ntoa(iph
->ip_dst
), sizeof(dst
));
619 "Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
620 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
621 ntohl(eigrph
->sequence
), ntohl(eigrph
->ack
), length
,
622 IF_NAME(ei
), src
, dst
);
625 /* Read rest of the packet and call each sort of packet routine. */
626 stream_forward_getp(ibuf
, EIGRP_HEADER_LEN
);
628 /* New testing block of code for handling Acks */
629 if (ntohl(eigrph
->ack
) != 0) {
630 struct eigrp_packet
*ep
= NULL
;
632 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
634 // neighbor must be valid, eigrp_nbr_get creates if none existed
637 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
638 if ((ep
) && (ntohl(eigrph
->ack
) == ep
->sequence_number
)) {
639 ep
= eigrp_fifo_pop(nbr
->retrans_queue
);
640 eigrp_packet_free(ep
);
642 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
643 && (ntohl(eigrph
->ack
)
644 == nbr
->init_sequence_number
)) {
645 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_UP
);
646 zlog_info("Neighbor(%s) adjacency became full",
647 inet_ntoa(nbr
->src
));
648 nbr
->init_sequence_number
= 0;
649 nbr
->recv_sequence_number
=
650 ntohl(eigrph
->sequence
);
651 eigrp_update_send_EOT(nbr
);
653 eigrp_send_packet_reliably(nbr
);
655 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
657 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
658 ep
= eigrp_fifo_pop(nbr
->multicast_queue
);
659 eigrp_packet_free(ep
);
660 if (nbr
->multicast_queue
->count
> 0) {
661 eigrp_send_packet_reliably(nbr
);
669 case EIGRP_OPC_HELLO
:
670 eigrp_hello_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
672 case EIGRP_OPC_PROBE
:
673 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
676 case EIGRP_OPC_QUERY
:
677 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
679 case EIGRP_OPC_REPLY
:
680 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
682 case EIGRP_OPC_REQUEST
:
683 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
686 case EIGRP_OPC_SIAQUERY
:
687 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
689 case EIGRP_OPC_SIAREPLY
:
690 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
692 case EIGRP_OPC_UPDATE
:
693 eigrp_update_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
697 "interface %s: EIGRP packet header type %d unsupported",
698 IF_NAME(ei
), opcode
);
705 static struct stream
*eigrp_recv_packet(int fd
, struct interface
**ifp
,
711 unsigned int ifindex
= 0;
713 /* Header and data both require alignment. */
714 char buff
[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
717 memset(&msgh
, 0, sizeof(struct msghdr
));
720 msgh
.msg_control
= (caddr_t
)buff
;
721 msgh
.msg_controllen
= sizeof(buff
);
723 ret
= stream_recvmsg(ibuf
, fd
, &msgh
, 0, (EIGRP_PACKET_MAX_LEN
+ 1));
725 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno
));
728 if ((unsigned int)ret
< sizeof(*iph
)) /* ret must be > 0 now */
731 "eigrp_recv_packet: discarding runt packet of length %d "
732 "(ip header size is %u)",
733 ret
, (unsigned int)sizeof(*iph
));
737 /* Note that there should not be alignment problems with this assignment
738 because this is at the beginning of the stream data buffer. */
739 iph
= (struct ip
*)STREAM_DATA(ibuf
);
740 sockopt_iphdrincl_swab_systoh(iph
);
742 ip_len
= iph
->ip_len
;
744 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
746 * Kernel network code touches incoming IP header parameters,
747 * before protocol specific processing.
749 * 1) Convert byteorder to host representation.
750 * --> ip_len, ip_id, ip_off
752 * 2) Adjust ip_len to strip IP header size!
753 * --> If user process receives entire IP packet via RAW
754 * socket, it must consider adding IP header size to
755 * the "ip_len" field of "ip" structure.
757 * For more details, see <netinet/ip_input.c>.
759 ip_len
= ip_len
+ (iph
->ip_hl
<< 2);
762 #if defined(__DragonFly__)
764 * in DragonFly's raw socket, ip_len/ip_off are read
765 * in network byte order.
766 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
768 ip_len
= ntohs(iph
->ip_len
) + (iph
->ip_hl
<< 2);
771 ifindex
= getsockopt_ifindex(AF_INET
, &msgh
);
773 *ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
777 "eigrp_recv_packet read length mismatch: ip_len is %d, "
778 "but recvmsg returned %d",
786 struct eigrp_fifo
*eigrp_fifo_new(void)
788 struct eigrp_fifo
*new;
790 new = XCALLOC(MTYPE_EIGRP_FIFO
, sizeof(struct eigrp_fifo
));
794 /* Free eigrp packet fifo. */
795 void eigrp_fifo_free(struct eigrp_fifo
*fifo
)
797 struct eigrp_packet
*ep
;
798 struct eigrp_packet
*next
;
800 for (ep
= fifo
->head
; ep
; ep
= next
) {
802 eigrp_packet_free(ep
);
804 fifo
->head
= fifo
->tail
= NULL
;
807 XFREE(MTYPE_EIGRP_FIFO
, fifo
);
810 /* Free eigrp fifo entries without destroying fifo itself*/
811 void eigrp_fifo_reset(struct eigrp_fifo
*fifo
)
813 struct eigrp_packet
*ep
;
814 struct eigrp_packet
*next
;
816 for (ep
= fifo
->head
; ep
; ep
= next
) {
818 eigrp_packet_free(ep
);
820 fifo
->head
= fifo
->tail
= NULL
;
824 struct eigrp_packet
*eigrp_packet_new(size_t size
, struct eigrp_neighbor
*nbr
)
826 struct eigrp_packet
*new;
828 new = XCALLOC(MTYPE_EIGRP_PACKET
, sizeof(struct eigrp_packet
));
829 new->s
= stream_new(size
);
830 new->retrans_counter
= 0;
836 void eigrp_send_packet_reliably(struct eigrp_neighbor
*nbr
)
838 struct eigrp_packet
*ep
;
840 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
843 struct eigrp_packet
*duplicate
;
844 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
845 /* Add packet to the top of the interface output queue*/
846 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
848 /*Start retransmission timer*/
849 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
850 EIGRP_PACKET_RETRANS_TIME
,
851 &ep
->t_retrans_timer
);
853 /*Increment sequence number counter*/
854 nbr
->ei
->eigrp
->sequence_number
++;
856 /* Hook thread to write packet. */
857 if (nbr
->ei
->on_write_q
== 0) {
858 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
859 nbr
->ei
->on_write_q
= 1;
861 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
862 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
866 /* Calculate EIGRP checksum */
867 void eigrp_packet_checksum(struct eigrp_interface
*ei
, struct stream
*s
,
870 struct eigrp_header
*eigrph
;
872 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
874 /* Calculate checksum. */
875 eigrph
->checksum
= in_cksum(eigrph
, length
);
878 /* Make EIGRP header. */
879 void eigrp_packet_header_init(int type
, struct eigrp
*eigrp
, struct stream
*s
,
880 uint32_t flags
, uint32_t sequence
, uint32_t ack
)
882 struct eigrp_header
*eigrph
;
885 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
887 eigrph
->version
= (uint8_t)EIGRP_HEADER_VERSION
;
888 eigrph
->opcode
= (uint8_t)type
;
889 eigrph
->checksum
= 0;
891 eigrph
->vrid
= htons(eigrp
->vrid
);
892 eigrph
->ASNumber
= htons(eigrp
->AS
);
893 eigrph
->ack
= htonl(ack
);
894 eigrph
->sequence
= htonl(sequence
);
895 // if(flags == EIGRP_INIT_FLAG)
896 // eigrph->sequence = htonl(3);
897 eigrph
->flags
= htonl(flags
);
899 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
900 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
901 htonl(eigrph
->sequence
), htonl(eigrph
->ack
));
903 stream_forward_endp(s
, EIGRP_HEADER_LEN
);
906 /* Add new packet to head of fifo. */
907 void eigrp_fifo_push(struct eigrp_fifo
*fifo
, struct eigrp_packet
*ep
)
909 ep
->next
= fifo
->head
;
912 if (fifo
->tail
== NULL
)
915 if (fifo
->count
!= 0)
916 fifo
->head
->previous
= ep
;
923 /* Return last fifo entry. */
924 struct eigrp_packet
*eigrp_fifo_next(struct eigrp_fifo
*fifo
)
929 void eigrp_packet_delete(struct eigrp_interface
*ei
)
931 struct eigrp_packet
*ep
;
933 ep
= eigrp_fifo_pop(ei
->obuf
);
936 eigrp_packet_free(ep
);
939 void eigrp_packet_free(struct eigrp_packet
*ep
)
944 THREAD_OFF(ep
->t_retrans_timer
);
946 XFREE(MTYPE_EIGRP_PACKET
, ep
);
949 /* EIGRP Header verification. */
950 static int eigrp_verify_header(struct stream
*ibuf
, struct eigrp_interface
*ei
,
951 struct ip
*iph
, struct eigrp_header
*eigrph
)
953 /* Check network mask, Silently discarded. */
954 if (!eigrp_check_network_mask(ei
, iph
->ip_src
)) {
956 "interface %s: eigrp_read network address is not same [%s]",
957 IF_NAME(ei
), inet_ntoa(iph
->ip_src
));
961 // /* Check authentication. The function handles logging actions, where
963 // if (! eigrp_check_auth(ei, eigrph))
969 /* Unbound socket will accept any Raw IP packets if proto is matched.
970 To prevent it, compare src IP address and i/f address with masking
972 static int eigrp_check_network_mask(struct eigrp_interface
*ei
,
973 struct in_addr ip_src
)
975 struct in_addr mask
, me
, him
;
977 if (ei
->type
== EIGRP_IFTYPE_POINTOPOINT
)
980 masklen2ip(ei
->address
->prefixlen
, &mask
);
982 me
.s_addr
= ei
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
983 him
.s_addr
= ip_src
.s_addr
& mask
.s_addr
;
985 if (IPV4_ADDR_SAME(&me
, &him
))
991 int eigrp_unack_packet_retrans(struct thread
*thread
)
993 struct eigrp_neighbor
*nbr
;
994 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
996 struct eigrp_packet
*ep
;
997 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
1000 struct eigrp_packet
*duplicate
;
1001 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1003 /* Add packet to the top of the interface output queue*/
1004 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1006 ep
->retrans_counter
++;
1007 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1008 return eigrp_retrans_count_exceeded(ep
, nbr
);
1010 /*Start retransmission timer*/
1011 ep
->t_retrans_timer
= NULL
;
1012 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
1013 EIGRP_PACKET_RETRANS_TIME
,
1014 &ep
->t_retrans_timer
);
1016 /* Hook thread to write packet. */
1017 if (nbr
->ei
->on_write_q
== 0) {
1018 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1019 nbr
->ei
->on_write_q
= 1;
1021 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1022 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1028 int eigrp_unack_multicast_packet_retrans(struct thread
*thread
)
1030 struct eigrp_neighbor
*nbr
;
1031 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1033 struct eigrp_packet
*ep
;
1034 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
1037 struct eigrp_packet
*duplicate
;
1038 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1039 /* Add packet to the top of the interface output queue*/
1040 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1042 ep
->retrans_counter
++;
1043 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1044 return eigrp_retrans_count_exceeded(ep
, nbr
);
1046 /*Start retransmission timer*/
1047 ep
->t_retrans_timer
= NULL
;
1048 thread_add_timer(master
, eigrp_unack_multicast_packet_retrans
,
1049 nbr
, EIGRP_PACKET_RETRANS_TIME
,
1050 &ep
->t_retrans_timer
);
1052 /* Hook thread to write packet. */
1053 if (nbr
->ei
->on_write_q
== 0) {
1054 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1055 nbr
->ei
->on_write_q
= 1;
1057 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1058 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1064 /* Get packet from tail of fifo. */
1065 struct eigrp_packet
*eigrp_fifo_pop(struct eigrp_fifo
*fifo
)
1067 struct eigrp_packet
*ep
= NULL
;
1072 fifo
->tail
= ep
->previous
;
1074 if (fifo
->tail
== NULL
)
1077 fifo
->tail
->next
= NULL
;
1085 struct eigrp_packet
*eigrp_packet_duplicate(struct eigrp_packet
*old
,
1086 struct eigrp_neighbor
*nbr
)
1088 struct eigrp_packet
*new;
1090 new = eigrp_packet_new(EIGRP_PACKET_MTU(nbr
->ei
->ifp
->mtu
), nbr
);
1091 new->length
= old
->length
;
1092 new->retrans_counter
= old
->retrans_counter
;
1093 new->dst
= old
->dst
;
1094 new->sequence_number
= old
->sequence_number
;
1095 stream_copy(new->s
, old
->s
);
1100 static struct TLV_IPv4_Internal_type
*eigrp_IPv4_InternalTLV_new()
1102 struct TLV_IPv4_Internal_type
*new;
1104 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV
,
1105 sizeof(struct TLV_IPv4_Internal_type
));
1110 struct TLV_IPv4_Internal_type
*eigrp_read_ipv4_tlv(struct stream
*s
)
1112 struct TLV_IPv4_Internal_type
*tlv
;
1114 tlv
= eigrp_IPv4_InternalTLV_new();
1116 tlv
->type
= stream_getw(s
);
1117 tlv
->length
= stream_getw(s
);
1118 tlv
->forward
.s_addr
= stream_getl(s
);
1119 tlv
->metric
.delay
= stream_getl(s
);
1120 tlv
->metric
.bandwidth
= stream_getl(s
);
1121 tlv
->metric
.mtu
[0] = stream_getc(s
);
1122 tlv
->metric
.mtu
[1] = stream_getc(s
);
1123 tlv
->metric
.mtu
[2] = stream_getc(s
);
1124 tlv
->metric
.hop_count
= stream_getc(s
);
1125 tlv
->metric
.reliability
= stream_getc(s
);
1126 tlv
->metric
.load
= stream_getc(s
);
1127 tlv
->metric
.tag
= stream_getc(s
);
1128 tlv
->metric
.flags
= stream_getc(s
);
1130 tlv
->prefix_length
= stream_getc(s
);
1132 if (tlv
->prefix_length
<= 8) {
1133 tlv
->destination_part
[0] = stream_getc(s
);
1134 tlv
->destination
.s_addr
= (tlv
->destination_part
[0]);
1135 } else if (tlv
->prefix_length
> 8 && tlv
->prefix_length
<= 16) {
1136 tlv
->destination_part
[0] = stream_getc(s
);
1137 tlv
->destination_part
[1] = stream_getc(s
);
1138 tlv
->destination
.s_addr
= ((tlv
->destination_part
[1] << 8)
1139 + tlv
->destination_part
[0]);
1140 } else if (tlv
->prefix_length
> 16 && tlv
->prefix_length
<= 24) {
1141 tlv
->destination_part
[0] = stream_getc(s
);
1142 tlv
->destination_part
[1] = stream_getc(s
);
1143 tlv
->destination_part
[2] = stream_getc(s
);
1144 tlv
->destination
.s_addr
= ((tlv
->destination_part
[2] << 16)
1145 + (tlv
->destination_part
[1] << 8)
1146 + tlv
->destination_part
[0]);
1147 } else if (tlv
->prefix_length
> 24 && tlv
->prefix_length
<= 32) {
1148 tlv
->destination_part
[0] = stream_getc(s
);
1149 tlv
->destination_part
[1] = stream_getc(s
);
1150 tlv
->destination_part
[2] = stream_getc(s
);
1151 tlv
->destination_part
[3] = stream_getc(s
);
1152 tlv
->destination
.s_addr
= ((tlv
->destination_part
[3] << 24)
1153 + (tlv
->destination_part
[2] << 16)
1154 + (tlv
->destination_part
[1] << 8)
1155 + tlv
->destination_part
[0]);
1160 uint16_t eigrp_add_internalTLV_to_stream(struct stream
*s
,
1161 struct eigrp_prefix_entry
*pe
)
1165 stream_putw(s
, EIGRP_TLV_IPv4_INT
);
1166 switch (pe
->destination
->prefixlen
) {
1176 length
= EIGRP_TLV_IPV4_SIZE_GRT_0_BIT
;
1177 stream_putw(s
, length
);
1187 length
= EIGRP_TLV_IPV4_SIZE_GRT_8_BIT
;
1188 stream_putw(s
, length
);
1198 length
= EIGRP_TLV_IPV4_SIZE_GRT_16_BIT
;
1199 stream_putw(s
, length
);
1209 length
= EIGRP_TLV_IPV4_SIZE_GRT_24_BIT
;
1210 stream_putw(s
, length
);
1213 zlog_err("%s: Unexpected prefix length: %d",
1214 __PRETTY_FUNCTION__
, pe
->destination
->prefixlen
);
1217 stream_putl(s
, 0x00000000);
1220 stream_putl(s
, pe
->reported_metric
.delay
);
1221 stream_putl(s
, pe
->reported_metric
.bandwidth
);
1222 stream_putc(s
, pe
->reported_metric
.mtu
[2]);
1223 stream_putc(s
, pe
->reported_metric
.mtu
[1]);
1224 stream_putc(s
, pe
->reported_metric
.mtu
[0]);
1225 stream_putc(s
, pe
->reported_metric
.hop_count
);
1226 stream_putc(s
, pe
->reported_metric
.reliability
);
1227 stream_putc(s
, pe
->reported_metric
.load
);
1228 stream_putc(s
, pe
->reported_metric
.tag
);
1229 stream_putc(s
, pe
->reported_metric
.flags
);
1231 stream_putc(s
, pe
->destination
->prefixlen
);
1233 stream_putc(s
, pe
->destination
->u
.prefix4
.s_addr
& 0xFF);
1234 if (pe
->destination
->prefixlen
> 8)
1235 stream_putc(s
, (pe
->destination
->u
.prefix4
.s_addr
>> 8) & 0xFF);
1236 if (pe
->destination
->prefixlen
> 16)
1238 (pe
->destination
->u
.prefix4
.s_addr
>> 16) & 0xFF);
1239 if (pe
->destination
->prefixlen
> 24)
1241 (pe
->destination
->u
.prefix4
.s_addr
>> 24) & 0xFF);
1246 uint16_t eigrp_add_authTLV_MD5_to_stream(struct stream
*s
,
1247 struct eigrp_interface
*ei
)
1250 struct keychain
*keychain
;
1251 struct TLV_MD5_Authentication_Type
*authTLV
;
1253 authTLV
= eigrp_authTLV_MD5_new();
1255 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1256 authTLV
->length
= htons(EIGRP_AUTH_MD5_TLV_SIZE
);
1257 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_MD5
);
1258 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_MD5_LEN
);
1259 authTLV
->key_sequence
= 0;
1260 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1262 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1264 key
= key_lookup_for_send(keychain
);
1266 free(ei
->params
.auth_keychain
);
1267 ei
->params
.auth_keychain
= NULL
;
1268 eigrp_authTLV_MD5_free(authTLV
);
1273 authTLV
->key_id
= htonl(key
->index
);
1274 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
1275 stream_put(s
, authTLV
,
1276 sizeof(struct TLV_MD5_Authentication_Type
));
1277 eigrp_authTLV_MD5_free(authTLV
);
1278 return EIGRP_AUTH_MD5_TLV_SIZE
;
1281 eigrp_authTLV_MD5_free(authTLV
);
1286 uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream
*s
,
1287 struct eigrp_interface
*ei
)
1290 struct keychain
*keychain
;
1291 struct TLV_SHA256_Authentication_Type
*authTLV
;
1293 authTLV
= eigrp_authTLV_SHA256_new();
1295 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1296 authTLV
->length
= htons(EIGRP_AUTH_SHA256_TLV_SIZE
);
1297 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_SHA256
);
1298 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_SHA256_LEN
);
1299 authTLV
->key_sequence
= 0;
1300 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1302 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1304 key
= key_lookup_for_send(keychain
);
1306 free(ei
->params
.auth_keychain
);
1307 ei
->params
.auth_keychain
= NULL
;
1308 eigrp_authTLV_SHA256_free(authTLV
);
1313 authTLV
->key_id
= 0;
1314 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_SHA256_LEN
);
1315 stream_put(s
, authTLV
,
1316 sizeof(struct TLV_SHA256_Authentication_Type
));
1317 eigrp_authTLV_SHA256_free(authTLV
);
1318 return EIGRP_AUTH_SHA256_TLV_SIZE
;
1321 eigrp_authTLV_SHA256_free(authTLV
);
1326 struct TLV_MD5_Authentication_Type
*eigrp_authTLV_MD5_new()
1328 struct TLV_MD5_Authentication_Type
*new;
1330 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV
,
1331 sizeof(struct TLV_MD5_Authentication_Type
));
1336 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type
*authTLV
)
1338 XFREE(MTYPE_EIGRP_AUTH_TLV
, authTLV
);
1341 struct TLV_SHA256_Authentication_Type
*eigrp_authTLV_SHA256_new()
1343 struct TLV_SHA256_Authentication_Type
*new;
1345 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV
,
1346 sizeof(struct TLV_SHA256_Authentication_Type
));
1351 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type
*authTLV
)
1353 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV
, authTLV
);
1356 void eigrp_IPv4_InternalTLV_free(
1357 struct TLV_IPv4_Internal_type
*IPv4_InternalTLV
)
1359 XFREE(MTYPE_EIGRP_IPV4_INT_TLV
, IPv4_InternalTLV
);
1362 struct TLV_Sequence_Type
*eigrp_SequenceTLV_new()
1364 struct TLV_Sequence_Type
*new;
1366 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV
, sizeof(struct TLV_Sequence_Type
));