📄 rsrr_unicast.c
字号:
return(0); } NoUnicast = 0; return(1);}intunicast_route1(u_long addr) { int i; struct sockaddr_in sin; if (init_failed) return(-1); if (read_routes() == -1) return(-1); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; i = rtfindx(&sin); if (i == -1 && have_default) { if (IsDebug(DEBUG_ROUTE)) { log(LOG_DEBUG, 0, "Using default route ...\n"); log(LOG_DEBUG, 0, "route out interface %s\n", default_route.ifname); } return(ifname_to_if(default_route.ifname)); } else if (i == -1) { if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, 0, "No route\n"); return(-1); } if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, 0, "route out interface %s\n", routes[i].ifname); return(ifname_to_if(routes[i].ifname));}intunicast_route(net_addr *addr){ switch (NET_GET_TYPE(addr)) { case NET_ADDR_IPv4: return(unicast_route1(NET_GET_ADDR_IPv4(addr).s_addr)); case NET_ADDR_UDP_IPv4: return(unicast_route1(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); }}intifname_to_if(char *name) { int i; for (i = 0; i < if_num; i++) if (strncmp(if_vec[i].if_name, name, IFNAMSIZ) == 0) return(i); log(LOG_ERR, 0, "Couldn't find interface %s\n", name); return(-1);}intread_routes() { struct mbuf mbf, *mbfp = &mbf; register struct mbuf *m; struct mbuf **rhash; int i, doinghost = 1; int hashsize; struct ifreq ifrbuf, *ifr = &ifrbuf; int status; kread(nl[N_RTHASHSIZE].n_value, (char *)&hashsize, sizeof (hashsize)); rhash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) ); kread(nl[N_RTHOST].n_value, (char *)rhash, hashsize*sizeof (struct mbuf *)); nroute = 0;again: for (i = 0; i < hashsize; i++) { if (rhash[i] == 0) continue; m = rhash[i]; while (m) { struct ifnet ifz, *ifp = &ifz; struct rtentry *rt; struct ifaddr ifx, *ifxp = &ifx; char ifbuf[IFNAMSIZ]; kread((u_long)m, (char *)mbfp, sizeof(struct mbuf)); rt = mtod(mbfp, struct rtentry *); assert(rt->rt_ifp); routes[nroute].dst = *(struct sockaddr_in *)&rt->rt_dst; routes[nroute].gw = *(struct sockaddr_in *)&rt->rt_gateway; kread((u_long)rt->rt_ifp, (char *)ifp, sizeof(struct ifnet)); assert(ifp->if_addrlist); kread((u_long)ifp->if_addrlist, (char *)ifxp, sizeof(struct ifaddr)); assert(ifxp->ifa_addr.sa_family == AF_INET); routes[nroute].out_if = *(struct sockaddr_in *)&ifx.ifa_addr; kread((u_long)ifp->if_name, ifbuf, IFNAMSIZ); sprintf(routes[nroute].ifname, "%s%d", ifbuf, ifp->if_unit); memcpy(ifr->ifr_name, routes[nroute].ifname, IFNAMSIZ); status = ioctl(unicast_fd, SIOCGIFNETMASK, ifr); if (status < 0) { perror("ioctl"); return(-1); } routes[nroute].netmask = *(struct sockaddr_in *)&ifr->ifr_addr; if (routes[nroute].dst.sin_addr.s_addr == INADDR_ANY) { default_route = routes[nroute]; have_default = 1; } else nroute++; assert(nroute < 256); m = mbfp->m_next; } } if (doinghost) { kread(nl[N_RTNET].n_value, (char *)rhash, hashsize*sizeof (struct mbuf *)); nhost = nroute; doinghost = 0; goto again; } free(rhash); return(1);}intkread(unsigned long addr, char *buf, unsigned nbytes) { return kvm_read(kd, addr, buf, nbytes);}/* * Find a route to dst as the kernel would. */intrtfindx(struct sockaddr_in *dst) { int i; for (i = 0; i < nhost; i++) if (memcmp(&routes[i].dst, dst, sizeof(struct sockaddr)) == 0) return(i); for (i = nhost; i < nroute; i++) if (net_match(dst, &routes[i])) return(i); return(-1);}intnet_match(struct sockaddr_in *dst, struct xroute *rp) { u_long nm = rp->netmask.sin_addr.s_addr; if (inet_netmatch(dst, &rp->dst)) { u_long ip1 = dst->sin_addr.s_addr; u_long ip2 = rp->dst.sin_addr.s_addr; if (inet_netmatch(dst, &rp->out_if)) { if ((ip1 & nm) == ip2) return(1); else return(0); } else return(1); } return(0);}intinet_netmatch(struct sockaddr_in *sin1, struct sockaddr_in *sin2) { return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr));}#endif /* ! sgi */#endif /* ! SOLARIS */#endif /* ! PF_ROUTE */#ifdef SOLARIS/* * Copyright (c) Sun Microsystems, Inc. 1994. All rights reserved. * * License is granted to copy, to use, and to make and to use derivative works * for research and evaluation purposes, provided that Sun Microsystems is * acknowledged in all documentation pertaining to any such copy or * derivative work. Sun Microsystems grants no other licenses expressed or * implied. The Sun Microsystems trade name should not be used in any * advertising without its written permission. * * SUN MICROSYSTEMS MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS * SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is provided "as is" * without express or implied warranty of any kind. * * These notices must be retained in any copies of any part of this software. *//* Portions of this code were dereived from Solaris route.c and netstat.c */#include <fcntl.h>#include <sys/stropts.h>#include <sys/socket.h>#include <net/route.h>#include <netinet/in.h>#include <inet/ip.h>#include <sys/tihdr.h>#include <sys/tiuser.h>#include <inet/mib2.h>/* * Following Solaris code was supplied by Don Hoffman of Sun Microsystems. *//* * Defines */#define MAX_ROUTES (4 * 512)#ifndef T_CURRENT#define T_CURRENT MI_T_CURRENT#endif#define SOLARIS_2_6 6static int t_current = T_CURRENT;/* * Structure definitions */typedef struct mib_item_s { struct mib_item_s *next_item; long group; long mib_id; long length; char *valp;} mib_item_t;struct xroute { char ifname[IFNAMSIZ]; struct sockaddr_in netmask; struct sockaddr_in out_if; struct sockaddr_in dst; struct sockaddr_in gw;};/* * Forward function declarations */static mib_item_t *mibget(int sd);static void mibfree(mib_item_t *);static int is_host(mib2_ipRouteEntry_t * rp);static int is_gateway(mib2_ipRouteEntry_t * rp);int putmsg(int, struct strbuf *, struct strbuf *, int);int getmsg(int, struct strbuf *, struct strbuf *, int *);/* * Globals */static int sd;static struct xroute routes[MAX_ROUTES];static struct xroute default_route;static int have_default = 0;static int nhost = 0;static int nroute = 0;static intifname_to_if(char *name){ int i; if (name) fprintf(stderr, "ifname is %s\n", name); for (i = 0; i < if_num; i++) if (strncmp(if_vec[i].if_name, name, IFNAMSIZ) == 0) return (i); log(LOG_ERR, 0, "Couldn't find interface %s\n", name);#ifdef SUNMOD return (0);#else return (-1);#endif}#ifdef SBMu_longunicast_route_gw_specific(u_long addr){ int i; struct sockaddr_in sin; if (read_routes() == -1) return (-1); memset(&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; i = rtfindx(&sin); if (i == -1 && have_default) { if (IsDebug(DEBUG_ROUTE)) { log(LOG_DEBUG, 0, "Using default route ...\n"); log(LOG_DEBUG, 0, "route out interface %s\n", default_route.ifname); } return (default_route.gw.sin_addr.s_addr); } else if (i >= 0) return (routes[i].gw.sin_addr.s_addr); else return -1;}#endifstatic intinet_netmatch(struct sockaddr_in * sin1, struct sockaddr_in * sin2){ return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr));}static intnet_match(struct sockaddr_in * dst, struct xroute * rp){ u_long nm = rp->netmask.sin_addr.s_addr; if (inet_netmatch(dst, &rp->dst)) { u_long ip1 = dst->sin_addr.s_addr; u_long ip2 = rp->dst.sin_addr.s_addr; if (inet_netmatch(dst, &rp->out_if)) { if ((ip1 & nm) == ip2) return (1); else return (0); } else return (1); } return (0);}/* * Find a route to dst as the kernel would. */static intrtfindx(struct sockaddr_in *dst){ struct sockaddr_in *sockp; int i; for (i = 0; i < nhost; i++) { sockp = &(routes[i].dst);#ifdef notdef log(LOG_DEBUG, 0, "routes[%d].dst, dst is %x,%x\n", i, sockp->sin_addr.s_addr, dst->sin_addr.s_addr); #endif if (memcmp(sockp, dst, sizeof (struct sockaddr)) == 0) return (i); } for (i = nhost; i < nroute; i++) if (net_match(dst, &routes[i])) return (i); return (-1);}static intread_routes(){ mib_item_t *item; mib_item_t *first_item = nilp(mib_item_t); mib2_ipRouteEntry_t *rp; int ret_code = 1; int doinghost; int i; /* Get the route list. */ /* * TBD: don't need to do this every time. Only to a new mibget every X * seconds? */ if ((first_item = mibget(sd)) == nilp(mib_item_t)) { close(sd); ret_code = -1; goto leave; } /* Look up the entry */ have_default = 0; nroute = 0; nhost = 0; /* host routes first */ doinghost = 1;again: for (item = first_item; item; item = item->next_item) { /* skip all the other trash that comes up the mib stream */ if ((item->group != MIB2_IP) || (item->mib_id != MIB2_IP_21)) continue; rp = (mib2_ipRouteEntry_t *) item->valp; for (; (u_long) rp < (u_long)(item->valp + item->length); rp++) { /* skip routes that aren't what we want this pass */ if (doinghost) { if (!is_host(rp)) continue; } else { if (!is_gateway(rp)) continue; } /* fill in the blanks */ memset(&routes[nroute], 0, sizeof (struct xroute)); routes[nroute].dst.sin_family = AF_INET; routes[nroute].dst.sin_addr.s_addr = rp->ipRouteDest; routes[nroute].gw.sin_family = AF_INET; routes[nroute].gw.sin_addr.s_addr = rp->ipRouteNextHop; routes[nroute].netmask.sin_family = AF_INET; routes[nroute].netmask.sin_addr.s_addr = rp->ipRouteMask; routes[nroute].out_if.sin_family = AF_INET; routes[nroute].out_if.sin_addr.s_addr = rp->ipRouteInfo.re_src_addr; if (rp->ipRouteIfIndex.o_length >= IFNAMSIZ) rp->ipRouteIfIndex.o_length = IFNAMSIZ - 1; for (i = 0; i < rp->ipRouteIfIndex.o_length; i++) routes[nroute].ifname[i] = rp->ipRouteIfIndex.o_bytes[i]; routes[nroute].ifname[i] = '\0'; if (routes[nroute].dst.sin_addr.s_addr == INADDR_ANY) { default_route = routes[nroute]; have_default = 1; } else nroute++; } } /* net routes next */ if (doinghost) { nhost = nroute; doinghost = 0; goto again; }leave: mibfree(first_item); first_item = nilp(mib_item_t); return ret_code;}static intis_host(mib2_ipRouteEntry_t * rp){ if (rp->ipRouteMask == (IpAddress) - 1) return 1; else return 0;}static intis_gateway(mib2_ipRouteEntry_t * rp){#ifndef PF_ROUTE if (rp->ipRouteInfo.re_ire_type == IRE_GATEWAY || rp->ipRouteInfo.re_ire_type == IRE_NET || rp->ipRouteInfo.re_ire_type == IRE_ROUTE_ASSOC || rp->ipRouteInfo.re_ire_type == IRE_ROUTE_REDIRECT) return 1; else return 0;#else if (rp->ipRouteInfo.re_ire_type == IRE_DEFAULT || rp->ipRouteInfo.re_ire_type == IRE_PREFIX || rp->ipRouteInfo.re_ire_type == IRE_HOST || rp->ipRouteInfo.re_ire_type == IRE_HOST_REDIRECT) return 1; else return 0;#endif}static mib_item_t * mibget (int sd){ char buf[512]; int flags; int i, j, getcode; struct strbuf ctlbuf, databuf; struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf; struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf; struct T_error_ack *tea = (struct T_error_ack *)buf; struct opthdr *req; mib_item_t *first_item = nilp(mib_item_t); mib_item_t *last_item = nilp(mib_item_t); mib_item_t *temp; int debug = 0; tor->PRIM_type = T_OPTMGMT_REQ; tor->OPT_offset = sizeof(struct T_optmgmt_req); tor->OPT_length = sizeof(struct opthdr); tor->MGMT_flags = t_current; req = (struct opthdr *)&tor[1]; req->level = MIB2_IP; /* any MIB2_xxx value ok here */ req->name = 0; req->len = 0; ctlbuf.buf = buf; ctlbuf.len = tor->OPT_length + tor->OPT_offset; flags = 0; if (putmsg(sd, &ctlbuf, nilp(struct strbuf), flags) == -1) { perror("mibget: putmsg(ctl) failed"); goto error_exit; } /* * each reply consists of a ctl part for one fixed structure * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK, * containing an opthdr structure. level/name identify the entry, * len is the size of the data part of the message. */ req = (struct opthdr *)&toa[1]; ctlbuf.maxlen = sizeof(buf); for (j=1; ; j++) { flags = 0; getcode = getmsg(sd, &ctlbuf, nilp(struct strbuf), &flags); if (getcode == -1) { perror("mibget getmsg(ctl) failed"); if (debug) { fprintf(stderr, "# level name len\n"); i = 0; for (last_item = first_item; last_item; last_item = last_item->next_item) printf("%d %4ld %5ld %ld\n", ++i, last_item->group, last_item->mib_id, last_item->length); } goto error_exit; } if (getcode == 0 && ctlbuf.len >= sizeof(struct T_optmgmt_ack) && toa->PRIM_type == T_OPTMGMT_ACK && toa->MGMT_flags == T_SUCCESS && req->len == 0) { if (debug) printf("mibget getmsg() %d returned EOD (level %ld, name %ld)\n", j, req->level, req->name); return first_item; /* this is EOD msg */ } if (ctlbuf.len >= sizeof(struct T_error_ack) && tea->PRIM_type == T_ERROR_ACK) { fprintf(stderr, "mibget %d gives (%d) T_ERROR_ACK: TLI_error = 0x%lx, UNIX_error = 0x%lx\n", j, getcode, tea->TLI_error, tea->UNIX_error); errno = (tea->TLI_error == TSYSERR) ? tea->UNIX_error : EPROTO; goto error_exit; } if (getcode != MOREDATA || ctlbuf.len < sizeof(struct T_optmgmt_ack) || toa->PRIM_type != T_OPTMGMT_ACK || toa->MGMT_flags != T_SUCCESS) { printf( "mibget getmsg(ctl) %d returned %d, ctlbuf.len = %d, PRIM_type = %ld\n", j, getcode, ctlbuf.len, toa->PRIM_type); if (toa->PRIM_type == T_OPTMGMT_ACK) printf( "T_OPTMGMT_ACK: MGMT_flags = 0x%lx, req->len = %ld\n", toa->MGMT_flags, req->len); errno = ENOMSG; goto error_exit; } temp = (mib_item_t *)malloc(sizeof(mib_item_t)); if (!temp) { perror("mibget malloc failed"); goto error_exit; } if (last_item) last_item->next_item = temp; else first_item = temp; last_item = temp; last_item->next_item = nilp(mib_item_t); last_item->group = req->level; last_item->mib_id = req->name; last_item->length = req->len; last_item->valp = (char *)malloc(req->len); if (debug) printf( "msg %d: group = %4ld mib_id = %5ld length = %ld\n", j, last_item->group, last_item->mib_id, last_item->length); databuf.maxlen = last_item->length; databuf.buf = last_item->valp; databuf.len = 0; flags = 0; getcode = getmsg(sd, nilp(struct strbuf), &databuf, &flags); if (getcode == -1) { perror("mibget getmsg(data) failed"); goto error_exit; } else if (getcode != 0) { printf( "mibget getmsg(data) returned %d, databuf.maxlen = %d, databuf.len = %d\n", getcode, databuf.maxlen, databuf.len); goto error_exit; } }error_exit:; while (first_item) { last_item = first_item; first_item = first_item->next_item; free(last_item); } return first_item;}static voidmibfree(mib_item_t * first_item){ mib_item_t *last_item; while (first_item) { last_item = first_item; first_item = first_item->next_item; free(last_item); }}intunicast_init_specific(void){ int release; release = getSolarisRelease(); if (release < SOLARIS_2_6) { t_current = 0x100; } sd = open("/dev/ip", O_RDWR); if (sd == -1) { log(LOG_INFO, 0, "Unicast routing information unavailable\n"); init_failed = 1; NoUnicast = 1; return 0; } return (1);}intunicast_route_specific(u_long addr){ int i; struct sockaddr_in sin; if (init_failed) return (-1); if (read_routes() == -1) return (-1); memset(&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; i = rtfindx(&sin); if (i == -1 && have_default) { if (strlen(default_route.ifname) == 0) { /* * The interface name is not set on def route. Look it * up. */ if ((i = rtfindx(&default_route.gw)) == -1) return (-1); } if (IsDebug(DEBUG_ROUTE)) { log(LOG_DEBUG, 0, "Using default route ...\n"); log(LOG_DEBUG, 0, "route out interface %s\n", default_route.ifname); } return (ifname_to_if(default_route.ifname)); } else if (i == -1) { if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, 0, "No route\n"); return (-1); } if (strlen(routes[i].ifname) == 0) { /* * The interface name is not set on GW routes. Look it up. */ if ((i = rtfindx(&routes[i].gw)) == -1) return (-1); } if (IsDebug(DEBUG_ROUTE)) log(LOG_DEBUG, 0, "route out interface %s\n", routes[i].ifname); return (ifname_to_if(routes[i].ifname));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -