]>
Commit | Line | Data |
---|---|---|
a94434b6 | 1 | /* RIPng peer support |
2 | * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> | |
3 | * | |
4 | * This file is part of GNU Zebra. | |
5 | * | |
6 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2, or (at your option) any | |
9 | * later version. | |
10 | * | |
11 | * GNU Zebra is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
896014f4 DL |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
a94434b6 | 19 | */ |
20 | ||
21 | /* RIPng support added by Vincent Jardin <vincent.jardin@6wind.com> | |
22 | * Copyright (C) 2002 6WIND | |
23 | */ | |
24 | ||
25 | #include <zebra.h> | |
26 | ||
27 | #include "if.h" | |
28 | #include "prefix.h" | |
29 | #include "command.h" | |
30 | #include "linklist.h" | |
31 | #include "thread.h" | |
32 | #include "memory.h" | |
33 | ||
34 | #include "ripngd/ripngd.h" | |
35 | #include "ripngd/ripng_nexthop.h" | |
36 | ||
37 | ||
38 | /* Linked list of RIPng peer. */ | |
39 | struct list *peer_list; | |
6b0655a2 | 40 | |
6ac29a51 PJ |
41 | static struct ripng_peer * |
42 | ripng_peer_new (void) | |
a94434b6 | 43 | { |
393deb9b | 44 | return XCALLOC (MTYPE_RIPNG_PEER, sizeof (struct ripng_peer)); |
a94434b6 | 45 | } |
46 | ||
6ac29a51 | 47 | static void |
a94434b6 | 48 | ripng_peer_free (struct ripng_peer *peer) |
49 | { | |
50 | XFREE (MTYPE_RIPNG_PEER, peer); | |
51 | } | |
52 | ||
53 | struct ripng_peer * | |
54 | ripng_peer_lookup (struct in6_addr *addr) | |
55 | { | |
56 | struct ripng_peer *peer; | |
1eb8ef25 | 57 | struct listnode *node, *nnode; |
a94434b6 | 58 | |
1eb8ef25 | 59 | for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) |
a94434b6 | 60 | { |
61 | if (IPV6_ADDR_SAME (&peer->addr, addr)) | |
62 | return peer; | |
63 | } | |
64 | return NULL; | |
65 | } | |
66 | ||
67 | struct ripng_peer * | |
68 | ripng_peer_lookup_next (struct in6_addr *addr) | |
69 | { | |
70 | struct ripng_peer *peer; | |
1eb8ef25 | 71 | struct listnode *node, *nnode; |
a94434b6 | 72 | |
1eb8ef25 | 73 | for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) |
a94434b6 | 74 | { |
75 | if (addr6_cmp(&peer->addr, addr) > 0) | |
76 | return peer; | |
77 | } | |
78 | return NULL; | |
79 | } | |
80 | ||
81 | /* RIPng peer is timeout. | |
82 | * Garbage collector. | |
83 | **/ | |
6ac29a51 | 84 | static int |
a94434b6 | 85 | ripng_peer_timeout (struct thread *t) |
86 | { | |
87 | struct ripng_peer *peer; | |
88 | ||
89 | peer = THREAD_ARG (t); | |
90 | listnode_delete (peer_list, peer); | |
91 | ripng_peer_free (peer); | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
96 | /* Get RIPng peer. At the same time update timeout thread. */ | |
6ac29a51 | 97 | static struct ripng_peer * |
a94434b6 | 98 | ripng_peer_get (struct in6_addr *addr) |
99 | { | |
100 | struct ripng_peer *peer; | |
101 | ||
102 | peer = ripng_peer_lookup (addr); | |
103 | ||
104 | if (peer) | |
105 | { | |
106 | if (peer->t_timeout) | |
107 | thread_cancel (peer->t_timeout); | |
108 | } | |
109 | else | |
110 | { | |
111 | peer = ripng_peer_new (); | |
112 | peer->addr = *addr; /* XXX */ | |
113 | listnode_add_sort (peer_list, peer); | |
114 | } | |
115 | ||
116 | /* Update timeout thread. */ | |
66e78ae6 QY |
117 | peer->t_timeout = NULL; |
118 | thread_add_timer(master, ripng_peer_timeout, peer, RIPNG_PEER_TIMER_DEFAULT, | |
119 | &peer->t_timeout); | |
a94434b6 | 120 | |
121 | /* Last update time set. */ | |
122 | time (&peer->uptime); | |
123 | ||
124 | return peer; | |
125 | } | |
126 | ||
127 | void | |
128 | ripng_peer_update (struct sockaddr_in6 *from, u_char version) | |
129 | { | |
130 | struct ripng_peer *peer; | |
131 | peer = ripng_peer_get (&from->sin6_addr); | |
132 | peer->version = version; | |
133 | } | |
134 | ||
135 | void | |
136 | ripng_peer_bad_route (struct sockaddr_in6 *from) | |
137 | { | |
138 | struct ripng_peer *peer; | |
139 | peer = ripng_peer_get (&from->sin6_addr); | |
140 | peer->recv_badroutes++; | |
141 | } | |
142 | ||
143 | void | |
144 | ripng_peer_bad_packet (struct sockaddr_in6 *from) | |
145 | { | |
146 | struct ripng_peer *peer; | |
147 | peer = ripng_peer_get (&from->sin6_addr); | |
148 | peer->recv_badpackets++; | |
149 | } | |
150 | ||
151 | /* Display peer uptime. */ | |
6ac29a51 | 152 | static char * |
a94434b6 | 153 | ripng_peer_uptime (struct ripng_peer *peer, char *buf, size_t len) |
154 | { | |
155 | time_t uptime; | |
156 | struct tm *tm; | |
157 | ||
158 | /* If there is no connection has been done before print `never'. */ | |
159 | if (peer->uptime == 0) | |
160 | { | |
161 | snprintf (buf, len, "never "); | |
162 | return buf; | |
163 | } | |
164 | ||
165 | /* Get current time. */ | |
166 | uptime = time (NULL); | |
167 | uptime -= peer->uptime; | |
168 | tm = gmtime (&uptime); | |
169 | ||
170 | /* Making formatted timer strings. */ | |
171 | #define ONE_DAY_SECOND 60*60*24 | |
172 | #define ONE_WEEK_SECOND 60*60*24*7 | |
173 | ||
174 | if (uptime < ONE_DAY_SECOND) | |
175 | snprintf (buf, len, "%02d:%02d:%02d", | |
176 | tm->tm_hour, tm->tm_min, tm->tm_sec); | |
177 | else if (uptime < ONE_WEEK_SECOND) | |
178 | snprintf (buf, len, "%dd%02dh%02dm", | |
179 | tm->tm_yday, tm->tm_hour, tm->tm_min); | |
180 | else | |
181 | snprintf (buf, len, "%02dw%dd%02dh", | |
182 | tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); | |
183 | return buf; | |
184 | } | |
185 | ||
186 | void | |
187 | ripng_peer_display (struct vty *vty) | |
188 | { | |
189 | struct ripng_peer *peer; | |
1eb8ef25 | 190 | struct listnode *node, *nnode; |
a94434b6 | 191 | #define RIPNG_UPTIME_LEN 25 |
192 | char timebuf[RIPNG_UPTIME_LEN]; | |
193 | ||
1eb8ef25 | 194 | for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) |
a94434b6 | 195 | { |
3a2ce6a1 | 196 | vty_out (vty, " %s %s%14s %10d %10d %10d %s%s", inet6_ntoa (peer->addr), |
a94434b6 | 197 | VTY_NEWLINE, " ", |
198 | peer->recv_badpackets, peer->recv_badroutes, | |
199 | ZEBRA_RIPNG_DISTANCE_DEFAULT, | |
200 | ripng_peer_uptime (peer, timebuf, RIPNG_UPTIME_LEN), | |
201 | VTY_NEWLINE); | |
202 | } | |
203 | } | |
204 | ||
6ac29a51 | 205 | static int |
a94434b6 | 206 | ripng_peer_list_cmp (struct ripng_peer *p1, struct ripng_peer *p2) |
207 | { | |
208 | return addr6_cmp(&p1->addr, &p2->addr) > 0; | |
209 | } | |
210 | ||
211 | void | |
212 | ripng_peer_init () | |
213 | { | |
214 | peer_list = list_new (); | |
215 | peer_list->cmp = (int (*)(void *, void *)) ripng_peer_list_cmp; | |
216 | } |