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 * 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/* RIPng support added by Vincent Jardin <vincent.jardin@6wind.com> 23 * Copyright (C) 2002 6WIND 24 */ 25 26#include <zebra.h> 27 28#include "if.h" 29#include "prefix.h" 30#include "command.h" 31#include "linklist.h" 32#include "thread.h" 33#include "memory.h" 34 35#include "ripngd/ripngd.h" 36#include "ripngd/ripng_nexthop.h" 37 38 39/* Linked list of RIPng peer. */ 40struct list *peer_list; 41 42static struct ripng_peer * 43ripng_peer_new (void) 44{ 45 return XCALLOC (MTYPE_RIPNG_PEER, sizeof (struct ripng_peer)); 46} 47 48static void 49ripng_peer_free (struct ripng_peer *peer) 50{ 51 XFREE (MTYPE_RIPNG_PEER, peer); 52} 53 54struct ripng_peer * 55ripng_peer_lookup (struct in6_addr *addr) 56{ 57 struct ripng_peer *peer; 58 struct listnode *node, *nnode; 59 60 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 61 { 62 if (IPV6_ADDR_SAME (&peer->addr, addr)) 63 return peer; 64 } 65 return NULL; 66} 67 68struct ripng_peer * 69ripng_peer_lookup_next (struct in6_addr *addr) 70{ 71 struct ripng_peer *peer; 72 struct listnode *node, *nnode; 73 74 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 75 { 76 if (addr6_cmp(&peer->addr, addr) > 0) 77 return peer; 78 } 79 return NULL; 80} 81 82/* RIPng peer is timeout. 83 * Garbage collector. 84 **/ 85static int 86ripng_peer_timeout (struct thread *t) 87{ 88 struct ripng_peer *peer; 89 90 peer = THREAD_ARG (t); 91 listnode_delete (peer_list, peer); 92 ripng_peer_free (peer); 93 94 return 0; 95} 96 97/* Get RIPng peer. At the same time update timeout thread. */ 98static struct ripng_peer * 99ripng_peer_get (struct in6_addr *addr) 100{ 101 struct ripng_peer *peer; 102 103 peer = ripng_peer_lookup (addr); 104 105 if (peer) 106 { 107 if (peer->t_timeout) 108 thread_cancel (peer->t_timeout); 109 } 110 else 111 { 112 peer = ripng_peer_new (); 113 peer->addr = *addr; /* XXX */ 114 listnode_add_sort (peer_list, peer); 115 } 116 117 /* Update timeout thread. */ 118 peer->t_timeout = thread_add_timer (master, ripng_peer_timeout, peer, 119 RIPNG_PEER_TIMER_DEFAULT); 120 121 /* Last update time set. */ 122 time (&peer->uptime); 123 124 return peer; 125} 126 127void 128ripng_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 135void 136ripng_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 143void 144ripng_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. */ 152static char * 153ripng_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 186void 187ripng_peer_display (struct vty *vty) 188{ 189 struct ripng_peer *peer; 190 struct listnode *node, *nnode; 191#define RIPNG_UPTIME_LEN 25 192 char timebuf[RIPNG_UPTIME_LEN]; 193 194 for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) 195 { 196 vty_out (vty, " %s %s%14s %10d %10d %10d %s%s", inet6_ntoa (peer->addr), 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 205static int 206ripng_peer_list_cmp (struct ripng_peer *p1, struct ripng_peer *p2) 207{ 208 return addr6_cmp(&p1->addr, &p2->addr) > 0; 209} 210 211void 212ripng_peer_init () 213{ 214 peer_list = list_new (); 215 peer_list->cmp = (int (*)(void *, void *)) ripng_peer_list_cmp; 216} 217