📄 rsrr_unicast.c
字号:
/* * @(#) $Id: rsrr_unicast.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_unicast.c **************************** * * * System-dependent Unicast route lookup routine * * * *********************************************************************/#define USYNCH 1#include "rsvp_daemon.h"#include <sys/param.h>#ifdef sun#ifdef SOLARIS#include <sys/stream.h>#include <inet/common.h>#undef IPOPT_EOL#undef IPOPT_NOP#undef IPOPT_LSRR#undef IPOPT_RR#undef IPOPT_SSRR#include <inet/ip.h>#else /* not SOLARIS */#include <sys/mbuf.h>#endif /* SOLARIS */#endif /* sun */u_long bmp_unicast;int unicast_result_ready;int unicast_query_waiting;int asynchronous = 1;static int init_failed = 0;int locate_LIH(unsigned int, net_addr *);intlocate_LIH(unsigned int ifidx, net_addr *addr){ int i; for (i = 0; i < if_num; i++) { if (IsNumAPI(i)) continue; if (ifidx == if_vec[i].if_index) { if (net_addr_equal(addr, &(NET_GET_IF_PHY_ADDR(&(if_vec[i].if_addr))))) return i; } } return -1;}#ifdef SOLARIS#include <sys/utsname.h>#define SOLARIS_2_6 6/* * Routing socket indicies */#define RTAX_DST 0#define RTAX_GATEWAY 1#define RTAX_NETMASK 2#define RTAX_GENMASK 3#define RTAX_IFP 4#define RTAX_IFA 5#define RTAX_AUTHOR 6#define RTAX_BRD 7#define RTAX_MAX 8static intgetSolarisRelease(void){ struct utsname n; int major, minor; char *period, *release; if (uname(&n) < 0) { perror("uname"); return (-1); } release = strdup(n.release); if ((period = strchr(release, '.'))) { *period = '\0'; minor = atoi(period + 1); } major = atoi(release); free (release); if (major != 5) return (-1); else return (minor);}#endif /* SOLARIS */#if defined(PF_ROUTE) && !defined(sgi_53) && !defined(linux)int seq; /* routing socket sequence num */int rskt; /* routing socket *//* * This code will assumes a routing socket and will work on many newer * BSD-like machines * *//* * Copyright 1995 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. 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 <errno.h>#include <net/if.h>#include <net/if.h>#include <net/if_dl.h>#include <net/route.h>#include <netinet/in.h>/* * Round up 'a' to next multiple of 'size' */ #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) /* * Step to next socket address structure; * if sa_len is 0, assume it is sizeof(u_long). */#define NEXT_SA(ap) ap = (struct sockaddr *) \ ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (u_long)) : \ sizeof(u_long)))#ifdef SOLARISstatic int useRoutingSocket = 0;#endif/* * For now, we open a new socket every time we want to get a route, to * save some effort in parsing. Eventually we should keep it open and * listen for changes. For now, just open and close it to make sure that * we can. */intunicast_init(void){#ifdef SOLARIS static int unicast_init_specific(); int release; if ((release = getSolarisRelease()) < 0) { init_failed = 1; NoUnicast = 1; return (0); } if (release >= SOLARIS_2_6) { rskt = socket(PF_ROUTE, SOCK_RAW, AF_INET); if (rskt < 0) { log(LOG_INFO, 0, "Unicast routing information unavailable\n"); init_failed = 1; NoUnicast = 1; return (0); } useRoutingSocket++; } else if (!unicast_init_specific()) { init_failed = 1; NoUnicast = 1; return (0); }#else /* SOLARIS */ rskt = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); if (rskt < 0) { init_failed = 1; NoUnicast = 1; log(LOG_INFO, 0, "Unicast routing information unavailable\n"); return 0; }#endif /* SOLARIS */ NoUnicast = 0; close(rskt); return 1;}#define RTM_BUFLEN 2048 /* XXX should be in header file */#define WORD_BNDARY(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))#ifdef SBMu_longunicast_route_gw_routing_socket(u_long addr){ int s, one = 1, i, len; struct sockaddr *sa;#ifdef SOLARIS struct sockaddr *rti_info[RTA_NUMBITS];#else struct sockaddr *rti_info[RTAX_MAX];#endif struct sockaddr_in *isa; struct rt_msghdr *mhp; caddr_t cp; char buf[RTM_BUFLEN]; if ((s = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { perror("socket"); return (-1); } setsockopt(s, SOL_SOCKET, SO_USELOOPBACK, (char *)&one, sizeof (one)); /* Set up GET message */ memset(buf, 0, sizeof buf); mhp = (struct rt_msghdr *)buf; cp = buf + sizeof(struct rt_msghdr); isa = (struct sockaddr_in *)cp; isa->sin_family = AF_INET; isa->sin_addr.s_addr = addr; mhp->rtm_version = RTM_VERSION; mhp->rtm_type = RTM_GET; mhp->rtm_addrs = RTA_GATEWAY; mhp->rtm_seq = ++seq; mhp->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); /* Send the message */ if (write(s, buf, (size_t)mhp->rtm_msglen) < 0) { log(LOG_ERR, errno, "writing message on routing socket\n"); close(s); return -1; } /* Read the reply */ do { len = read(s, buf, sizeof buf); } while (len > 0 && mhp->rtm_seq != seq && mhp->rtm_pid != getpid()); close(s); if (len < 0 || mhp->rtm_errno) { if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, errno, "unicast route lookup failed"); return -1; } if (len == 0) { log(LOG_ERR, 0, "unicast route lookup is confused"); return -1; } sa = (struct sockaddr *) (mhp + 1); get_route_info(sa, rti_info, mhp); isa = NULL; for (i = 0; i < RTAX_MAX; i++) { switch(mhp->rtm_addrs & (1 << i)) { case RTA_GATEWAY: isa = (struct sockaddr_in *)rti_info[i]; break; } } if (!isa) return (-1); else return (isa->sin_addr.s_addr);}u_longunicast_route_gw(u_long addr){#ifdef SOLARIS if (useRoutingSocket) return unicast_route_gw_routing_socket(addr); else return unicast_route_gw_specific(addr);#else unicast_route_gw_routing_socket(addr);#endif}static voidget_route_info(struct sockaddr *sa, struct sockaddr **rti_info, struct rt_msghdr *mhp){ int i;#ifdef SOLARIS caddr_t cp; cp = (caddr_t)sa; for (i = 0; i < RTA_NUMBITS; i++) { switch (mhp->rtm_addrs & (1 << i)) { case RTA_DST: case RTA_GATEWAY: case RTA_NETMASK: case RTA_GENMASK: case RTA_AUTHOR: case RTA_IFA: rti_info[i] = (struct sockaddr *)cp; cp += sizeof (struct sockaddr_in); break; case RTA_IFP: rti_info[i] = (struct sockaddr *)cp; cp += sizeof (struct sockaddr_dl); break; } }#else for (i = 0; i < RTAX_MAX; i++) { if (mhp->rtm_addrs & (1 << i)) { rti_info[i] = sa; NEXT_SA(sa); } else rti_info[i] = NULL; } #endif}#endif#ifdef SOLARISintunicast_route(net_addr *addr){ static int unicast_route_routing_socket(net_addr *); static int unicast_route_specific(u_long); switch (NET_GET_TYPE(addr)) { case NET_ADDR_IPv4: if (useRoutingSocket) return (unicast_route_routing_socket(addr)); else return(unicast_route_specific( NET_GET_ADDR_IPv4(addr).s_addr)); case NET_ADDR_UDP_IPv4: if (useRoutingSocket) return (unicast_route_routing_socket(addr)); else return(unicast_route_specific( NET_GET_ADDR_UDP_IPv4(addr).sin_addr.s_addr)); default: return(0); }}#endif /* SOLARIS *//* * Find the kernel's idea of the route to destination DEST (in host order) */int#ifdef SOLARISunicast_route_routing_socket(net_addr *addr)#elseunicast_route(net_addr *addr)#endif{ struct sockaddr *sp; struct sockaddr_in *s4; struct rt_msghdr *mhp; net_addr *addr2; char buf[RTM_BUFLEN]; int one, sz; int sock; int pid;#ifdef USYNCH int s; int len; struct sockaddr *sa;#ifdef SOLARIS caddr_t cp; struct sockaddr *rti_info[RTA_NUMBITS];#else struct sockaddr *rti_info[RTAX_MAX];#endif net_addr nadr; struct sockaddr_dl *sdlp; char ifname[IFNAMSIZ]; int i; int ifidx = 0;#endif /* USYNCH */#ifdef USE_IPV6 struct sockaddr_in6 *s6;#endif /* USE_IPV6 */#ifdef USYNCH /* Open socket */ s = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); if (s < 0) { log(LOG_ERR, errno, "Could not open routing socket"); return -1; } else sock = s;#else /* USYNCH */ sock = rskt;#endif /* !USYNCH */ one = 1; setsockopt(sock, SOL_SOCKET, SO_USELOOPBACK, (char *) &one, sizeof one); /* Set up GET message */ memset(buf, 0, sizeof buf); mhp = (struct rt_msghdr *)buf; sp = (struct sockaddr *) &buf[WORD_BNDARY(sizeof (struct rt_msghdr))]; addr2 = net_addr_ip(addr); switch (NET_GET_TYPE(addr2)) { case NET_ADDR_IPv4: sz = sizeof(struct sockaddr_in); s4 = (struct sockaddr_in *) sp; s4->sin_family = AF_INET; s4->sin_addr.s_addr = NET_GET_ADDR_IPv4(addr2).s_addr; s4->sin_port = 0;#ifdef SOCKADDR_LEN s4->sin_len = sz;#endif break;#ifdef USE_IPV6 case NET_ADDR_IPv6: sz = sizeof(struct sockaddr_in6); s6 = (struct sockaddr_in6 *) sp; s6->sin6_family = AF_INET6; s6->sin6_addr = NET_GET_ADDR_IPv6(addr2); s6->sin6_port = 0;#ifdef SOCKADDR_LEN s6->sin6_len = sz;#endif break;#endif /* USE_IPV6 */ default: return(-1); } mhp->rtm_version = RTM_VERSION; mhp->rtm_type = RTM_GET; /* mhp->rtm_addrs = RTA_DST|RTA_IFP; */ mhp->rtm_addrs = RTA_DST|RTA_IFP|RTA_IFA; mhp->rtm_seq = ++seq; mhp->rtm_pid = pid = getpid(); mhp->rtm_msglen = ((char *)(sp)) + sz - buf; /* Send the message */ if (write(sock, buf, (size_t)mhp->rtm_msglen) < 0) { log(LOG_ERR, errno, "writing message on routing socket\n");#ifdef USYNCH close(sock);#endif /* USYNCH */ return -1; }#if !defined(USYNCH) asynchronous = 1; return 0; #else /* USYNCH */ /* Read the reply */ do { len = read(sock, buf, sizeof buf); } while (len > 0 && mhp->rtm_seq != seq && mhp->rtm_pid != pid); close(sock); if (len < 0 || mhp->rtm_errno) { if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, errno, "unicast route lookup failed"); return -1; } if (len == 0) { log(LOG_ERR, 0, "unicast route lookup is confused"); return -1; } sa = (struct sockaddr *) (mhp + 1); #ifdef SOLARIS cp = (caddr_t)sa; for (i = 0; i < RTA_NUMBITS; i++) { switch (mhp->rtm_addrs & (1 << i)) { case RTA_DST: case RTA_GATEWAY: case RTA_NETMASK: case RTA_GENMASK: case RTA_AUTHOR: case RTA_IFA: rti_info[i] = (struct sockaddr *)cp; cp += sizeof (struct sockaddr_in); break; case RTA_IFP: rti_info[i] = (struct sockaddr *)cp; cp += sizeof (struct sockaddr_dl); break; } }#else for (i = 0; i < RTAX_MAX; i++) { if (mhp->rtm_addrs & (1 << i)) { rti_info[i] = sa; NEXT_SA(sa); } else rti_info[i] = NULL; } #endif if ((sa = rti_info[RTAX_IFP]) != NULL) { sdlp = (struct sockaddr_dl *)sa; if (sdlp->sdl_family != AF_LINK || sdlp->sdl_nlen == 0) { if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, 0, "unicast route through weird ifp"); return -1; } strncpy(ifname, sdlp->sdl_data, sdlp->sdl_nlen); if (sdlp->sdl_nlen < IFNAMSIZ) ifname[sdlp->sdl_nlen] = '\0'; ifidx = if_nametoindex(ifname); } if ((sa = rti_info[RTAX_IFA]) != NULL) { switch (sa->sa_family) { case AF_INET: s4 = (struct sockaddr_in *)sa; NET_SET_ADDR_IPv4(&nadr, s4->sin_addr); break;#ifdef USE_IPV6 case AF_INET6: s6 = (struct sockaddr_in6 *)sa; NET_SET_ADDR_IPv6(&nadr, s6->sin6_addr); break;#endif /* USE_IPV6 */ default: return (-1); } } else return -1; asynchronous = 0; return (locate_LIH(ifidx, &nadr));#endif /* USYNCH */}# else/* * ifndef PF_ROUTE - no routing socket. OS-specific code required, */#ifdef SOLARISstatic int unicast_init_specific();static int unicast_route_specific(u_long);intunicast_init(void){ return (unicast_init_specific());}#ifdef SBMstatic int unicast_route_gw_specific(u_long);u_longunicast_route_gw(u_long addr){ return (unicast_route_gw_specific(addr));}#endifintunicast_route(net_addr *addr){ switch (NET_GET_TYPE(addr)) { case NET_ADDR_IPv4: return(unicast_route_specific( NET_GET_ADDR_IPv4(addr).s_addr)); case NET_ADDR_UDP_IPv4: return(unicast_route_specific( NET_GET_ADDR_UDP_IPv4(addr).sin_addr.s_addr));#ifdef USE_IPV6#ifdef WORKAROUNDS case NET_ADDR_IPv6: return(local_v6); case NET_ADDR_UDP_IPv6: return(local_v6);#endif /* WORKAROUNDS */#endif /* USE_IPV6 */ default: return(-1); }}#else /* end of SOLARIS */#ifdef linuxint dst_route_oif(net_addr *);int dst_init();intunicast_init(void){ if (dst_init(NULL) < 0) { init_failed = 1; NoUnicast = 1; log(LOG_INFO, 0, "Unicast routing information unavailable"); return 0; } NoUnicast = 0; return 1;}/* * Find the kernel's idea of the route to destination DEST (in host order) */intunicast_route(net_addr *addr){ return dst_route_oif(addr);}/* ------------------------------------------------------------------------ *//* * libroute.c Interface to Linux routing engine. * * 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. * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <syslog.h>#include <fcntl.h>#include <linux/types.h>#include <sys/socket.h>#include <string.h>#include <errno.h>#include <sys/time.h>#include <linux/rtnetlink.h>#include "libnetlink.h"#include "libroute.h"#include "rsvp_daemon.h"#define MAXDSTENTRIES 128#define R_ASYNC_TMO 2#define R_CANCEL_TMO 20#define R_SYNC_TMO 5#define R_GC_TMO 300#define R_STALETIME 15#define R_LOAD 30#define MSG_TRUNC 0x20#define MSG_DONTWAIT 0x40 /* Nonblocking io */static struct rtnl_handle rt_nl;static const __u32 zerokey[KEYLEN];static struct dstentry *dsttable[256];static struct dstentry *dstqueue;static void (*dst_refresh)(struct dstentry*);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -