📄 ripng.c
字号:
/* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "include.h"#include "bgp.h"#include "router.h"#include "task.h"#include "rt_table.h"#include "aspath.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"#include "ripng_var.h"int ripsock; /* socket for RIPng UDP */int rip_use_sitelocal = 0;/* if we handle site-local addrs */byte ripbuf[RIPNG_BUFSIZ];byte rippkt[RIPNG_MAXPKT]; /* should discover path MTU */struct ripif *ripifs; struct sockaddr_in6 ripsin; /* ff02::9.RIPNG_PORT *//* * RIP message types */char *rip_msgstr[] = { "", "Request", "Response"};/* * rip_init() */void rip_init(){ struct ripif *ripif;#ifndef ADVANCEDAPI int hops;#endif struct ifinfo *ife; struct timeval tv; extern struct ifinfo *ifentry; ripifs = NULL; /* random seed */ gettimeofday(&tv, NULL); srandom(tv.tv_usec ^ tv.tv_sec); ife = ifentry; while (ife) { /* for each available I/F */ if (ife->ifi_flags & IFF_UP && ife->ifi_flags & IFF_MULTICAST) /* XXX */ { MALLOC(ripif, struct ripif); ripif->rip_ife = ife; /* (1998/05/21) */ if (IN6_IS_ADDR_UNSPECIFIED(&ife->ifi_laddr)) { ripif->rip_mode |= IFS_NORIPIN; ripif->rip_mode |= IFS_NORIPOUT; } if (ripifs) insque(ripif, ripifs); else { ripif->rip_next = ripif->rip_prev = ripif; ripifs = ripif; } } if ((ife = ife->ifi_next) == ifentry) break; } /* End of rip_init() */}voidrip_sockinit(){ task *tsk; struct ripif *ripif; struct ipv6_mreq mreq; int on; extern task *taskhead; extern fd_set fdmask; /* for RIPng */ if ((ripsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) fatal("<rip_init>: socket"); memset(&ripsin, 0, sizeof(ripsin)); /* sockaddr_in6 */ memset(&mreq, 0, sizeof(mreq)); ripsin.sin6_len = sizeof(struct sockaddr_in6); ripsin.sin6_family = AF_INET6; ripsin.sin6_port = htons(RIPNG_PORT); ripsin.sin6_flowinfo = 0; /* bind must be called before filling RIPNG_DEST in ripsin */ if (bind(ripsock, (struct sockaddr *)&ripsin, sizeof(ripsin)) < 0) fatal("<rip_init>: bind"); if (inet_pton(AF_INET6, RIPNG_DEST, (void *)&ripsin.sin6_addr) != 1) fatal("<rip_init>: inet_pton"); mreq.ipv6mr_multiaddr = ripsin.sin6_addr; for (ripif = ripifs; ripif; ) { /* XXX: odd loop */ if ((ripif->rip_mode & IFS_NORIPIN) != 0) goto nextif; mreq.ipv6mr_interface = ripif->rip_ife->ifi_ifn->if_index; if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0) fatal("<rip_init>: setsockopt: IPV6_JOIN_GROUP"); nextif: if ((ripif = ripif->rip_next) == ripifs) break; }#ifndef ADVANCEDAPI hops = RIPNG_HOPLIMIT; if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(int)) < 0) fatal("<rip_init>: setsockopt IPV6_MULTICAST_HOPS");#endif /* ADVANCEDAPI */ on = 0; if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on)) < 0) fatal("<rip_init>: setsockopt IPV6_MULTICAST_LOOP");#ifdef ADVANCEDAPI on = 1;#ifdef IPV6_RECVPKTINFO if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) fatal("<rip_init>: setsockopt(IPV6_RECVPKTINFO)");#else /* old adv. API */ if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) fatal("<rip_init>: setsockopt(IPV6_PKTINFO)");#endif on = 1;#ifdef IPV6_RECVPKTINFO if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) fatal("<rip_init>: setsockopt(IPV6_RECVPKTINFO)");#else /* old adv. API */ if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) fatal("<rip_init>: setsockopt(IPV6_PKTINFO)");#endif #endif /* ADVANCEDAPI */ FD_SET(ripsock, &fdmask); MALLOC(tsk, task); if (taskhead) { insque(tsk, taskhead); } else { taskhead = tsk; tsk->tsk_next = tsk; tsk->tsk_prev = tsk; } tsk->tsk_timename = RIP_DUMP_TIMER; tsk->tsk_rip = NULL; tsk->tsk_timefull.tv_sec = 1; /* immediately */ tsk->tsk_timefull.tv_usec = 0; task_timer_update(tsk);}/* * rip_inport_init: initilize Adj_Ribs_Out for RIPng */voidrip_import_init(){ struct ripif *ripif = ripifs; extern byte bgpyes; extern struct ifinfo *ifentry; extern struct rpcb *bgb; while (ripif) { struct ripif *outripif; struct ifinfo *outife; struct rpcb *outbnp; /* Include ripif itself, for "specific request". */ outripif = ripifs; while(outripif) { struct rtproto *rtp; MALLOC(rtp, struct rtproto); rtp->rtp_type = RTPROTO_RIP; rtp->rtp_rip = outripif; if (ripif->rip_adj_ribs_out) insque(rtp, ripif->rip_adj_ribs_out); else { rtp->rtp_next = rtp->rtp_prev = rtp; ripif->rip_adj_ribs_out = rtp; } if ((outripif = outripif->rip_next) == ripifs) /* global */ break; } /* while(outripif) */ outife = ifentry; /* Don't include ife itself */ while (outife) { struct rtproto *rtp; if (ripif->rip_ife != outife) { MALLOC(rtp, struct rtproto); rtp->rtp_type = RTPROTO_IF; rtp->rtp_if = outife; if (ripif->rip_adj_ribs_out) insque(rtp, ripif->rip_adj_ribs_out); else { rtp->rtp_next = rtp->rtp_prev = rtp; ripif->rip_adj_ribs_out = rtp; } } if ((outife = outife->ifi_next) == ifentry) /* global */ break; } /* while(outife) */ if (bgpyes) { outbnp = bgb; while(outbnp) {/* Import All eBGP routes into RIP (1998/05/21) */ struct rtproto *rtp; if (!(outbnp->rp_mode & BGPO_IGP)) { MALLOC(rtp, struct rtproto); rtp->rtp_type = RTPROTO_BGP; rtp->rtp_bgp = outbnp; if (ripif->rip_adj_ribs_out) insque(rtp, ripif->rip_adj_ribs_out); else { rtp->rtp_next = rtp->rtp_prev = rtp; ripif->rip_adj_ribs_out = rtp; } } if ((outbnp = outbnp->rp_next) == bgb) /* global */ break; } /* while (struct rpcb) */ } if ((ripif = ripif->rip_next) == ripifs) break; } /* while (global "ripifs") */ }/* * rip_query_dump() */voidrip_query_dump(){ struct ripif *ripif; struct in6_pktinfo spktinfo; struct riphdr *rp; struct ripinfo6 *np; /* RIPng RTE */ memset(rippkt, 0, RIPNG_MAXPKT); rp = (struct riphdr *)rippkt; /* outgoing RIPng header */ rp->riph_cmd = RIPNGCMD_REQUEST; rp->riph_vers = RIPNG_VERSION; rp->riph_zero2 = 0; np = (struct ripinfo6 *)(rippkt + sizeof(struct riphdr)); np->rip6_metric = RIPNG_METRIC_UNREACHABLE; ripif = ripifs; /* global */ while(ripif) { if (!(ripif->rip_mode & IFS_NORIPOUT)) { spktinfo.ipi6_addr = ripif->rip_ife->ifi_laddr; /* copy */ spktinfo.ipi6_ifindex = ripif->rip_ife->ifi_ifn->if_index; if (rip_sendmsg(&ripsin, /* ff02::9.RIPNG_PORT */ &spktinfo, /* source address, I/F */ sizeof(struct riphdr) + sizeof(struct ripinfo6))) ripif->rip_reqsentfail++; ripif->rip_requestsent++; } if ((ripif = ripif->rip_next) == ripifs) break; }}struct sockaddr_in6 fsock; /* sender's address *//* * * rip_input() * */void rip_input(){ struct ripif *ripif; int nn; /* number of RTEs */ int len; /* recvmsg */ int flen; /* sizeof From addr (for Adv. API) */ struct ifinfo *ife; struct riphdr *rp; /* RIPng header */ extern struct ifinfo *ifentry; struct msghdr rmsghdr; /* Adv. API */ struct iovec rmsgiov; /* buffer for data (gather) */ static char *cmsg = NULL; /* buffer for ancillary data */ int cmsglen; struct cmsghdr *ch; /* Adv. API */ struct in6_pktinfo *rpktinfo; /* received I/F address */ struct in6_pktinfo spktinfo; /* sending source I/F */ int *rhoplimit; /* Adv. API */ char ifname[IFNAMSIZ]; cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); memset(&fsock, 0, sizeof(struct sockaddr_in6)); /* sender's addr/port */ memset(ripbuf, 0, RIPNG_BUFSIZ); memset(rippkt, 0, RIPNG_MAXPKT); memset(&rmsghdr, 0, sizeof(struct msghdr)); memset(&rmsgiov, 0, sizeof(struct iovec)); if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL) { fatalx("<rip_input>: malloc failed"); } memset(cmsg, 0, cmsglen); memset(&spktinfo, 0, sizeof(struct in6_pktinfo)); rpktinfo = NULL; rhoplimit = NULL;/*** Adv. API ***/ flen = sizeof(struct sockaddr_in6); rmsghdr.msg_name = (caddr_t)&fsock; /* sender's addr/port */ rmsghdr.msg_namelen = flen; /* size of address */ rmsgiov.iov_base = (void *)ripbuf; /* buffer, base should be void */ rmsgiov.iov_len = sizeof(ripbuf); /* 1500 (receiving buffer len) */ rmsghdr.msg_iov = &rmsgiov; rmsghdr.msg_iovlen = 1; /* 1 iovec obj. */#ifdef ADVANCEDAPI rmsghdr.msg_control = (caddr_t)cmsg; /* buffer for ancillary data */ rmsghdr.msg_controllen = cmsglen;#else rmsghdr.msg_control = (caddr_t)0; rmsghdr.msg_controllen = 0;#endif /* ADVANCEDAPI */ rmsghdr.msg_flags = 0; /* ? */ len = 0; if ((len = recvmsg(ripsock, &rmsghdr, 0)) < 0) /* Adv. API */ fatal("<rip_input>: recvmsg"); if (IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) CLEAR_IN6_LINKLOCAL_IFINDEX(&fsock.sin6_addr); /* for safty */#ifdef ADVANCEDAPI for (ch = CMSG_FIRSTHDR(&rmsghdr);ch; ch = CMSG_NXTHDR(&rmsghdr, ch)) { if (ch->cmsg_level == IPPROTO_IPV6 && ch->cmsg_type == IPV6_PKTINFO && ch->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { rpktinfo = (struct in6_pktinfo *)CMSG_DATA(ch); } if (ch->cmsg_level == IPPROTO_IPV6 && ch->cmsg_type == IPV6_HOPLIMIT && ch->cmsg_len == CMSG_LEN(sizeof(int))) { rhoplimit = (int *)CMSG_DATA(ch); } } if (rpktinfo == NULL) { fatalx("<rip_input>: Can't get received interface"); return; }#else /* for older hydranger */ { struct ifinfo *ife; static struct in6_pktinfo rrpktinfo; if ((ife = find_if_by_addr(&fsock.sin6_addr)) == NULL) fatalx("<rip_input>: find_if_by_addr"); rrpktinfo.ipi6_ifindex = ife->ifi_ifn->if_index; rpktinfo = &rrpktinfo; }#endif /* ADVANCEDAPI */ IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng RECV from %s+%d (%s)", ip6str2(&fsock), ntohs(fsock.sin6_port), if_indextoname(rpktinfo->ipi6_ifindex, ifname)); /* Received I/F */ if ((ripif = find_rip_by_index((u_int)rpktinfo->ipi6_ifindex)) == NULL) { syslog(LOG_ERR, "<rip_input>: RIP received at Unknown I/F %d (ignored)", rpktinfo->ipi6_ifindex); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -