136352Ssklower /* 250228Ssklower * Copyright (c) 1988, 1991 Regents of the University of California. 336352Ssklower * All rights reserved. 436352Ssklower * 544466Sbostic * %sccs.include.redist.c% 636352Ssklower * 7*52631Ssklower * @(#)rtsock.c 7.25 (Berkeley) 02/21/92 836352Ssklower */ 936352Ssklower 1036352Ssklower #include "param.h" 1152564Ssklower #include "proc.h" 1236352Ssklower #include "mbuf.h" 1336352Ssklower #include "socket.h" 1436352Ssklower #include "socketvar.h" 1536352Ssklower #include "domain.h" 1636352Ssklower #include "protosw.h" 1736352Ssklower 1836352Ssklower #include "af.h" 1940446Ssklower #include "if.h" 2036352Ssklower #include "route.h" 2136352Ssklower #include "raw_cb.h" 2236352Ssklower 2352564Ssklower struct sockaddr route_dst = { 2, PF_ROUTE, }; 2452564Ssklower struct sockaddr route_src = { 2, PF_ROUTE, }; 2552564Ssklower struct sockproto route_proto = { PF_ROUTE, }; 2637472Ssklower 2752564Ssklower struct walkarg { 2852564Ssklower int w_op, w_arg, w_given, w_needed, w_tmemsize; 2952564Ssklower caddr_t w_where, w_tmem; 3052564Ssklower }; 3152564Ssklower 3252564Ssklower static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 3352564Ssklower static struct mbuf *rt_msg1 __P((int, struct rt_addrinfo *)); 3452564Ssklower static int rt_msg2 __P((int, struct rt_addrinfo *, caddr_t, 3552564Ssklower struct walkarg *)); 3652564Ssklower 3752564Ssklower /* Sleazy use of local variables throughout file, warning!!!! */ 3852564Ssklower #define dst info.rti_info[RTAX_DST] 3952564Ssklower #define gate info.rti_info[RTAX_GATEWAY] 4052564Ssklower #define netmask info.rti_info[RTAX_NETMASK] 4152564Ssklower #define genmask info.rti_info[RTAX_GENMASK] 4252564Ssklower #define ifpaddr info.rti_info[RTAX_IFP] 4352564Ssklower #define ifaaddr info.rti_info[RTAX_IFA] 4452564Ssklower #define brdaddr info.rti_info[RTAX_BRD] 4552564Ssklower 4636352Ssklower /*ARGSUSED*/ 4740446Ssklower route_usrreq(so, req, m, nam, control) 4836352Ssklower register struct socket *so; 4936352Ssklower int req; 5040446Ssklower struct mbuf *m, *nam, *control; 5136352Ssklower { 5236352Ssklower register int error = 0; 5336352Ssklower register struct rawcb *rp = sotorawcb(so); 5444949Ssklower int s; 5537472Ssklower if (req == PRU_ATTACH) { 5637472Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 5737472Ssklower if (so->so_pcb = (caddr_t)rp) 5837472Ssklower bzero(so->so_pcb, sizeof(*rp)); 5937472Ssklower 6037472Ssklower } 6136352Ssklower if (req == PRU_DETACH && rp) { 6236352Ssklower int af = rp->rcb_proto.sp_protocol; 6336352Ssklower if (af == AF_INET) 6436352Ssklower route_cb.ip_count--; 6536352Ssklower else if (af == AF_NS) 6636352Ssklower route_cb.ns_count--; 6736352Ssklower else if (af == AF_ISO) 6836352Ssklower route_cb.iso_count--; 6936352Ssklower route_cb.any_count--; 7036352Ssklower } 7144949Ssklower s = splnet(); 7240446Ssklower error = raw_usrreq(so, req, m, nam, control); 7336352Ssklower rp = sotorawcb(so); 7437472Ssklower if (req == PRU_ATTACH && rp) { 7536352Ssklower int af = rp->rcb_proto.sp_protocol; 7637472Ssklower if (error) { 7737472Ssklower free((caddr_t)rp, M_PCB); 7844949Ssklower splx(s); 7937472Ssklower return (error); 8037472Ssklower } 8136352Ssklower if (af == AF_INET) 8236352Ssklower route_cb.ip_count++; 8336352Ssklower else if (af == AF_NS) 8436352Ssklower route_cb.ns_count++; 8536352Ssklower else if (af == AF_ISO) 8636352Ssklower route_cb.iso_count++; 8737472Ssklower rp->rcb_faddr = &route_src; 8836352Ssklower route_cb.any_count++; 8936352Ssklower soisconnected(so); 9042356Ssklower so->so_options |= SO_USELOOPBACK; 9136352Ssklower } 9244949Ssklower splx(s); 9336352Ssklower return (error); 9436352Ssklower } 9536352Ssklower 9637472Ssklower /*ARGSUSED*/ 9736352Ssklower route_output(m, so) 9836352Ssklower register struct mbuf *m; 9936352Ssklower struct socket *so; 10036352Ssklower { 10144949Ssklower register struct rt_msghdr *rtm = 0; 10236352Ssklower register struct rtentry *rt = 0; 10340446Ssklower struct rtentry *saved_nrt = 0; 10452564Ssklower struct rt_addrinfo info; 10537472Ssklower int len, error = 0; 10643336Ssklower struct ifnet *ifp = 0; 10747465Ssklower struct ifaddr *ifa = 0; 10847465Ssklower struct ifaddr *ifaof_ifpforaddr(), *ifa_ifwithroute(); 10936352Ssklower 11040446Ssklower #define senderr(e) { error = e; goto flush;} 11140786Ssklower if (m == 0 || m->m_len < sizeof(long)) 11238847Ssklower return (ENOBUFS); 11340786Ssklower if ((m = m_pullup(m, sizeof(long))) == 0) 11440786Ssklower return (ENOBUFS); 11536352Ssklower if ((m->m_flags & M_PKTHDR) == 0) 11638847Ssklower panic("route_output"); 11736352Ssklower len = m->m_pkthdr.len; 11844949Ssklower if (len < sizeof(*rtm) || 11944949Ssklower len != mtod(m, struct rt_msghdr *)->rtm_msglen) 12040446Ssklower senderr(EINVAL); 12136352Ssklower R_Malloc(rtm, struct rt_msghdr *, len); 12236352Ssklower if (rtm == 0) 12340446Ssklower senderr(ENOBUFS); 12436352Ssklower m_copydata(m, 0, len, (caddr_t)rtm); 12540786Ssklower if (rtm->rtm_version != RTM_VERSION) 12640446Ssklower senderr(EPROTONOSUPPORT); 12748729Ssklower rtm->rtm_pid = curproc->p_pid; 12852564Ssklower info.rti_addrs = rtm->rtm_addrs; 12952564Ssklower rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); 13052564Ssklower if (dst == 0) 13140786Ssklower senderr(EINVAL); 13252564Ssklower if (genmask) { 13343336Ssklower struct radix_node *t, *rn_addmask(); 13443336Ssklower t = rn_addmask(genmask, 1, 2); 13543336Ssklower if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) 13643336Ssklower genmask = (struct sockaddr *)(t->rn_key); 13743336Ssklower else 13843336Ssklower senderr(ENOBUFS); 13936352Ssklower } 14036352Ssklower switch (rtm->rtm_type) { 14152564Ssklower 14236352Ssklower case RTM_ADD: 14340786Ssklower if (gate == 0) 14440786Ssklower senderr(EINVAL); 14536352Ssklower error = rtrequest(RTM_ADD, dst, gate, netmask, 14636352Ssklower rtm->rtm_flags, &saved_nrt); 14740786Ssklower if (error == 0 && saved_nrt) { 14840786Ssklower rt_setmetrics(rtm->rtm_inits, 14940786Ssklower &rtm->rtm_rmx, &saved_nrt->rt_rmx); 15040446Ssklower saved_nrt->rt_refcnt--; 15143336Ssklower saved_nrt->rt_genmask = genmask; 15240786Ssklower } 15336352Ssklower break; 15436352Ssklower 15536352Ssklower case RTM_DELETE: 15636352Ssklower error = rtrequest(RTM_DELETE, dst, gate, netmask, 15737472Ssklower rtm->rtm_flags, (struct rtentry **)0); 15836352Ssklower break; 15936352Ssklower 16036352Ssklower case RTM_GET: 16136352Ssklower case RTM_CHANGE: 16236352Ssklower case RTM_LOCK: 16336352Ssklower rt = rtalloc1(dst, 0); 16436352Ssklower if (rt == 0) 16540446Ssklower senderr(ESRCH); 16647465Ssklower if (rtm->rtm_type != RTM_GET) { 16747465Ssklower if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0) 16847465Ssklower senderr(ESRCH); 16947465Ssklower if (rt->rt_nodes->rn_dupedkey && 17047465Ssklower (netmask == 0 || 17147465Ssklower Bcmp(netmask, rt_mask(rt), netmask->sa_len))) 17245183Ssklower senderr(ETOOMANYREFS); 17345183Ssklower } 17436352Ssklower switch(rtm->rtm_type) { 17536352Ssklower 17636352Ssklower case RTM_GET: 17752564Ssklower dst = rt_key(rt); 17852564Ssklower gate = rt->rt_gateway; 17952564Ssklower netmask = rt_mask(rt); 18052564Ssklower genmask = rt->rt_genmask; 18145656Ssklower if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 18252564Ssklower if (ifp = rt->rt_ifp) { 18352564Ssklower ifpaddr = ifp->if_addrlist->ifa_addr; 18445656Ssklower ifaaddr = rt->rt_ifa->ifa_addr; 18552564Ssklower rtm->rtm_index = ifp->if_index; 18645656Ssklower } else { 18752564Ssklower ifpaddr = 0; 18852564Ssklower ifaaddr = 0; 18952564Ssklower } 19045656Ssklower } 19152564Ssklower len = rt_msg2(RTM_GET, &info, (caddr_t)0, 19252564Ssklower (struct walkarg *)0); 19336352Ssklower if (len > rtm->rtm_msglen) { 19436352Ssklower struct rt_msghdr *new_rtm; 19536352Ssklower R_Malloc(new_rtm, struct rt_msghdr *, len); 19636352Ssklower if (new_rtm == 0) 19740446Ssklower senderr(ENOBUFS); 19836352Ssklower Bcopy(rtm, new_rtm, rtm->rtm_msglen); 19936352Ssklower Free(rtm); rtm = new_rtm; 20036352Ssklower } 20152564Ssklower (void)rt_msg2(RTM_GET, &info, (caddr_t)rtm, 20252564Ssklower (struct walkarg *)0); 20345183Ssklower rtm->rtm_flags = rt->rt_flags; 20445183Ssklower rtm->rtm_rmx = rt->rt_rmx; 20536352Ssklower break; 20636352Ssklower 20736352Ssklower case RTM_CHANGE: 20850229Ssklower if (gate && rt_setgate(rt, rt_key(rt), gate)) 20940446Ssklower senderr(EDQUOT); 21043336Ssklower /* new gateway could require new ifaddr, ifp; 21143336Ssklower flags may also be different; ifp may be specified 21243336Ssklower by ll sockaddr when protocol address is ambiguous */ 21347465Ssklower if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && 21447465Ssklower (ifp = ifa->ifa_ifp)) 21547465Ssklower ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, 21647465Ssklower ifp); 21747465Ssklower else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || 21847465Ssklower (ifa = ifa_ifwithroute(rt->rt_flags, 21947465Ssklower rt_key(rt), gate))) 22047465Ssklower ifp = ifa->ifa_ifp; 22143336Ssklower if (ifa) { 22247465Ssklower register struct ifaddr *oifa = rt->rt_ifa; 22347465Ssklower if (oifa != ifa) { 22447465Ssklower if (oifa && oifa->ifa_rtrequest) 22547465Ssklower oifa->ifa_rtrequest(RTM_DELETE, 22647465Ssklower rt, gate); 22743336Ssklower rt->rt_ifa = ifa; 22847465Ssklower rt->rt_ifp = ifp; 22943336Ssklower } 23043336Ssklower } 23147465Ssklower rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 23247465Ssklower &rt->rt_rmx); 23343336Ssklower if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 23443336Ssklower rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); 23543336Ssklower if (genmask) 23643336Ssklower rt->rt_genmask = genmask; 23736352Ssklower /* 23836352Ssklower * Fall into 23936352Ssklower */ 24040786Ssklower case RTM_LOCK: 24150811Ssklower rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 24240786Ssklower rt->rt_rmx.rmx_locks |= 24340786Ssklower (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 24436352Ssklower break; 24536352Ssklower } 24652564Ssklower break; 24736352Ssklower 24836352Ssklower default: 24940446Ssklower senderr(EOPNOTSUPP); 25036352Ssklower } 25136352Ssklower 25236352Ssklower flush: 25336352Ssklower if (rtm) { 25436352Ssklower if (error) 25536352Ssklower rtm->rtm_errno = error; 25636352Ssklower else 25736352Ssklower rtm->rtm_flags |= RTF_DONE; 25836352Ssklower } 25936352Ssklower cleanup: 26036352Ssklower if (rt) 26136352Ssklower rtfree(rt); 26242356Ssklower { 26342356Ssklower register struct rawcb *rp = 0; 26442356Ssklower /* 26542356Ssklower * Check to see if we don't want our own messages. 26642356Ssklower */ 26742356Ssklower if ((so->so_options & SO_USELOOPBACK) == 0) { 26842356Ssklower if (route_cb.any_count <= 1) { 26942356Ssklower if (rtm) 27042356Ssklower Free(rtm); 27142356Ssklower m_freem(m); 27242356Ssklower return (error); 27342356Ssklower } 27442356Ssklower /* There is another listener, so construct message */ 27542356Ssklower rp = sotorawcb(so); 27642356Ssklower } 27745656Ssklower if (rtm) { 27845656Ssklower m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 27938847Ssklower Free(rtm); 28038847Ssklower } 28142356Ssklower if (rp) 28242356Ssklower rp->rcb_proto.sp_family = 0; /* Avoid us */ 28345183Ssklower if (dst) 28445183Ssklower route_proto.sp_protocol = dst->sa_family; 28538847Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 28642356Ssklower if (rp) 28742356Ssklower rp->rcb_proto.sp_family = PF_ROUTE; 28842356Ssklower } 28936352Ssklower return (error); 29036352Ssklower } 29136352Ssklower 29243336Ssklower rt_setmetrics(which, in, out) 29340786Ssklower u_long which; 29440786Ssklower register struct rt_metrics *in, *out; 29540786Ssklower { 29640786Ssklower #define metric(f, e) if (which & (f)) out->e = in->e; 29740786Ssklower metric(RTV_RPIPE, rmx_recvpipe); 29840786Ssklower metric(RTV_SPIPE, rmx_sendpipe); 29940786Ssklower metric(RTV_SSTHRESH, rmx_ssthresh); 30040786Ssklower metric(RTV_RTT, rmx_rtt); 30140786Ssklower metric(RTV_RTTVAR, rmx_rttvar); 30240786Ssklower metric(RTV_HOPCOUNT, rmx_hopcount); 30340786Ssklower metric(RTV_MTU, rmx_mtu); 30450228Ssklower metric(RTV_EXPIRE, rmx_expire); 30540786Ssklower #undef metric 30640786Ssklower } 30740786Ssklower 30852564Ssklower #define ROUNDUP(a) \ 30952564Ssklower ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 31052564Ssklower #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 31152564Ssklower 31252564Ssklower static void 31352564Ssklower rt_xaddrs(cp, cplim, rtinfo) 31452564Ssklower register caddr_t cp, cplim; 31552564Ssklower register struct rt_addrinfo *rtinfo; 31652564Ssklower { 31752564Ssklower register struct sockaddr *sa; 31852564Ssklower register int i; 31952564Ssklower 32052564Ssklower bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 32152564Ssklower for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 32252564Ssklower if ((rtinfo->rti_addrs & (1 << i)) == 0) 32352564Ssklower continue; 32452564Ssklower rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 32552564Ssklower ADVANCE(cp, sa); 32652564Ssklower } 32752564Ssklower } 32836352Ssklower /* 32936352Ssklower * Copy data from a buffer back into the indicated mbuf chain, 33036352Ssklower * starting "off" bytes from the beginning, extending the mbuf 33136352Ssklower * chain if necessary. 33236352Ssklower */ 33336352Ssklower m_copyback(m0, off, len, cp) 33436352Ssklower struct mbuf *m0; 33536352Ssklower register int off; 33636352Ssklower register int len; 33736352Ssklower caddr_t cp; 33836352Ssklower 33936352Ssklower { 34036352Ssklower register int mlen; 34136352Ssklower register struct mbuf *m = m0, *n; 34236352Ssklower int totlen = 0; 34336352Ssklower 34436352Ssklower if (m0 == 0) 34536352Ssklower return; 34648729Ssklower while (off > (mlen = m->m_len)) { 34736352Ssklower off -= mlen; 34836352Ssklower totlen += mlen; 34936352Ssklower if (m->m_next == 0) { 35036352Ssklower n = m_getclr(M_DONTWAIT, m->m_type); 35136352Ssklower if (n == 0) 35236352Ssklower goto out; 35336352Ssklower n->m_len = min(MLEN, len + off); 35436352Ssklower m->m_next = n; 35536352Ssklower } 35636352Ssklower m = m->m_next; 35736352Ssklower } 35836352Ssklower while (len > 0) { 35936352Ssklower mlen = min (m->m_len - off, len); 36037472Ssklower bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 36136352Ssklower cp += mlen; 36236352Ssklower len -= mlen; 36336352Ssklower mlen += off; 36436352Ssklower off = 0; 36536352Ssklower totlen += mlen; 36636352Ssklower if (len == 0) 36736352Ssklower break; 36836352Ssklower if (m->m_next == 0) { 36936352Ssklower n = m_get(M_DONTWAIT, m->m_type); 37036352Ssklower if (n == 0) 37136352Ssklower break; 37236352Ssklower n->m_len = min(MLEN, len); 37336352Ssklower m->m_next = n; 37436352Ssklower } 37536352Ssklower m = m->m_next; 37636352Ssklower } 37736352Ssklower out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 37836352Ssklower m->m_pkthdr.len = totlen; 37936352Ssklower } 38036352Ssklower 38152564Ssklower static struct mbuf * 38252564Ssklower rt_msg1(type, rtinfo) 38352564Ssklower int type; 38452564Ssklower register struct rt_addrinfo *rtinfo; 38536352Ssklower { 38636352Ssklower register struct rt_msghdr *rtm; 38736352Ssklower register struct mbuf *m; 38852564Ssklower register int i; 38952564Ssklower register struct sockaddr *sa; 39052564Ssklower int len, dlen; 39136352Ssklower 39236352Ssklower m = m_gethdr(M_DONTWAIT, MT_DATA); 39336352Ssklower if (m == 0) 39452564Ssklower return (m); 39552564Ssklower switch (type) { 39652564Ssklower 39752564Ssklower case RTM_DELADDR: 39852564Ssklower case RTM_NEWADDR: 39952564Ssklower len = sizeof(struct ifa_msghdr); 40052564Ssklower break; 40152564Ssklower 40252564Ssklower case RTM_IFINFO: 40352564Ssklower len = sizeof(struct if_msghdr); 40452564Ssklower break; 40552564Ssklower 40652564Ssklower default: 40752564Ssklower len = sizeof(struct rt_msghdr); 40852564Ssklower } 40952564Ssklower if (len > MHLEN) 41052564Ssklower panic("rt_msg1"); 41152564Ssklower m->m_pkthdr.len = m->m_len = len; 41236352Ssklower m->m_pkthdr.rcvif = 0; 41336352Ssklower rtm = mtod(m, struct rt_msghdr *); 41452564Ssklower bzero((caddr_t)rtm, len); 41552564Ssklower for (i = 0; i < RTAX_MAX; i++) { 41652564Ssklower if ((sa = rtinfo->rti_info[i]) == NULL) 41752564Ssklower continue; 41852564Ssklower rtinfo->rti_addrs |= (1 << i); 41952564Ssklower dlen = ROUNDUP(sa->sa_len); 42052564Ssklower m_copyback(m, len, dlen, (caddr_t)sa); 42152564Ssklower len += dlen; 42252564Ssklower } 42352564Ssklower if (m->m_pkthdr.len != len) { 42452564Ssklower m_freem(m); 42552564Ssklower return (NULL); 42652564Ssklower } 42736352Ssklower rtm->rtm_msglen = len; 42840786Ssklower rtm->rtm_version = RTM_VERSION; 42936352Ssklower rtm->rtm_type = type; 43052564Ssklower return (m); 43152564Ssklower } 43252564Ssklower 43352564Ssklower static int 43452564Ssklower rt_msg2(type, rtinfo, cp, w) 43552564Ssklower int type; 43652564Ssklower register struct rt_addrinfo *rtinfo; 43752564Ssklower caddr_t cp; 43852564Ssklower struct walkarg *w; 43952564Ssklower { 44052564Ssklower register int i; 44152564Ssklower int len, dlen, second_time = 0; 44252564Ssklower caddr_t cp0; 44352564Ssklower 44452564Ssklower rtinfo->rti_addrs = 0; 44552564Ssklower again: 44652564Ssklower switch (type) { 44752564Ssklower 44852564Ssklower case RTM_DELADDR: 44952564Ssklower case RTM_NEWADDR: 45052564Ssklower len = sizeof(struct ifa_msghdr); 45152564Ssklower break; 45252564Ssklower 45352564Ssklower case RTM_IFINFO: 45452564Ssklower len = sizeof(struct if_msghdr); 45552564Ssklower break; 45652564Ssklower 45752564Ssklower default: 45852564Ssklower len = sizeof(struct rt_msghdr); 45936352Ssklower } 46052564Ssklower if (cp0 = cp) 46152564Ssklower cp += len; 46252564Ssklower for (i = 0; i < RTAX_MAX; i++) { 46352564Ssklower register struct sockaddr *sa; 46452564Ssklower 46552564Ssklower if ((sa = rtinfo->rti_info[i]) == 0) 46652564Ssklower continue; 46752564Ssklower rtinfo->rti_addrs |= (1 << i); 46852564Ssklower dlen = ROUNDUP(sa->sa_len); 46952564Ssklower if (cp) { 47052564Ssklower bcopy((caddr_t)sa, cp, (unsigned)dlen); 47152564Ssklower cp += dlen; 47252564Ssklower } 47336352Ssklower len += dlen; 47436352Ssklower } 47552564Ssklower if (cp == 0 && w != NULL && !second_time) { 47652564Ssklower register struct walkarg *rw = w; 47752564Ssklower 47852564Ssklower rw->w_needed += len; 47952564Ssklower if (rw->w_needed <= 0 && rw->w_where) { 48052564Ssklower if (rw->w_tmemsize < len) { 48152564Ssklower if (rw->w_tmem) 48252564Ssklower free(rw->w_tmem, M_RTABLE); 48352564Ssklower if (rw->w_tmem = (caddr_t) 48452564Ssklower malloc(len, M_RTABLE, M_NOWAIT)) 48552564Ssklower rw->w_tmemsize = len; 48652564Ssklower } 48752564Ssklower if (rw->w_tmem) { 48852564Ssklower cp = rw->w_tmem; 48952564Ssklower second_time = 1; 49052564Ssklower goto again; 49152564Ssklower } else 49252564Ssklower rw->w_where = 0; 49352564Ssklower } 49436352Ssklower } 49552564Ssklower if (cp) { 49652564Ssklower register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 49752564Ssklower 49852564Ssklower rtm->rtm_version = RTM_VERSION; 49952564Ssklower rtm->rtm_type = type; 50052564Ssklower rtm->rtm_msglen = len; 50136352Ssklower } 50252564Ssklower return (len); 50352564Ssklower } 50452564Ssklower 50552564Ssklower /* 50652564Ssklower * This routine is called to generate a message from the routing 50752564Ssklower * socket indicating that a redirect has occured, a routing lookup 50852564Ssklower * has failed, or that a protocol has detected timeouts to a particular 50952564Ssklower * destination. 51052564Ssklower */ 51152564Ssklower rt_missmsg(type, rtinfo, flags, error) 51252564Ssklower int type, flags, error; 51352564Ssklower register struct rt_addrinfo *rtinfo; 51452564Ssklower { 51552564Ssklower register struct rt_msghdr *rtm; 51652564Ssklower register struct mbuf *m; 51752564Ssklower register int i; 51852564Ssklower struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 51952564Ssklower 52052564Ssklower if (route_cb.any_count == 0) 52136352Ssklower return; 52252564Ssklower m = rt_msg1(type, rtinfo); 52352564Ssklower if (m == 0) 52452564Ssklower return; 52552564Ssklower rtm = mtod(m, struct rt_msghdr *); 52652564Ssklower rtm->rtm_flags = RTF_DONE | flags; 52737472Ssklower rtm->rtm_errno = error; 52852564Ssklower rtm->rtm_addrs = rtinfo->rti_addrs; 52952564Ssklower route_proto.sp_protocol = sa ? sa->sa_family : 0; 53036352Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 53136352Ssklower } 53236352Ssklower 53352564Ssklower /* 53452564Ssklower * This routine is called to generate a message from the routing 53552564Ssklower * socket indicating that the status of a network interface has changed. 53652564Ssklower */ 53752564Ssklower rt_ifmsg(ifp) 53852564Ssklower register struct ifnet *ifp; 53952564Ssklower { 54052564Ssklower register struct if_msghdr *ifm; 54152564Ssklower struct mbuf *m; 54252564Ssklower struct rt_addrinfo info; 54352564Ssklower 54452564Ssklower if (route_cb.any_count == 0) 54552564Ssklower return; 54652564Ssklower bzero((caddr_t)&info, sizeof(info)); 54752564Ssklower m = rt_msg1(RTM_IFINFO, &info); 54852564Ssklower if (m == 0) 54952564Ssklower return; 55052564Ssklower ifm = mtod(m, struct if_msghdr *); 55152564Ssklower ifm->ifm_index = ifp->if_index; 55252564Ssklower ifm->ifm_flags = ifp->if_flags; 55352564Ssklower ifm->ifm_data = ifp->if_data; 55452564Ssklower ifm->ifm_addrs = 0; 55552564Ssklower route_proto.sp_protocol = 0; 55652564Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 55752564Ssklower } 55852564Ssklower 55952564Ssklower /* 56052564Ssklower * This is called to generate messages from the routing socket 56152564Ssklower * indicating a network interface has had addresses associated with it. 56252564Ssklower * if we ever reverse the logic and replace messages TO the routing 56352564Ssklower * socket indicate a request to configure interfaces, then it will 56452564Ssklower * be unnecessary as the routing socket will automatically generate 56552564Ssklower * copies of it. 56652564Ssklower */ 56752564Ssklower rt_newaddrmsg(cmd, ifa, error, rt) 56852564Ssklower int cmd, error; 56952564Ssklower register struct ifaddr *ifa; 57052564Ssklower register struct rtentry *rt; 57152564Ssklower { 57252564Ssklower struct rt_addrinfo info; 57352564Ssklower struct sockaddr *sa; 57452564Ssklower int pass; 57552564Ssklower struct mbuf *m; 57652564Ssklower struct ifnet *ifp = ifa->ifa_ifp; 57752564Ssklower 57852564Ssklower if (route_cb.any_count == 0) 57952564Ssklower return; 58052564Ssklower for (pass = 1; pass < 3; pass++) { 58152564Ssklower bzero((caddr_t)&info, sizeof(info)); 58252564Ssklower if ((cmd == RTM_ADD && pass == 1) || 58352564Ssklower (cmd == RTM_DELETE && pass == 2)) { 58452564Ssklower register struct ifa_msghdr *ifam; 58552564Ssklower int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 58652564Ssklower 58752564Ssklower ifaaddr = sa = ifa->ifa_addr; 58852564Ssklower ifpaddr = ifp->if_addrlist->ifa_addr; 58952564Ssklower netmask = ifa->ifa_netmask; 59052564Ssklower brdaddr = ifa->ifa_dstaddr; 59152564Ssklower if ((m = rt_msg1(ncmd, &info)) == NULL) 59252564Ssklower continue; 59352564Ssklower ifam = mtod(m, struct ifa_msghdr *); 59452564Ssklower ifam->ifam_index = ifp->if_index; 59552564Ssklower ifam->ifam_metric = ifa->ifa_metric; 59652564Ssklower ifam->ifam_addrs = info.rti_addrs; 59752564Ssklower } 59852564Ssklower if ((cmd == RTM_ADD && pass == 2) || 59952564Ssklower (cmd == RTM_DELETE && pass == 1)) { 60052564Ssklower register struct rt_msghdr *rtm; 60152564Ssklower 60252564Ssklower if (rt == 0) 60352564Ssklower continue; 60452564Ssklower netmask = rt_mask(rt); 60552564Ssklower dst = sa = rt_key(rt); 60652564Ssklower gate = rt->rt_gateway; 60752564Ssklower if ((m = rt_msg1(cmd, &info)) == NULL) 60852564Ssklower continue; 60952564Ssklower rtm = mtod(m, struct rt_msghdr *); 61052564Ssklower rtm->rtm_index = ifp->if_index; 61152564Ssklower rtm->rtm_flags |= rt->rt_flags; 61252564Ssklower rtm->rtm_errno = error; 61352564Ssklower rtm->rtm_addrs = info.rti_addrs; 61452564Ssklower } 61552564Ssklower route_proto.sp_protocol = sa ? sa->sa_family : 0; 61652564Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 61752564Ssklower } 61852564Ssklower } 61952564Ssklower 62040446Ssklower #include "kinfo.h" 62136352Ssklower /* 62240446Ssklower * This is used in dumping the kernel table via getkinfo(). 62340446Ssklower */ 62440446Ssklower rt_dumpentry(rn, w) 62540446Ssklower struct radix_node *rn; 62640446Ssklower register struct walkarg *w; 62740446Ssklower { 62840446Ssklower register struct sockaddr *sa; 62940446Ssklower register struct rtentry *rt = (struct rtentry *)rn; 63052564Ssklower int n, error = 0, size; 63152564Ssklower struct rt_addrinfo info; 63240446Ssklower 63340446Ssklower if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 63450812Ssklower return 0; 63552564Ssklower bzero((caddr_t)&info, sizeof(info)); 63652564Ssklower dst = rt_key(rt); 63752564Ssklower gate = rt->rt_gateway; 63852564Ssklower netmask = rt_mask(rt); 63952564Ssklower genmask = rt->rt_genmask; 64052564Ssklower size = rt_msg2(RTM_GET, &info, 0, w); 64152564Ssklower if (w->w_where && w->w_tmem) { 64252564Ssklower register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 64340446Ssklower 64452564Ssklower rtm->rtm_flags = rt->rt_flags; 64552564Ssklower rtm->rtm_use = rt->rt_use; 64652564Ssklower rtm->rtm_rmx = rt->rt_rmx; 64752564Ssklower rtm->rtm_index = rt->rt_ifp->if_index; 64852564Ssklower rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 64952564Ssklower rtm->rtm_addrs = info.rti_addrs; 65052564Ssklower if (error = copyout((caddr_t)rtm, w->w_where, size)) 65152564Ssklower w->w_where = NULL; 65252564Ssklower else 65352564Ssklower w->w_where += size; 65440446Ssklower } 65552564Ssklower return (error); 65652564Ssklower } 65752564Ssklower 65852564Ssklower kinfo_iflist(af, w) 65952564Ssklower int af; 66052564Ssklower register struct walkarg *w; 66152564Ssklower { 66252564Ssklower register struct ifnet *ifp; 66352564Ssklower register struct ifaddr *ifa; 66452564Ssklower struct rt_addrinfo info; 66552564Ssklower struct sockaddr *sa; 66652564Ssklower int len, error = 0; 66752564Ssklower 66852564Ssklower bzero((caddr_t)&info, sizeof(info)); 66952564Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 670*52631Ssklower if (w->w_arg && w->w_arg != ifp->if_index) 671*52631Ssklower continue; 67252564Ssklower ifa = ifp->if_addrlist; 67352564Ssklower ifpaddr = ifa->ifa_addr; 67452564Ssklower len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 67552564Ssklower ifpaddr = 0; 67652564Ssklower if (w->w_where && w->w_tmem) { 67752564Ssklower register struct if_msghdr *ifm; 67852564Ssklower 67952564Ssklower ifm = (struct if_msghdr *)w->w_tmem; 68052564Ssklower ifm->ifm_index = ifp->if_index; 68152564Ssklower ifm->ifm_flags = ifp->if_flags; 68252564Ssklower ifm->ifm_data = ifp->if_data; 68352564Ssklower ifm->ifm_addrs = info.rti_addrs; 68452564Ssklower if (error = copyout((caddr_t)ifm, w->w_where, len)) 68552564Ssklower return (error); 68652564Ssklower w->w_where += len; 68752564Ssklower } 68852564Ssklower while (ifa = ifa->ifa_next) { 689*52631Ssklower if (af && af != ifa->ifa_addr->sa_family) 690*52631Ssklower continue; 69152564Ssklower ifaaddr = ifa->ifa_addr; 69252564Ssklower netmask = ifa->ifa_netmask; 69352564Ssklower brdaddr = ifa->ifa_dstaddr; 69452564Ssklower len = rt_msg2(RTM_NEWADDR, &info, 0, w); 69552564Ssklower if (w->w_where && w->w_tmem) { 69652564Ssklower register struct ifa_msghdr *ifam; 69752564Ssklower 69852564Ssklower ifam = (struct ifa_msghdr *)w->w_tmem; 69952564Ssklower ifam->ifam_index = ifa->ifa_ifp->if_index; 70052564Ssklower ifam->ifam_flags = ifa->ifa_flags; 70152564Ssklower ifam->ifam_metric = ifa->ifa_metric; 70252564Ssklower ifam->ifam_addrs = info.rti_addrs; 70352564Ssklower if (error = copyout(w->w_tmem, w->w_where, len)) 70452564Ssklower return (error); 70552564Ssklower w->w_where += len; 70652564Ssklower } 70752564Ssklower } 708*52631Ssklower ifaaddr = netmask = brdaddr = 0; 70952564Ssklower } 71040446Ssklower return (0); 71140446Ssklower } 71240446Ssklower 71340446Ssklower kinfo_rtable(op, where, given, arg, needed) 71440446Ssklower int op, arg; 71540446Ssklower caddr_t where; 71640446Ssklower int *given, *needed; 71740446Ssklower { 71840446Ssklower register struct radix_node_head *rnh; 71952564Ssklower int i, s, error = EINVAL; 72040446Ssklower u_char af = ki_af(op); 72140446Ssklower struct walkarg w; 72240446Ssklower 72340446Ssklower Bzero(&w, sizeof(w)); 72440446Ssklower if ((w.w_where = where) && given) 72540446Ssklower w.w_given = *given; 72640446Ssklower w.w_needed = 0 - w.w_given; 72740446Ssklower w.w_arg = arg; 728*52631Ssklower w.w_op = op = ki_op(op); 72940446Ssklower 73040446Ssklower s = splnet(); 73152564Ssklower switch (op) { 73252564Ssklower 73352564Ssklower case KINFO_RT_DUMP: 73452564Ssklower case KINFO_RT_FLAGS: 73552564Ssklower for (i = 1; i <= AF_MAX; i++) 73652564Ssklower if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 73752564Ssklower (error = rnh->rnh_walk(rnh->rnh_treetop, 73852564Ssklower rt_dumpentry, &w))) 73952564Ssklower break; 74052564Ssklower break; 74152564Ssklower 74252564Ssklower case KINFO_RT_IFLIST: 74352564Ssklower error = kinfo_iflist(af, &w); 74440446Ssklower } 74552564Ssklower splx(s); 74652564Ssklower if (w.w_tmem) 74752564Ssklower free(w.w_tmem, M_RTABLE); 74840446Ssklower w.w_needed += w.w_given; 74940446Ssklower if (where && given) 75040446Ssklower *given = w.w_where - where; 75140446Ssklower else 75240446Ssklower w.w_needed = (11 * w.w_needed) / 10; 75340446Ssklower *needed = w.w_needed; 75440446Ssklower return (error); 75540446Ssklower } 75640446Ssklower 75740446Ssklower /* 75836352Ssklower * Definitions of protocols supported in the ROUTE domain. 75936352Ssklower */ 76036352Ssklower 76136352Ssklower int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); 76236352Ssklower extern struct domain routedomain; /* or at least forward */ 76336352Ssklower 76436352Ssklower struct protosw routesw[] = { 76536352Ssklower { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 76636352Ssklower raw_input, route_output, raw_ctlinput, 0, 76736352Ssklower route_usrreq, 76836352Ssklower raw_init, 0, 0, 0, 76936352Ssklower } 77036352Ssklower }; 77136352Ssklower 77236352Ssklower int unp_externalize(), unp_dispose(); 77336352Ssklower 77436352Ssklower struct domain routedomain = 77536352Ssklower { PF_ROUTE, "route", 0, 0, 0, 77636352Ssklower routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 777