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