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
)
302 int eigrp_write(struct thread
*thread
)
304 struct eigrp
*eigrp
= THREAD_ARG(thread
);
305 struct eigrp_header
*eigrph
;
306 struct eigrp_interface
*ei
;
307 struct eigrp_packet
*ep
;
308 struct sockaddr_in sa_dst
;
312 u_int16_t opcode
= 0;
313 u_int32_t seqno
, ack
;
317 struct listnode
*node
;
318 #ifdef WANT_EIGRP_WRITE_FRAGMENT
319 static u_int16_t ipid
= 0;
320 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
322 /* clang-format off */
323 #define EIGRP_WRITE_IPHL_SHIFT 2
325 eigrp
->t_write
= NULL
;
327 node
= listhead(eigrp
->oi_write_q
);
329 ei
= listgetdata(node
);
332 #ifdef WANT_EIGRP_WRITE_FRAGMENT
333 /* seed ipid static with low order bits of time */
335 ipid
= (time(NULL
) & 0xffff);
336 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
338 /* Get one packet from queue. */
339 ep
= eigrp_fifo_next(ei
->obuf
);
341 assert(ep
->length
>= EIGRP_HEADER_LEN
);
343 if (ep
->dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
))
344 eigrp_if_ipmulticast(eigrp
, ei
->address
, ei
->ifp
->ifindex
);
346 memset(&iph
, 0, sizeof(struct ip
));
347 memset(&sa_dst
, 0, sizeof(sa_dst
));
350 * We build and schedule packets to go out
351 * in the future. In the mean time we may
352 * process some update packets from the
353 * neighbor, thus making it necessary
354 * to update the ack we are using for
355 * this outgoing packet.
357 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
358 opcode
= eigrph
->opcode
;
359 seqno
= ntohl(eigrph
->sequence
);
360 ack
= ntohl(eigrph
->ack
);
361 if (ep
->nbr
&& (ack
!= ep
->nbr
->recv_sequence_number
)) {
362 eigrph
->ack
= htonl(ep
->nbr
->recv_sequence_number
);
363 ack
= ep
->nbr
->recv_sequence_number
;
364 eigrph
->checksum
= 0;
365 eigrp_packet_checksum(ei
, ep
->s
, ep
->length
);
368 sa_dst
.sin_family
= AF_INET
;
369 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
370 sa_dst
.sin_len
= sizeof(sa_dst
);
371 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
372 sa_dst
.sin_addr
= ep
->dst
;
373 sa_dst
.sin_port
= htons(0);
375 /* Set DONTROUTE flag if dst is unicast. */
376 if (!IN_MULTICAST(htonl(ep
->dst
.s_addr
)))
377 flags
= MSG_DONTROUTE
;
379 iph
.ip_hl
= sizeof(struct ip
) >> EIGRP_WRITE_IPHL_SHIFT
;
380 /* it'd be very strange for header to not be 4byte-word aligned but.. */
381 if (sizeof(struct ip
)
382 > (unsigned int)(iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
))
383 iph
.ip_hl
++; /* we presume sizeof struct ip cant overflow
386 iph
.ip_v
= IPVERSION
;
387 iph
.ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
388 iph
.ip_len
= (iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
) + ep
->length
;
390 #if defined(__DragonFly__)
392 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
394 iph
.ip_len
= htons(iph
.ip_len
);
398 iph
.ip_ttl
= EIGRP_IP_TTL
;
399 iph
.ip_p
= IPPROTO_EIGRPIGP
;
401 iph
.ip_src
.s_addr
= ei
->address
->u
.prefix4
.s_addr
;
402 iph
.ip_dst
.s_addr
= ep
->dst
.s_addr
;
404 memset(&msg
, 0, sizeof(msg
));
405 msg
.msg_name
= (caddr_t
)&sa_dst
;
406 msg
.msg_namelen
= sizeof(sa_dst
);
410 iov
[0].iov_base
= (char *)&iph
;
411 iov
[0].iov_len
= iph
.ip_hl
<< EIGRP_WRITE_IPHL_SHIFT
;
412 iov
[1].iov_base
= STREAM_PNT(ep
->s
);
413 iov
[1].iov_len
= ep
->length
;
415 /* send final fragment (could be first) */
416 sockopt_iphdrincl_swab_htosys(&iph
);
417 ret
= sendmsg(eigrp
->fd
, &msg
, flags
);
418 sockopt_iphdrincl_swab_systoh(&iph
);
420 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND
)) {
421 eigrph
= (struct eigrp_header
*)STREAM_DATA(ep
->s
);
422 opcode
= eigrph
->opcode
;
423 zlog_debug("Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
424 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
426 inet_ntoa(ep
->dst
), IF_NAME(ei
), ret
);
431 "*** sendmsg in eigrp_write failed to %s, "
432 "id %d, off %d, len %d, interface %s, mtu %u: %s",
433 inet_ntoa(iph
.ip_dst
), iph
.ip_id
, iph
.ip_off
,
434 iph
.ip_len
, ei
->ifp
->name
, ei
->ifp
->mtu
,
435 safe_strerror(errno
));
437 /* Now delete packet from queue. */
438 eigrp_packet_delete(ei
);
440 if (eigrp_fifo_next(ei
->obuf
) == NULL
) {
442 list_delete_node(eigrp
->oi_write_q
, node
);
445 /* If packets still remain in queue, call write thread. */
446 if (!list_isempty(eigrp
->oi_write_q
)) {
447 eigrp
->t_write
= NULL
;
448 thread_add_write(master
, eigrp_write
, eigrp
, eigrp
->fd
,
455 /* Starting point of packet process function. */
456 int eigrp_read(struct thread
*thread
)
461 struct eigrp_interface
*ei
;
463 struct eigrp_header
*eigrph
;
464 struct interface
*ifp
;
465 struct eigrp_neighbor
*nbr
;
467 u_int16_t opcode
= 0;
468 u_int16_t length
= 0;
470 /* first of all get interface pointer. */
471 eigrp
= THREAD_ARG(thread
);
473 /* prepare for next packet. */
474 eigrp
->t_read
= NULL
;
475 thread_add_read(master
, eigrp_read
, eigrp
, eigrp
->fd
, &eigrp
->t_read
);
477 stream_reset(eigrp
->ibuf
);
478 if (!(ibuf
= eigrp_recv_packet(eigrp
->fd
, &ifp
, eigrp
->ibuf
))) {
479 /* This raw packet is known to be at least as big as its IP
484 /* Note that there should not be alignment problems with this assignment
485 because this is at the beginning of the stream data buffer. */
486 iph
= (struct ip
*)STREAM_DATA(ibuf
);
488 // Substract IPv4 header size from EIGRP Packet itself
490 length
= (iph
->ip_len
) - 20U;
493 /* IP Header dump. */
494 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
495 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
496 eigrp_ip_header_dump(iph
);
498 /* Note that sockopt_iphdrincl_swab_systoh was called in
499 * eigrp_recv_packet. */
502 /* Handle cases where the platform does not support retrieving
504 and also platforms (such as Solaris 8) that claim to support
506 retrieval but do not. */
507 c
= if_lookup_address((void *)&iph
->ip_src
, AF_INET
,
516 /* associate packet with eigrp interface */
517 ei
= eigrp_if_lookup_recv_if(eigrp
, iph
->ip_src
, ifp
);
519 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
521 after the checks below are passed. These checks in turn access the
522 fields of unverified "eigrph" structure for their own purposes and
523 must remain very accurate in doing this.
528 /* Self-originated packet should be discarded silently. */
529 if (eigrp_if_lookup_by_local_addr(eigrp
, NULL
, iph
->ip_src
)
530 || (IPV4_ADDR_SAME(&iph
->ip_src
.s_addr
, &ei
->address
->u
.prefix4
))) {
531 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
533 "eigrp_read[%s]: Dropping self-originated packet",
534 inet_ntoa(iph
->ip_src
));
538 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
539 by eigrp_recv_packet() to be correct). */
541 stream_forward_getp(ibuf
, (iph
->ip_hl
* 4));
542 eigrph
= (struct eigrp_header
*)STREAM_PNT(ibuf
);
544 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)
545 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
546 eigrp_header_dump(eigrph
);
548 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
549 // stream_get_getp(ibuf)))
552 /* Now it is safe to access all fields of EIGRP packet header. */
553 /* associate packet with eigrp interface */
554 ei
= eigrp_if_lookup_recv_if(eigrp
, iph
->ip_src
, ifp
);
556 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
558 after the checks below are passed. These checks in turn access the
559 fields of unverified "eigrph" structure for their own purposes and
560 must remain very accurate in doing this.
565 /* If incoming interface is passive one, ignore it. */
566 if (ei
&& EIGRP_IF_PASSIVE_STATUS(ei
) == EIGRP_IF_PASSIVE
) {
567 char buf
[3][INET_ADDRSTRLEN
];
569 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
571 "ignoring packet from router %s sent to %s, "
572 "received on a passive interface, %s",
573 inet_ntop(AF_INET
, &eigrph
->vrid
, buf
[0],
575 inet_ntop(AF_INET
, &iph
->ip_dst
, buf
[1],
577 inet_ntop(AF_INET
, &ei
->address
->u
.prefix4
,
578 buf
[2], sizeof(buf
[2])));
580 if (iph
->ip_dst
.s_addr
== htonl(EIGRP_MULTICAST_ADDRESS
)) {
581 /* Try to fix multicast membership.
582 * Some OS:es may have problems in this area,
583 * make sure it is removed.
585 EI_MEMBER_JOINED(ei
, MEMBER_ALLROUTERS
);
586 eigrp_if_set_multicast(ei
);
591 /* else it must be a local eigrp interface, check it was received on
594 else if (ei
->ifp
!= ifp
) {
595 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
596 zlog_warn("Packet from [%s] received on wrong link %s",
597 inet_ntoa(iph
->ip_src
), ifp
->name
);
601 /* Verify more EIGRP header fields. */
602 ret
= eigrp_verify_header(ibuf
, ei
, iph
, eigrph
);
604 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
))
606 "eigrp_read[%s]: Header check failed, dropping.",
607 inet_ntoa(iph
->ip_src
));
611 /* calcualte the eigrp packet length, and move the pounter to the
612 start of the eigrp TLVs */
613 opcode
= eigrph
->opcode
;
615 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV
)) {
616 char src
[100], dst
[100];
618 strcpy(src
, inet_ntoa(iph
->ip_src
));
619 strcpy(dst
, inet_ntoa(iph
->ip_dst
));
620 zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
621 lookup_msg(eigrp_packet_type_str
, opcode
, NULL
),
622 ntohl(eigrph
->sequence
), ntohl(eigrph
->ack
), length
,
623 IF_NAME(ei
), src
, dst
);
626 /* Read rest of the packet and call each sort of packet routine. */
627 stream_forward_getp(ibuf
, EIGRP_HEADER_LEN
);
629 /* New testing block of code for handling Acks */
630 if (ntohl(eigrph
->ack
) != 0) {
631 struct eigrp_packet
*ep
= NULL
;
633 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
635 // neighbor must be valid, eigrp_nbr_get creates if none existed
638 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
639 if ((ep
) && (ntohl(eigrph
->ack
) == ep
->sequence_number
)) {
640 ep
= eigrp_fifo_pop(nbr
->retrans_queue
);
641 eigrp_packet_free(ep
);
643 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
644 && (ntohl(eigrph
->ack
) == 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
);
654 eigrp_send_packet_reliably(nbr
);
656 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
658 if (ntohl(eigrph
->ack
) == ep
->sequence_number
) {
659 ep
= eigrp_fifo_pop(nbr
->multicast_queue
);
660 eigrp_packet_free(ep
);
661 if (nbr
->multicast_queue
->count
> 0) {
662 eigrp_send_packet_reliably(nbr
);
670 case EIGRP_OPC_HELLO
:
671 eigrp_hello_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
673 case EIGRP_OPC_PROBE
:
674 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
677 case EIGRP_OPC_QUERY
:
678 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
680 case EIGRP_OPC_REPLY
:
681 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
683 case EIGRP_OPC_REQUEST
:
684 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
687 case EIGRP_OPC_SIAQUERY
:
688 eigrp_query_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
690 case EIGRP_OPC_SIAREPLY
:
691 eigrp_reply_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
693 case EIGRP_OPC_UPDATE
:
694 eigrp_update_receive(eigrp
, iph
, eigrph
, ibuf
, ei
, length
);
698 "interface %s: EIGRP packet header type %d unsupported",
699 IF_NAME(ei
), opcode
);
706 static struct stream
*eigrp_recv_packet(int fd
, struct interface
**ifp
,
712 unsigned int ifindex
= 0;
714 /* Header and data both require alignment. */
715 char buff
[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
718 memset(&msgh
, 0, sizeof(struct msghdr
));
721 msgh
.msg_control
= (caddr_t
)buff
;
722 msgh
.msg_controllen
= sizeof(buff
);
724 ret
= stream_recvmsg(ibuf
, fd
, &msgh
, 0, (EIGRP_PACKET_MAX_LEN
+ 1));
726 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno
));
729 if ((unsigned int)ret
< sizeof(iph
)) /* ret must be > 0 now */
732 "eigrp_recv_packet: discarding runt packet of length %d "
733 "(ip header size is %u)",
734 ret
, (u_int
)sizeof(iph
));
738 /* Note that there should not be alignment problems with this assignment
739 because this is at the beginning of the stream data buffer. */
740 iph
= (struct ip
*)STREAM_DATA(ibuf
);
741 sockopt_iphdrincl_swab_systoh(iph
);
743 ip_len
= iph
->ip_len
;
745 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
747 * Kernel network code touches incoming IP header parameters,
748 * before protocol specific processing.
750 * 1) Convert byteorder to host representation.
751 * --> ip_len, ip_id, ip_off
753 * 2) Adjust ip_len to strip IP header size!
754 * --> If user process receives entire IP packet via RAW
755 * socket, it must consider adding IP header size to
756 * the "ip_len" field of "ip" structure.
758 * For more details, see <netinet/ip_input.c>.
760 ip_len
= ip_len
+ (iph
->ip_hl
<< 2);
763 #if defined(__DragonFly__)
765 * in DragonFly's raw socket, ip_len/ip_off are read
766 * in network byte order.
767 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
769 ip_len
= ntohs(iph
->ip_len
) + (iph
->ip_hl
<< 2);
772 ifindex
= getsockopt_ifindex(AF_INET
, &msgh
);
774 *ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
778 "eigrp_recv_packet read length mismatch: ip_len is %d, "
779 "but recvmsg returned %d",
787 struct eigrp_fifo
*eigrp_fifo_new(void)
789 struct eigrp_fifo
*new;
791 new = XCALLOC(MTYPE_EIGRP_FIFO
, sizeof(struct eigrp_fifo
));
795 /* Free eigrp packet fifo. */
796 void eigrp_fifo_free(struct eigrp_fifo
*fifo
)
798 struct eigrp_packet
*ep
;
799 struct eigrp_packet
*next
;
801 for (ep
= fifo
->head
; ep
; ep
= next
) {
803 eigrp_packet_free(ep
);
805 fifo
->head
= fifo
->tail
= NULL
;
808 XFREE(MTYPE_EIGRP_FIFO
, fifo
);
811 /* Free eigrp fifo entries without destroying fifo itself*/
812 void eigrp_fifo_reset(struct eigrp_fifo
*fifo
)
814 struct eigrp_packet
*ep
;
815 struct eigrp_packet
*next
;
817 for (ep
= fifo
->head
; ep
; ep
= next
) {
819 eigrp_packet_free(ep
);
821 fifo
->head
= fifo
->tail
= NULL
;
825 struct eigrp_packet
*eigrp_packet_new(size_t size
, struct eigrp_neighbor
*nbr
)
827 struct eigrp_packet
*new;
829 new = XCALLOC(MTYPE_EIGRP_PACKET
, sizeof(struct eigrp_packet
));
830 new->s
= stream_new(size
);
831 new->retrans_counter
= 0;
837 void eigrp_send_packet_reliably(struct eigrp_neighbor
*nbr
)
839 struct eigrp_packet
*ep
;
841 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
844 struct eigrp_packet
*duplicate
;
845 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
846 /* Add packet to the top of the interface output queue*/
847 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
849 /*Start retransmission timer*/
850 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
851 EIGRP_PACKET_RETRANS_TIME
,
852 &ep
->t_retrans_timer
);
854 /*Increment sequence number counter*/
855 nbr
->ei
->eigrp
->sequence_number
++;
857 /* Hook thread to write packet. */
858 if (nbr
->ei
->on_write_q
== 0) {
859 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
860 nbr
->ei
->on_write_q
= 1;
862 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
863 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
867 /* Calculate EIGRP checksum */
868 void eigrp_packet_checksum(struct eigrp_interface
*ei
, struct stream
*s
,
871 struct eigrp_header
*eigrph
;
873 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
875 /* Calculate checksum. */
876 eigrph
->checksum
= in_cksum(eigrph
, length
);
879 /* Make EIGRP header. */
880 void eigrp_packet_header_init(int type
, struct eigrp
*eigrp
,
881 struct stream
*s
, u_int32_t flags
,
882 u_int32_t sequence
, u_int32_t ack
)
884 struct eigrp_header
*eigrph
;
887 eigrph
= (struct eigrp_header
*)STREAM_DATA(s
);
889 eigrph
->version
= (u_char
)EIGRP_HEADER_VERSION
;
890 eigrph
->opcode
= (u_char
)type
;
891 eigrph
->checksum
= 0;
893 eigrph
->vrid
= htons(eigrp
->vrid
);
894 eigrph
->ASNumber
= htons(eigrp
->AS
);
895 eigrph
->ack
= htonl(ack
);
896 eigrph
->sequence
= htonl(sequence
);
897 // if(flags == EIGRP_INIT_FLAG)
898 // eigrph->sequence = htonl(3);
899 eigrph
->flags
= htonl(flags
);
901 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL
))
902 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
903 htonl(eigrph
->sequence
), htonl(eigrph
->ack
));
905 stream_forward_endp(s
, EIGRP_HEADER_LEN
);
908 /* Add new packet to head of fifo. */
909 void eigrp_fifo_push(struct eigrp_fifo
*fifo
, struct eigrp_packet
*ep
)
911 ep
->next
= fifo
->head
;
914 if (fifo
->tail
== NULL
)
917 if (fifo
->count
!= 0)
918 fifo
->head
->previous
= ep
;
925 /* Return last fifo entry. */
926 struct eigrp_packet
*eigrp_fifo_next(struct eigrp_fifo
*fifo
)
931 void eigrp_packet_delete(struct eigrp_interface
*ei
)
933 struct eigrp_packet
*ep
;
935 ep
= eigrp_fifo_pop(ei
->obuf
);
938 eigrp_packet_free(ep
);
941 void eigrp_packet_free(struct eigrp_packet
*ep
)
946 THREAD_OFF(ep
->t_retrans_timer
);
948 XFREE(MTYPE_EIGRP_PACKET
, ep
);
953 /* EIGRP Header verification. */
954 static int eigrp_verify_header(struct stream
*ibuf
, struct eigrp_interface
*ei
,
955 struct ip
*iph
, struct eigrp_header
*eigrph
)
957 /* Check network mask, Silently discarded. */
958 if (!eigrp_check_network_mask(ei
, iph
->ip_src
)) {
960 "interface %s: eigrp_read network address is not same [%s]",
961 IF_NAME(ei
), inet_ntoa(iph
->ip_src
));
965 // /* Check authentication. The function handles logging actions, where
967 // if (! eigrp_check_auth(ei, eigrph))
973 /* Unbound socket will accept any Raw IP packets if proto is matched.
974 To prevent it, compare src IP address and i/f address with masking
976 static int eigrp_check_network_mask(struct eigrp_interface
*ei
,
977 struct in_addr ip_src
)
979 struct in_addr mask
, me
, him
;
981 if (ei
->type
== EIGRP_IFTYPE_POINTOPOINT
)
984 masklen2ip(ei
->address
->prefixlen
, &mask
);
986 me
.s_addr
= ei
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
987 him
.s_addr
= ip_src
.s_addr
& mask
.s_addr
;
989 if (IPV4_ADDR_SAME(&me
, &him
))
995 int eigrp_unack_packet_retrans(struct thread
*thread
)
997 struct eigrp_neighbor
*nbr
;
998 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1000 struct eigrp_packet
*ep
;
1001 ep
= eigrp_fifo_next(nbr
->retrans_queue
);
1004 struct eigrp_packet
*duplicate
;
1005 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1007 /* Add packet to the top of the interface output queue*/
1008 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1010 ep
->retrans_counter
++;
1011 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1012 return eigrp_retrans_count_exceeded(ep
, nbr
);
1014 /*Start retransmission timer*/
1015 ep
->t_retrans_timer
= NULL
;
1016 thread_add_timer(master
, eigrp_unack_packet_retrans
, nbr
,
1017 EIGRP_PACKET_RETRANS_TIME
,
1018 &ep
->t_retrans_timer
);
1020 /* Hook thread to write packet. */
1021 if (nbr
->ei
->on_write_q
== 0) {
1022 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1023 nbr
->ei
->on_write_q
= 1;
1025 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1026 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1032 int eigrp_unack_multicast_packet_retrans(struct thread
*thread
)
1034 struct eigrp_neighbor
*nbr
;
1035 nbr
= (struct eigrp_neighbor
*)THREAD_ARG(thread
);
1037 struct eigrp_packet
*ep
;
1038 ep
= eigrp_fifo_next(nbr
->multicast_queue
);
1041 struct eigrp_packet
*duplicate
;
1042 duplicate
= eigrp_packet_duplicate(ep
, nbr
);
1043 /* Add packet to the top of the interface output queue*/
1044 eigrp_fifo_push(nbr
->ei
->obuf
, duplicate
);
1046 ep
->retrans_counter
++;
1047 if (ep
->retrans_counter
== EIGRP_PACKET_RETRANS_MAX
)
1048 return eigrp_retrans_count_exceeded(ep
, nbr
);
1050 /*Start retransmission timer*/
1051 ep
->t_retrans_timer
= NULL
;
1052 thread_add_timer(master
, eigrp_unack_multicast_packet_retrans
,
1053 nbr
, EIGRP_PACKET_RETRANS_TIME
,
1054 &ep
->t_retrans_timer
);
1056 /* Hook thread to write packet. */
1057 if (nbr
->ei
->on_write_q
== 0) {
1058 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
1059 nbr
->ei
->on_write_q
= 1;
1061 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
,
1062 nbr
->ei
->eigrp
->fd
, &nbr
->ei
->eigrp
->t_write
);
1068 /* Get packet from tail of fifo. */
1069 struct eigrp_packet
*eigrp_fifo_pop(struct eigrp_fifo
*fifo
)
1071 struct eigrp_packet
*ep
= NULL
;
1076 fifo
->tail
= ep
->previous
;
1078 if (fifo
->tail
== NULL
)
1081 fifo
->tail
->next
= NULL
;
1089 struct eigrp_packet
*eigrp_packet_duplicate(struct eigrp_packet
*old
,
1090 struct eigrp_neighbor
*nbr
)
1092 struct eigrp_packet
*new;
1094 new = eigrp_packet_new(nbr
->ei
->ifp
->mtu
, nbr
);
1095 new->length
= old
->length
;
1096 new->retrans_counter
= old
->retrans_counter
;
1097 new->dst
= old
->dst
;
1098 new->sequence_number
= old
->sequence_number
;
1099 stream_copy(new->s
, old
->s
);
1104 struct TLV_IPv4_Internal_type
*eigrp_read_ipv4_tlv(struct stream
*s
)
1106 struct TLV_IPv4_Internal_type
*tlv
;
1108 tlv
= eigrp_IPv4_InternalTLV_new();
1110 tlv
->type
= stream_getw(s
);
1111 tlv
->length
= stream_getw(s
);
1112 tlv
->forward
.s_addr
= stream_getl(s
);
1113 tlv
->metric
.delay
= stream_getl(s
);
1114 tlv
->metric
.bandwidth
= stream_getl(s
);
1115 tlv
->metric
.mtu
[0] = stream_getc(s
);
1116 tlv
->metric
.mtu
[1] = stream_getc(s
);
1117 tlv
->metric
.mtu
[2] = stream_getc(s
);
1118 tlv
->metric
.hop_count
= stream_getc(s
);
1119 tlv
->metric
.reliability
= stream_getc(s
);
1120 tlv
->metric
.load
= stream_getc(s
);
1121 tlv
->metric
.tag
= stream_getc(s
);
1122 tlv
->metric
.flags
= stream_getc(s
);
1124 tlv
->prefix_length
= stream_getc(s
);
1126 if (tlv
->prefix_length
<= 8) {
1127 tlv
->destination_part
[0] = stream_getc(s
);
1128 tlv
->destination
.s_addr
= (tlv
->destination_part
[0]);
1129 } else if (tlv
->prefix_length
> 8 && tlv
->prefix_length
<= 16) {
1130 tlv
->destination_part
[0] = stream_getc(s
);
1131 tlv
->destination_part
[1] = stream_getc(s
);
1132 tlv
->destination
.s_addr
= ((tlv
->destination_part
[1] << 8)
1133 + tlv
->destination_part
[0]);
1134 } else if (tlv
->prefix_length
> 16 && tlv
->prefix_length
<= 24) {
1135 tlv
->destination_part
[0] = stream_getc(s
);
1136 tlv
->destination_part
[1] = stream_getc(s
);
1137 tlv
->destination_part
[2] = stream_getc(s
);
1138 tlv
->destination
.s_addr
= ((tlv
->destination_part
[2] << 16)
1139 + (tlv
->destination_part
[1] << 8)
1140 + tlv
->destination_part
[0]);
1141 } else if (tlv
->prefix_length
> 24 && tlv
->prefix_length
<= 32) {
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_part
[3] = stream_getc(s
);
1146 tlv
->destination
.s_addr
= ((tlv
->destination_part
[3] << 24)
1147 + (tlv
->destination_part
[2] << 16)
1148 + (tlv
->destination_part
[1] << 8)
1149 + tlv
->destination_part
[0]);
1154 u_int16_t
eigrp_add_internalTLV_to_stream(struct stream
*s
,
1155 struct eigrp_prefix_entry
*pe
)
1159 stream_putw(s
, EIGRP_TLV_IPv4_INT
);
1160 if (pe
->destination_ipv4
->prefixlen
<= 8) {
1161 stream_putw(s
, 0x001A);
1164 if ((pe
->destination_ipv4
->prefixlen
> 8)
1165 && (pe
->destination_ipv4
->prefixlen
<= 16)) {
1166 stream_putw(s
, 0x001B);
1169 if ((pe
->destination_ipv4
->prefixlen
> 16)
1170 && (pe
->destination_ipv4
->prefixlen
<= 24)) {
1171 stream_putw(s
, 0x001C);
1174 if (pe
->destination_ipv4
->prefixlen
> 24) {
1175 stream_putw(s
, 0x001D);
1179 stream_putl(s
, 0x00000000);
1182 stream_putl(s
, pe
->reported_metric
.delay
);
1183 stream_putl(s
, pe
->reported_metric
.bandwidth
);
1184 stream_putc(s
, pe
->reported_metric
.mtu
[2]);
1185 stream_putc(s
, pe
->reported_metric
.mtu
[1]);
1186 stream_putc(s
, pe
->reported_metric
.mtu
[0]);
1187 stream_putc(s
, pe
->reported_metric
.hop_count
);
1188 stream_putc(s
, pe
->reported_metric
.reliability
);
1189 stream_putc(s
, pe
->reported_metric
.load
);
1190 stream_putc(s
, pe
->reported_metric
.tag
);
1191 stream_putc(s
, pe
->reported_metric
.flags
);
1193 stream_putc(s
, pe
->destination_ipv4
->prefixlen
);
1195 if (pe
->destination_ipv4
->prefixlen
<= 8) {
1196 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1198 if ((pe
->destination_ipv4
->prefixlen
> 8)
1199 && (pe
->destination_ipv4
->prefixlen
<= 16)) {
1200 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1202 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1204 if ((pe
->destination_ipv4
->prefixlen
> 16)
1205 && (pe
->destination_ipv4
->prefixlen
<= 24)) {
1206 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1208 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1210 (pe
->destination_ipv4
->prefix
.s_addr
>> 16) & 0xFF);
1212 if (pe
->destination_ipv4
->prefixlen
> 24) {
1213 stream_putc(s
, pe
->destination_ipv4
->prefix
.s_addr
& 0xFF);
1215 (pe
->destination_ipv4
->prefix
.s_addr
>> 8) & 0xFF);
1217 (pe
->destination_ipv4
->prefix
.s_addr
>> 16) & 0xFF);
1219 (pe
->destination_ipv4
->prefix
.s_addr
>> 24) & 0xFF);
1225 u_int16_t
eigrp_add_authTLV_MD5_to_stream(struct stream
*s
,
1226 struct eigrp_interface
*ei
)
1229 struct keychain
*keychain
;
1230 struct TLV_MD5_Authentication_Type
*authTLV
;
1232 authTLV
= eigrp_authTLV_MD5_new();
1234 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1235 authTLV
->length
= htons(EIGRP_AUTH_MD5_TLV_SIZE
);
1236 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_MD5
);
1237 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_MD5_LEN
);
1238 authTLV
->key_sequence
= 0;
1239 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1241 keychain
= keychain_lookup(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1243 key
= key_lookup_for_send(keychain
);
1245 free(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1246 IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
= NULL
;
1247 eigrp_authTLV_MD5_free(authTLV
);
1252 authTLV
->key_id
= htonl(key
->index
);
1253 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_MD5_LEN
);
1254 stream_put(s
, authTLV
,
1255 sizeof(struct TLV_MD5_Authentication_Type
));
1256 eigrp_authTLV_MD5_free(authTLV
);
1257 return EIGRP_AUTH_MD5_TLV_SIZE
;
1260 eigrp_authTLV_MD5_free(authTLV
);
1265 u_int16_t
eigrp_add_authTLV_SHA256_to_stream(struct stream
*s
,
1266 struct eigrp_interface
*ei
)
1269 struct keychain
*keychain
;
1270 struct TLV_SHA256_Authentication_Type
*authTLV
;
1272 authTLV
= eigrp_authTLV_SHA256_new();
1274 authTLV
->type
= htons(EIGRP_TLV_AUTH
);
1275 authTLV
->length
= htons(EIGRP_AUTH_SHA256_TLV_SIZE
);
1276 authTLV
->auth_type
= htons(EIGRP_AUTH_TYPE_SHA256
);
1277 authTLV
->auth_length
= htons(EIGRP_AUTH_TYPE_SHA256_LEN
);
1278 authTLV
->key_sequence
= 0;
1279 memset(authTLV
->Nullpad
, 0, sizeof(authTLV
->Nullpad
));
1281 keychain
= keychain_lookup(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1283 key
= key_lookup_for_send(keychain
);
1285 free(IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
);
1286 IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
= NULL
;
1287 eigrp_authTLV_SHA256_free(authTLV
);
1292 authTLV
->key_id
= 0;
1293 memset(authTLV
->digest
, 0, EIGRP_AUTH_TYPE_SHA256_LEN
);
1294 stream_put(s
, authTLV
,
1295 sizeof(struct TLV_SHA256_Authentication_Type
));
1296 eigrp_authTLV_SHA256_free(authTLV
);
1297 return EIGRP_AUTH_SHA256_TLV_SIZE
;
1300 eigrp_authTLV_SHA256_free(authTLV
);
1305 struct TLV_MD5_Authentication_Type
*eigrp_authTLV_MD5_new()
1307 struct TLV_MD5_Authentication_Type
*new;
1309 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV
,
1310 sizeof(struct TLV_MD5_Authentication_Type
));
1315 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type
*authTLV
)
1317 XFREE(MTYPE_EIGRP_AUTH_TLV
, authTLV
);
1320 struct TLV_SHA256_Authentication_Type
*eigrp_authTLV_SHA256_new()
1322 struct TLV_SHA256_Authentication_Type
*new;
1324 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV
,
1325 sizeof(struct TLV_SHA256_Authentication_Type
));
1330 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type
*authTLV
)
1332 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV
, authTLV
);
1335 struct TLV_IPv4_Internal_type
*eigrp_IPv4_InternalTLV_new()
1337 struct TLV_IPv4_Internal_type
*new;
1339 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV
,
1340 sizeof(struct TLV_IPv4_Internal_type
));
1345 void eigrp_IPv4_InternalTLV_free(
1346 struct TLV_IPv4_Internal_type
*IPv4_InternalTLV
)
1348 XFREE(MTYPE_EIGRP_IPV4_INT_TLV
, IPv4_InternalTLV
);
1351 struct TLV_Sequence_Type
*eigrp_SequenceTLV_new()
1353 struct TLV_Sequence_Type
*new;
1355 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV
, sizeof(struct TLV_Sequence_Type
));