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 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include "if.h" 25#include "prefix.h" 26#include "command.h" 27#include "linklist.h" 28#include "thread.h" 29#include "memory.h" 30 31#include "ripd/ripd.h" 32 33/* Linked list of RIP peer. */ 34struct list *peer_list; 35 36static struct rip_peer * 37rip_peer_new (void) 38{ 39 return XCALLOC (MTYPE_RIP_PEER, sizeof (struct rip_peer)); 40} 41 42static void 43rip_peer_free (struct rip_peer *peer) 44{ 45 XFREE (MTYPE_RIP_PEER, peer); 46} 47 48struct rip_peer * 49rip_peer_lookup (struct in_addr *addr) 50{ 51 struct rip_peer *peer; 52 struct listnode *node, *nnode; 53 54 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 55 { 56 if (IPV4_ADDR_SAME (&peer->addr, addr)) 57 return peer; 58 } 59 return NULL; 60} 61 62struct rip_peer * 63rip_peer_lookup_next (struct in_addr *addr) 64{ 65 struct rip_peer *peer; 66 struct listnode *node, *nnode; 67 68 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 69 { 70 if (htonl (peer->addr.s_addr) > htonl (addr->s_addr)) 71 return peer; 72 } 73 return NULL; 74} 75 76/* RIP peer is timeout. */ 77static int 78rip_peer_timeout (struct thread *t) 79{ 80 struct rip_peer *peer; 81 82 peer = THREAD_ARG (t); 83 listnode_delete (peer_list, peer); 84 rip_peer_free (peer); 85 86 return 0; 87} 88 89/* Get RIP peer. At the same time update timeout thread. */ 90static struct rip_peer * 91rip_peer_get (struct in_addr *addr) 92{ 93 struct rip_peer *peer; 94 95 peer = rip_peer_lookup (addr); 96 97 if (peer) 98 { 99 if (peer->t_timeout) 100 thread_cancel (peer->t_timeout); 101 } 102 else 103 { 104 peer = rip_peer_new (); 105 peer->addr = *addr; 106 listnode_add_sort (peer_list, peer); 107 } 108 109 /* Update timeout thread. */ 110 peer->t_timeout = thread_add_timer (master, rip_peer_timeout, peer, 111 RIP_PEER_TIMER_DEFAULT); 112 113 /* Last update time set. */ 114 time (&peer->uptime); 115 116 return peer; 117} 118 119void 120rip_peer_update (struct sockaddr_in *from, u_char version) 121{ 122 struct rip_peer *peer; 123 peer = rip_peer_get (&from->sin_addr); 124 peer->version = version; 125} 126 127void 128rip_peer_bad_route (struct sockaddr_in *from) 129{ 130 struct rip_peer *peer; 131 peer = rip_peer_get (&from->sin_addr); 132 peer->recv_badroutes++; 133} 134 135void 136rip_peer_bad_packet (struct sockaddr_in *from) 137{ 138 struct rip_peer *peer; 139 peer = rip_peer_get (&from->sin_addr); 140 peer->recv_badpackets++; 141} 142 143/* Display peer uptime. */ 144static char * 145rip_peer_uptime (struct rip_peer *peer, char *buf, size_t len) 146{ 147 time_t uptime; 148 struct tm *tm; 149 150 /* If there is no connection has been done before print `never'. */ 151 if (peer->uptime == 0) 152 { 153 snprintf (buf, len, "never "); 154 return buf; 155 } 156 157 /* Get current time. */ 158 uptime = time (NULL); 159 uptime -= peer->uptime; 160 tm = gmtime (&uptime); 161 162 /* Making formatted timer strings. */ 163#define ONE_DAY_SECOND 60*60*24 164#define ONE_WEEK_SECOND 60*60*24*7 165 166 if (uptime < ONE_DAY_SECOND) 167 snprintf (buf, len, "%02d:%02d:%02d", 168 tm->tm_hour, tm->tm_min, tm->tm_sec); 169 else if (uptime < ONE_WEEK_SECOND) 170 snprintf (buf, len, "%dd%02dh%02dm", 171 tm->tm_yday, tm->tm_hour, tm->tm_min); 172 else 173 snprintf (buf, len, "%02dw%dd%02dh", 174 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); 175 return buf; 176} 177 178void 179rip_peer_display (struct vty *vty) 180{ 181 struct rip_peer *peer; 182 struct listnode *node, *nnode; 183#define RIP_UPTIME_LEN 25 184 char timebuf[RIP_UPTIME_LEN]; 185 186 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 187 { 188 vty_out (vty, " %-16s %9d %9d %9d %s%s", inet_ntoa (peer->addr), 189 peer->recv_badpackets, peer->recv_badroutes, 190 ZEBRA_RIP_DISTANCE_DEFAULT, 191 rip_peer_uptime (peer, timebuf, RIP_UPTIME_LEN), 192 VTY_NEWLINE); 193 } 194} 195 196static int 197rip_peer_list_cmp (struct rip_peer *p1, struct rip_peer *p2) 198{ 199 return htonl (p1->addr.s_addr) > htonl (p2->addr.s_addr); 200} 201 202void 203rip_peer_init (void) 204{ 205 peer_list = list_new (); 206 peer_list->cmp = (int (*)(void *, void *)) rip_peer_list_cmp; 207} 208