📄 rtsock.c
字号:
/* $Id: rtsock.c,v 1.2 1996/01/16 14:22:01 chris Exp $ *//* * Copyright (c) 1988, 1991 Regents of the University of California. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)rtsock.c 7.18 (Berkeley) 6/27/91 */#include "param.h"#include "mbuf.h"#include "proc.h"#include "socket.h"#include "socketvar.h"#include "domain.h"#include "protosw.h"#include "af.h"#include "if.h"#include "route.h"#include "raw_cb.h"#include "machine/mtpr.h"#ifdef NO_DATAstruct sockaddr route_dst;struct sockaddr route_src;struct sockproto route_proto;#elsestruct sockaddr route_dst = { 2, PF_ROUTE, };struct sockaddr route_src = { 2, PF_ROUTE, };struct sockproto route_proto = { PF_ROUTE, };#endifroute_init (){#ifdef NO_DATA route_dst.sa_len = route_src.sa_len = 2; route_dst.sa_family = route_src.sa_family = PF_ROUTE; route_proto.sp_family = PF_ROUTE;#endif raw_init ();}/*ARGSUSED*/route_usrreq(so, req, m, nam, control) register struct socket *so; int req; struct mbuf *m, *nam, *control;{ register int error = 0; register struct rawcb *rp = sotorawcb(so); int s; if (req == PRU_ATTACH) { MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); if (so->so_pcb = (caddr_t)rp) bzero(so->so_pcb, sizeof(*rp)); } if (req == PRU_DETACH && rp) { int af = rp->rcb_proto.sp_protocol; if (af == AF_INET) route_cb.ip_count--; else if (af == AF_NS) route_cb.ns_count--; else if (af == AF_ISO) route_cb.iso_count--; route_cb.any_count--; } s = splnet(); error = raw_usrreq(so, req, m, nam, control); rp = sotorawcb(so); if (req == PRU_ATTACH && rp) { int af = rp->rcb_proto.sp_protocol; if (error) { free((caddr_t)rp, M_PCB); splx(s); return (error); } if (af == AF_INET) route_cb.ip_count++; else if (af == AF_NS) route_cb.ns_count++; else if (af == AF_ISO) route_cb.iso_count++; rp->rcb_faddr = &route_src; route_cb.any_count++; soisconnected(so); so->so_options |= SO_USELOOPBACK; } splx(s); return (error);}#define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))/*ARGSUSED*/route_output(m, so) register struct mbuf *m; struct socket *so;{ register struct rt_msghdr *rtm = 0; register struct rtentry *rt = 0; struct rtentry *saved_nrt = 0; struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *genmask = 0; struct sockaddr *ifpaddr = 0, *ifaaddr = 0; caddr_t cp, lim; int len, error = 0; struct ifnet *ifp = 0; struct ifaddr *ifa = 0; struct ifaddr *ifaof_ifpforaddr(), *ifa_ifwithroute();#define senderr(e) { error = e; goto flush;} if (m == 0 || m->m_len < sizeof(long)) return (ENOBUFS); if ((m = m_pullup(m, sizeof(long))) == 0) return (ENOBUFS); if ((m->m_flags & M_PKTHDR) == 0) panic("route_output"); len = m->m_pkthdr.len; if (len < sizeof(*rtm) || len != mtod(m, struct rt_msghdr *)->rtm_msglen) senderr(EINVAL); R_Malloc(rtm, struct rt_msghdr *, len); if (rtm == 0) senderr(ENOBUFS); m_copydata(m, 0, len, (caddr_t)rtm); if (rtm->rtm_version != RTM_VERSION) senderr(EPROTONOSUPPORT); rtm->rtm_pid = curproc->p_pid; lim = len + (caddr_t) rtm; cp = (caddr_t) (rtm + 1); if (rtm->rtm_addrs & RTA_DST) { dst = (struct sockaddr *)cp; ADVANCE(cp, dst); } else senderr(EINVAL); if ((rtm->rtm_addrs & RTA_GATEWAY) && cp < lim) { gate = (struct sockaddr *)cp; ADVANCE(cp, gate); } if ((rtm->rtm_addrs & RTA_NETMASK) && cp < lim) { netmask = (struct sockaddr *)cp; ADVANCE(cp, netmask); } if ((rtm->rtm_addrs & RTA_GENMASK) && cp < lim) { struct radix_node *t, *rn_addmask(); genmask = (struct sockaddr *)cp; ADVANCE(cp, genmask); t = rn_addmask(genmask, 1, 2); if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) genmask = (struct sockaddr *)(t->rn_key); else senderr(ENOBUFS); } if ((rtm->rtm_addrs & RTA_IFP) && cp < lim) { ifpaddr = (struct sockaddr *)cp; ADVANCE(cp, ifpaddr); } if ((rtm->rtm_addrs & RTA_IFA) && cp < lim) { ifaaddr = (struct sockaddr *)cp; } switch (rtm->rtm_type) { case RTM_ADD: if (gate == 0) senderr(EINVAL); error = rtrequest(RTM_ADD, dst, gate, netmask, rtm->rtm_flags, &saved_nrt); if (error == 0 && saved_nrt) { rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &saved_nrt->rt_rmx); saved_nrt->rt_refcnt--; saved_nrt->rt_genmask = genmask; } break; case RTM_DELETE: error = rtrequest(RTM_DELETE, dst, gate, netmask, rtm->rtm_flags, (struct rtentry **)0); break; case RTM_GET: case RTM_CHANGE: case RTM_LOCK: rt = rtalloc1(dst, 0); if (rt == 0) senderr(ESRCH); if (rtm->rtm_type != RTM_GET) { if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0) senderr(ESRCH); if (rt->rt_nodes->rn_dupedkey && (netmask == 0 || Bcmp(netmask, rt_mask(rt), netmask->sa_len))) senderr(ETOOMANYREFS); } switch(rtm->rtm_type) { case RTM_GET: dst = rt_key(rt); len = sizeof(*rtm); ADVANCE(len, dst); rtm->rtm_addrs |= RTA_DST; if (gate = rt->rt_gateway) { ADVANCE(len, gate); rtm->rtm_addrs |= RTA_GATEWAY; } else rtm->rtm_addrs &= ~RTA_GATEWAY; if (netmask = rt_mask(rt)) { ADVANCE(len, netmask); rtm->rtm_addrs |= RTA_NETMASK; } else rtm->rtm_addrs &= ~RTA_NETMASK; if (genmask = rt->rt_genmask) { ADVANCE(len, genmask); rtm->rtm_addrs |= RTA_GENMASK; } else rtm->rtm_addrs &= ~RTA_GENMASK; if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { if (rt->rt_ifp == 0) goto badif; for (ifa = rt->rt_ifp->if_addrlist; ifa && ifa->ifa_addr->sa_family != AF_LINK; ifa = ifa->ifa_next){} if (ifa && rt->rt_ifa) { ifpaddr = ifa->ifa_addr; ADVANCE(len, ifpaddr); ifaaddr = rt->rt_ifa->ifa_addr; ADVANCE(len, ifaaddr); rtm->rtm_addrs |= RTA_IFP | RTA_IFA; } else { badif: ifpaddr = 0; rtm->rtm_addrs &= ~(RTA_IFP | RTA_IFA); } } if (len > rtm->rtm_msglen) { struct rt_msghdr *new_rtm; R_Malloc(new_rtm, struct rt_msghdr *, len); if (new_rtm == 0) senderr(ENOBUFS); Bcopy(rtm, new_rtm, rtm->rtm_msglen); Free(rtm); rtm = new_rtm; } rtm->rtm_msglen = len; rtm->rtm_flags = rt->rt_flags; rtm->rtm_rmx = rt->rt_rmx; cp = (caddr_t) (1 + rtm); len = ROUNDUP(dst->sa_len); Bcopy(dst, cp, len); cp += len; if (gate) { len = ROUNDUP(gate->sa_len); Bcopy(gate, cp, len); cp += len; } if (netmask) { len = ROUNDUP(netmask->sa_len); Bcopy(netmask, cp, len); cp += len; } if (genmask) { len = ROUNDUP(genmask->sa_len); Bcopy(genmask, cp, len); cp += len; } if (ifpaddr) { len = ROUNDUP(ifpaddr->sa_len); Bcopy(ifpaddr, cp, len); cp += len; len = ROUNDUP(ifaaddr->sa_len); Bcopy(ifaaddr, cp, len); cp += len; } break; case RTM_CHANGE: if (gate && (gate->sa_len > (len = rt->rt_gateway->sa_len))) senderr(EDQUOT); /* 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); rt->rt_ifa = ifa; rt->rt_ifp = ifp; } } if (gate) Bcopy(gate, rt->rt_gateway, len); 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 & rtm->rtm_rmx.rmx_locks); rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); break; } goto cleanup; default: senderr(EOPNOTSUPP); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -