Line data Source code
1 : /* RIP 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 : *
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
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "if.h"
24 : #include "prefix.h"
25 : #include "command.h"
26 : #include "linklist.h"
27 : #include "thread.h"
28 : #include "memory.h"
29 :
30 : #include "ripd/ripd.h"
31 :
32 3 : DEFINE_MTYPE_STATIC(RIPD, RIP_PEER, "RIP peer");
33 :
34 0 : static struct rip_peer *rip_peer_new(void)
35 : {
36 0 : return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));
37 : }
38 :
39 0 : static void rip_peer_free(struct rip_peer *peer)
40 : {
41 0 : THREAD_OFF(peer->t_timeout);
42 0 : XFREE(MTYPE_RIP_PEER, peer);
43 0 : }
44 :
45 0 : struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr)
46 : {
47 0 : struct rip_peer *peer;
48 0 : struct listnode *node, *nnode;
49 :
50 0 : for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
51 0 : if (IPV4_ADDR_SAME(&peer->addr, addr))
52 0 : return peer;
53 : }
54 : return NULL;
55 : }
56 :
57 0 : struct rip_peer *rip_peer_lookup_next(struct rip *rip, struct in_addr *addr)
58 : {
59 0 : struct rip_peer *peer;
60 0 : struct listnode *node, *nnode;
61 :
62 0 : for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
63 0 : if (htonl(peer->addr.s_addr) > htonl(addr->s_addr))
64 0 : return peer;
65 : }
66 : return NULL;
67 : }
68 :
69 : /* RIP peer is timeout. */
70 0 : static void rip_peer_timeout(struct thread *t)
71 : {
72 0 : struct rip_peer *peer;
73 :
74 0 : peer = THREAD_ARG(t);
75 0 : listnode_delete(peer->rip->peer_list, peer);
76 0 : rip_peer_free(peer);
77 0 : }
78 :
79 : /* Get RIP peer. At the same time update timeout thread. */
80 0 : static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)
81 : {
82 0 : struct rip_peer *peer;
83 :
84 0 : peer = rip_peer_lookup(rip, addr);
85 :
86 0 : if (peer) {
87 0 : THREAD_OFF(peer->t_timeout);
88 : } else {
89 0 : peer = rip_peer_new();
90 0 : peer->rip = rip;
91 0 : peer->addr = *addr;
92 0 : listnode_add_sort(rip->peer_list, peer);
93 : }
94 :
95 : /* Update timeout thread. */
96 0 : thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT,
97 : &peer->t_timeout);
98 :
99 : /* Last update time set. */
100 0 : time(&peer->uptime);
101 :
102 0 : return peer;
103 : }
104 :
105 0 : void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version)
106 : {
107 0 : struct rip_peer *peer;
108 0 : peer = rip_peer_get(rip, &from->sin_addr);
109 0 : peer->version = version;
110 0 : }
111 :
112 0 : void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from)
113 : {
114 0 : struct rip_peer *peer;
115 0 : peer = rip_peer_get(rip, &from->sin_addr);
116 0 : peer->recv_badroutes++;
117 0 : }
118 :
119 0 : void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from)
120 : {
121 0 : struct rip_peer *peer;
122 0 : peer = rip_peer_get(rip, &from->sin_addr);
123 0 : peer->recv_badpackets++;
124 0 : }
125 :
126 : /* Display peer uptime. */
127 0 : static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
128 : {
129 0 : time_t uptime;
130 :
131 : /* If there is no connection has been done before print `never'. */
132 0 : if (peer->uptime == 0) {
133 0 : snprintf(buf, len, "never ");
134 0 : return buf;
135 : }
136 :
137 : /* Get current time. */
138 0 : uptime = time(NULL);
139 0 : uptime -= peer->uptime;
140 :
141 0 : frrtime_to_interval(uptime, buf, len);
142 :
143 0 : return buf;
144 : }
145 :
146 1 : void rip_peer_display(struct vty *vty, struct rip *rip)
147 : {
148 1 : struct rip_peer *peer;
149 1 : struct listnode *node, *nnode;
150 : #define RIP_UPTIME_LEN 25
151 1 : char timebuf[RIP_UPTIME_LEN];
152 :
153 2 : for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
154 0 : vty_out(vty, " %-16pI4 %9d %9d %9d %s\n",
155 : &peer->addr, peer->recv_badpackets,
156 : peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT,
157 : rip_peer_uptime(peer, timebuf, RIP_UPTIME_LEN));
158 : }
159 1 : }
160 :
161 0 : int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
162 : {
163 0 : if (p2->addr.s_addr == p1->addr.s_addr)
164 : return 0;
165 :
166 0 : return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1;
167 : }
168 :
169 0 : void rip_peer_list_del(void *arg)
170 : {
171 0 : rip_peer_free(arg);
172 0 : }
|