]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_packet.c
Merge branch 'master' into docuser
[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(ei->params.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 (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(nbr->ei->params.auth_keychain);
193 if (keychain)
194 key = key_lookup_for_send(keychain);
195
196 if (!key) {
197 zlog_warn(
198 "Interface %s: Expected key value not found in config",
199 nbr->ei->ifp->name);
200 return 0;
201 }
202
203 memset(&ctx, 0, sizeof(ctx));
204 MD5Init(&ctx);
205
206 /* Generate a digest. Each situation needs different handling */
207 if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) {
208 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
209 MD5Update(&ctx, key->string, strlen(key->string));
210 if (strlen(key->string) < 16)
211 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
212 } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) {
213 MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE);
214 } else if (flags & EIGRP_AUTH_UPDATE_FLAG) {
215 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
216 MD5Update(&ctx, key->string, strlen(key->string));
217 if (strlen(key->string) < 16)
218 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
219 if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) {
220 MD5Update(&ctx,
221 ibuf + (EIGRP_HEADER_LEN
222 + EIGRP_AUTH_MD5_TLV_SIZE),
223 backup_end - 20
224 - (EIGRP_HEADER_LEN
225 + EIGRP_AUTH_MD5_TLV_SIZE));
226 }
227 }
228
229 MD5Final(digest, &ctx);
230
231 /* compare the two */
232 if (memcmp(orig, digest, EIGRP_AUTH_TYPE_MD5_LEN) != 0) {
233 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
234 IF_NAME(nbr->ei));
235 return 0;
236 }
237
238 /* save neighbor's crypt_seqnum */
239 nbr->crypt_seqnum = authTLV->key_sequence;
240
241 return 1;
242 }
243
244 int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
245 u_char flags)
246 {
247 struct key *key = NULL;
248 struct keychain *keychain;
249 char source_ip[PREFIX_STRLEN];
250
251 unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
252 unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0};
253
254 HMAC_SHA256_CTX ctx;
255 void *ibuf;
256 size_t backup_get, backup_end;
257 struct TLV_SHA256_Authentication_Type *auth_TLV;
258
259 ibuf = s->data;
260 backup_end = s->endp;
261 backup_get = s->getp;
262
263 auth_TLV = eigrp_authTLV_SHA256_new();
264
265 stream_set_getp(s, EIGRP_HEADER_LEN);
266 stream_get(auth_TLV, s, EIGRP_AUTH_SHA256_TLV_SIZE);
267 stream_set_getp(s, backup_get);
268
269 keychain = keychain_lookup(ei->params.auth_keychain);
270 if (keychain)
271 key = key_lookup_for_send(keychain);
272
273 if (!key) {
274 zlog_warn(
275 "Interface %s: Expected key value not found in config",
276 ei->ifp->name);
277 eigrp_authTLV_SHA256_free(auth_TLV);
278 return 0;
279 }
280
281 inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, PREFIX_STRLEN);
282
283 memset(&ctx, 0, sizeof(ctx));
284 buffer[0] = '\n';
285 memcpy(buffer + 1, key, strlen(key->string));
286 memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip));
287 HMAC__SHA256_Init(&ctx, buffer,
288 1 + strlen(key->string) + strlen(source_ip));
289 HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf));
290 HMAC__SHA256_Final(digest, &ctx);
291
292
293 /* Put hmac-sha256 digest to it's place */
294 memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_SHA256_LEN);
295
296 stream_set_endp(s, EIGRP_HEADER_LEN);
297 stream_put(s, auth_TLV, EIGRP_AUTH_SHA256_TLV_SIZE);
298 stream_set_endp(s, backup_end);
299
300 eigrp_authTLV_SHA256_free(auth_TLV);
301
302 return EIGRP_AUTH_TYPE_SHA256_LEN;
303 }
304
305 int eigrp_check_sha256_digest(struct stream *s,
306 struct TLV_SHA256_Authentication_Type *authTLV,
307 struct eigrp_neighbor *nbr, u_char flags)
308 {
309 return 1;
310 }
311
312 int eigrp_write(struct thread *thread)
313 {
314 struct eigrp *eigrp = THREAD_ARG(thread);
315 struct eigrp_header *eigrph;
316 struct eigrp_interface *ei;
317 struct eigrp_packet *ep;
318 struct sockaddr_in sa_dst;
319 struct ip iph;
320 struct msghdr msg;
321 struct iovec iov[2];
322 u_int32_t seqno, ack;
323
324 int ret;
325 int flags = 0;
326 struct listnode *node;
327 #ifdef WANT_EIGRP_WRITE_FRAGMENT
328 static u_int16_t ipid = 0;
329 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
330 #define EIGRP_WRITE_IPHL_SHIFT 2
331
332 eigrp->t_write = NULL;
333
334 node = listhead(eigrp->oi_write_q);
335 assert(node);
336 ei = listgetdata(node);
337 assert(ei);
338
339 #ifdef WANT_EIGRP_WRITE_FRAGMENT
340 /* seed ipid static with low order bits of time */
341 if (ipid == 0)
342 ipid = (time(NULL) & 0xffff);
343 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
344
345 /* Get one packet from queue. */
346 ep = eigrp_fifo_next(ei->obuf);
347 if (!ep) {
348 zlog_err("%s: Interface %s no packet on queue?",
349 __PRETTY_FUNCTION__, ei->ifp->name);
350 goto out;
351 }
352 if (ep->length < EIGRP_HEADER_LEN) {
353 zlog_err("%s: Packet just has a header?", __PRETTY_FUNCTION__);
354 eigrp_header_dump((struct eigrp_header *)ep->s->data);
355 eigrp_packet_delete(ei);
356 goto out;
357 }
358
359 if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS))
360 eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex);
361
362 memset(&iph, 0, sizeof(struct ip));
363 memset(&sa_dst, 0, sizeof(sa_dst));
364
365 /*
366 * We build and schedule packets to go out
367 * in the future. In the mean time we may
368 * process some update packets from the
369 * neighbor, thus making it necessary
370 * to update the ack we are using for
371 * this outgoing packet.
372 */
373 eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
374 seqno = ntohl(eigrph->sequence);
375 ack = ntohl(eigrph->ack);
376 if (ep->nbr && (ack != ep->nbr->recv_sequence_number)) {
377 eigrph->ack = htonl(ep->nbr->recv_sequence_number);
378 ack = ep->nbr->recv_sequence_number;
379 eigrph->checksum = 0;
380 eigrp_packet_checksum(ei, ep->s, ep->length);
381 }
382
383 sa_dst.sin_family = AF_INET;
384 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
385 sa_dst.sin_len = sizeof(sa_dst);
386 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
387 sa_dst.sin_addr = ep->dst;
388 sa_dst.sin_port = htons(0);
389
390 /* Set DONTROUTE flag if dst is unicast. */
391 if (!IN_MULTICAST(htonl(ep->dst.s_addr)))
392 flags = MSG_DONTROUTE;
393
394 iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT;
395 /* it'd be very strange for header to not be 4byte-word aligned but.. */
396 if (sizeof(struct ip)
397 > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT))
398 iph.ip_hl++; /* we presume sizeof struct ip cant overflow
399 ip_hl.. */
400
401 iph.ip_v = IPVERSION;
402 iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
403 iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length;
404
405 #if defined(__DragonFly__)
406 /*
407 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
408 */
409 iph.ip_len = htons(iph.ip_len);
410 #endif
411
412 iph.ip_off = 0;
413 iph.ip_ttl = EIGRP_IP_TTL;
414 iph.ip_p = IPPROTO_EIGRPIGP;
415 iph.ip_sum = 0;
416 iph.ip_src.s_addr = ei->address->u.prefix4.s_addr;
417 iph.ip_dst.s_addr = ep->dst.s_addr;
418
419 memset(&msg, 0, sizeof(msg));
420 msg.msg_name = (caddr_t)&sa_dst;
421 msg.msg_namelen = sizeof(sa_dst);
422 msg.msg_iov = iov;
423 msg.msg_iovlen = 2;
424
425 iov[0].iov_base = (char *)&iph;
426 iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT;
427 iov[1].iov_base = stream_pnt(ep->s);
428 iov[1].iov_len = ep->length;
429
430 /* send final fragment (could be first) */
431 sockopt_iphdrincl_swab_htosys(&iph);
432 ret = sendmsg(eigrp->fd, &msg, flags);
433 sockopt_iphdrincl_swab_systoh(&iph);
434
435 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) {
436 eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
437 zlog_debug(
438 "Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
439 lookup_msg(eigrp_packet_type_str, eigrph->opcode, NULL),
440 seqno, ack, inet_ntoa(ep->dst), IF_NAME(ei), ret);
441 }
442
443 if (ret < 0)
444 zlog_warn(
445 "*** sendmsg in eigrp_write failed to %s, "
446 "id %d, off %d, len %d, interface %s, mtu %u: %s",
447 inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off,
448 iph.ip_len, ei->ifp->name, ei->ifp->mtu,
449 safe_strerror(errno));
450
451 /* Now delete packet from queue. */
452 eigrp_packet_delete(ei);
453
454 out:
455 if (eigrp_fifo_next(ei->obuf) == NULL) {
456 ei->on_write_q = 0;
457 list_delete_node(eigrp->oi_write_q, node);
458 }
459
460 /* If packets still remain in queue, call write thread. */
461 if (!list_isempty(eigrp->oi_write_q)) {
462 eigrp->t_write = NULL;
463 thread_add_write(master, eigrp_write, eigrp, eigrp->fd,
464 &eigrp->t_write);
465 }
466
467 return 0;
468 }
469
470 /* Starting point of packet process function. */
471 int eigrp_read(struct thread *thread)
472 {
473 int ret;
474 struct stream *ibuf;
475 struct eigrp *eigrp;
476 struct eigrp_interface *ei;
477 struct ip *iph;
478 struct eigrp_header *eigrph;
479 struct interface *ifp;
480 struct eigrp_neighbor *nbr;
481
482 u_int16_t opcode = 0;
483 u_int16_t length = 0;
484
485 /* first of all get interface pointer. */
486 eigrp = THREAD_ARG(thread);
487
488 /* prepare for next packet. */
489 eigrp->t_read = NULL;
490 thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read);
491
492 stream_reset(eigrp->ibuf);
493 if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) {
494 /* This raw packet is known to be at least as big as its IP
495 * header. */
496 return -1;
497 }
498
499 /* Note that there should not be alignment problems with this assignment
500 because this is at the beginning of the stream data buffer. */
501 iph = (struct ip *)STREAM_DATA(ibuf);
502
503 // Substract IPv4 header size from EIGRP Packet itself
504 if (iph->ip_v == 4)
505 length = (iph->ip_len) - 20U;
506
507
508 /* IP Header dump. */
509 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
510 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
511 eigrp_ip_header_dump(iph);
512
513 /* Note that sockopt_iphdrincl_swab_systoh was called in
514 * eigrp_recv_packet. */
515 if (ifp == NULL) {
516 struct connected *c;
517 /* Handle cases where the platform does not support retrieving
518 the ifindex,
519 and also platforms (such as Solaris 8) that claim to support
520 ifindex
521 retrieval but do not. */
522 c = if_lookup_address((void *)&iph->ip_src, AF_INET,
523 VRF_DEFAULT);
524
525 if (c == NULL)
526 return 0;
527
528 ifp = c->ifp;
529 }
530
531 /* associate packet with eigrp interface */
532 ei = ifp->info;
533
534 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
535 only
536 after the checks below are passed. These checks in turn access the
537 fields of unverified "eigrph" structure for their own purposes and
538 must remain very accurate in doing this.
539 */
540 if (!ei)
541 return 0;
542
543 /* Self-originated packet should be discarded silently. */
544 if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src)
545 || (IPV4_ADDR_SAME(&iph->ip_src, &ei->address->u.prefix4))) {
546 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
547 zlog_debug(
548 "eigrp_read[%s]: Dropping self-originated packet",
549 inet_ntoa(iph->ip_src));
550 return 0;
551 }
552
553 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
554 by eigrp_recv_packet() to be correct). */
555
556 stream_forward_getp(ibuf, (iph->ip_hl * 4));
557 eigrph = (struct eigrp_header *)stream_pnt(ibuf);
558
559 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
560 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
561 eigrp_header_dump(eigrph);
562
563 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
564 // stream_get_getp(ibuf)))
565 // return -1;
566
567 /* If incoming interface is passive one, ignore it. */
568 if (ei && eigrp_if_is_passive(ei)) {
569 char buf[3][INET_ADDRSTRLEN];
570
571 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
572 zlog_debug(
573 "ignoring packet from router %s sent to %s, "
574 "received on a passive interface, %s",
575 inet_ntop(AF_INET, &eigrph->vrid, buf[0],
576 sizeof(buf[0])),
577 inet_ntop(AF_INET, &iph->ip_dst, buf[1],
578 sizeof(buf[1])),
579 inet_ntop(AF_INET, &ei->address->u.prefix4,
580 buf[2], sizeof(buf[2])));
581
582 if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) {
583 eigrp_if_set_multicast(ei);
584 }
585 return 0;
586 }
587
588 /* else it must be a local eigrp interface, check it was received on
589 * correct link
590 */
591 else if (ei->ifp != ifp) {
592 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
593 zlog_warn("Packet from [%s] received on wrong link %s",
594 inet_ntoa(iph->ip_src), ifp->name);
595 return 0;
596 }
597
598 /* Verify more EIGRP header fields. */
599 ret = eigrp_verify_header(ibuf, ei, iph, eigrph);
600 if (ret < 0) {
601 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
602 zlog_debug(
603 "eigrp_read[%s]: Header check failed, dropping.",
604 inet_ntoa(iph->ip_src));
605 return ret;
606 }
607
608 /* calcualte the eigrp packet length, and move the pounter to the
609 start of the eigrp TLVs */
610 opcode = eigrph->opcode;
611
612 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
613 char src[PREFIX_STRLEN], dst[PREFIX_STRLEN];
614
615 strlcpy(src, inet_ntoa(iph->ip_src), sizeof(src));
616 strlcpy(dst, inet_ntoa(iph->ip_dst), sizeof(dst));
617 zlog_debug(
618 "Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
619 lookup_msg(eigrp_packet_type_str, opcode, NULL),
620 ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
621 IF_NAME(ei), src, dst);
622 }
623
624 /* Read rest of the packet and call each sort of packet routine. */
625 stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
626
627 /* New testing block of code for handling Acks */
628 if (ntohl(eigrph->ack) != 0) {
629 struct eigrp_packet *ep = NULL;
630
631 nbr = eigrp_nbr_get(ei, eigrph, iph);
632
633 // neighbor must be valid, eigrp_nbr_get creates if none existed
634 assert(nbr);
635
636 ep = eigrp_fifo_next(nbr->retrans_queue);
637 if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) {
638 ep = eigrp_fifo_pop(nbr->retrans_queue);
639 eigrp_packet_free(ep);
640
641 if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
642 && (ntohl(eigrph->ack)
643 == nbr->init_sequence_number)) {
644 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
645 zlog_info("Neighbor(%s) adjacency became full",
646 inet_ntoa(nbr->src));
647 nbr->init_sequence_number = 0;
648 nbr->recv_sequence_number =
649 ntohl(eigrph->sequence);
650 eigrp_update_send_EOT(nbr);
651 } else
652 eigrp_send_packet_reliably(nbr);
653 }
654 ep = eigrp_fifo_next(nbr->multicast_queue);
655 if (ep) {
656 if (ntohl(eigrph->ack) == ep->sequence_number) {
657 ep = eigrp_fifo_pop(nbr->multicast_queue);
658 eigrp_packet_free(ep);
659 if (nbr->multicast_queue->count > 0) {
660 eigrp_send_packet_reliably(nbr);
661 }
662 }
663 }
664 }
665
666
667 switch (opcode) {
668 case EIGRP_OPC_HELLO:
669 eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length);
670 break;
671 case EIGRP_OPC_PROBE:
672 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
673 // length);
674 break;
675 case EIGRP_OPC_QUERY:
676 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
677 break;
678 case EIGRP_OPC_REPLY:
679 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
680 break;
681 case EIGRP_OPC_REQUEST:
682 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
683 // length);
684 break;
685 case EIGRP_OPC_SIAQUERY:
686 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
687 break;
688 case EIGRP_OPC_SIAREPLY:
689 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
690 break;
691 case EIGRP_OPC_UPDATE:
692 eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length);
693 break;
694 default:
695 zlog_warn(
696 "interface %s: EIGRP packet header type %d unsupported",
697 IF_NAME(ei), opcode);
698 break;
699 }
700
701 return 0;
702 }
703
704 static struct stream *eigrp_recv_packet(int fd, struct interface **ifp,
705 struct stream *ibuf)
706 {
707 int ret;
708 struct ip *iph;
709 u_int16_t ip_len;
710 unsigned int ifindex = 0;
711 struct iovec iov;
712 /* Header and data both require alignment. */
713 char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
714 struct msghdr msgh;
715
716 memset(&msgh, 0, sizeof(struct msghdr));
717 msgh.msg_iov = &iov;
718 msgh.msg_iovlen = 1;
719 msgh.msg_control = (caddr_t)buff;
720 msgh.msg_controllen = sizeof(buff);
721
722 ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1));
723 if (ret < 0) {
724 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
725 return NULL;
726 }
727 if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
728 {
729 zlog_warn(
730 "eigrp_recv_packet: discarding runt packet of length %d "
731 "(ip header size is %u)",
732 ret, (u_int)sizeof(iph));
733 return NULL;
734 }
735
736 /* Note that there should not be alignment problems with this assignment
737 because this is at the beginning of the stream data buffer. */
738 iph = (struct ip *)STREAM_DATA(ibuf);
739 sockopt_iphdrincl_swab_systoh(iph);
740
741 ip_len = iph->ip_len;
742
743 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
744 /*
745 * Kernel network code touches incoming IP header parameters,
746 * before protocol specific processing.
747 *
748 * 1) Convert byteorder to host representation.
749 * --> ip_len, ip_id, ip_off
750 *
751 * 2) Adjust ip_len to strip IP header size!
752 * --> If user process receives entire IP packet via RAW
753 * socket, it must consider adding IP header size to
754 * the "ip_len" field of "ip" structure.
755 *
756 * For more details, see <netinet/ip_input.c>.
757 */
758 ip_len = ip_len + (iph->ip_hl << 2);
759 #endif
760
761 #if defined(__DragonFly__)
762 /*
763 * in DragonFly's raw socket, ip_len/ip_off are read
764 * in network byte order.
765 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
766 */
767 ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
768 #endif
769
770 ifindex = getsockopt_ifindex(AF_INET, &msgh);
771
772 *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
773
774 if (ret != ip_len) {
775 zlog_warn(
776 "eigrp_recv_packet read length mismatch: ip_len is %d, "
777 "but recvmsg returned %d",
778 ip_len, ret);
779 return NULL;
780 }
781
782 return ibuf;
783 }
784
785 struct eigrp_fifo *eigrp_fifo_new(void)
786 {
787 struct eigrp_fifo *new;
788
789 new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo));
790 return new;
791 }
792
793 /* Free eigrp packet fifo. */
794 void eigrp_fifo_free(struct eigrp_fifo *fifo)
795 {
796 struct eigrp_packet *ep;
797 struct eigrp_packet *next;
798
799 for (ep = fifo->head; ep; ep = next) {
800 next = ep->next;
801 eigrp_packet_free(ep);
802 }
803 fifo->head = fifo->tail = NULL;
804 fifo->count = 0;
805
806 XFREE(MTYPE_EIGRP_FIFO, fifo);
807 }
808
809 /* Free eigrp fifo entries without destroying fifo itself*/
810 void eigrp_fifo_reset(struct eigrp_fifo *fifo)
811 {
812 struct eigrp_packet *ep;
813 struct eigrp_packet *next;
814
815 for (ep = fifo->head; ep; ep = next) {
816 next = ep->next;
817 eigrp_packet_free(ep);
818 }
819 fifo->head = fifo->tail = NULL;
820 fifo->count = 0;
821 }
822
823 struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
824 {
825 struct eigrp_packet *new;
826
827 new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
828 new->s = stream_new(size);
829 new->retrans_counter = 0;
830 new->nbr = nbr;
831
832 return new;
833 }
834
835 void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr)
836 {
837 struct eigrp_packet *ep;
838
839 ep = eigrp_fifo_next(nbr->retrans_queue);
840
841 if (ep) {
842 struct eigrp_packet *duplicate;
843 duplicate = eigrp_packet_duplicate(ep, nbr);
844 /* Add packet to the top of the interface output queue*/
845 eigrp_fifo_push(nbr->ei->obuf, duplicate);
846
847 /*Start retransmission timer*/
848 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
849 EIGRP_PACKET_RETRANS_TIME,
850 &ep->t_retrans_timer);
851
852 /*Increment sequence number counter*/
853 nbr->ei->eigrp->sequence_number++;
854
855 /* Hook thread to write packet. */
856 if (nbr->ei->on_write_q == 0) {
857 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
858 nbr->ei->on_write_q = 1;
859 }
860 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
861 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
862 }
863 }
864
865 /* Calculate EIGRP checksum */
866 void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
867 u_int16_t length)
868 {
869 struct eigrp_header *eigrph;
870
871 eigrph = (struct eigrp_header *)STREAM_DATA(s);
872
873 /* Calculate checksum. */
874 eigrph->checksum = in_cksum(eigrph, length);
875 }
876
877 /* Make EIGRP header. */
878 void eigrp_packet_header_init(int type, struct eigrp *eigrp, struct stream *s,
879 u_int32_t flags, u_int32_t sequence,
880 u_int32_t ack)
881 {
882 struct eigrp_header *eigrph;
883
884 stream_reset(s);
885 eigrph = (struct eigrp_header *)STREAM_DATA(s);
886
887 eigrph->version = (u_char)EIGRP_HEADER_VERSION;
888 eigrph->opcode = (u_char)type;
889 eigrph->checksum = 0;
890
891 eigrph->vrid = htons(eigrp->vrid);
892 eigrph->ASNumber = htons(eigrp->AS);
893 eigrph->ack = htonl(ack);
894 eigrph->sequence = htonl(sequence);
895 // if(flags == EIGRP_INIT_FLAG)
896 // eigrph->sequence = htonl(3);
897 eigrph->flags = htonl(flags);
898
899 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
900 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
901 htonl(eigrph->sequence), htonl(eigrph->ack));
902
903 stream_forward_endp(s, EIGRP_HEADER_LEN);
904 }
905
906 /* Add new packet to head of fifo. */
907 void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
908 {
909 ep->next = fifo->head;
910 ep->previous = NULL;
911
912 if (fifo->tail == NULL)
913 fifo->tail = ep;
914
915 if (fifo->count != 0)
916 fifo->head->previous = ep;
917
918 fifo->head = ep;
919
920 fifo->count++;
921 }
922
923 /* Return last fifo entry. */
924 struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
925 {
926 return fifo->tail;
927 }
928
929 void eigrp_packet_delete(struct eigrp_interface *ei)
930 {
931 struct eigrp_packet *ep;
932
933 ep = eigrp_fifo_pop(ei->obuf);
934
935 if (ep)
936 eigrp_packet_free(ep);
937 }
938
939 void eigrp_packet_free(struct eigrp_packet *ep)
940 {
941 if (ep->s)
942 stream_free(ep->s);
943
944 THREAD_OFF(ep->t_retrans_timer);
945
946 XFREE(MTYPE_EIGRP_PACKET, ep);
947
948 ep = NULL;
949 }
950
951 /* EIGRP Header verification. */
952 static int eigrp_verify_header(struct stream *ibuf, struct eigrp_interface *ei,
953 struct ip *iph, struct eigrp_header *eigrph)
954 {
955 /* Check network mask, Silently discarded. */
956 if (!eigrp_check_network_mask(ei, iph->ip_src)) {
957 zlog_warn(
958 "interface %s: eigrp_read network address is not same [%s]",
959 IF_NAME(ei), inet_ntoa(iph->ip_src));
960 return -1;
961 }
962 //
963 // /* Check authentication. The function handles logging actions, where
964 // required. */
965 // if (! eigrp_check_auth(ei, eigrph))
966 // return -1;
967
968 return 0;
969 }
970
971 /* Unbound socket will accept any Raw IP packets if proto is matched.
972 To prevent it, compare src IP address and i/f address with masking
973 i/f network mask. */
974 static int eigrp_check_network_mask(struct eigrp_interface *ei,
975 struct in_addr ip_src)
976 {
977 struct in_addr mask, me, him;
978
979 if (ei->type == EIGRP_IFTYPE_POINTOPOINT)
980 return 1;
981
982 masklen2ip(ei->address->prefixlen, &mask);
983
984 me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr;
985 him.s_addr = ip_src.s_addr & mask.s_addr;
986
987 if (IPV4_ADDR_SAME(&me, &him))
988 return 1;
989
990 return 0;
991 }
992
993 int eigrp_unack_packet_retrans(struct thread *thread)
994 {
995 struct eigrp_neighbor *nbr;
996 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
997
998 struct eigrp_packet *ep;
999 ep = eigrp_fifo_next(nbr->retrans_queue);
1000
1001 if (ep) {
1002 struct eigrp_packet *duplicate;
1003 duplicate = eigrp_packet_duplicate(ep, nbr);
1004
1005 /* Add packet to the top of the interface output queue*/
1006 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1007
1008 ep->retrans_counter++;
1009 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1010 return eigrp_retrans_count_exceeded(ep, nbr);
1011
1012 /*Start retransmission timer*/
1013 ep->t_retrans_timer = NULL;
1014 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
1015 EIGRP_PACKET_RETRANS_TIME,
1016 &ep->t_retrans_timer);
1017
1018 /* Hook thread to write packet. */
1019 if (nbr->ei->on_write_q == 0) {
1020 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1021 nbr->ei->on_write_q = 1;
1022 }
1023 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1024 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1025 }
1026
1027 return 0;
1028 }
1029
1030 int eigrp_unack_multicast_packet_retrans(struct thread *thread)
1031 {
1032 struct eigrp_neighbor *nbr;
1033 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
1034
1035 struct eigrp_packet *ep;
1036 ep = eigrp_fifo_next(nbr->multicast_queue);
1037
1038 if (ep) {
1039 struct eigrp_packet *duplicate;
1040 duplicate = eigrp_packet_duplicate(ep, nbr);
1041 /* Add packet to the top of the interface output queue*/
1042 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1043
1044 ep->retrans_counter++;
1045 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1046 return eigrp_retrans_count_exceeded(ep, nbr);
1047
1048 /*Start retransmission timer*/
1049 ep->t_retrans_timer = NULL;
1050 thread_add_timer(master, eigrp_unack_multicast_packet_retrans,
1051 nbr, EIGRP_PACKET_RETRANS_TIME,
1052 &ep->t_retrans_timer);
1053
1054 /* Hook thread to write packet. */
1055 if (nbr->ei->on_write_q == 0) {
1056 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1057 nbr->ei->on_write_q = 1;
1058 }
1059 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1060 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1061 }
1062
1063 return 0;
1064 }
1065
1066 /* Get packet from tail of fifo. */
1067 struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
1068 {
1069 struct eigrp_packet *ep = NULL;
1070
1071 ep = fifo->tail;
1072
1073 if (ep) {
1074 fifo->tail = ep->previous;
1075
1076 if (fifo->tail == NULL)
1077 fifo->head = NULL;
1078 else
1079 fifo->tail->next = NULL;
1080
1081 fifo->count--;
1082 }
1083
1084 return ep;
1085 }
1086
1087 struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
1088 struct eigrp_neighbor *nbr)
1089 {
1090 struct eigrp_packet *new;
1091
1092 new = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
1093 new->length = old->length;
1094 new->retrans_counter = old->retrans_counter;
1095 new->dst = old->dst;
1096 new->sequence_number = old->sequence_number;
1097 stream_copy(new->s, old->s);
1098
1099 return new;
1100 }
1101
1102 static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
1103 {
1104 struct TLV_IPv4_Internal_type *new;
1105
1106 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
1107 sizeof(struct TLV_IPv4_Internal_type));
1108
1109 return new;
1110 }
1111
1112 struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
1113 {
1114 struct TLV_IPv4_Internal_type *tlv;
1115
1116 tlv = eigrp_IPv4_InternalTLV_new();
1117
1118 tlv->type = stream_getw(s);
1119 tlv->length = stream_getw(s);
1120 tlv->forward.s_addr = stream_getl(s);
1121 tlv->metric.delay = stream_getl(s);
1122 tlv->metric.bandwidth = stream_getl(s);
1123 tlv->metric.mtu[0] = stream_getc(s);
1124 tlv->metric.mtu[1] = stream_getc(s);
1125 tlv->metric.mtu[2] = stream_getc(s);
1126 tlv->metric.hop_count = stream_getc(s);
1127 tlv->metric.reliability = stream_getc(s);
1128 tlv->metric.load = stream_getc(s);
1129 tlv->metric.tag = stream_getc(s);
1130 tlv->metric.flags = stream_getc(s);
1131
1132 tlv->prefix_length = stream_getc(s);
1133
1134 if (tlv->prefix_length <= 8) {
1135 tlv->destination_part[0] = stream_getc(s);
1136 tlv->destination.s_addr = (tlv->destination_part[0]);
1137 } else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) {
1138 tlv->destination_part[0] = stream_getc(s);
1139 tlv->destination_part[1] = stream_getc(s);
1140 tlv->destination.s_addr = ((tlv->destination_part[1] << 8)
1141 + tlv->destination_part[0]);
1142 } else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) {
1143 tlv->destination_part[0] = stream_getc(s);
1144 tlv->destination_part[1] = stream_getc(s);
1145 tlv->destination_part[2] = stream_getc(s);
1146 tlv->destination.s_addr = ((tlv->destination_part[2] << 16)
1147 + (tlv->destination_part[1] << 8)
1148 + tlv->destination_part[0]);
1149 } else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) {
1150 tlv->destination_part[0] = stream_getc(s);
1151 tlv->destination_part[1] = stream_getc(s);
1152 tlv->destination_part[2] = stream_getc(s);
1153 tlv->destination_part[3] = stream_getc(s);
1154 tlv->destination.s_addr = ((tlv->destination_part[3] << 24)
1155 + (tlv->destination_part[2] << 16)
1156 + (tlv->destination_part[1] << 8)
1157 + tlv->destination_part[0]);
1158 }
1159 return tlv;
1160 }
1161
1162 u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
1163 struct eigrp_prefix_entry *pe)
1164 {
1165 u_int16_t length;
1166
1167 stream_putw(s, EIGRP_TLV_IPv4_INT);
1168 switch (pe->destination->prefixlen) {
1169 case 0:
1170 case 1:
1171 case 2:
1172 case 3:
1173 case 4:
1174 case 5:
1175 case 6:
1176 case 7:
1177 case 8:
1178 length = EIGRP_TLV_IPV4_SIZE_GRT_0_BIT;
1179 stream_putw(s, length);
1180 break;
1181 case 9:
1182 case 10:
1183 case 11:
1184 case 12:
1185 case 13:
1186 case 14:
1187 case 15:
1188 case 16:
1189 length = EIGRP_TLV_IPV4_SIZE_GRT_8_BIT;
1190 stream_putw(s, length);
1191 break;
1192 case 17:
1193 case 18:
1194 case 19:
1195 case 20:
1196 case 21:
1197 case 22:
1198 case 23:
1199 case 24:
1200 length = EIGRP_TLV_IPV4_SIZE_GRT_16_BIT;
1201 stream_putw(s, length);
1202 break;
1203 case 25:
1204 case 26:
1205 case 27:
1206 case 28:
1207 case 29:
1208 case 30:
1209 case 31:
1210 case 32:
1211 length = EIGRP_TLV_IPV4_SIZE_GRT_24_BIT;
1212 stream_putw(s, length);
1213 break;
1214 default:
1215 zlog_err("%s: Unexpected prefix length: %d",
1216 __PRETTY_FUNCTION__, pe->destination->prefixlen);
1217 return 0;
1218 }
1219 stream_putl(s, 0x00000000);
1220
1221 /*Metric*/
1222 stream_putl(s, pe->reported_metric.delay);
1223 stream_putl(s, pe->reported_metric.bandwidth);
1224 stream_putc(s, pe->reported_metric.mtu[2]);
1225 stream_putc(s, pe->reported_metric.mtu[1]);
1226 stream_putc(s, pe->reported_metric.mtu[0]);
1227 stream_putc(s, pe->reported_metric.hop_count);
1228 stream_putc(s, pe->reported_metric.reliability);
1229 stream_putc(s, pe->reported_metric.load);
1230 stream_putc(s, pe->reported_metric.tag);
1231 stream_putc(s, pe->reported_metric.flags);
1232
1233 stream_putc(s, pe->destination->prefixlen);
1234
1235 stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
1236 if (pe->destination->prefixlen > 8)
1237 stream_putc(s, (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
1238 if (pe->destination->prefixlen > 16)
1239 stream_putc(s,
1240 (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
1241 if (pe->destination->prefixlen > 24)
1242 stream_putc(s,
1243 (pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
1244
1245 return length;
1246 }
1247
1248 u_int16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s,
1249 struct eigrp_interface *ei)
1250 {
1251 struct key *key;
1252 struct keychain *keychain;
1253 struct TLV_MD5_Authentication_Type *authTLV;
1254
1255 authTLV = eigrp_authTLV_MD5_new();
1256
1257 authTLV->type = htons(EIGRP_TLV_AUTH);
1258 authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE);
1259 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5);
1260 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN);
1261 authTLV->key_sequence = 0;
1262 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1263
1264 keychain = keychain_lookup(ei->params.auth_keychain);
1265 if (keychain)
1266 key = key_lookup_for_send(keychain);
1267 else {
1268 free(ei->params.auth_keychain);
1269 ei->params.auth_keychain = NULL;
1270 eigrp_authTLV_MD5_free(authTLV);
1271 return 0;
1272 }
1273
1274 if (key) {
1275 authTLV->key_id = htonl(key->index);
1276 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
1277 stream_put(s, authTLV,
1278 sizeof(struct TLV_MD5_Authentication_Type));
1279 eigrp_authTLV_MD5_free(authTLV);
1280 return EIGRP_AUTH_MD5_TLV_SIZE;
1281 }
1282
1283 eigrp_authTLV_MD5_free(authTLV);
1284
1285 return 0;
1286 }
1287
1288 u_int16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s,
1289 struct eigrp_interface *ei)
1290 {
1291 struct key *key;
1292 struct keychain *keychain;
1293 struct TLV_SHA256_Authentication_Type *authTLV;
1294
1295 authTLV = eigrp_authTLV_SHA256_new();
1296
1297 authTLV->type = htons(EIGRP_TLV_AUTH);
1298 authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE);
1299 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256);
1300 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN);
1301 authTLV->key_sequence = 0;
1302 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1303
1304 keychain = keychain_lookup(ei->params.auth_keychain);
1305 if (keychain)
1306 key = key_lookup_for_send(keychain);
1307 else {
1308 free(ei->params.auth_keychain);
1309 ei->params.auth_keychain = NULL;
1310 eigrp_authTLV_SHA256_free(authTLV);
1311 return 0;
1312 }
1313
1314 if (key) {
1315 authTLV->key_id = 0;
1316 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_SHA256_LEN);
1317 stream_put(s, authTLV,
1318 sizeof(struct TLV_SHA256_Authentication_Type));
1319 eigrp_authTLV_SHA256_free(authTLV);
1320 return EIGRP_AUTH_SHA256_TLV_SIZE;
1321 }
1322
1323 eigrp_authTLV_SHA256_free(authTLV);
1324
1325 return 0;
1326 }
1327
1328 struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new()
1329 {
1330 struct TLV_MD5_Authentication_Type *new;
1331
1332 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV,
1333 sizeof(struct TLV_MD5_Authentication_Type));
1334
1335 return new;
1336 }
1337
1338 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV)
1339 {
1340 XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV);
1341 }
1342
1343 struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new()
1344 {
1345 struct TLV_SHA256_Authentication_Type *new;
1346
1347 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV,
1348 sizeof(struct TLV_SHA256_Authentication_Type));
1349
1350 return new;
1351 }
1352
1353 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
1354 {
1355 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
1356 }
1357
1358 void eigrp_IPv4_InternalTLV_free(
1359 struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
1360 {
1361 XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV);
1362 }
1363
1364 struct TLV_Sequence_Type *eigrp_SequenceTLV_new()
1365 {
1366 struct TLV_Sequence_Type *new;
1367
1368 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type));
1369
1370 return new;
1371 }