]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_packet.c
Merge pull request #1007 from donaldsharp/clear_help_str
[mirror_frr.git] / eigrpd / eigrp_packet.c
1 /*
2 * EIGRP General Sending and Receiving of EIGRP Packets.
3 * Copyright (C) 2013-2014
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 *
11 * This file is part of GNU Zebra.
12 *
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
16 * later version.
17 *
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.
22 *
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
26 */
27
28 #include <zebra.h>
29
30 #include "thread.h"
31 #include "memory.h"
32 #include "linklist.h"
33 #include "vty.h"
34 #include "keychain.h"
35 #include "prefix.h"
36 #include "if.h"
37 #include "table.h"
38 #include "sockunion.h"
39 #include "stream.h"
40 #include "log.h"
41 #include "sockopt.h"
42 #include "checksum.h"
43 #include "md5.h"
44 #include "sha256.h"
45
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"
58
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"},
71 {0}};
72
73
74 static unsigned char zeropad[16] = {0};
75
76 /* Forward function reference*/
77 static struct stream *eigrp_recv_packet(int, struct interface **,
78 struct stream *);
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);
82
83 static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep,
84 struct eigrp_neighbor *nbr)
85 {
86 return 1;
87 }
88
89 int eigrp_make_md5_digest(struct eigrp_interface *ei, struct stream *s,
90 u_char flags)
91 {
92 struct key *key = NULL;
93 struct keychain *keychain;
94
95 unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN];
96 MD5_CTX ctx;
97 u_char *ibuf;
98 size_t backup_get, backup_end;
99 struct TLV_MD5_Authentication_Type *auth_TLV;
100
101 ibuf = s->data;
102 backup_end = s->endp;
103 backup_get = s->getp;
104
105 auth_TLV = eigrp_authTLV_MD5_new();
106
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);
110
111 keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
112 if (keychain)
113 key = key_lookup_for_send(keychain);
114 else {
115 eigrp_authTLV_MD5_free(auth_TLV);
116 return EIGRP_AUTH_TYPE_NONE;
117 }
118
119 memset(&ctx, 0, sizeof(ctx));
120 MD5Init(&ctx);
121
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)) {
136 MD5Update(&ctx,
137 ibuf + (EIGRP_HEADER_LEN
138 + EIGRP_AUTH_MD5_TLV_SIZE),
139 backup_end - 20
140 - (EIGRP_HEADER_LEN
141 + EIGRP_AUTH_MD5_TLV_SIZE));
142 }
143 }
144
145 MD5Final(digest, &ctx);
146
147 /* Append md5 digest to the end of the stream. */
148 memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN);
149
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);
153
154 eigrp_authTLV_MD5_free(auth_TLV);
155 return EIGRP_AUTH_TYPE_MD5_LEN;
156 }
157
158 int eigrp_check_md5_digest(struct stream *s,
159 struct TLV_MD5_Authentication_Type *authTLV,
160 struct eigrp_neighbor *nbr, u_char flags)
161 {
162 MD5_CTX ctx;
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;
167 u_char *ibuf;
168 size_t backup_end;
169 struct TLV_MD5_Authentication_Type *auth_TLV;
170 struct eigrp_header *eigrph;
171
172 if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) {
173 zlog_warn(
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));
177 return 0;
178 }
179
180 eigrph = (struct eigrp_header *)s->data;
181 eigrph->checksum = 0;
182
183 auth_TLV = (struct TLV_MD5_Authentication_Type *)(s->data
184 + EIGRP_HEADER_LEN);
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);
188
189 ibuf = s->data;
190 backup_end = s->endp;
191
192 keychain = keychain_lookup(IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain);
193 if (keychain)
194 key = key_lookup_for_send(keychain);
195
196 memset(&ctx, 0, sizeof(ctx));
197 MD5Init(&ctx);
198
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)) {
213 MD5Update(&ctx,
214 ibuf + (EIGRP_HEADER_LEN
215 + EIGRP_AUTH_MD5_TLV_SIZE),
216 backup_end - 20
217 - (EIGRP_HEADER_LEN
218 + EIGRP_AUTH_MD5_TLV_SIZE));
219 }
220 }
221
222 MD5Final(digest, &ctx);
223
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",
227 IF_NAME(nbr->ei));
228 return 0;
229 }
230
231 /* save neighbor's crypt_seqnum */
232 if (nbr)
233 nbr->crypt_seqnum = authTLV->key_sequence;
234
235 return 1;
236 }
237
238 int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
239 u_char flags)
240 {
241 struct key *key = NULL;
242 struct keychain *keychain;
243 char *source_ip;
244
245 unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
246 unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0};
247 HMAC_SHA256_CTX ctx;
248 void *ibuf;
249 size_t backup_get, backup_end;
250 struct TLV_SHA256_Authentication_Type *auth_TLV;
251
252 ibuf = s->data;
253 backup_end = s->endp;
254 backup_get = s->getp;
255
256 auth_TLV = eigrp_authTLV_SHA256_new();
257
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);
261
262 keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
263 if (keychain)
264 key = key_lookup_for_send(keychain);
265
266 // saved_len[index] = strnzcpyn(saved_key[index], key,
267 // PLAINTEXT_LENGTH + 1);
268
269 source_ip = calloc(16, sizeof(char));
270 inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16);
271
272 memset(&ctx, 0, sizeof(ctx));
273 buffer[0] = '\n';
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);
280
281
282 /* Put hmac-sha256 digest to it's place */
283 memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_SHA256_LEN);
284
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);
288
289 eigrp_authTLV_SHA256_free(auth_TLV);
290 free(source_ip);
291
292 return EIGRP_AUTH_TYPE_SHA256_LEN;
293 }
294
295 int eigrp_check_sha256_digest(struct stream *s,
296 struct TLV_SHA256_Authentication_Type *authTLV,
297 struct eigrp_neighbor *nbr, u_char flags)
298 {
299 return 1;
300 }
301
302 int eigrp_write(struct thread *thread)
303 {
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;
309 struct ip iph;
310 struct msghdr msg;
311 struct iovec iov[2];
312 u_int16_t opcode = 0;
313 u_int32_t seqno, ack;
314
315 int ret;
316 int flags = 0;
317 struct listnode *node;
318 #ifdef WANT_EIGRP_WRITE_FRAGMENT
319 static u_int16_t ipid = 0;
320 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
321 /* $FRR indent$ */
322 /* clang-format off */
323 #define EIGRP_WRITE_IPHL_SHIFT 2
324
325 eigrp->t_write = NULL;
326
327 node = listhead(eigrp->oi_write_q);
328 assert(node);
329 ei = listgetdata(node);
330 assert(ei);
331
332 #ifdef WANT_EIGRP_WRITE_FRAGMENT
333 /* seed ipid static with low order bits of time */
334 if (ipid == 0)
335 ipid = (time(NULL) & 0xffff);
336 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
337
338 /* Get one packet from queue. */
339 ep = eigrp_fifo_next(ei->obuf);
340 assert(ep);
341 assert(ep->length >= EIGRP_HEADER_LEN);
342
343 if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS))
344 eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex);
345
346 memset(&iph, 0, sizeof(struct ip));
347 memset(&sa_dst, 0, sizeof(sa_dst));
348
349 /*
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.
356 */
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);
366 }
367
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);
374
375 /* Set DONTROUTE flag if dst is unicast. */
376 if (!IN_MULTICAST(htonl(ep->dst.s_addr)))
377 flags = MSG_DONTROUTE;
378
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
384 ip_hl.. */
385
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;
389
390 #if defined(__DragonFly__)
391 /*
392 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
393 */
394 iph.ip_len = htons(iph.ip_len);
395 #endif
396
397 iph.ip_off = 0;
398 iph.ip_ttl = EIGRP_IP_TTL;
399 iph.ip_p = IPPROTO_EIGRPIGP;
400 iph.ip_sum = 0;
401 iph.ip_src.s_addr = ei->address->u.prefix4.s_addr;
402 iph.ip_dst.s_addr = ep->dst.s_addr;
403
404 memset(&msg, 0, sizeof(msg));
405 msg.msg_name = (caddr_t)&sa_dst;
406 msg.msg_namelen = sizeof(sa_dst);
407 msg.msg_iov = iov;
408 msg.msg_iovlen = 2;
409
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;
414
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);
419
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),
425 seqno, ack,
426 inet_ntoa(ep->dst), IF_NAME(ei), ret);
427 }
428
429 if (ret < 0)
430 zlog_warn(
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));
436
437 /* Now delete packet from queue. */
438 eigrp_packet_delete(ei);
439
440 if (eigrp_fifo_next(ei->obuf) == NULL) {
441 ei->on_write_q = 0;
442 list_delete_node(eigrp->oi_write_q, node);
443 }
444
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,
449 &eigrp->t_write);
450 }
451
452 return 0;
453 }
454
455 /* Starting point of packet process function. */
456 int eigrp_read(struct thread *thread)
457 {
458 int ret;
459 struct stream *ibuf;
460 struct eigrp *eigrp;
461 struct eigrp_interface *ei;
462 struct ip *iph;
463 struct eigrp_header *eigrph;
464 struct interface *ifp;
465 struct eigrp_neighbor *nbr;
466
467 u_int16_t opcode = 0;
468 u_int16_t length = 0;
469
470 /* first of all get interface pointer. */
471 eigrp = THREAD_ARG(thread);
472
473 /* prepare for next packet. */
474 eigrp->t_read = NULL;
475 thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read);
476
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
480 * header. */
481 return -1;
482 }
483
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);
487
488 // Substract IPv4 header size from EIGRP Packet itself
489 if (iph->ip_v == 4)
490 length = (iph->ip_len) - 20U;
491
492
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);
497
498 /* Note that sockopt_iphdrincl_swab_systoh was called in
499 * eigrp_recv_packet. */
500 if (ifp == NULL) {
501 struct connected *c;
502 /* Handle cases where the platform does not support retrieving
503 the ifindex,
504 and also platforms (such as Solaris 8) that claim to support
505 ifindex
506 retrieval but do not. */
507 c = if_lookup_address((void *)&iph->ip_src, AF_INET,
508 VRF_DEFAULT);
509
510 if (c == NULL)
511 return 0;
512
513 ifp = c->ifp;
514 }
515
516 /* associate packet with eigrp interface */
517 ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp);
518
519 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
520 only
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.
524 */
525 if (!ei)
526 return 0;
527
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))
532 zlog_debug(
533 "eigrp_read[%s]: Dropping self-originated packet",
534 inet_ntoa(iph->ip_src));
535 return 0;
536 }
537
538 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
539 by eigrp_recv_packet() to be correct). */
540
541 stream_forward_getp(ibuf, (iph->ip_hl * 4));
542 eigrph = (struct eigrp_header *)STREAM_PNT(ibuf);
543
544 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
545 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
546 eigrp_header_dump(eigrph);
547
548 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
549 // stream_get_getp(ibuf)))
550 // return -1;
551
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);
555
556 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
557 only
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.
561 */
562 if (!ei)
563 return 0;
564
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];
568
569 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
570 zlog_debug(
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],
574 sizeof(buf[0])),
575 inet_ntop(AF_INET, &iph->ip_dst, buf[1],
576 sizeof(buf[1])),
577 inet_ntop(AF_INET, &ei->address->u.prefix4,
578 buf[2], sizeof(buf[2])));
579
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.
584 */
585 EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS);
586 eigrp_if_set_multicast(ei);
587 }
588 return 0;
589 }
590
591 /* else it must be a local eigrp interface, check it was received on
592 * correct link
593 */
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);
598 return 0;
599 }
600
601 /* Verify more EIGRP header fields. */
602 ret = eigrp_verify_header(ibuf, ei, iph, eigrph);
603 if (ret < 0) {
604 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
605 zlog_debug(
606 "eigrp_read[%s]: Header check failed, dropping.",
607 inet_ntoa(iph->ip_src));
608 return ret;
609 }
610
611 /* calcualte the eigrp packet length, and move the pounter to the
612 start of the eigrp TLVs */
613 opcode = eigrph->opcode;
614
615 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
616 char src[100], dst[100];
617
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);
624 }
625
626 /* Read rest of the packet and call each sort of packet routine. */
627 stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
628
629 /* New testing block of code for handling Acks */
630 if (ntohl(eigrph->ack) != 0) {
631 struct eigrp_packet *ep = NULL;
632
633 nbr = eigrp_nbr_get(ei, eigrph, iph);
634
635 // neighbor must be valid, eigrp_nbr_get creates if none existed
636 assert(nbr);
637
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);
642
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);
652 }
653 else
654 eigrp_send_packet_reliably(nbr);
655 }
656 ep = eigrp_fifo_next(nbr->multicast_queue);
657 if (ep) {
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);
663 }
664 }
665 }
666 }
667
668
669 switch (opcode) {
670 case EIGRP_OPC_HELLO:
671 eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length);
672 break;
673 case EIGRP_OPC_PROBE:
674 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
675 // length);
676 break;
677 case EIGRP_OPC_QUERY:
678 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
679 break;
680 case EIGRP_OPC_REPLY:
681 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
682 break;
683 case EIGRP_OPC_REQUEST:
684 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
685 // length);
686 break;
687 case EIGRP_OPC_SIAQUERY:
688 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
689 break;
690 case EIGRP_OPC_SIAREPLY:
691 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
692 break;
693 case EIGRP_OPC_UPDATE:
694 eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length);
695 break;
696 default:
697 zlog_warn(
698 "interface %s: EIGRP packet header type %d unsupported",
699 IF_NAME(ei), opcode);
700 break;
701 }
702
703 return 0;
704 }
705
706 static struct stream *eigrp_recv_packet(int fd, struct interface **ifp,
707 struct stream *ibuf)
708 {
709 int ret;
710 struct ip *iph;
711 u_int16_t ip_len;
712 unsigned int ifindex = 0;
713 struct iovec iov;
714 /* Header and data both require alignment. */
715 char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
716 struct msghdr msgh;
717
718 memset(&msgh, 0, sizeof(struct msghdr));
719 msgh.msg_iov = &iov;
720 msgh.msg_iovlen = 1;
721 msgh.msg_control = (caddr_t)buff;
722 msgh.msg_controllen = sizeof(buff);
723
724 ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1));
725 if (ret < 0) {
726 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
727 return NULL;
728 }
729 if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
730 {
731 zlog_warn(
732 "eigrp_recv_packet: discarding runt packet of length %d "
733 "(ip header size is %u)",
734 ret, (u_int)sizeof(iph));
735 return NULL;
736 }
737
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);
742
743 ip_len = iph->ip_len;
744
745 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
746 /*
747 * Kernel network code touches incoming IP header parameters,
748 * before protocol specific processing.
749 *
750 * 1) Convert byteorder to host representation.
751 * --> ip_len, ip_id, ip_off
752 *
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.
757 *
758 * For more details, see <netinet/ip_input.c>.
759 */
760 ip_len = ip_len + (iph->ip_hl << 2);
761 #endif
762
763 #if defined(__DragonFly__)
764 /*
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!
768 */
769 ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
770 #endif
771
772 ifindex = getsockopt_ifindex(AF_INET, &msgh);
773
774 *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
775
776 if (ret != ip_len) {
777 zlog_warn(
778 "eigrp_recv_packet read length mismatch: ip_len is %d, "
779 "but recvmsg returned %d",
780 ip_len, ret);
781 return NULL;
782 }
783
784 return ibuf;
785 }
786
787 struct eigrp_fifo *eigrp_fifo_new(void)
788 {
789 struct eigrp_fifo *new;
790
791 new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo));
792 return new;
793 }
794
795 /* Free eigrp packet fifo. */
796 void eigrp_fifo_free(struct eigrp_fifo *fifo)
797 {
798 struct eigrp_packet *ep;
799 struct eigrp_packet *next;
800
801 for (ep = fifo->head; ep; ep = next) {
802 next = ep->next;
803 eigrp_packet_free(ep);
804 }
805 fifo->head = fifo->tail = NULL;
806 fifo->count = 0;
807
808 XFREE(MTYPE_EIGRP_FIFO, fifo);
809 }
810
811 /* Free eigrp fifo entries without destroying fifo itself*/
812 void eigrp_fifo_reset(struct eigrp_fifo *fifo)
813 {
814 struct eigrp_packet *ep;
815 struct eigrp_packet *next;
816
817 for (ep = fifo->head; ep; ep = next) {
818 next = ep->next;
819 eigrp_packet_free(ep);
820 }
821 fifo->head = fifo->tail = NULL;
822 fifo->count = 0;
823 }
824
825 struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
826 {
827 struct eigrp_packet *new;
828
829 new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
830 new->s = stream_new(size);
831 new->retrans_counter = 0;
832 new->nbr = nbr;
833
834 return new;
835 }
836
837 void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr)
838 {
839 struct eigrp_packet *ep;
840
841 ep = eigrp_fifo_next(nbr->retrans_queue);
842
843 if (ep) {
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);
848
849 /*Start retransmission timer*/
850 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
851 EIGRP_PACKET_RETRANS_TIME,
852 &ep->t_retrans_timer);
853
854 /*Increment sequence number counter*/
855 nbr->ei->eigrp->sequence_number++;
856
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;
861 }
862 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
863 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
864 }
865 }
866
867 /* Calculate EIGRP checksum */
868 void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
869 u_int16_t length)
870 {
871 struct eigrp_header *eigrph;
872
873 eigrph = (struct eigrp_header *)STREAM_DATA(s);
874
875 /* Calculate checksum. */
876 eigrph->checksum = in_cksum(eigrph, length);
877 }
878
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)
883 {
884 struct eigrp_header *eigrph;
885
886 stream_reset(s);
887 eigrph = (struct eigrp_header *)STREAM_DATA(s);
888
889 eigrph->version = (u_char)EIGRP_HEADER_VERSION;
890 eigrph->opcode = (u_char)type;
891 eigrph->checksum = 0;
892
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);
900
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));
904
905 stream_forward_endp(s, EIGRP_HEADER_LEN);
906 }
907
908 /* Add new packet to head of fifo. */
909 void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
910 {
911 ep->next = fifo->head;
912 ep->previous = NULL;
913
914 if (fifo->tail == NULL)
915 fifo->tail = ep;
916
917 if (fifo->count != 0)
918 fifo->head->previous = ep;
919
920 fifo->head = ep;
921
922 fifo->count++;
923 }
924
925 /* Return last fifo entry. */
926 struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
927 {
928 return fifo->tail;
929 }
930
931 void eigrp_packet_delete(struct eigrp_interface *ei)
932 {
933 struct eigrp_packet *ep;
934
935 ep = eigrp_fifo_pop(ei->obuf);
936
937 if (ep)
938 eigrp_packet_free(ep);
939 }
940
941 void eigrp_packet_free(struct eigrp_packet *ep)
942 {
943 if (ep->s)
944 stream_free(ep->s);
945
946 THREAD_OFF(ep->t_retrans_timer);
947
948 XFREE(MTYPE_EIGRP_PACKET, ep);
949
950 ep = NULL;
951 }
952
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)
956 {
957 /* Check network mask, Silently discarded. */
958 if (!eigrp_check_network_mask(ei, iph->ip_src)) {
959 zlog_warn(
960 "interface %s: eigrp_read network address is not same [%s]",
961 IF_NAME(ei), inet_ntoa(iph->ip_src));
962 return -1;
963 }
964 //
965 // /* Check authentication. The function handles logging actions, where
966 // required. */
967 // if (! eigrp_check_auth(ei, eigrph))
968 // return -1;
969
970 return 0;
971 }
972
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
975 i/f network mask. */
976 static int eigrp_check_network_mask(struct eigrp_interface *ei,
977 struct in_addr ip_src)
978 {
979 struct in_addr mask, me, him;
980
981 if (ei->type == EIGRP_IFTYPE_POINTOPOINT)
982 return 1;
983
984 masklen2ip(ei->address->prefixlen, &mask);
985
986 me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr;
987 him.s_addr = ip_src.s_addr & mask.s_addr;
988
989 if (IPV4_ADDR_SAME(&me, &him))
990 return 1;
991
992 return 0;
993 }
994
995 int eigrp_unack_packet_retrans(struct thread *thread)
996 {
997 struct eigrp_neighbor *nbr;
998 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
999
1000 struct eigrp_packet *ep;
1001 ep = eigrp_fifo_next(nbr->retrans_queue);
1002
1003 if (ep) {
1004 struct eigrp_packet *duplicate;
1005 duplicate = eigrp_packet_duplicate(ep, nbr);
1006
1007 /* Add packet to the top of the interface output queue*/
1008 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1009
1010 ep->retrans_counter++;
1011 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1012 return eigrp_retrans_count_exceeded(ep, nbr);
1013
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);
1019
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;
1024 }
1025 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1026 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1027 }
1028
1029 return 0;
1030 }
1031
1032 int eigrp_unack_multicast_packet_retrans(struct thread *thread)
1033 {
1034 struct eigrp_neighbor *nbr;
1035 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
1036
1037 struct eigrp_packet *ep;
1038 ep = eigrp_fifo_next(nbr->multicast_queue);
1039
1040 if (ep) {
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);
1045
1046 ep->retrans_counter++;
1047 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1048 return eigrp_retrans_count_exceeded(ep, nbr);
1049
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);
1055
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;
1060 }
1061 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1062 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1063 }
1064
1065 return 0;
1066 }
1067
1068 /* Get packet from tail of fifo. */
1069 struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
1070 {
1071 struct eigrp_packet *ep = NULL;
1072
1073 ep = fifo->tail;
1074
1075 if (ep) {
1076 fifo->tail = ep->previous;
1077
1078 if (fifo->tail == NULL)
1079 fifo->head = NULL;
1080 else
1081 fifo->tail->next = NULL;
1082
1083 fifo->count--;
1084 }
1085
1086 return ep;
1087 }
1088
1089 struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
1090 struct eigrp_neighbor *nbr)
1091 {
1092 struct eigrp_packet *new;
1093
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);
1100
1101 return new;
1102 }
1103
1104 struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
1105 {
1106 struct TLV_IPv4_Internal_type *tlv;
1107
1108 tlv = eigrp_IPv4_InternalTLV_new();
1109
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);
1123
1124 tlv->prefix_length = stream_getc(s);
1125
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]);
1150 }
1151 return tlv;
1152 }
1153
1154 u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
1155 struct eigrp_prefix_entry *pe)
1156 {
1157 u_int16_t length;
1158
1159 stream_putw(s, EIGRP_TLV_IPv4_INT);
1160 if (pe->destination_ipv4->prefixlen <= 8) {
1161 stream_putw(s, 0x001A);
1162 length = 0x001A;
1163 }
1164 if ((pe->destination_ipv4->prefixlen > 8)
1165 && (pe->destination_ipv4->prefixlen <= 16)) {
1166 stream_putw(s, 0x001B);
1167 length = 0x001B;
1168 }
1169 if ((pe->destination_ipv4->prefixlen > 16)
1170 && (pe->destination_ipv4->prefixlen <= 24)) {
1171 stream_putw(s, 0x001C);
1172 length = 0x001C;
1173 }
1174 if (pe->destination_ipv4->prefixlen > 24) {
1175 stream_putw(s, 0x001D);
1176 length = 0x001D;
1177 }
1178
1179 stream_putl(s, 0x00000000);
1180
1181 /*Metric*/
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);
1192
1193 stream_putc(s, pe->destination_ipv4->prefixlen);
1194
1195 if (pe->destination_ipv4->prefixlen <= 8) {
1196 stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
1197 }
1198 if ((pe->destination_ipv4->prefixlen > 8)
1199 && (pe->destination_ipv4->prefixlen <= 16)) {
1200 stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
1201 stream_putc(s,
1202 (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
1203 }
1204 if ((pe->destination_ipv4->prefixlen > 16)
1205 && (pe->destination_ipv4->prefixlen <= 24)) {
1206 stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
1207 stream_putc(s,
1208 (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
1209 stream_putc(s,
1210 (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
1211 }
1212 if (pe->destination_ipv4->prefixlen > 24) {
1213 stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
1214 stream_putc(s,
1215 (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
1216 stream_putc(s,
1217 (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
1218 stream_putc(s,
1219 (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF);
1220 }
1221
1222 return length;
1223 }
1224
1225 u_int16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s,
1226 struct eigrp_interface *ei)
1227 {
1228 struct key *key;
1229 struct keychain *keychain;
1230 struct TLV_MD5_Authentication_Type *authTLV;
1231
1232 authTLV = eigrp_authTLV_MD5_new();
1233
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));
1240
1241 keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
1242 if (keychain)
1243 key = key_lookup_for_send(keychain);
1244 else {
1245 free(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
1246 IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL;
1247 eigrp_authTLV_MD5_free(authTLV);
1248 return 0;
1249 }
1250
1251 if (key) {
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;
1258 }
1259
1260 eigrp_authTLV_MD5_free(authTLV);
1261
1262 return 0;
1263 }
1264
1265 u_int16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s,
1266 struct eigrp_interface *ei)
1267 {
1268 struct key *key;
1269 struct keychain *keychain;
1270 struct TLV_SHA256_Authentication_Type *authTLV;
1271
1272 authTLV = eigrp_authTLV_SHA256_new();
1273
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));
1280
1281 keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
1282 if (keychain)
1283 key = key_lookup_for_send(keychain);
1284 else {
1285 free(IF_DEF_PARAMS(ei->ifp)->auth_keychain);
1286 IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL;
1287 eigrp_authTLV_SHA256_free(authTLV);
1288 return 0;
1289 }
1290
1291 if (key) {
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;
1298 }
1299
1300 eigrp_authTLV_SHA256_free(authTLV);
1301
1302 return 0;
1303 }
1304
1305 struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new()
1306 {
1307 struct TLV_MD5_Authentication_Type *new;
1308
1309 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV,
1310 sizeof(struct TLV_MD5_Authentication_Type));
1311
1312 return new;
1313 }
1314
1315 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV)
1316 {
1317 XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV);
1318 }
1319
1320 struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new()
1321 {
1322 struct TLV_SHA256_Authentication_Type *new;
1323
1324 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV,
1325 sizeof(struct TLV_SHA256_Authentication_Type));
1326
1327 return new;
1328 }
1329
1330 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
1331 {
1332 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
1333 }
1334
1335 struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
1336 {
1337 struct TLV_IPv4_Internal_type *new;
1338
1339 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
1340 sizeof(struct TLV_IPv4_Internal_type));
1341
1342 return new;
1343 }
1344
1345 void eigrp_IPv4_InternalTLV_free(
1346 struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
1347 {
1348 XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV);
1349 }
1350
1351 struct TLV_Sequence_Type *eigrp_SequenceTLV_new()
1352 {
1353 struct TLV_Sequence_Type *new;
1354
1355 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type));
1356
1357 return new;
1358 }