📄 rtsock.c
字号:
Free(rtm); rtm = new_rtm; } (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, (struct walkarg *)0); rtm->rtm_flags = rt->rt_flags; rtm->rtm_rmx = rt->rt_rmx; rtm->rtm_addrs = info.rti_addrs; break;#ifdef ROUTER_STACK case RTM_NEWCHANGE: /* * Use the exact match selected with the gateway * address, if available. Save the primary route * in case the change operation alters the weight. */ if (pGateway) { saved_nrt = rt; rt = (struct rtentry *)pRoute; } /* Access the new gateway value for a route, if any. */ gate = info.rti_info[RTAX_AUTHOR];#endif case RTM_CHANGE: if (gate && rt_setgate(rt, rt_key(rt), gate)) senderr(ENOSPC);#ifdef ROUTER_STACK /* Only remove cloned routes when altering the primary entry. */ if ( ((ROUTE_ENTRY *)rt)->primaryRouteFlag) {#endif /* ROUTER_STACK */ if (gate && (rt_key(rt)->sa_family == AF_INET)) { /* * Remove any cloned routes using the * (now obsolete) gateway. */ if ( (rt->rt_flags & RTF_CLONING) && rt_mask (rt)) rn_walksubtree (rnh, rt_key (rt), rt_mask (rt), rt_fixdelete, rt); }#ifdef ROUTER_STACK /* End of condition for cloned route removal */ }#endif /* new gateway could require new ifaddr, ifp; flags may also be different; ifp may be specified by ll sockaddr when protocol address is ambiguous */ if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && (ifp = ifa->ifa_ifp)) ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, ifp); else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || (ifa = ifa_ifwithroute(rt->rt_flags, rt_key(rt), gate))) ifp = ifa->ifa_ifp; if (ifa) { register struct ifaddr *oifa = rt->rt_ifa; if (oifa != ifa) { if (oifa && oifa->ifa_rtrequest) oifa->ifa_rtrequest(RTM_DELETE, rt, gate); IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; ifa->ifa_refcnt++; rt->rt_ifp = ifp; } }#ifdef ROUTER_STACK /* * Note: Setting the metrics does not change the new weight * value for the selected route entry, since that * alteration could replace the current route before * completing all the changes required. */#endif rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx); if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); if (genmask) rt->rt_genmask = genmask; /* * Fall into */ case RTM_LOCK: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); rt->rt_rmx.rmx_locks |= (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); break; }#ifdef ROUTER_STACK /* * Since a weight change could replace the primary route * visible to the IP forwarding process and the original * routing socket messages, reorganizing the routes must * wait until after all the prior changes so that any new * copy of the selected route is correct. */ switch(rtm->rtm_type) { case RTM_CHANGE: case RTM_NEWCHANGE: /* Do nothing if the weight did not change. */ if ( (rtm->rtm_inits & RTV_WEIGHT) == 0) break; /* * Get the primary route to find the matching group * for an existing entry when updating the weight. */ if (saved_nrt) { /* * The new change operation set a gateway to get * an exact match and saved the primary route. */ pRoute = (ROUTE_ENTRY *)saved_nrt; } else { /* * The original change operation only modifies the * primary route. The new change operation also * alters that entry if no gateway is set. */ pRoute = (ROUTE_ENTRY *)rt; } routeWeightUpdate (pRoute, protoId, (ROUTE_ENTRY *)rt, gate, rtm->rtm_rmx.weight); if (saved_nrt) { /* * Release the reference to the primary route * if a specified gateway used an exact match. */ rtfree (saved_nrt); } break; }#endif /* ROUTER_STACK */ break; default: senderr(EOPNOTSUPP); }flush:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ if (error) { WV_NET_EVENT_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 29, 4, WV_NETEVENT_RTOUTPUT_FAIL, WV_NET_SEND, so->so_fd, error) }#endif /* INCLUDE_WVNET */#endif if (rtm) { if (error) rtm->rtm_errno = error; else rtm->rtm_flags |= RTF_DONE; } if (rt) rtfree(rt); { register struct rawcb *rp = 0; /* * Check to see if we don't want our own messages. */ if ((so->so_options & SO_USELOOPBACK) == 0) { if (route_cb.any_count <= 1) { if (rtm) Free(rtm); m_freem(m); return (error); } /* There is another listener, so construct message */ rp = sotorawcb(so); } if (rtm) { m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); Free(rtm); } if (rp) rp->rcb_proto.sp_family = 0; /* Avoid us */ if (dst) route_proto.sp_protocol = dst->sa_family; raw_input(m, &route_proto, &route_src, &route_dst); if (rp) rp->rcb_proto.sp_family = PF_ROUTE; } return (error);}static voidrt_setmetrics(which, in, out) u_long which; register struct rt_metrics *in, *out;{#define metric(f, e) if (which & (f)) out->e = in->e; metric(RTV_RPIPE, rmx_recvpipe); metric(RTV_SPIPE, rmx_sendpipe); metric(RTV_SSTHRESH, rmx_ssthresh); metric(RTV_RTT, rmx_rtt); metric(RTV_RTTVAR, rmx_rttvar); metric(RTV_HOPCOUNT, rmx_hopcount); metric(RTV_MTU, rmx_mtu); metric(RTV_EXPIRE, rmx_expire);#ifdef ROUTER_STACK /* * Set the values for the new additional metrics, * except the weight, which must be postponed when * altering that value. */ metric(RTV_VALUE1, value1) metric(RTV_VALUE2, value2) metric(RTV_VALUE3, value3) metric(RTV_VALUE4, value4) metric(RTV_VALUE5, value5) metric(RTV_ROUTETAG, routeTag)#endif /* ROUTER_STACK */#undef metric}#define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))static voidrt_xaddrs(cp, cplim, rtinfo) register caddr_t cp, cplim; register struct rt_addrinfo *rtinfo;{ register struct sockaddr *sa; register int i; bzero((char *)rtinfo->rti_info, sizeof(rtinfo->rti_info)); for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { if ((rtinfo->rti_addrs & (1 << i)) == 0) continue; rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; ADVANCE(cp, sa); }}struct mbuf *rt_msg1(type, rtinfo) int type; register struct rt_addrinfo *rtinfo;{ register struct rt_msghdr *rtm; register struct mbuf *m; register int i; register struct sockaddr *sa; int len, dlen; m = mHdrClGet(M_DONTWAIT, MT_DATA, CL_SIZE_128, TRUE); if (m == 0) return (m); switch (type) { case RTM_DELADDR: case RTM_NEWADDR: len = sizeof(struct ifa_msghdr); break; case RTM_IFINFO: len = sizeof(struct if_msghdr); break; default: len = sizeof(struct rt_msghdr); } if (len > m->m_extSize) panic("rt_msg1"); m->m_pkthdr.len = m->m_len = len; m->m_pkthdr.rcvif = 0; rtm = mtod(m, struct rt_msghdr *); bzero((caddr_t)rtm, len); for (i = 0; i < RTAX_MAX; i++) { if ((sa = rtinfo->rti_info[i]) == NULL) continue; rtinfo->rti_addrs |= (1 << i); dlen = ROUNDUP(sa->sa_len); m_copyback(m, len, dlen, (caddr_t)sa); len += dlen; } if (m->m_pkthdr.len != len) { m_freem(m); return (NULL); } rtm->rtm_msglen = len; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = type; return (m);}static intrt_msg2(type, rtinfo, cp, w) int type; register struct rt_addrinfo *rtinfo; caddr_t cp; struct walkarg *w;{ register int i; int len, dlen, second_time = 0; caddr_t cp0; rtinfo->rti_addrs = 0;again: switch (type) { case RTM_DELADDR: case RTM_NEWADDR: len = sizeof(struct ifa_msghdr); break; case RTM_IFINFO: len = sizeof(struct if_msghdr); break; default: len = sizeof(struct rt_msghdr); } if ((cp0 = cp)) cp += len; for (i = 0; i < RTAX_MAX; i++) { register struct sockaddr *sa; if ((sa = rtinfo->rti_info[i]) == 0) continue; rtinfo->rti_addrs |= (1 << i); dlen = ROUNDUP(sa->sa_len); if (cp) { bcopy((caddr_t)sa, cp, (unsigned)dlen); cp += dlen; } len += dlen; } if (cp == 0 && w != NULL && !second_time) { register struct walkarg *rw = w; rw->w_needed += len; if (rw->w_needed <= 0 && rw->w_where) { if (rw->w_tmemsize < len) { if (rw->w_tmem) { FREE(rw->w_tmem, MT_RTABLE); } MALLOC(rw->w_tmem, caddr_t, len, MT_RTABLE, M_DONTWAIT); if (rw->w_tmem) rw->w_tmemsize = len; } if (rw->w_tmem) { cp = rw->w_tmem; second_time = 1; goto again; } else rw->w_where = 0; } } if (cp) { register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = type; rtm->rtm_msglen = len; } return (len);}/* * This routine is called to generate a message from the routing * socket indicating that a redirect has occured, a routing lookup * has failed, or that a protocol has detected timeouts to a particular * destination. */voidrt_missmsg(type, rtinfo, flags, error) int type, flags, error; register struct rt_addrinfo *rtinfo;{ register struct rt_msghdr *rtm; register struct mbuf *m; struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; if (route_cb.any_count == 0) return; m = rt_msg1(type, rtinfo); if (m == 0) return; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_flags = RTF_DONE | flags; rtm->rtm_errno = error; rtm->rtm_addrs = rtinfo->rti_addrs; route_proto.sp_protocol = sa ? sa->sa_family : 0; raw_input(m, &route_proto, &route_src, &route_dst);}/* * This routine is called to generate a message from the routing * socket indicating that the status of a network interface has changed. */voidrt_ifmsg(ifp) register struct ifnet *ifp;{ register struct if_msghdr *ifm; struct mbuf *m; struct rt_addrinfo info; if (route_cb.any_count == 0) return; bzero((caddr_t)&info, sizeof(info)); m = rt_msg1(RTM_IFINFO, &info); if (m == 0) return; ifm = mtod(m, struct if_msghdr *); ifm->ifm_index = ifp->if_index; ifm->ifm_flags = ifp->if_flags; ifm->ifm_data = ifp->if_data; ifm->ifm_addrs = 0; route_proto.sp_protocol = 0; raw_input(m, &route_proto, &route_src, &route_dst);}/* * This is called to generate messages from the routing socket * indicating a network interface has had addresses associated with it. * if we ever reverse the logic and replace messages TO the routing * socket indicate a request to configure interfaces, then it will * be unnecessary as the routing socket will automatically generate * copies of it. */voidrt_newaddrmsg(cmd, ifa, error, rt) int cmd, error; register struct ifaddr *ifa; register struct rtentry *rt;{ struct rt_addrinfo info; struct sockaddr *sa = NULL; int pass; struct mbuf *m = NULL; struct ifnet *ifp = ifa->ifa_ifp; int ncmd; if (route_cb.any_count == 0) return; for (pass = 1; pass < 3; pass++) { bzero((caddr_t)&info, sizeof(info)); if ((cmd == RTM_ADD && pass == 1) || (cmd == RTM_DELETE && pass == 2)) { register struct ifa_msghdr *ifam; ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; ifaaddr = sa = ifa->ifa_addr; ifpaddr = ifp->if_addrlist->ifa_addr; netmask = ifa->ifa_netmask; brdaddr = ifa->ifa_dstaddr; if ((m = rt_msg1(ncmd, &info)) == NULL) continue; ifam = mtod(m, struct ifa_msghdr *); ifam->ifam_index = ifp->if_index; ifam->ifam_metric = ifa->ifa_metric; ifam->ifam_flags = ifa->ifa_flags; ifam->ifam_addrs = info.rti_addrs; } if ((cmd == RTM_ADD && pass == 2) || (cmd == RTM_DELETE && pass == 1)) { register struct rt_msghdr *rtm; if (rt == 0) continue; ncmd = cmd; netmask = rt_mask(rt); dst = sa = rt_key(rt); gate = rt->rt_gateway;#ifdef ROUTER_STACK /* Use a different message type for additional routes. */ if ( ((ROUTE_ENTRY *)rt)->primaryRouteFlag == FALSE) { if (ncmd == RTM_ADD) ncmd = RTM_ADDEXTRA; else ncmd = RTM_DELEXTRA; }#endif /* ROUTER_STACK */ if ((m = rt_msg1(ncmd, &info)) == NULL) continue; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_index = ifp->if_index; rtm->rtm_flags |= rt->rt_flags; rtm->rtm_errno = error; rtm->rtm_addrs = info.rti_addrs; } route_proto.sp_protocol = sa ? sa->sa_family : 0; raw_input(m, &route_proto, &route_src, &route_dst); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -