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(IF_DEF_PARAMS(ei
->ifp
)->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
, u_char 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 (nbr
&& 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(IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_keychain
);
194 key
= key_lookup_for_send(keychain
);
196 memset(&ctx
, 0, sizeof(ctx
));
199 /* Generate a digest. Each situation needs different handling */
200 if (flags
& EIGRP_AUTH_BASIC_HELLO_FLAG
) {
201 MD5Update(&ctx
, ibuf
, EIGRP_MD5_BASIC_COMPUTE
);
202 MD5Update(&ctx
, key
->string
, strlen(key
->string
));
203 if (strlen(key
->string
) < 16)
204 MD5Update(&ctx
, zeropad
, 16 - strlen(key
->string
));
205 } else if (flags
& EIGRP_AUTH_UPDATE_INIT_FLAG
) {
206 MD5Update(&ctx
, ibuf
, EIGRP_MD5_UPDATE_INIT_COMPUTE
);
207 } else if (flags
& EIGRP_AUTH_UPDATE_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 if (backup_end
> (EIGRP_HEADER_LEN
+ EIGRP_AUTH_MD5_TLV_SIZE
)) {
214 ibuf
+ (EIGRP_HEADER_LEN
215 + EIGRP_AUTH_MD5_TLV_SIZE
),
218 + EIGRP_AUTH_MD5_TLV_SIZE
));
222 MD5Final(digest
, &ctx
);
224 /* compare the two */
225 if (memcmp(orig
, digest
, EIGRP_AUTH_TYPE_MD5_LEN
) != 0) {
226 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
231 /* save neighbor's crypt_seqnum */
233 nbr
->crypt_seqnum
= authTLV
->key_sequence
;
238 int eigrp_make_sha256_digest(struct eigrp_interface
*ei
, struct stream
*s
,
241 struct key
*key
= NULL
;
242 struct keychain
*keychain
;
245 unsigned char digest
[EIGRP_AUTH_TYPE_SHA256_LEN
];
246 unsigned char buffer
[1 + PLAINTEXT_LENGTH
+ 45 + 1] = {0};
249 size_t backup_get
, backup_end
;
250 struct TLV_SHA256_Authentication_Type
*auth_TLV
;
253 backup_end
= s
->endp
;
254 backup_get
= s
->getp
;
256 auth_TLV
= eigrp_authTLV_SHA256_new();
258 stream_set_getp(s
, EIGRP_HEADER_LEN
);
259 stream_get(auth_TLV
, s
, EIGRP_AUTH_SHA256_TLV_SIZE
);
260 stream_set_getp(s
, backup_get
);
262 keychain
= keychain_lookup(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
264 key
= key_lookup_for_send(keychain
);
266 // saved_len[index] = strnzcpyn(saved_key[index], key,
267 // PLAINTEXT_LENGTH + 1);
269 source_ip
= calloc(16, sizeof(char));
270 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
, source_ip
, 16);
272 memset(&ctx
, 0, sizeof(ctx
));
274 memcpy(buffer
+ 1, key
, strlen(key
->string
));
275 memcpy(buffer
+ 1 + strlen(key
->string
), source_ip
, strlen(source_ip
));
276 HMAC__SHA256_Init(&ctx
, buffer
,
277 1 + strlen(key
->string
) + strlen(source_ip
));
278 HMAC__SHA256_Update(&ctx
, ibuf
, strlen(ibuf
));
279 HMAC__SHA256_Final(digest
, &ctx
);
282 /* Put hmac-sha256 digest to it's place */
283 memcpy(auth_TLV
->digest
, digest
, EIGRP_AUTH_TYPE_SHA256_LEN
);
285 stream_set_endp(s
, EIGRP_HEADER_LEN
);
286 stream_put(s
, auth_TLV
, EIGRP_AUTH_SHA256_TLV_SIZE
);
287 stream_set_endp(s
, backup_end
);
289 eigrp_authTLV_SHA256_free(auth_TLV
);
292 return EIGRP_AUTH_TYPE_SHA256_LEN
;
295 int eigrp_check_sha256_digest(struct stream
*s
,
296 struct TLV_SHA256_Authentication_Type
*authTLV
,
297 struct eigrp_neighbor
*nbr
, u_char flags
)
305 * This routing dumps the contents of the IP packet either received or
308 static void eigrp_packet_dump(struct stream
*s
)
314 int eigrp_write(struct thread
*thread
)
316 struct eigrp
*eigrp
= THREAD_ARG(thread
);
317 struct eigrp_header
*eigrph
;
318 struct eigrp_interface
*ei
;
319 struct eigrp_packet
*ep
;
320 struct sockaddr_in sa_dst
;
324 u_int16_t opcode
= 0;
328 struct listnode
*node
;
329 #ifdef WANT_EIGRP_WRITE_FRAGMENT
330 static u_int16_t ipid
= 0;
331 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
333 /* clang-format off */
334 #define EIGRP_WRITE_IPHL_SHIFT 2
336 eigrp
->t_write
= NULL
;
338 node
= listhead(eigrp
->oi_write_q
);
340 ei
= listgetdata(node
);
343 #ifdef WANT_EIGRP_WRITE_FRAGMENT
344 /* seed ipid static with low order bits of time */
346 ipid
= (time(NULL
) & 0xffff);
347 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
349 /* Get one packet from queue. */
350 ep
= eigrp_fifo_head(ei
->obuf
);
352 assert(ep
->length
>= EIGRP_HEADER_LEN
);
354 if (ep
->dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
))
355 eigrp_if_ipmulticast(eigrp
, ei
->address
, ei
->ifp
->ifindex
);
357 memset(&iph
, 0, sizeof(struct ip
));
358 memset(&sa_dst
, 0, sizeof(sa_dst
));
360 sa_dst
.sin_family
= AF_INET
;
361 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
362 sa_dst
.sin_len
= sizeof(sa_dst
);
363 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
364 sa_dst
.sin_addr
= ep
->dst
;
365 sa_dst
.sin_port
= htons(0);
367 /* Set DONTROUTE flag if dst is unicast. */
368 if (!IN_MULTICAST(htonl(ep
->dst
.s_addr
)))
369 flags
= MSG_DONTROUTE
;
371 iph
.ip_hl
= sizeof(struct ip
) >> EIGRP_WRITE_IPHL_SHIFT
;
372 /* it'd be very strange for header to not be 4byte-word aligned but.. */
373 if (sizeof(struct ip
)
374 > (unsigned int)(iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
))
375 iph
.ip_hl
++; /* we presume sizeof struct ip cant overflow
378 iph
.ip_v
= IPVERSION
;
379 iph
.ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
380 iph
.ip_len
= (iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
) + ep
->length
;
382 #if defined(__DragonFly__)
384 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
386 iph
.ip_len
= htons(iph
.ip_len
);
390 iph
.ip_ttl
= EIGRP_IP_TTL
;
391 iph
.ip_p
= IPPROTO_EIGRPIGP
;
393 iph
.ip_src
.s_addr
= ei
->address
->u
.prefix4
.s_addr
;
394 iph
.ip_dst
.s_addr
= ep
->dst
.s_addr
;
396 memset(&msg
, 0, sizeof(msg
));
397 msg
.msg_name
= (caddr_t
)&sa_dst
;
398 msg
.msg_namelen
= sizeof(sa_dst
);
402 iov
[0].iov_base
= (char *)&iph
;
403 iov
[0].iov_len
= iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
;
404 iov
[1].iov_base
= STREAM_PNT(ep
->s
);
405 iov
[1].iov_len
= ep
->length
;
407 /* send final fragment (could be first) */
408 sockopt_iphdrincl_swab_htosys(&iph
);
409 ret
= sendmsg(eigrp
->fd
, &msg
, flags
);
410 sockopt_iphdrincl_swab_systoh(&iph
);
412 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)) {
413 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
414 opcode
= eigrph
->opcode
;
415 zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].",
416 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
417 inet_ntoa(ep
->dst
), IF_NAME(ei
), ret
);
422 "*** sendmsg in eigrp_write failed to %s, "
423 "id %d, off %d, len %d, interface %s, mtu %u: %s",
424 inet_ntoa(iph
.ip_dst
), iph
.ip_id
, iph
.ip_off
,
425 iph
.ip_len
, ei
->ifp
->name
, ei
->ifp
->mtu
,
426 safe_strerror(errno
));
428 /* Show debug sending packet. */
429 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)
430 && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))) {
432 "-----------------------------------------------------");
433 eigrp_ip_header_dump(&iph
);
434 stream_set_getp(ep
->s
, 0);
435 eigrp_packet_dump(ep
->s
);
437 "-----------------------------------------------------");
440 /* Now delete packet from queue. */
441 eigrp_packet_delete(ei
);
443 if (eigrp_fifo_head(ei
->obuf
) == NULL
) {
445 list_delete_node(eigrp
->oi_write_q
, node
);
448 /* If packets still remain in queue, call write thread. */
449 if (!list_isempty(eigrp
->oi_write_q
)) {
450 eigrp
->t_write
= NULL
;
451 thread_add_write(master
, eigrp_write
, eigrp
, eigrp
->fd
,
458 /* Starting point of packet process function. */
459 int eigrp_read(struct thread
*thread
)
464 struct eigrp_interface
*ei
;
466 struct eigrp_header
*eigrph
;
467 struct interface
*ifp
;
468 struct eigrp_neighbor
*nbr
;
470 u_int16_t opcode
= 0;
471 u_int16_t length
= 0;
473 /* first of all get interface pointer. */
474 eigrp
= THREAD_ARG(thread
);
476 /* prepare for next packet. */
477 eigrp
->t_read
= NULL
;
478 thread_add_read(master
, eigrp_read
, eigrp
, eigrp
->fd
, &eigrp
->t_read
);
480 stream_reset(eigrp
->ibuf
);
481 if (!(ibuf
= eigrp_recv_packet(eigrp
->fd
, &ifp
, eigrp
->ibuf
))) {
482 /* This raw packet is known to be at least as big as its IP
487 /* Note that there should not be alignment problems with this assignment
488 because this is at the beginning of the stream data buffer. */
489 iph
= (struct ip
*)STREAM_DATA(ibuf
);
491 // Substract IPv4 header size from EIGRP Packet itself
493 length
= (iph
->ip_len
) - 20U;
496 /* IP Header dump. */
497 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
498 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
499 eigrp_ip_header_dump(iph
);
501 /* Note that sockopt_iphdrincl_swab_systoh was called in
502 * eigrp_recv_packet. */
505 /* Handle cases where the platform does not support retrieving
507 and also platforms (such as Solaris 8) that claim to support
509 retrieval but do not. */
510 c
= if_lookup_address((void *)&iph
->ip_src
, AF_INET
,
519 /* associate packet with eigrp interface */
520 ei
= eigrp_if_lookup_recv_if(eigrp
, iph
->ip_src
, ifp
);
522 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
524 after the checks below are passed. These checks in turn access the
525 fields of unverified "eigrph" structure for their own purposes and
526 must remain very accurate in doing this.
531 /* Self-originated packet should be discarded silently. */
532 if (eigrp_if_lookup_by_local_addr(eigrp
, NULL
, iph
->ip_src
)
533 || (IPV4_ADDR_SAME(&iph
->ip_src
.s_addr
, &ei
->address
->u
.prefix4
))) {
534 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
536 "eigrp_read[%s]: Dropping self-originated packet",
537 inet_ntoa(iph
->ip_src
));
541 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
542 by eigrp_recv_packet() to be correct). */
544 stream_forward_getp(ibuf
, (iph
->ip_hl
* 4));
545 eigrph
= (struct eigrp_header
*)STREAM_PNT(ibuf
);
547 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
548 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
549 eigrp_header_dump(eigrph
);
551 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
552 // stream_get_getp(ibuf)))
555 /* Now it is safe to access all fields of EIGRP packet header. */
556 /* associate packet with eigrp interface */
557 ei
= eigrp_if_lookup_recv_if(eigrp
, iph
->ip_src
, ifp
);
559 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
561 after the checks below are passed. These checks in turn access the
562 fields of unverified "eigrph" structure for their own purposes and
563 must remain very accurate in doing this.
568 /* If incoming interface is passive one, ignore it. */
569 if (ei
&& EIGRP_IF_PASSIVE_STATUS(ei
) == EIGRP_IF_PASSIVE
) {
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 /* Try to fix multicast membership.
585 * Some OS:es may have problems in this area,
586 * make sure it is removed.
588 EI_MEMBER_JOINED(ei
, MEMBER_ALLROUTERS
);
589 eigrp_if_set_multicast(ei
);
594 /* else it must be a local eigrp interface, check it was received on
597 else if (ei
->ifp
!= ifp
) {
598 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
599 zlog_warn("Packet from [%s] received on wrong link %s",
600 inet_ntoa(iph
->ip_src
), ifp
->name
);
604 /* Verify more EIGRP header fields. */
605 ret
= eigrp_verify_header(ibuf
, ei
, iph
, eigrph
);
607 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
609 "eigrp_read[%s]: Header check failed, dropping.",
610 inet_ntoa(iph
->ip_src
));
614 /* calcualte the eigrp packet length, and move the pounter to the
615 start of the eigrp TLVs */
616 opcode
= eigrph
->opcode
;
618 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
620 "Received [%s] length [%u] via [%s] src [%s] dst [%s]",
621 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
), length
,
622 IF_NAME(ei
), inet_ntoa(iph
->ip_src
),
623 inet_ntoa(iph
->ip_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 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
632 /* neighbor must be valid, eigrp_nbr_get creates if none existed
636 struct eigrp_packet
*ep
;
638 ep
= eigrp_fifo_tail(nbr
->retrans_queue
);
640 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
641 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
642 && (ntohl(eigrph
->ack
)
643 == nbr
->init_sequence_number
)) {
644 eigrp_nbr_state_set(nbr
,
647 "Neighbor adjacency became full");
648 nbr
->init_sequence_number
= 0;
649 nbr
->recv_sequence_number
=
650 ntohl(eigrph
->sequence
);
651 eigrp_update_send_EOT(nbr
);
653 ep
= eigrp_fifo_pop_tail(nbr
->retrans_queue
);
654 eigrp_packet_free(ep
);
655 if (nbr
->retrans_queue
->count
> 0) {
656 eigrp_send_packet_reliably(nbr
);
660 ep
= eigrp_fifo_tail(nbr
->multicast_queue
);
662 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
663 ep
= eigrp_fifo_pop_tail(nbr
->multicast_queue
);
664 eigrp_packet_free(ep
);
665 if (nbr
->multicast_queue
->count
> 0) {
666 eigrp_send_packet_reliably(nbr
);
674 case EIGRP_OPC_HELLO
:
675 eigrp_hello_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
677 case EIGRP_OPC_PROBE
:
678 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
681 case EIGRP_OPC_QUERY
:
682 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
684 case EIGRP_OPC_REPLY
:
685 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
687 case EIGRP_OPC_REQUEST
:
688 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
691 case EIGRP_OPC_SIAQUERY
:
692 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
694 case EIGRP_OPC_SIAREPLY
:
695 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
697 case EIGRP_OPC_UPDATE
:
698 eigrp_update_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
702 "interface %s: EIGRP packet header type %d unsupported",
703 IF_NAME(ei
), opcode
);
710 static struct stream
*eigrp_recv_packet(int fd
, struct interface
**ifp
,
716 unsigned int ifindex
= 0;
718 /* Header and data both require alignment. */
719 char buff
[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
722 memset(&msgh
, 0, sizeof(struct msghdr
));
725 msgh
.msg_control
= (caddr_t
)buff
;
726 msgh
.msg_controllen
= sizeof(buff
);
728 ret
= stream_recvmsg(ibuf
, fd
, &msgh
, 0, (EIGRP_PACKET_MAX_LEN
+ 1));
730 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno
));
733 if ((unsigned int)ret
< sizeof(iph
)) /* ret must be > 0 now */
736 "eigrp_recv_packet: discarding runt packet of length %d "
737 "(ip header size is %u)",
738 ret
, (u_int
)sizeof(iph
));
742 /* Note that there should not be alignment problems with this assignment
743 because this is at the beginning of the stream data buffer. */
744 iph
= (struct ip
*)STREAM_DATA(ibuf
);
745 sockopt_iphdrincl_swab_systoh(iph
);
747 ip_len
= iph
->ip_len
;
749 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
751 * Kernel network code touches incoming IP header parameters,
752 * before protocol specific processing.
754 * 1) Convert byteorder to host representation.
755 * --> ip_len, ip_id, ip_off
757 * 2) Adjust ip_len to strip IP header size!
758 * --> If user process receives entire IP packet via RAW
759 * socket, it must consider adding IP header size to
760 * the "ip_len" field of "ip" structure.
762 * For more details, see <netinet/ip_input.c>.
764 ip_len
= ip_len
+ (iph
->ip_hl
<< 2);
767 #if defined(__DragonFly__)
769 * in DragonFly's raw socket, ip_len/ip_off are read
770 * in network byte order.
771 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
773 ip_len
= ntohs(iph
->ip_len
) + (iph
->ip_hl
<< 2);
776 ifindex
= getsockopt_ifindex(AF_INET
, &msgh
);
778 *ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
782 "eigrp_recv_packet read length mismatch: ip_len is %d, "
783 "but recvmsg returned %d",
791 struct eigrp_fifo
*eigrp_fifo_new(void)
793 struct eigrp_fifo
*new;
795 new = XCALLOC(MTYPE_EIGRP_FIFO
, sizeof(struct eigrp_fifo
));
799 /* Free eigrp packet fifo. */
800 void eigrp_fifo_free(struct eigrp_fifo
*fifo
)
802 struct eigrp_packet
*ep
;
803 struct eigrp_packet
*next
;
805 for (ep
= fifo
->head
; ep
; ep
= next
) {
807 eigrp_packet_free(ep
);
809 fifo
->head
= fifo
->tail
= NULL
;
812 XFREE(MTYPE_EIGRP_FIFO
, fifo
);
815 /* Free eigrp fifo entries without destroying fifo itself*/
816 void eigrp_fifo_reset(struct eigrp_fifo
*fifo
)
818 struct eigrp_packet
*ep
;
819 struct eigrp_packet
*next
;
821 for (ep
= fifo
->head
; ep
; ep
= next
) {
823 eigrp_packet_free(ep
);
825 fifo
->head
= fifo
->tail
= NULL
;
829 struct eigrp_packet
*eigrp_packet_new(size_t size
)
831 struct eigrp_packet
*new;
833 new = XCALLOC(MTYPE_EIGRP_PACKET
, sizeof(struct eigrp_packet
));
834 new->s
= stream_new(size
);
835 new->retrans_counter
= 0;
840 void eigrp_send_packet_reliably(struct eigrp_neighbor
*nbr
)
842 struct eigrp_packet
*ep
;
844 ep
= eigrp_fifo_tail(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_head(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_interface
*ei
,
884 struct stream
*s
, u_int32_t flags
,
885 u_int32_t sequence
, u_int32_t ack
)
887 struct eigrp_header
*eigrph
;
890 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
892 eigrph
->version
= (u_char
)EIGRP_HEADER_VERSION
;
893 eigrph
->opcode
= (u_char
)type
;
894 eigrph
->checksum
= 0;
896 eigrph
->vrid
= htons(ei
->eigrp
->vrid
);
897 eigrph
->ASNumber
= htons(ei
->eigrp
->AS
);
898 eigrph
->ack
= htonl(ack
);
899 eigrph
->sequence
= htonl(sequence
);
900 // if(flags == EIGRP_INIT_FLAG)
901 // eigrph->sequence = htonl(3);
902 eigrph
->flags
= htonl(flags
);
904 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
905 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
906 htonl(eigrph
->sequence
), htonl(eigrph
->ack
));
908 stream_forward_endp(s
, EIGRP_HEADER_LEN
);
911 /* Add new packet to head of fifo. */
912 void eigrp_fifo_push_head(struct eigrp_fifo
*fifo
, struct eigrp_packet
*ep
)
914 ep
->next
= fifo
->head
;
917 if (fifo
->tail
== NULL
)
920 if (fifo
->count
!= 0)
921 fifo
->head
->previous
= ep
;
928 /* Return first fifo entry. */
929 struct eigrp_packet
*eigrp_fifo_head(struct eigrp_fifo
*fifo
)
934 /* Return last fifo entry. */
935 struct eigrp_packet
*eigrp_fifo_tail(struct eigrp_fifo
*fifo
)
940 void eigrp_packet_delete(struct eigrp_interface
*ei
)
942 struct eigrp_packet
*ep
;
944 ep
= eigrp_fifo_pop(ei
->obuf
);
947 eigrp_packet_free(ep
);
950 /* Delete first packet from fifo. */
951 struct eigrp_packet
*eigrp_fifo_pop(struct eigrp_fifo
*fifo
)
953 struct eigrp_packet
*ep
;
958 fifo
->head
= ep
->next
;
960 if (fifo
->head
== NULL
)
963 fifo
->head
->previous
= NULL
;
971 void eigrp_packet_free(struct eigrp_packet
*ep
)
976 THREAD_OFF(ep
->t_retrans_timer
);
978 XFREE(MTYPE_EIGRP_PACKET
, ep
);
983 /* EIGRP Header verification. */
984 static int eigrp_verify_header(struct stream
*ibuf
, struct eigrp_interface
*ei
,
985 struct ip
*iph
, struct eigrp_header
*eigrph
)
987 /* Check network mask, Silently discarded. */
988 if (!eigrp_check_network_mask(ei
, iph
->ip_src
)) {
990 "interface %s: eigrp_read network address is not same [%s]",
991 IF_NAME(ei
), inet_ntoa(iph
->ip_src
));
995 // /* Check authentication. The function handles logging actions, where
997 // if (! eigrp_check_auth(ei, eigrph))
1003 /* Unbound socket will accept any Raw IP packets if proto is matched.
1004 To prevent it, compare src IP address and i/f address with masking
1005 i/f network mask. */
1006 static int eigrp_check_network_mask(struct eigrp_interface
*ei
,
1007 struct in_addr ip_src
)
1009 struct in_addr mask
, me
, him
;
1011 if (ei
->type
== EIGRP_IFTYPE_POINTOPOINT
)
1014 masklen2ip(ei
->address
->prefixlen
, &mask
);
1016 me
.s_addr
= ei
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
1017 him
.s_addr
= ip_src
.s_addr
& mask
.s_addr
;
1019 if (IPV4_ADDR_SAME(&me
, &him
))
1025 int eigrp_unack_packet_retrans(struct thread
*thread
)
1027 struct eigrp_neighbor
*nbr
;
1028 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1030 struct eigrp_packet
*ep
;
1031 ep
= eigrp_fifo_tail(nbr
->retrans_queue
);
1034 struct eigrp_packet
*duplicate
;
1035 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1037 /* Add packet to the top of the interface output queue*/
1038 eigrp_fifo_push_head(nbr
->ei
->obuf
, duplicate
);
1040 ep
->retrans_counter
++;
1041 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1042 return eigrp_retrans_count_exceeded(ep
, nbr
);
1044 /*Start retransmission timer*/
1045 ep
->t_retrans_timer
= NULL
;
1046 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
1047 EIGRP_PACKET_RETRANS_TIME
,
1048 &ep
->t_retrans_timer
);
1050 /* Hook thread to write packet. */
1051 if (nbr
->ei
->on_write_q
== 0) {
1052 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1053 nbr
->ei
->on_write_q
= 1;
1055 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1056 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1062 int eigrp_unack_multicast_packet_retrans(struct thread
*thread
)
1064 struct eigrp_neighbor
*nbr
;
1065 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1067 struct eigrp_packet
*ep
;
1068 ep
= eigrp_fifo_tail(nbr
->multicast_queue
);
1071 struct eigrp_packet
*duplicate
;
1072 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1073 /* Add packet to the top of the interface output queue*/
1074 eigrp_fifo_push_head(nbr
->ei
->obuf
, duplicate
);
1076 ep
->retrans_counter
++;
1077 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1078 return eigrp_retrans_count_exceeded(ep
, nbr
);
1080 /*Start retransmission timer*/
1081 ep
->t_retrans_timer
= NULL
;
1082 thread_add_timer(master
, eigrp_unack_multicast_packet_retrans
,
1083 nbr
, EIGRP_PACKET_RETRANS_TIME
,
1084 &ep
->t_retrans_timer
);
1086 /* Hook thread to write packet. */
1087 if (nbr
->ei
->on_write_q
== 0) {
1088 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1089 nbr
->ei
->on_write_q
= 1;
1091 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1092 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1098 /* Get packet from tail of fifo. */
1099 struct eigrp_packet
*eigrp_fifo_pop_tail(struct eigrp_fifo
*fifo
)
1101 struct eigrp_packet
*ep
;
1106 fifo
->tail
= ep
->previous
;
1108 if (fifo
->tail
== NULL
)
1111 fifo
->tail
->next
= NULL
;
1119 struct eigrp_packet
*eigrp_packet_duplicate(struct eigrp_packet
*old
,
1120 struct eigrp_neighbor
*nbr
)
1122 struct eigrp_packet
*new;
1124 new = eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
1125 new->length
= old
->length
;
1126 new->retrans_counter
= old
->retrans_counter
;
1127 new->dst
= old
->dst
;
1128 new->sequence_number
= old
->sequence_number
;
1129 stream_copy(new->s
, old
->s
);
1134 struct TLV_IPv4_Internal_type
*eigrp_read_ipv4_tlv(struct stream
*s
)
1136 struct TLV_IPv4_Internal_type
*tlv
;
1138 tlv
= eigrp_IPv4_InternalTLV_new();
1140 tlv
->type
= stream_getw(s
);
1141 tlv
->length
= stream_getw(s
);
1142 tlv
->forward
.s_addr
= stream_getl(s
);
1143 tlv
->metric
.delay
= stream_getl(s
);
1144 tlv
->metric
.bandwidth
= stream_getl(s
);
1145 tlv
->metric
.mtu
[0] = stream_getc(s
);
1146 tlv
->metric
.mtu
[1] = stream_getc(s
);
1147 tlv
->metric
.mtu
[2] = stream_getc(s
);
1148 tlv
->metric
.hop_count
= stream_getc(s
);
1149 tlv
->metric
.reliability
= stream_getc(s
);
1150 tlv
->metric
.load
= stream_getc(s
);
1151 tlv
->metric
.tag
= stream_getc(s
);
1152 tlv
->metric
.flags
= stream_getc(s
);
1154 tlv
->prefix_length
= stream_getc(s
);
1156 if (tlv
->prefix_length
<= 8) {
1157 tlv
->destination_part
[0] = stream_getc(s
);
1158 tlv
->destination
.s_addr
= (tlv
->destination_part
[0]);
1159 } else if (tlv
->prefix_length
> 8 && tlv
->prefix_length
<= 16) {
1160 tlv
->destination_part
[0] = stream_getc(s
);
1161 tlv
->destination_part
[1] = stream_getc(s
);
1162 tlv
->destination
.s_addr
= ((tlv
->destination_part
[1] << 8)
1163 + tlv
->destination_part
[0]);
1164 } else if (tlv
->prefix_length
> 16 && tlv
->prefix_length
<= 24) {
1165 tlv
->destination_part
[0] = stream_getc(s
);
1166 tlv
->destination_part
[1] = stream_getc(s
);
1167 tlv
->destination_part
[2] = stream_getc(s
);
1168 tlv
->destination
.s_addr
= ((tlv
->destination_part
[2] << 16)
1169 + (tlv
->destination_part
[1] << 8)
1170 + tlv
->destination_part
[0]);
1171 } else if (tlv
->prefix_length
> 24 && tlv
->prefix_length
<= 32) {
1172 tlv
->destination_part
[0] = stream_getc(s
);
1173 tlv
->destination_part
[1] = stream_getc(s
);
1174 tlv
->destination_part
[2] = stream_getc(s
);
1175 tlv
->destination_part
[3] = stream_getc(s
);
1176 tlv
->destination
.s_addr
= ((tlv
->destination_part
[3] << 24)
1177 + (tlv
->destination_part
[2] << 16)
1178 + (tlv
->destination_part
[1] << 8)
1179 + tlv
->destination_part
[0]);
1184 u_int16_t
eigrp_add_internalTLV_to_stream(struct stream
*s
,
1185 struct eigrp_prefix_entry
*pe
)
1189 stream_putw(s
, EIGRP_TLV_IPv4_INT
);
1190 if (pe
->destination_ipv4
->prefixlen
<= 8) {
1191 stream_putw(s
, 0x001A);
1194 if ((pe
->destination_ipv4
->prefixlen
> 8)
1195 && (pe
->destination_ipv4
->prefixlen
<= 16)) {
1196 stream_putw(s
, 0x001B);
1199 if ((pe
->destination_ipv4
->prefixlen
> 16)
1200 && (pe
->destination_ipv4
->prefixlen
<= 24)) {
1201 stream_putw(s
, 0x001C);
1204 if (pe
->destination_ipv4
->prefixlen
> 24) {
1205 stream_putw(s
, 0x001D);
1209 stream_putl(s
, 0x00000000);
1212 stream_putl(s
, pe
->reported_metric
.delay
);
1213 stream_putl(s
, pe
->reported_metric
.bandwidth
);
1214 stream_putc(s
, pe
->reported_metric
.mtu
[2]);
1215 stream_putc(s
, pe
->reported_metric
.mtu
[1]);
1216 stream_putc(s
, pe
->reported_metric
.mtu
[0]);
1217 stream_putc(s
, pe
->reported_metric
.hop_count
);
1218 stream_putc(s
, pe
->reported_metric
.reliability
);
1219 stream_putc(s
, pe
->reported_metric
.load
);
1220 stream_putc(s
, pe
->reported_metric
.tag
);
1221 stream_putc(s
, pe
->reported_metric
.flags
);
1223 stream_putc(s
, pe
->destination_ipv4
->prefixlen
);
1225 if (pe
->destination_ipv4
->prefixlen
<= 8) {
1226 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1228 if ((pe
->destination_ipv4
->prefixlen
> 8)
1229 && (pe
->destination_ipv4
->prefixlen
<= 16)) {
1230 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1232 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1234 if ((pe
->destination_ipv4
->prefixlen
> 16)
1235 && (pe
->destination_ipv4
->prefixlen
<= 24)) {
1236 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1238 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1240 (pe
->destination_ipv4
->prefix
.s_addr
>> 16) & 0xFF);
1242 if (pe
->destination_ipv4
->prefixlen
> 24) {
1243 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1245 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1247 (pe
->destination_ipv4
->prefix
.s_addr
>> 16) & 0xFF);
1249 (pe
->destination_ipv4
->prefix
.s_addr
>> 24) & 0xFF);
1255 u_int16_t
eigrp_add_authTLV_MD5_to_stream(struct stream
*s
,
1256 struct eigrp_interface
*ei
)
1259 struct keychain
*keychain
;
1260 struct TLV_MD5_Authentication_Type
*authTLV
;
1262 authTLV
= eigrp_authTLV_MD5_new();
1264 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1265 authTLV
->length
= htons(EIGRP_AUTH_MD5_TLV_SIZE
);
1266 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_MD5
);
1267 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_MD5_LEN
);
1268 authTLV
->key_sequence
= 0;
1269 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1271 keychain
= keychain_lookup(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1273 key
= key_lookup_for_send(keychain
);
1275 free(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1276 IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
= NULL
;
1277 eigrp_authTLV_MD5_free(authTLV
);
1282 authTLV
->key_id
= htonl(key
->index
);
1283 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
1284 stream_put(s
, authTLV
,
1285 sizeof(struct TLV_MD5_Authentication_Type
));
1286 eigrp_authTLV_MD5_free(authTLV
);
1287 return EIGRP_AUTH_MD5_TLV_SIZE
;
1290 eigrp_authTLV_MD5_free(authTLV
);
1295 u_int16_t
eigrp_add_authTLV_SHA256_to_stream(struct stream
*s
,
1296 struct eigrp_interface
*ei
)
1299 struct keychain
*keychain
;
1300 struct TLV_SHA256_Authentication_Type
*authTLV
;
1302 authTLV
= eigrp_authTLV_SHA256_new();
1304 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1305 authTLV
->length
= htons(EIGRP_AUTH_SHA256_TLV_SIZE
);
1306 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_SHA256
);
1307 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_SHA256_LEN
);
1308 authTLV
->key_sequence
= 0;
1309 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1311 keychain
= keychain_lookup(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1313 key
= key_lookup_for_send(keychain
);
1315 free(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1316 IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
= NULL
;
1317 eigrp_authTLV_SHA256_free(authTLV
);
1322 authTLV
->key_id
= 0;
1323 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_SHA256_LEN
);
1324 stream_put(s
, authTLV
,
1325 sizeof(struct TLV_SHA256_Authentication_Type
));
1326 eigrp_authTLV_SHA256_free(authTLV
);
1327 return EIGRP_AUTH_SHA256_TLV_SIZE
;
1330 eigrp_authTLV_SHA256_free(authTLV
);
1335 struct TLV_MD5_Authentication_Type
*eigrp_authTLV_MD5_new()
1337 struct TLV_MD5_Authentication_Type
*new;
1339 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV
,
1340 sizeof(struct TLV_MD5_Authentication_Type
));
1345 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type
*authTLV
)
1347 XFREE(MTYPE_EIGRP_AUTH_TLV
, authTLV
);
1350 struct TLV_SHA256_Authentication_Type
*eigrp_authTLV_SHA256_new()
1352 struct TLV_SHA256_Authentication_Type
*new;
1354 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV
,
1355 sizeof(struct TLV_SHA256_Authentication_Type
));
1360 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type
*authTLV
)
1362 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV
, authTLV
);
1365 struct TLV_IPv4_Internal_type
*eigrp_IPv4_InternalTLV_new()
1367 struct TLV_IPv4_Internal_type
*new;
1369 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV
,
1370 sizeof(struct TLV_IPv4_Internal_type
));
1375 void eigrp_IPv4_InternalTLV_free(
1376 struct TLV_IPv4_Internal_type
*IPv4_InternalTLV
)
1378 XFREE(MTYPE_EIGRP_IPV4_INT_TLV
, IPv4_InternalTLV
);
1381 struct TLV_Sequence_Type
*eigrp_SequenceTLV_new()
1383 struct TLV_Sequence_Type
*new;
1385 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV
, sizeof(struct TLV_Sequence_Type
));