📄 rip2.c
字号:
/* * * NX-ROUTED * RIP-2 Routing Daemon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Copyright (C) 2002 Valery Kholodkov * Copyright (C) 2002 Andy Pershin * Copyright (C) 2002 Antony Kholodkov * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <time.h>#include "ctlfile.h"#include "router.h"#include "socket.h"#include "timers.h"#include "link.h"#include "util.h"#include "rip.h"struct rip2_header { unsigned char command; unsigned char version; unsigned short zero;};struct rip2_rte { unsigned short family; unsigned short rtag; unsigned int address; unsigned int netmask; unsigned int nexthop; unsigned int metric;};struct rip2_auth { u_int16_t xffff; u_int16_t type; char password[16];};extern struct rproto rip2_proto;struct rtable *rip2_announce_table;struct socket *rip2_socket;int rip_version=2;int rip2_auth=0;int rip2_multicast=0;int rip2_unicast=0;int rip2_allowqueries=0;int rip2_silent=0;unsigned int rip2_nextpartupd=0;unsigned int rip2_nextfullupd=0;unsigned int rip2_lastrequest_time = 0;unsigned int rip2_lastrequest_count = 0;#if 1 #define RIP_PORT_DEFAULT 520#define INADDR_RIP_GROUP 0xe0000009 /* 224.0.0.9 *//* Set up a multicast socket options for IPv4 * This is here so that people only have to do their OS multicast mess * in one place rather than all through zebra, ospfd, and ripd * NB: This is a hookpoint for specific OS functionality */intsetsockopt_multicast_ipv4(int sock, int optname, struct in_addr if_addr, struct in_addr mcast_addr, unsigned int ifindex){ struct ip_mreqn mreqn; switch (optname) { case IP_MULTICAST_IF: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: memset (&mreqn, 0, sizeof(mreqn)); if (mcast_addr.s_addr) mreqn.imr_multiaddr = mcast_addr; //mreqn.imr_multiaddr.s_addr = mcast_addr; if (ifindex) mreqn.imr_ifindex = ifindex; else mreqn.imr_address = if_addr; return setsockopt(sock, IPPROTO_IP, optname, (void *)&mreqn, sizeof(mreqn)); break; default: /* Can out and give an understandable error */ //errno = EINVAL; return -1; break; }}/* Utility function to set boradcast option to the socket. */intsockopt_broadcast (int sock){ int ret; int on = 1; ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on); if (ret < 0) { error ("can't set sockopt SO_BROADCAST to socket %d", sock); return -1; } return 0;}intsockopt_reuseaddr (int sock){ int ret; int on = 1; ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof (on)); if (ret < 0) { error ( "can't set sockopt SO_REUSEADDR to socket %d", sock); return -1; } return 0;}voidrip_interface_multicast_set (int sock, struct link *p){ int ret; struct sockaddr_in from; struct in_addr addr; struct in_addr maddr; addr.s_addr = htonl(p->address); maddr.s_addr = htonl(p->multicast); if (setsockopt_multicast_ipv4 (sock, IP_ADD_MEMBERSHIP, addr, maddr, 0) < 0) { error ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock); return; } maddr.s_addr = htonl(0); if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, maddr, 0) < 0) { error ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock); return; } /* Bind myself. */ memset (&from, 0, sizeof (struct sockaddr_in)); /* Set RIP port. */ from.sin_port = htons (RIP_PORT_DEFAULT); /* Address shoud be any address. */ from.sin_family = AF_INET; from.sin_addr = addr;#ifdef HAVE_SIN_LEN from.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */ ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in)); if (ret < 0) { //error ("Can't bind socket: %s", strerror (errno)); return; } return;}/* RIP packet send to destination address. */intmulti_send_packet (caddr_t buf, int size, struct sockaddr_in *to, struct link *p){ int ret; struct sockaddr_in sin; int sock; /* Make destination address. */ memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET;#ifdef HAVE_SIN_LEN sin.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */ /* When destination is specified, use it's port and address. */ if (to) { //sock = rip->sock; sin.sin_port = to->sin_port; sin.sin_addr = to->sin_addr; } else { sock = socket (AF_INET, SOCK_DGRAM, 0); sockopt_broadcast (sock); sockopt_reuseaddr (sock); /*sockopt_reuseport (sock);*/ sin.sin_port = htons (RIP_PORT_DEFAULT); sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); /* Set multicast interface. */ rip_interface_multicast_set (sock, p); } ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin, sizeof (struct sockaddr_in)); if (ret < 0) debug(5,"can't send packet "); if (! to) close (sock); return ret;}#endif /*agui*/struct rtable *rip2_calculate_partial_rtable(struct rtable *announce_table) { struct rtable *rtable; struct route *p,*q; rtable = new_rtable(); p = announce_table->routes; while(p) { if(p->flags & RF_CHANGED) { p->flags &= ~RF_CHANGED; q = dup_route(p); add_route(rtable,q); } p = p->next; } return rtable;}void rip2_announce(void *arg) { struct rproto *rproto = (struct rproto *)arg;#ifdef PARTIAL_UPDATES struct rtable *partial_rtable;#endif debug(5, "rip2_announce 1 \n"); if(rproto == NULL) return; debug(5,"rip2_announce 2 \n"); // Prevent partial update now (not completed for this version) /* this is madness.. thousends of timers! rip2_nextpartupd = 0; rip2_nextfullupd = time(NULL) + RIP_SUPPLYTIME; set_timer(&rip2_announce,&rip2_proto,RIP_SUPPLYTIME); */ /* I loose 1 whole second somewhere, and because of that, the rip2_announce * timer doesn't get set again.. But where?? * HACK: Add 1 second tolerance (thats that -1 for q;)) */ if ((rip2_nextfullupd-1) <= time(NULL)) { debug(5,"rip2_announce 3"); /* this was not a triggerd update (but regular 30 sec), thou shall repeate it in time again */ rip2_nextpartupd = 0; rip2_nextfullupd = time(NULL) + RIP_SUPPLYTIME; set_timer(&rip2_announce,&rip2_proto,RIP_SUPPLYTIME); } if(rip2_nextpartupd == 0) { debug(5,"rip2_announce 4"); //if(debuglevel < 7){ // printf("######"); // dump_rtable(rip2_announce_table); //} rip2_announce_table = system_read_rtable(); /// announce_routes(rproto,rip2_announce_table); return; } debug(5,"rip2_announce 5");#ifdef PARTIAL_UPDATES partial_rtable = rip2_calculate_partial_rtable(rip2_announce_table); announce_routes(rproto,partial_rtable); free_rtable(partial_rtable); #endif rip2_nextpartupd = 0;}int rip2_init_config(){ rip2_multicast = get_param_b("rip2","multicast",0); rip2_silent = get_param_b("rip2","silent",0); rip2_allowqueries = get_param_b("rip2","allowqueries",1); return 0;}int rip2_init_protocol(struct rproto *rproto) { if(rip2_silent) log_msg("Silent mode on"); rip2_announce_table = new_rtable(); return 0;}int rip2_init() { struct sockaddr_in sin; struct servent *svp; struct socket *socket; /* * 檩磐 握治偈 邢以 */ debug(5,"rip2_init run\n"); svp = getservbyname ("router", "udp"); if (svp != (struct servent *) 0) rip2_proto.port = ntohs(svp->s_port); // Initializing configuration files if(rip2_init_protocol(&rip2_proto) < 0) { error("Unable to initialize RIP2"); return -1; } // 蚺巧釉疑艺磐 幸显纤咸 if(register_routing_protocol(&rip2_proto) < 0) { error("Unable to register RIP2 routing protocol"); return -1; } if((socket = socket_create(&rip2_proto)) == NULL) { error("Unable to create RIP2 socket"); return -1; } if(socket_bind_to_local_port(socket,rip2_proto.port) < 0) { error("Unable to bind socket to local address"); return -1; } if(rip2_multicast) { debug(5,"rip2_multicast mode"); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(RIP_MCAST); sin.sin_port = htons(rip2_proto.port); if(socket_bind_to_multicast(socket,&sin) < 0) { error("Unable to set multicast membership"); return -1; } } if(socketlist_add(socket) < 0) { error("Unable to register RIP2 socket"); return -1; } // 笤磷赏 粤释乓 瘟 廖衔淤 // Full update will be in 3 seconds // rip2_nextfullupd = time(NULL) + 3; if(set_timer(&rip2_announce,&rip2_proto,3) < 0) { error("Unable to register RIP2 broadcasting timer"); return -1; } // 钫 耘信邑 呐抑稍
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -