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_network.h"
55 #include "eigrpd/eigrp_topology.h"
56 #include "eigrpd/eigrp_fsm.h"
57 #include "eigrpd/eigrp_memory.h"
59 /* Packet Type String. */
60 const struct message eigrp_packet_type_str
[] = {
61 {EIGRP_OPC_UPDATE
, "Update"},
62 {EIGRP_OPC_REQUEST
, "Request"},
63 {EIGRP_OPC_QUERY
, "Query"},
64 {EIGRP_OPC_REPLY
, "Reply"},
65 {EIGRP_OPC_HELLO
, "Hello"},
66 {EIGRP_OPC_IPXSAP
, "IPX-SAP"},
67 {EIGRP_OPC_PROBE
, "Probe"},
68 {EIGRP_OPC_ACK
, "Ack"},
69 {EIGRP_OPC_SIAQUERY
, "SIAQuery"},
70 {EIGRP_OPC_SIAREPLY
, "SIAReply"},
74 static unsigned char zeropad
[16] = {0};
76 /* Forward function reference*/
77 static struct stream
*eigrp_recv_packet(int, struct interface
**,
79 static int eigrp_verify_header(struct stream
*, struct eigrp_interface
*,
80 struct ip
*, struct eigrp_header
*);
81 static int eigrp_check_network_mask(struct eigrp_interface
*, struct in_addr
);
83 static int eigrp_retrans_count_exceeded(struct eigrp_packet
*ep
,
84 struct eigrp_neighbor
*nbr
)
89 int eigrp_make_md5_digest(struct eigrp_interface
*ei
, struct stream
*s
,
92 struct key
*key
= NULL
;
93 struct keychain
*keychain
;
95 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
98 size_t backup_get
, backup_end
;
99 struct TLV_MD5_Authentication_Type
*auth_TLV
;
102 backup_end
= s
->endp
;
103 backup_get
= s
->getp
;
105 auth_TLV
= eigrp_authTLV_MD5_new();
107 stream_set_getp(s
, EIGRP_HEADER_LEN
);
108 stream_get(auth_TLV
, s
, EIGRP_AUTH_MD5_TLV_SIZE
);
109 stream_set_getp(s
, backup_get
);
111 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
113 key
= key_lookup_for_send(keychain
);
115 eigrp_authTLV_MD5_free(auth_TLV
);
116 return EIGRP_AUTH_TYPE_NONE
;
119 memset(&ctx
, 0, sizeof(ctx
));
122 /* Generate a digest. Each situation needs different handling */
123 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
124 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
125 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
126 if (strlen(key
->string
) < 16)
127 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
128 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
129 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
130 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
131 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
132 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
133 if (strlen(key
->string
) < 16)
134 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
135 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
137 ibuf
+ (EIGRP_HEADER_LEN
138 + EIGRP_AUTH_MD5_TLV_SIZE
),
141 + EIGRP_AUTH_MD5_TLV_SIZE
));
145 MD5Final(digest
, &ctx
);
147 /* Append md5 digest to the end of the stream. */
148 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
150 stream_set_endp(s
, EIGRP_HEADER_LEN
);
151 stream_put(s
, auth_TLV
, EIGRP_AUTH_MD5_TLV_SIZE
);
152 stream_set_endp(s
, backup_end
);
154 eigrp_authTLV_MD5_free(auth_TLV
);
155 return EIGRP_AUTH_TYPE_MD5_LEN
;
158 int eigrp_check_md5_digest(struct stream
*s
,
159 struct TLV_MD5_Authentication_Type
*authTLV
,
160 struct eigrp_neighbor
*nbr
, uint8_t flags
)
163 unsigned char digest
[EIGRP_AUTH_TYPE_MD5_LEN
];
164 unsigned char orig
[EIGRP_AUTH_TYPE_MD5_LEN
];
165 struct key
*key
= NULL
;
166 struct keychain
*keychain
;
169 struct TLV_MD5_Authentication_Type
*auth_TLV
;
170 struct eigrp_header
*eigrph
;
172 if (ntohl(nbr
->crypt_seqnum
) > ntohl(authTLV
->key_sequence
)) {
174 "interface %s: eigrp_check_md5 bad sequence %d (expect %d)",
175 IF_NAME(nbr
->ei
), ntohl(authTLV
->key_sequence
),
176 ntohl(nbr
->crypt_seqnum
));
180 eigrph
= (struct eigrp_header
*)s
->data
;
181 eigrph
->checksum
= 0;
183 auth_TLV
= (struct TLV_MD5_Authentication_Type
*)(s
->data
185 memcpy(orig
, auth_TLV
->digest
, EIGRP_AUTH_TYPE_MD5_LEN
);
186 memset(digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
187 memset(auth_TLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
190 backup_end
= s
->endp
;
192 keychain
= keychain_lookup(nbr
->ei
->params
.auth_keychain
);
194 key
= key_lookup_for_send(keychain
);
198 "Interface %s: Expected key value not found in config",
203 memset(&ctx
, 0, sizeof(ctx
));
206 /* Generate a digest. Each situation needs different handling */
207 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
208 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
209 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
210 if (strlen(key
->string
) < 16)
211 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
212 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
213 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
214 } else if (flags
& EIGRP_AUTH_UPDATE_FLAG
) {
215 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
216 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
217 if (strlen(key
->string
) < 16)
218 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
219 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
221 ibuf
+ (EIGRP_HEADER_LEN
222 + EIGRP_AUTH_MD5_TLV_SIZE
),
225 + EIGRP_AUTH_MD5_TLV_SIZE
));
229 MD5Final(digest
, &ctx
);
231 /* compare the two */
232 if (memcmp(orig
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
) != 0) {
233 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
238 /* save neighbor's crypt_seqnum */
239 nbr
->crypt_seqnum
= authTLV
->key_sequence
;
244 int eigrp_make_sha256_digest(struct eigrp_interface
*ei
, struct stream
*s
,
247 struct key
*key
= NULL
;
248 struct keychain
*keychain
;
249 char source_ip
[PREFIX_STRLEN
];
251 unsigned char digest
[EIGRP_AUTH_TYPE_SHA256_LEN
];
252 unsigned char buffer
[1 + PLAINTEXT_LENGTH
+ 45 + 1] = {0};
256 size_t backup_get
, backup_end
;
257 struct TLV_SHA256_Authentication_Type
*auth_TLV
;
260 backup_end
= s
->endp
;
261 backup_get
= s
->getp
;
263 auth_TLV
= eigrp_authTLV_SHA256_new();
265 stream_set_getp(s
, EIGRP_HEADER_LEN
);
266 stream_get(auth_TLV
, s
, EIGRP_AUTH_SHA256_TLV_SIZE
);
267 stream_set_getp(s
, backup_get
);
269 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
271 key
= key_lookup_for_send(keychain
);
275 "Interface %s: Expected key value not found in config",
277 eigrp_authTLV_SHA256_free(auth_TLV
);
281 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
, source_ip
, PREFIX_STRLEN
);
283 memset(&ctx
, 0, sizeof(ctx
));
285 memcpy(buffer
+ 1, key
, strlen(key
->string
));
286 memcpy(buffer
+ 1 + strlen(key
->string
), source_ip
, strlen(source_ip
));
287 HMAC__SHA256_Init(&ctx
, buffer
,
288 1 + strlen(key
->string
) + strlen(source_ip
));
289 HMAC__SHA256_Update(&ctx
, ibuf
, strlen(ibuf
));
290 HMAC__SHA256_Final(digest
, &ctx
);
293 /* Put hmac-sha256 digest to it's place */
294 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_SHA256_LEN
);
296 stream_set_endp(s
, EIGRP_HEADER_LEN
);
297 stream_put(s
, auth_TLV
, EIGRP_AUTH_SHA256_TLV_SIZE
);
298 stream_set_endp(s
, backup_end
);
300 eigrp_authTLV_SHA256_free(auth_TLV
);
302 return EIGRP_AUTH_TYPE_SHA256_LEN
;
305 int eigrp_check_sha256_digest(struct stream
*s
,
306 struct TLV_SHA256_Authentication_Type
*authTLV
,
307 struct eigrp_neighbor
*nbr
, uint8_t flags
)
312 int eigrp_write(struct thread
*thread
)
314 struct eigrp
*eigrp
= THREAD_ARG(thread
);
315 struct eigrp_header
*eigrph
;
316 struct eigrp_interface
*ei
;
317 struct eigrp_packet
*ep
;
318 struct sockaddr_in sa_dst
;
326 struct listnode
*node
;
327 #ifdef WANT_EIGRP_WRITE_FRAGMENT
328 static uint16_t ipid
= 0;
329 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
330 #define EIGRP_WRITE_IPHL_SHIFT 2
332 eigrp
->t_write
= NULL
;
334 node
= listhead(eigrp
->oi_write_q
);
336 ei
= listgetdata(node
);
339 #ifdef WANT_EIGRP_WRITE_FRAGMENT
340 /* seed ipid static with low order bits of time */
342 ipid
= (time(NULL
) & 0xffff);
343 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
345 /* Get one packet from queue. */
346 ep
= eigrp_fifo_next(ei
->obuf
);
348 zlog_err("%s: Interface %s no packet on queue?",
349 __PRETTY_FUNCTION__
, ei
->ifp
->name
);
352 if (ep
->length
< EIGRP_HEADER_LEN
) {
353 zlog_err("%s: Packet just has a header?", __PRETTY_FUNCTION__
);
354 eigrp_header_dump((struct eigrp_header
*)ep
->s
->data
);
355 eigrp_packet_delete(ei
);
359 if (ep
->dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
))
360 eigrp_if_ipmulticast(eigrp
, ei
->address
, ei
->ifp
->ifindex
);
362 memset(&iph
, 0, sizeof(struct ip
));
363 memset(&sa_dst
, 0, sizeof(sa_dst
));
366 * We build and schedule packets to go out
367 * in the future. In the mean time we may
368 * process some update packets from the
369 * neighbor, thus making it necessary
370 * to update the ack we are using for
371 * this outgoing packet.
373 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
374 seqno
= ntohl(eigrph
->sequence
);
375 ack
= ntohl(eigrph
->ack
);
376 if (ep
->nbr
&& (ack
!= ep
->nbr
->recv_sequence_number
)) {
377 eigrph
->ack
= htonl(ep
->nbr
->recv_sequence_number
);
378 ack
= ep
->nbr
->recv_sequence_number
;
379 eigrph
->checksum
= 0;
380 eigrp_packet_checksum(ei
, ep
->s
, ep
->length
);
383 sa_dst
.sin_family
= AF_INET
;
384 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
385 sa_dst
.sin_len
= sizeof(sa_dst
);
386 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
387 sa_dst
.sin_addr
= ep
->dst
;
388 sa_dst
.sin_port
= htons(0);
390 /* Set DONTROUTE flag if dst is unicast. */
391 if (!IN_MULTICAST(htonl(ep
->dst
.s_addr
)))
392 flags
= MSG_DONTROUTE
;
394 iph
.ip_hl
= sizeof(struct ip
) >> EIGRP_WRITE_IPHL_SHIFT
;
395 /* it'd be very strange for header to not be 4byte-word aligned but.. */
396 if (sizeof(struct ip
)
397 > (unsigned int)(iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
))
398 iph
.ip_hl
++; /* we presume sizeof struct ip cant overflow
401 iph
.ip_v
= IPVERSION
;
402 iph
.ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
403 iph
.ip_len
= (iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
) + ep
->length
;
405 #if defined(__DragonFly__)
407 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
409 iph
.ip_len
= htons(iph
.ip_len
);
413 iph
.ip_ttl
= EIGRP_IP_TTL
;
414 iph
.ip_p
= IPPROTO_EIGRPIGP
;
416 iph
.ip_src
.s_addr
= ei
->address
->u
.prefix4
.s_addr
;
417 iph
.ip_dst
.s_addr
= ep
->dst
.s_addr
;
419 memset(&msg
, 0, sizeof(msg
));
420 msg
.msg_name
= (caddr_t
)&sa_dst
;
421 msg
.msg_namelen
= sizeof(sa_dst
);
425 iov
[0].iov_base
= (char *)&iph
;
426 iov
[0].iov_len
= iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
;
427 iov
[1].iov_base
= stream_pnt(ep
->s
);
428 iov
[1].iov_len
= ep
->length
;
430 /* send final fragment (could be first) */
431 sockopt_iphdrincl_swab_htosys(&iph
);
432 ret
= sendmsg(eigrp
->fd
, &msg
, flags
);
433 sockopt_iphdrincl_swab_systoh(&iph
);
435 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)) {
436 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
438 "Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
439 lookup_msg(eigrp_packet_type_str
, eigrph
->opcode
, NULL
),
440 seqno
, ack
, inet_ntoa(ep
->dst
), IF_NAME(ei
), ret
);
445 "*** sendmsg in eigrp_write failed to %s, "
446 "id %d, off %d, len %d, interface %s, mtu %u: %s",
447 inet_ntoa(iph
.ip_dst
), iph
.ip_id
, iph
.ip_off
,
448 iph
.ip_len
, ei
->ifp
->name
, ei
->ifp
->mtu
,
449 safe_strerror(errno
));
451 /* Now delete packet from queue. */
452 eigrp_packet_delete(ei
);
455 if (eigrp_fifo_next(ei
->obuf
) == NULL
) {
457 list_delete_node(eigrp
->oi_write_q
, node
);
460 /* If packets still remain in queue, call write thread. */
461 if (!list_isempty(eigrp
->oi_write_q
)) {
462 eigrp
->t_write
= NULL
;
463 thread_add_write(master
, eigrp_write
, eigrp
, eigrp
->fd
,
470 /* Starting point of packet process function. */
471 int eigrp_read(struct thread
*thread
)
476 struct eigrp_interface
*ei
;
478 struct eigrp_header
*eigrph
;
479 struct interface
*ifp
;
480 struct eigrp_neighbor
*nbr
;
485 /* first of all get interface pointer. */
486 eigrp
= THREAD_ARG(thread
);
488 /* prepare for next packet. */
489 eigrp
->t_read
= NULL
;
490 thread_add_read(master
, eigrp_read
, eigrp
, eigrp
->fd
, &eigrp
->t_read
);
492 stream_reset(eigrp
->ibuf
);
493 if (!(ibuf
= eigrp_recv_packet(eigrp
->fd
, &ifp
, eigrp
->ibuf
))) {
494 /* This raw packet is known to be at least as big as its IP
499 /* Note that there should not be alignment problems with this assignment
500 because this is at the beginning of the stream data buffer. */
501 iph
= (struct ip
*)STREAM_DATA(ibuf
);
503 // Substract IPv4 header size from EIGRP Packet itself
505 length
= (iph
->ip_len
) - 20U;
508 /* IP Header dump. */
509 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
510 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
511 eigrp_ip_header_dump(iph
);
513 /* Note that sockopt_iphdrincl_swab_systoh was called in
514 * eigrp_recv_packet. */
517 /* Handle cases where the platform does not support retrieving
519 and also platforms (such as Solaris 8) that claim to support
521 retrieval but do not. */
522 c
= if_lookup_address((void *)&iph
->ip_src
, AF_INET
,
531 /* associate packet with eigrp interface */
534 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
536 after the checks below are passed. These checks in turn access the
537 fields of unverified "eigrph" structure for their own purposes and
538 must remain very accurate in doing this.
543 /* Self-originated packet should be discarded silently. */
544 if (eigrp_if_lookup_by_local_addr(eigrp
, NULL
, iph
->ip_src
)
545 || (IPV4_ADDR_SAME(&iph
->ip_src
, &ei
->address
->u
.prefix4
))) {
546 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
548 "eigrp_read[%s]: Dropping self-originated packet",
549 inet_ntoa(iph
->ip_src
));
553 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
554 by eigrp_recv_packet() to be correct). */
556 stream_forward_getp(ibuf
, (iph
->ip_hl
* 4));
557 eigrph
= (struct eigrp_header
*)stream_pnt(ibuf
);
559 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
560 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
561 eigrp_header_dump(eigrph
);
563 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
564 // stream_get_getp(ibuf)))
567 /* If incoming interface is passive one, ignore it. */
568 if (ei
&& eigrp_if_is_passive(ei
)) {
569 char buf
[3][INET_ADDRSTRLEN
];
571 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
573 "ignoring packet from router %s sent to %s, "
574 "received on a passive interface, %s",
575 inet_ntop(AF_INET
, &eigrph
->vrid
, buf
[0],
577 inet_ntop(AF_INET
, &iph
->ip_dst
, buf
[1],
579 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
,
580 buf
[2], sizeof(buf
[2])));
582 if (iph
->ip_dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
)) {
583 eigrp_if_set_multicast(ei
);
588 /* else it must be a local eigrp interface, check it was received on
591 else if (ei
->ifp
!= ifp
) {
592 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
593 zlog_warn("Packet from [%s] received on wrong link %s",
594 inet_ntoa(iph
->ip_src
), ifp
->name
);
598 /* Verify more EIGRP header fields. */
599 ret
= eigrp_verify_header(ibuf
, ei
, iph
, eigrph
);
601 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
603 "eigrp_read[%s]: Header check failed, dropping.",
604 inet_ntoa(iph
->ip_src
));
608 /* calcualte the eigrp packet length, and move the pounter to the
609 start of the eigrp TLVs */
610 opcode
= eigrph
->opcode
;
612 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)) {
613 char src
[PREFIX_STRLEN
], dst
[PREFIX_STRLEN
];
615 strlcpy(src
, inet_ntoa(iph
->ip_src
), sizeof(src
));
616 strlcpy(dst
, inet_ntoa(iph
->ip_dst
), sizeof(dst
));
618 "Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
619 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
620 ntohl(eigrph
->sequence
), ntohl(eigrph
->ack
), length
,
621 IF_NAME(ei
), src
, dst
);
624 /* Read rest of the packet and call each sort of packet routine. */
625 stream_forward_getp(ibuf
, EIGRP_HEADER_LEN
);
627 /* New testing block of code for handling Acks */
628 if (ntohl(eigrph
->ack
) != 0) {
629 struct eigrp_packet
*ep
= NULL
;
631 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
633 // neighbor must be valid, eigrp_nbr_get creates if none existed
636 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
637 if ((ep
) && (ntohl(eigrph
->ack
) == ep
->sequence_number
)) {
638 ep
= eigrp_fifo_pop(nbr
->retrans_queue
);
639 eigrp_packet_free(ep
);
641 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
642 && (ntohl(eigrph
->ack
)
643 == nbr
->init_sequence_number
)) {
644 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_UP
);
645 zlog_info("Neighbor(%s) adjacency became full",
646 inet_ntoa(nbr
->src
));
647 nbr
->init_sequence_number
= 0;
648 nbr
->recv_sequence_number
=
649 ntohl(eigrph
->sequence
);
650 eigrp_update_send_EOT(nbr
);
652 eigrp_send_packet_reliably(nbr
);
654 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
656 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
657 ep
= eigrp_fifo_pop(nbr
->multicast_queue
);
658 eigrp_packet_free(ep
);
659 if (nbr
->multicast_queue
->count
> 0) {
660 eigrp_send_packet_reliably(nbr
);
668 case EIGRP_OPC_HELLO
:
669 eigrp_hello_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
671 case EIGRP_OPC_PROBE
:
672 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
675 case EIGRP_OPC_QUERY
:
676 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
678 case EIGRP_OPC_REPLY
:
679 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
681 case EIGRP_OPC_REQUEST
:
682 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
685 case EIGRP_OPC_SIAQUERY
:
686 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
688 case EIGRP_OPC_SIAREPLY
:
689 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
691 case EIGRP_OPC_UPDATE
:
692 eigrp_update_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
696 "interface %s: EIGRP packet header type %d unsupported",
697 IF_NAME(ei
), opcode
);
704 static struct stream
*eigrp_recv_packet(int fd
, struct interface
**ifp
,
710 unsigned int ifindex
= 0;
712 /* Header and data both require alignment. */
713 char buff
[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
716 memset(&msgh
, 0, sizeof(struct msghdr
));
719 msgh
.msg_control
= (caddr_t
)buff
;
720 msgh
.msg_controllen
= sizeof(buff
);
722 ret
= stream_recvmsg(ibuf
, fd
, &msgh
, 0, (EIGRP_PACKET_MAX_LEN
+ 1));
724 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno
));
727 if ((unsigned int)ret
< sizeof(iph
)) /* ret must be > 0 now */
730 "eigrp_recv_packet: discarding runt packet of length %d "
731 "(ip header size is %u)",
732 ret
, (unsigned int)sizeof(iph
));
736 /* Note that there should not be alignment problems with this assignment
737 because this is at the beginning of the stream data buffer. */
738 iph
= (struct ip
*)STREAM_DATA(ibuf
);
739 sockopt_iphdrincl_swab_systoh(iph
);
741 ip_len
= iph
->ip_len
;
743 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
745 * Kernel network code touches incoming IP header parameters,
746 * before protocol specific processing.
748 * 1) Convert byteorder to host representation.
749 * --> ip_len, ip_id, ip_off
751 * 2) Adjust ip_len to strip IP header size!
752 * --> If user process receives entire IP packet via RAW
753 * socket, it must consider adding IP header size to
754 * the "ip_len" field of "ip" structure.
756 * For more details, see <netinet/ip_input.c>.
758 ip_len
= ip_len
+ (iph
->ip_hl
<< 2);
761 #if defined(__DragonFly__)
763 * in DragonFly's raw socket, ip_len/ip_off are read
764 * in network byte order.
765 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
767 ip_len
= ntohs(iph
->ip_len
) + (iph
->ip_hl
<< 2);
770 ifindex
= getsockopt_ifindex(AF_INET
, &msgh
);
772 *ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
776 "eigrp_recv_packet read length mismatch: ip_len is %d, "
777 "but recvmsg returned %d",
785 struct eigrp_fifo
*eigrp_fifo_new(void)
787 struct eigrp_fifo
*new;
789 new = XCALLOC(MTYPE_EIGRP_FIFO
, sizeof(struct eigrp_fifo
));
793 /* Free eigrp packet fifo. */
794 void eigrp_fifo_free(struct eigrp_fifo
*fifo
)
796 struct eigrp_packet
*ep
;
797 struct eigrp_packet
*next
;
799 for (ep
= fifo
->head
; ep
; ep
= next
) {
801 eigrp_packet_free(ep
);
803 fifo
->head
= fifo
->tail
= NULL
;
806 XFREE(MTYPE_EIGRP_FIFO
, fifo
);
809 /* Free eigrp fifo entries without destroying fifo itself*/
810 void eigrp_fifo_reset(struct eigrp_fifo
*fifo
)
812 struct eigrp_packet
*ep
;
813 struct eigrp_packet
*next
;
815 for (ep
= fifo
->head
; ep
; ep
= next
) {
817 eigrp_packet_free(ep
);
819 fifo
->head
= fifo
->tail
= NULL
;
823 struct eigrp_packet
*eigrp_packet_new(size_t size
, struct eigrp_neighbor
*nbr
)
825 struct eigrp_packet
*new;
827 new = XCALLOC(MTYPE_EIGRP_PACKET
, sizeof(struct eigrp_packet
));
828 new->s
= stream_new(size
);
829 new->retrans_counter
= 0;
835 void eigrp_send_packet_reliably(struct eigrp_neighbor
*nbr
)
837 struct eigrp_packet
*ep
;
839 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
842 struct eigrp_packet
*duplicate
;
843 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
844 /* Add packet to the top of the interface output queue*/
845 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
847 /*Start retransmission timer*/
848 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
849 EIGRP_PACKET_RETRANS_TIME
,
850 &ep
->t_retrans_timer
);
852 /*Increment sequence number counter*/
853 nbr
->ei
->eigrp
->sequence_number
++;
855 /* Hook thread to write packet. */
856 if (nbr
->ei
->on_write_q
== 0) {
857 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
858 nbr
->ei
->on_write_q
= 1;
860 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
861 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
865 /* Calculate EIGRP checksum */
866 void eigrp_packet_checksum(struct eigrp_interface
*ei
, struct stream
*s
,
869 struct eigrp_header
*eigrph
;
871 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
873 /* Calculate checksum. */
874 eigrph
->checksum
= in_cksum(eigrph
, length
);
877 /* Make EIGRP header. */
878 void eigrp_packet_header_init(int type
, struct eigrp
*eigrp
, struct stream
*s
,
879 uint32_t flags
, uint32_t sequence
, uint32_t ack
)
881 struct eigrp_header
*eigrph
;
884 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
886 eigrph
->version
= (uint8_t)EIGRP_HEADER_VERSION
;
887 eigrph
->opcode
= (uint8_t)type
;
888 eigrph
->checksum
= 0;
890 eigrph
->vrid
= htons(eigrp
->vrid
);
891 eigrph
->ASNumber
= htons(eigrp
->AS
);
892 eigrph
->ack
= htonl(ack
);
893 eigrph
->sequence
= htonl(sequence
);
894 // if(flags == EIGRP_INIT_FLAG)
895 // eigrph->sequence = htonl(3);
896 eigrph
->flags
= htonl(flags
);
898 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
899 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
900 htonl(eigrph
->sequence
), htonl(eigrph
->ack
));
902 stream_forward_endp(s
, EIGRP_HEADER_LEN
);
905 /* Add new packet to head of fifo. */
906 void eigrp_fifo_push(struct eigrp_fifo
*fifo
, struct eigrp_packet
*ep
)
908 ep
->next
= fifo
->head
;
911 if (fifo
->tail
== NULL
)
914 if (fifo
->count
!= 0)
915 fifo
->head
->previous
= ep
;
922 /* Return last fifo entry. */
923 struct eigrp_packet
*eigrp_fifo_next(struct eigrp_fifo
*fifo
)
928 void eigrp_packet_delete(struct eigrp_interface
*ei
)
930 struct eigrp_packet
*ep
;
932 ep
= eigrp_fifo_pop(ei
->obuf
);
935 eigrp_packet_free(ep
);
938 void eigrp_packet_free(struct eigrp_packet
*ep
)
943 THREAD_OFF(ep
->t_retrans_timer
);
945 XFREE(MTYPE_EIGRP_PACKET
, ep
);
950 /* EIGRP Header verification. */
951 static int eigrp_verify_header(struct stream
*ibuf
, struct eigrp_interface
*ei
,
952 struct ip
*iph
, struct eigrp_header
*eigrph
)
954 /* Check network mask, Silently discarded. */
955 if (!eigrp_check_network_mask(ei
, iph
->ip_src
)) {
957 "interface %s: eigrp_read network address is not same [%s]",
958 IF_NAME(ei
), inet_ntoa(iph
->ip_src
));
962 // /* Check authentication. The function handles logging actions, where
964 // if (! eigrp_check_auth(ei, eigrph))
970 /* Unbound socket will accept any Raw IP packets if proto is matched.
971 To prevent it, compare src IP address and i/f address with masking
973 static int eigrp_check_network_mask(struct eigrp_interface
*ei
,
974 struct in_addr ip_src
)
976 struct in_addr mask
, me
, him
;
978 if (ei
->type
== EIGRP_IFTYPE_POINTOPOINT
)
981 masklen2ip(ei
->address
->prefixlen
, &mask
);
983 me
.s_addr
= ei
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
984 him
.s_addr
= ip_src
.s_addr
& mask
.s_addr
;
986 if (IPV4_ADDR_SAME(&me
, &him
))
992 int eigrp_unack_packet_retrans(struct thread
*thread
)
994 struct eigrp_neighbor
*nbr
;
995 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
997 struct eigrp_packet
*ep
;
998 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
1001 struct eigrp_packet
*duplicate
;
1002 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1004 /* Add packet to the top of the interface output queue*/
1005 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1007 ep
->retrans_counter
++;
1008 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1009 return eigrp_retrans_count_exceeded(ep
, nbr
);
1011 /*Start retransmission timer*/
1012 ep
->t_retrans_timer
= NULL
;
1013 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
1014 EIGRP_PACKET_RETRANS_TIME
,
1015 &ep
->t_retrans_timer
);
1017 /* Hook thread to write packet. */
1018 if (nbr
->ei
->on_write_q
== 0) {
1019 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1020 nbr
->ei
->on_write_q
= 1;
1022 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1023 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1029 int eigrp_unack_multicast_packet_retrans(struct thread
*thread
)
1031 struct eigrp_neighbor
*nbr
;
1032 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1034 struct eigrp_packet
*ep
;
1035 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
1038 struct eigrp_packet
*duplicate
;
1039 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1040 /* Add packet to the top of the interface output queue*/
1041 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1043 ep
->retrans_counter
++;
1044 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1045 return eigrp_retrans_count_exceeded(ep
, nbr
);
1047 /*Start retransmission timer*/
1048 ep
->t_retrans_timer
= NULL
;
1049 thread_add_timer(master
, eigrp_unack_multicast_packet_retrans
,
1050 nbr
, EIGRP_PACKET_RETRANS_TIME
,
1051 &ep
->t_retrans_timer
);
1053 /* Hook thread to write packet. */
1054 if (nbr
->ei
->on_write_q
== 0) {
1055 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1056 nbr
->ei
->on_write_q
= 1;
1058 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1059 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1065 /* Get packet from tail of fifo. */
1066 struct eigrp_packet
*eigrp_fifo_pop(struct eigrp_fifo
*fifo
)
1068 struct eigrp_packet
*ep
= NULL
;
1073 fifo
->tail
= ep
->previous
;
1075 if (fifo
->tail
== NULL
)
1078 fifo
->tail
->next
= NULL
;
1086 struct eigrp_packet
*eigrp_packet_duplicate(struct eigrp_packet
*old
,
1087 struct eigrp_neighbor
*nbr
)
1089 struct eigrp_packet
*new;
1091 new = eigrp_packet_new(nbr
->ei
->ifp
->mtu
, nbr
);
1092 new->length
= old
->length
;
1093 new->retrans_counter
= old
->retrans_counter
;
1094 new->dst
= old
->dst
;
1095 new->sequence_number
= old
->sequence_number
;
1096 stream_copy(new->s
, old
->s
);
1101 static struct TLV_IPv4_Internal_type
*eigrp_IPv4_InternalTLV_new()
1103 struct TLV_IPv4_Internal_type
*new;
1105 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV
,
1106 sizeof(struct TLV_IPv4_Internal_type
));
1111 struct TLV_IPv4_Internal_type
*eigrp_read_ipv4_tlv(struct stream
*s
)
1113 struct TLV_IPv4_Internal_type
*tlv
;
1115 tlv
= eigrp_IPv4_InternalTLV_new();
1117 tlv
->type
= stream_getw(s
);
1118 tlv
->length
= stream_getw(s
);
1119 tlv
->forward
.s_addr
= stream_getl(s
);
1120 tlv
->metric
.delay
= stream_getl(s
);
1121 tlv
->metric
.bandwidth
= stream_getl(s
);
1122 tlv
->metric
.mtu
[0] = stream_getc(s
);
1123 tlv
->metric
.mtu
[1] = stream_getc(s
);
1124 tlv
->metric
.mtu
[2] = stream_getc(s
);
1125 tlv
->metric
.hop_count
= stream_getc(s
);
1126 tlv
->metric
.reliability
= stream_getc(s
);
1127 tlv
->metric
.load
= stream_getc(s
);
1128 tlv
->metric
.tag
= stream_getc(s
);
1129 tlv
->metric
.flags
= stream_getc(s
);
1131 tlv
->prefix_length
= stream_getc(s
);
1133 if (tlv
->prefix_length
<= 8) {
1134 tlv
->destination_part
[0] = stream_getc(s
);
1135 tlv
->destination
.s_addr
= (tlv
->destination_part
[0]);
1136 } else if (tlv
->prefix_length
> 8 && tlv
->prefix_length
<= 16) {
1137 tlv
->destination_part
[0] = stream_getc(s
);
1138 tlv
->destination_part
[1] = stream_getc(s
);
1139 tlv
->destination
.s_addr
= ((tlv
->destination_part
[1] << 8)
1140 + tlv
->destination_part
[0]);
1141 } else if (tlv
->prefix_length
> 16 && tlv
->prefix_length
<= 24) {
1142 tlv
->destination_part
[0] = stream_getc(s
);
1143 tlv
->destination_part
[1] = stream_getc(s
);
1144 tlv
->destination_part
[2] = stream_getc(s
);
1145 tlv
->destination
.s_addr
= ((tlv
->destination_part
[2] << 16)
1146 + (tlv
->destination_part
[1] << 8)
1147 + tlv
->destination_part
[0]);
1148 } else if (tlv
->prefix_length
> 24 && tlv
->prefix_length
<= 32) {
1149 tlv
->destination_part
[0] = stream_getc(s
);
1150 tlv
->destination_part
[1] = stream_getc(s
);
1151 tlv
->destination_part
[2] = stream_getc(s
);
1152 tlv
->destination_part
[3] = stream_getc(s
);
1153 tlv
->destination
.s_addr
= ((tlv
->destination_part
[3] << 24)
1154 + (tlv
->destination_part
[2] << 16)
1155 + (tlv
->destination_part
[1] << 8)
1156 + tlv
->destination_part
[0]);
1161 uint16_t eigrp_add_internalTLV_to_stream(struct stream
*s
,
1162 struct eigrp_prefix_entry
*pe
)
1166 stream_putw(s
, EIGRP_TLV_IPv4_INT
);
1167 switch (pe
->destination
->prefixlen
) {
1177 length
= EIGRP_TLV_IPV4_SIZE_GRT_0_BIT
;
1178 stream_putw(s
, length
);
1188 length
= EIGRP_TLV_IPV4_SIZE_GRT_8_BIT
;
1189 stream_putw(s
, length
);
1199 length
= EIGRP_TLV_IPV4_SIZE_GRT_16_BIT
;
1200 stream_putw(s
, length
);
1210 length
= EIGRP_TLV_IPV4_SIZE_GRT_24_BIT
;
1211 stream_putw(s
, length
);
1214 zlog_err("%s: Unexpected prefix length: %d",
1215 __PRETTY_FUNCTION__
, pe
->destination
->prefixlen
);
1218 stream_putl(s
, 0x00000000);
1221 stream_putl(s
, pe
->reported_metric
.delay
);
1222 stream_putl(s
, pe
->reported_metric
.bandwidth
);
1223 stream_putc(s
, pe
->reported_metric
.mtu
[2]);
1224 stream_putc(s
, pe
->reported_metric
.mtu
[1]);
1225 stream_putc(s
, pe
->reported_metric
.mtu
[0]);
1226 stream_putc(s
, pe
->reported_metric
.hop_count
);
1227 stream_putc(s
, pe
->reported_metric
.reliability
);
1228 stream_putc(s
, pe
->reported_metric
.load
);
1229 stream_putc(s
, pe
->reported_metric
.tag
);
1230 stream_putc(s
, pe
->reported_metric
.flags
);
1232 stream_putc(s
, pe
->destination
->prefixlen
);
1234 stream_putc(s
, pe
->destination
->u
.prefix4
.s_addr
& 0xFF);
1235 if (pe
->destination
->prefixlen
> 8)
1236 stream_putc(s
, (pe
->destination
->u
.prefix4
.s_addr
>> 8) & 0xFF);
1237 if (pe
->destination
->prefixlen
> 16)
1239 (pe
->destination
->u
.prefix4
.s_addr
>> 16) & 0xFF);
1240 if (pe
->destination
->prefixlen
> 24)
1242 (pe
->destination
->u
.prefix4
.s_addr
>> 24) & 0xFF);
1247 uint16_t eigrp_add_authTLV_MD5_to_stream(struct stream
*s
,
1248 struct eigrp_interface
*ei
)
1251 struct keychain
*keychain
;
1252 struct TLV_MD5_Authentication_Type
*authTLV
;
1254 authTLV
= eigrp_authTLV_MD5_new();
1256 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1257 authTLV
->length
= htons(EIGRP_AUTH_MD5_TLV_SIZE
);
1258 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_MD5
);
1259 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_MD5_LEN
);
1260 authTLV
->key_sequence
= 0;
1261 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1263 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1265 key
= key_lookup_for_send(keychain
);
1267 free(ei
->params
.auth_keychain
);
1268 ei
->params
.auth_keychain
= NULL
;
1269 eigrp_authTLV_MD5_free(authTLV
);
1274 authTLV
->key_id
= htonl(key
->index
);
1275 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
1276 stream_put(s
, authTLV
,
1277 sizeof(struct TLV_MD5_Authentication_Type
));
1278 eigrp_authTLV_MD5_free(authTLV
);
1279 return EIGRP_AUTH_MD5_TLV_SIZE
;
1282 eigrp_authTLV_MD5_free(authTLV
);
1287 uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream
*s
,
1288 struct eigrp_interface
*ei
)
1291 struct keychain
*keychain
;
1292 struct TLV_SHA256_Authentication_Type
*authTLV
;
1294 authTLV
= eigrp_authTLV_SHA256_new();
1296 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1297 authTLV
->length
= htons(EIGRP_AUTH_SHA256_TLV_SIZE
);
1298 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_SHA256
);
1299 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_SHA256_LEN
);
1300 authTLV
->key_sequence
= 0;
1301 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1303 keychain
= keychain_lookup(ei
->params
.auth_keychain
);
1305 key
= key_lookup_for_send(keychain
);
1307 free(ei
->params
.auth_keychain
);
1308 ei
->params
.auth_keychain
= NULL
;
1309 eigrp_authTLV_SHA256_free(authTLV
);
1314 authTLV
->key_id
= 0;
1315 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_SHA256_LEN
);
1316 stream_put(s
, authTLV
,
1317 sizeof(struct TLV_SHA256_Authentication_Type
));
1318 eigrp_authTLV_SHA256_free(authTLV
);
1319 return EIGRP_AUTH_SHA256_TLV_SIZE
;
1322 eigrp_authTLV_SHA256_free(authTLV
);
1327 struct TLV_MD5_Authentication_Type
*eigrp_authTLV_MD5_new()
1329 struct TLV_MD5_Authentication_Type
*new;
1331 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV
,
1332 sizeof(struct TLV_MD5_Authentication_Type
));
1337 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type
*authTLV
)
1339 XFREE(MTYPE_EIGRP_AUTH_TLV
, authTLV
);
1342 struct TLV_SHA256_Authentication_Type
*eigrp_authTLV_SHA256_new()
1344 struct TLV_SHA256_Authentication_Type
*new;
1346 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV
,
1347 sizeof(struct TLV_SHA256_Authentication_Type
));
1352 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type
*authTLV
)
1354 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV
, authTLV
);
1357 void eigrp_IPv4_InternalTLV_free(
1358 struct TLV_IPv4_Internal_type
*IPv4_InternalTLV
)
1360 XFREE(MTYPE_EIGRP_IPV4_INT_TLV
, IPv4_InternalTLV
);
1363 struct TLV_Sequence_Type
*eigrp_SequenceTLV_new()
1365 struct TLV_Sequence_Type
*new;
1367 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV
, sizeof(struct TLV_Sequence_Type
));