📄 ospfd_xorp.c
字号:
/* * OSPFD routing daemon * Copyright (C) 1998 by John T. Moy * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <net/if.h>#include "ospf_module.h"#include "config.h"#include "libxorp/xorp.h"#include "libxorp/xlog.h"#include "libxipc/xrl_std_router.hh"#include "ospfinc.h"#include "monitor.h"#include "system.h"#include "tcppkt.h"#include "os-instance.h"#include "ospf_config.h"#include "ospfd_xorp.h"#include "xrl_target.h"/* Initialize the FreeBSD interface. * Open the network interface. * Start the random number generator. */XorpOspfd::XorpOspfd(EventLoop& e, XrlRouter& r) : OSInstance(e, OSPFD_MON_PORT), _router(r), _rib_client(&r){ const char *ospfd_log_file = "/tmp/ospfd.log"; debug_msg("----\nXorpOspfd\n"); rlimit rlim; next_phyint = 0; memset(phys, 0, sizeof(phys)); (void) gettimeofday(&last_time, NULL); _changing_routerid = false; _change_complete = false; _dumping_remnants = false; // Allow core files rlim.rlim_max = RLIM_INFINITY; (void) setrlimit(RLIMIT_CORE, &rlim); // Open log file if ((_logstr = fopen(ospfd_log_file, "w"))==NULL) { XLOG_FATAL("Logfile open failed: %s", strerror(errno)); } // Open monitoring listen socket monitor_listen(); // Open network if ((_netfd = socket(AF_INET, SOCK_RAW, PROT_OSPF)) == -1) { XLOG_FATAL("Network open failed: %s", strerror(errno)); } // We will supply headers on output int hincl = 1; setsockopt(_netfd, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); // Call receive raw when _netfd has data to be read if (_eventloop.add_selector(_netfd, SEL_RD, callback(this, &XorpOspfd::raw_receive)) == false) { XLOG_FATAL("Failed to add net fd."); } // Open ioctl socket if ((_udpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { XLOG_FATAL("Failed to open UDP socket: %s", strerror(errno)); } // Start random number generator srand(getpid()); // Will open multicast fd if requested to later _igmpfd = -1; // Set up one second timer _one_sec_ticker = _eventloop.new_periodic(1000, callback(this, &XorpOspfd::one_second_tick));}char buffer[MAX_IP_PKTSIZE];// External declarationsbool get_prefix(const char *prefix, InAddr &net, InMask &mask);void quit(int){ XorpOspfd* ospfd_sys = static_cast<XorpOspfd*>(sys); ospfd_sys->_changing_routerid = false; ospf->shutdown(10);}/* Process packets received on a raw socket. Could * be either the OSPF socket or the IGMP socket. */void XorpOspfd::raw_receive(int fd, SelectorMask m){ assert(SEL_RD == m); debug_msg("----\nraw_receive\n"); int plen; int rcvint = -1;#if 1 unsigned int fromlen; plen = recvfrom(fd, buffer, sizeof(buffer), 0, 0, &fromlen); if (plen < 0) { XLOG_ERROR("recvfrom: %s", strerror(errno)); return; }#else msghdr msg; iovec iov; byte cmsgbuf[128]; msg.msg_name = 0; msg.msg_namelen = 0; iov.iov_len = sizeof(buffer); iov.iov_base = buffer; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); plen = recvmsg(fd, &msg, 0); if (plen < 0) { XLOG_ERROR("recvmsg: %s", strerror(errno)); return; } else { cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { in_pktinfo *pktinfo; pktinfo = (in_pktinfo *) CMSG_DATA(cmsg); rcvint = pktinfo->ipi_ifindex; break; } } }#endif struct ip *iph = (struct ip *)buffer; InPkt *pkt = (InPkt *) buffer; //FreeBSD gives us the packet with the IP length in host //byte order, but ospfd expects it in network byte order. Fix it //here so we don't need to change the rest of ospfd. // //Even worse, FreeBSD modifies the IP header length to remove the IP //length to remove the IP header - add it back on. pkt->i_len = ntoh16(pkt->i_len + (iph->ip_hl*4)); // assert(pkt->i_len <= sizeof(buffer)); // always true // Dispatch based on IP protocol switch (pkt->i_prot) { case PROT_OSPF: debug_msg("it's OSPF\n"); ospf->rxpkt(rcvint, pkt, plen); break; case PROT_IGMP: debug_msg("it's IGMP\n"); ospf->rxigmp(rcvint, pkt, plen); break; case 0: ospf->mclookup(pkt->i_src, pkt->i_dest); break; default: break; }}/* Update the program's notion of time, which is in milliseconds * since program start. Wait until receiving the timer signal * to update a full second. */void XorpOspfd::time_update(){ debug_msg("----\ntime_update\n"); timeval now; // Current idea of time int timediff; (void) gettimeofday(&now, NULL); timediff = 1000*(now.tv_sec - last_time.tv_sec); timediff += (now.tv_usec - last_time.tv_usec)/1000; if ((timediff + sys_etime.msec) < 1000) sys_etime.msec += timediff; last_time = now;}/* Signal handler for the one second timer. * Up the elapsed time to the next whole second. */bool XorpOspfd::one_second_tick(){ // debug_msg("----\none_second_timer\n"); timeval now; // Current idea of time (void) gettimeofday(&now, NULL); sys_etime.sec++; sys_etime.msec = 0; last_time = now; return true;}/* Destructor not expected to be called during the life * of the program. */XorpOspfd::~XorpOspfd(){}/* Find the physical interface to which a given address * belongs. Returns -1 if no matching interface * can be found. */int XorpOspfd::get_phyint(InAddr addr){ debug_msg("----\nget_phyint\n"); int i; for (i=0; i < MAXIFs; i++) { BSDPhyInt *phyp; phyp = phys[i]; if (phyp && (phyp->addr & phyp->mask) == (addr & phyp->mask)) return(i); } return(-1);}/* Read the IP interface information out of the FreeBSD * kernel. */void XorpOspfd::read_kernel_interfaces(){ debug_msg("----\nread_kernel_interfaces\n"); ifconf cfgreq; ifreq *ifrp; ifreq *end; size_t size; char *ifcbuf; int blen; AVLsearch iter(&directs); DirectRoute *rte; blen = MAXIFs*sizeof(ifreq); ifcbuf = new char[blen]; cfgreq.ifc_buf = ifcbuf; cfgreq.ifc_len = blen; if (ioctl(_udpfd, SIOCGIFCONF, (char *)&cfgreq) < 0) { XLOG_ERROR("Failed to read interface config: %s", strerror(errno)); exit(1); } /* Clear current list of interfaces and directly * attached subnets, since we're going to reread * them. */ interface_map.clear(); while ((rte = (DirectRoute *)iter.next())) rte->valid = false; ifrp = (ifreq *) ifcbuf; end = (ifreq *)(ifcbuf + cfgreq.ifc_len); for (; ifrp < end; ifrp = (ifreq *)(((byte *)ifrp) + size)) { BSDPhyInt *phyp; byte *phystr; ifreq ifr; sockaddr_in *insock; InAddr addr; // Find next interface structure in list size=_SIZEOF_ADDR_IFREQ(*ifrp) ; // IP interfaces only if (ifrp->ifr_addr.sa_family != AF_INET) continue; debug_msg("IFname: %s\n", ifrp->ifr_name); // Ignore loopback interfaces // Also ignore "down" interfaces // Get interface flags short ifflags; memcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); if (ioctl(_udpfd, SIOCGIFFLAGS, (char *)&ifr) < 0) { XLOG_ERROR("SIOCGIFFLAGS Failed: %s", strerror(errno)); exit(1); } if ((ifr.ifr_flags & IFF_LOOPBACK) != 0) continue; ifflags = ifr.ifr_flags; debug_msg("Flags=%x\n", ifflags); /* Found a legitimate interface * Add physical interface and * IP address maps */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -