]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
a94434b6 | 2 | /* RIPng peer support |
3 | * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> | |
a94434b6 | 4 | */ |
5 | ||
6 | /* RIPng support added by Vincent Jardin <vincent.jardin@6wind.com> | |
7 | * Copyright (C) 2002 6WIND | |
8 | */ | |
9 | ||
10 | #include <zebra.h> | |
11 | ||
12 | #include "if.h" | |
13 | #include "prefix.h" | |
14 | #include "command.h" | |
15 | #include "linklist.h" | |
cb37cb33 | 16 | #include "event.h" |
a94434b6 | 17 | #include "memory.h" |
18 | ||
19 | #include "ripngd/ripngd.h" | |
20 | #include "ripngd/ripng_nexthop.h" | |
21 | ||
bf8d3d6a | 22 | DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_PEER, "RIPng peer"); |
b3a7e30d | 23 | |
d62a17ae | 24 | static struct ripng_peer *ripng_peer_new(void) |
a94434b6 | 25 | { |
d62a17ae | 26 | return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer)); |
a94434b6 | 27 | } |
28 | ||
d62a17ae | 29 | static void ripng_peer_free(struct ripng_peer *peer) |
a94434b6 | 30 | { |
e16d030c | 31 | EVENT_OFF(peer->t_timeout); |
d62a17ae | 32 | XFREE(MTYPE_RIPNG_PEER, peer); |
a94434b6 | 33 | } |
34 | ||
5c84b9a5 | 35 | struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr) |
a94434b6 | 36 | { |
d62a17ae | 37 | struct ripng_peer *peer; |
38 | struct listnode *node, *nnode; | |
39 | ||
ecece94c | 40 | for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { |
d62a17ae | 41 | if (IPV6_ADDR_SAME(&peer->addr, addr)) |
42 | return peer; | |
43 | } | |
44 | return NULL; | |
a94434b6 | 45 | } |
46 | ||
5c84b9a5 RW |
47 | struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng, |
48 | struct in6_addr *addr) | |
a94434b6 | 49 | { |
d62a17ae | 50 | struct ripng_peer *peer; |
51 | struct listnode *node, *nnode; | |
52 | ||
ecece94c | 53 | for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { |
d62a17ae | 54 | if (addr6_cmp(&peer->addr, addr) > 0) |
55 | return peer; | |
56 | } | |
57 | return NULL; | |
a94434b6 | 58 | } |
59 | ||
60 | /* RIPng peer is timeout. | |
61 | * Garbage collector. | |
62 | **/ | |
e6685141 | 63 | static void ripng_peer_timeout(struct event *t) |
a94434b6 | 64 | { |
d62a17ae | 65 | struct ripng_peer *peer; |
a94434b6 | 66 | |
e16d030c | 67 | peer = EVENT_ARG(t); |
5c84b9a5 | 68 | listnode_delete(peer->ripng->peer_list, peer); |
d62a17ae | 69 | ripng_peer_free(peer); |
a94434b6 | 70 | } |
71 | ||
72 | /* Get RIPng peer. At the same time update timeout thread. */ | |
5c84b9a5 RW |
73 | static struct ripng_peer *ripng_peer_get(struct ripng *ripng, |
74 | struct in6_addr *addr) | |
a94434b6 | 75 | { |
d62a17ae | 76 | struct ripng_peer *peer; |
77 | ||
5c84b9a5 | 78 | peer = ripng_peer_lookup(ripng, addr); |
d62a17ae | 79 | |
80 | if (peer) { | |
e16d030c | 81 | EVENT_OFF(peer->t_timeout); |
d62a17ae | 82 | } else { |
83 | peer = ripng_peer_new(); | |
5c84b9a5 RW |
84 | peer->ripng = ripng; |
85 | peer->addr = *addr; | |
ecece94c | 86 | listnode_add_sort(ripng->peer_list, peer); |
d62a17ae | 87 | } |
88 | ||
89 | /* Update timeout thread. */ | |
907a2395 DS |
90 | event_add_timer(master, ripng_peer_timeout, peer, |
91 | RIPNG_PEER_TIMER_DEFAULT, &peer->t_timeout); | |
d62a17ae | 92 | |
93 | /* Last update time set. */ | |
94 | time(&peer->uptime); | |
95 | ||
96 | return peer; | |
a94434b6 | 97 | } |
98 | ||
5c84b9a5 RW |
99 | void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from, |
100 | uint8_t version) | |
a94434b6 | 101 | { |
d62a17ae | 102 | struct ripng_peer *peer; |
5c84b9a5 | 103 | peer = ripng_peer_get(ripng, &from->sin6_addr); |
d62a17ae | 104 | peer->version = version; |
a94434b6 | 105 | } |
106 | ||
5c84b9a5 | 107 | void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from) |
a94434b6 | 108 | { |
d62a17ae | 109 | struct ripng_peer *peer; |
5c84b9a5 | 110 | peer = ripng_peer_get(ripng, &from->sin6_addr); |
d62a17ae | 111 | peer->recv_badroutes++; |
a94434b6 | 112 | } |
113 | ||
5c84b9a5 | 114 | void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from) |
a94434b6 | 115 | { |
d62a17ae | 116 | struct ripng_peer *peer; |
5c84b9a5 | 117 | peer = ripng_peer_get(ripng, &from->sin6_addr); |
d62a17ae | 118 | peer->recv_badpackets++; |
a94434b6 | 119 | } |
120 | ||
121 | /* Display peer uptime. */ | |
d62a17ae | 122 | static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len) |
a94434b6 | 123 | { |
d62a17ae | 124 | time_t uptime; |
d62a17ae | 125 | |
126 | /* If there is no connection has been done before print `never'. */ | |
127 | if (peer->uptime == 0) { | |
128 | snprintf(buf, len, "never "); | |
129 | return buf; | |
130 | } | |
131 | ||
132 | /* Get current time. */ | |
133 | uptime = time(NULL); | |
134 | uptime -= peer->uptime; | |
d0636ead MS |
135 | |
136 | frrtime_to_interval(uptime, buf, len); | |
137 | ||
d62a17ae | 138 | return buf; |
a94434b6 | 139 | } |
140 | ||
5c84b9a5 | 141 | void ripng_peer_display(struct vty *vty, struct ripng *ripng) |
a94434b6 | 142 | { |
d62a17ae | 143 | struct ripng_peer *peer; |
144 | struct listnode *node, *nnode; | |
a94434b6 | 145 | #define RIPNG_UPTIME_LEN 25 |
d62a17ae | 146 | char timebuf[RIPNG_UPTIME_LEN]; |
147 | ||
ecece94c | 148 | for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { |
2e5b3f37 MS |
149 | vty_out(vty, " %pI6 \n%14s %10d %10d %10d %s\n", |
150 | &peer->addr, " ", peer->recv_badpackets, | |
d62a17ae | 151 | peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT, |
152 | ripng_peer_uptime(peer, timebuf, RIPNG_UPTIME_LEN)); | |
153 | } | |
a94434b6 | 154 | } |
155 | ||
ecece94c | 156 | int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) |
a94434b6 | 157 | { |
27fa3398 | 158 | return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr)); |
a94434b6 | 159 | } |
56bf1cb2 RW |
160 | |
161 | void ripng_peer_list_del(void *arg) | |
162 | { | |
163 | ripng_peer_free(arg); | |
164 | } |