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