136352Ssklower /* 250228Ssklower * Copyright (c) 1988, 1991 Regents of the University of California. 336352Ssklower * All rights reserved. 436352Ssklower * 544466Sbostic * %sccs.include.redist.c% 636352Ssklower * 7*52564Ssklower * @(#)rtsock.c 7.24 (Berkeley) 02/18/92 836352Ssklower */ 936352Ssklower 1036352Ssklower #include "param.h" 11*52564Ssklower #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 23*52564Ssklower struct sockaddr route_dst = { 2, PF_ROUTE, }; 24*52564Ssklower struct sockaddr route_src = { 2, PF_ROUTE, }; 25*52564Ssklower struct sockproto route_proto = { PF_ROUTE, }; 2637472Ssklower 27*52564Ssklower struct walkarg { 28*52564Ssklower int w_op, w_arg, w_given, w_needed, w_tmemsize; 29*52564Ssklower caddr_t w_where, w_tmem; 30*52564Ssklower }; 31*52564Ssklower 32*52564Ssklower static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 33*52564Ssklower static struct mbuf *rt_msg1 __P((int, struct rt_addrinfo *)); 34*52564Ssklower static int rt_msg2 __P((int, struct rt_addrinfo *, caddr_t, 35*52564Ssklower struct walkarg *)); 36*52564Ssklower 37*52564Ssklower /* Sleazy use of local variables throughout file, warning!!!! */ 38*52564Ssklower #define dst info.rti_info[RTAX_DST] 39*52564Ssklower #define gate info.rti_info[RTAX_GATEWAY] 40*52564Ssklower #define netmask info.rti_info[RTAX_NETMASK] 41*52564Ssklower #define genmask info.rti_info[RTAX_GENMASK] 42*52564Ssklower #define ifpaddr info.rti_info[RTAX_IFP] 43*52564Ssklower #define ifaaddr info.rti_info[RTAX_IFA] 44*52564Ssklower #define brdaddr info.rti_info[RTAX_BRD] 45*52564Ssklower 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; 104*52564Ssklower 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; 128*52564Ssklower info.rti_addrs = rtm->rtm_addrs; 129*52564Ssklower rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); 130*52564Ssklower if (dst == 0) 13140786Ssklower senderr(EINVAL); 132*52564Ssklower 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) { 141*52564Ssklower 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: 177*52564Ssklower dst = rt_key(rt); 178*52564Ssklower gate = rt->rt_gateway; 179*52564Ssklower netmask = rt_mask(rt); 180*52564Ssklower genmask = rt->rt_genmask; 18145656Ssklower if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 182*52564Ssklower if (ifp = rt->rt_ifp) { 183*52564Ssklower ifpaddr = ifp->if_addrlist->ifa_addr; 18445656Ssklower ifaaddr = rt->rt_ifa->ifa_addr; 185*52564Ssklower rtm->rtm_index = ifp->if_index; 18645656Ssklower } else { 187*52564Ssklower ifpaddr = 0; 188*52564Ssklower ifaaddr = 0; 189*52564Ssklower } 19045656Ssklower } 191*52564Ssklower len = rt_msg2(RTM_GET, &info, (caddr_t)0, 192*52564Ssklower (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 } 201*52564Ssklower (void)rt_msg2(RTM_GET, &info, (caddr_t)rtm, 202*52564Ssklower (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 } 246*52564Ssklower 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 308*52564Ssklower #define ROUNDUP(a) \ 309*52564Ssklower ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 310*52564Ssklower #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 311*52564Ssklower 312*52564Ssklower static void 313*52564Ssklower rt_xaddrs(cp, cplim, rtinfo) 314*52564Ssklower register caddr_t cp, cplim; 315*52564Ssklower register struct rt_addrinfo *rtinfo; 316*52564Ssklower { 317*52564Ssklower register struct sockaddr *sa; 318*52564Ssklower register int i; 319*52564Ssklower 320*52564Ssklower bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 321*52564Ssklower for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 322*52564Ssklower if ((rtinfo->rti_addrs & (1 << i)) == 0) 323*52564Ssklower continue; 324*52564Ssklower rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 325*52564Ssklower ADVANCE(cp, sa); 326*52564Ssklower } 327*52564Ssklower } 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 381*52564Ssklower static struct mbuf * 382*52564Ssklower rt_msg1(type, rtinfo) 383*52564Ssklower int type; 384*52564Ssklower register struct rt_addrinfo *rtinfo; 38536352Ssklower { 38636352Ssklower register struct rt_msghdr *rtm; 38736352Ssklower register struct mbuf *m; 388*52564Ssklower register int i; 389*52564Ssklower register struct sockaddr *sa; 390*52564Ssklower int len, dlen; 39136352Ssklower 39236352Ssklower m = m_gethdr(M_DONTWAIT, MT_DATA); 39336352Ssklower if (m == 0) 394*52564Ssklower return (m); 395*52564Ssklower switch (type) { 396*52564Ssklower 397*52564Ssklower case RTM_DELADDR: 398*52564Ssklower case RTM_NEWADDR: 399*52564Ssklower len = sizeof(struct ifa_msghdr); 400*52564Ssklower break; 401*52564Ssklower 402*52564Ssklower case RTM_IFINFO: 403*52564Ssklower len = sizeof(struct if_msghdr); 404*52564Ssklower break; 405*52564Ssklower 406*52564Ssklower default: 407*52564Ssklower len = sizeof(struct rt_msghdr); 408*52564Ssklower } 409*52564Ssklower if (len > MHLEN) 410*52564Ssklower panic("rt_msg1"); 411*52564Ssklower m->m_pkthdr.len = m->m_len = len; 41236352Ssklower m->m_pkthdr.rcvif = 0; 41336352Ssklower rtm = mtod(m, struct rt_msghdr *); 414*52564Ssklower bzero((caddr_t)rtm, len); 415*52564Ssklower for (i = 0; i < RTAX_MAX; i++) { 416*52564Ssklower if ((sa = rtinfo->rti_info[i]) == NULL) 417*52564Ssklower continue; 418*52564Ssklower rtinfo->rti_addrs |= (1 << i); 419*52564Ssklower dlen = ROUNDUP(sa->sa_len); 420*52564Ssklower m_copyback(m, len, dlen, (caddr_t)sa); 421*52564Ssklower len += dlen; 422*52564Ssklower } 423*52564Ssklower if (m->m_pkthdr.len != len) { 424*52564Ssklower m_freem(m); 425*52564Ssklower return (NULL); 426*52564Ssklower } 42736352Ssklower rtm->rtm_msglen = len; 42840786Ssklower rtm->rtm_version = RTM_VERSION; 42936352Ssklower rtm->rtm_type = type; 430*52564Ssklower return (m); 431*52564Ssklower } 432*52564Ssklower 433*52564Ssklower static int 434*52564Ssklower rt_msg2(type, rtinfo, cp, w) 435*52564Ssklower int type; 436*52564Ssklower register struct rt_addrinfo *rtinfo; 437*52564Ssklower caddr_t cp; 438*52564Ssklower struct walkarg *w; 439*52564Ssklower { 440*52564Ssklower register int i; 441*52564Ssklower int len, dlen, second_time = 0; 442*52564Ssklower caddr_t cp0; 443*52564Ssklower 444*52564Ssklower rtinfo->rti_addrs = 0; 445*52564Ssklower again: 446*52564Ssklower switch (type) { 447*52564Ssklower 448*52564Ssklower case RTM_DELADDR: 449*52564Ssklower case RTM_NEWADDR: 450*52564Ssklower len = sizeof(struct ifa_msghdr); 451*52564Ssklower break; 452*52564Ssklower 453*52564Ssklower case RTM_IFINFO: 454*52564Ssklower len = sizeof(struct if_msghdr); 455*52564Ssklower break; 456*52564Ssklower 457*52564Ssklower default: 458*52564Ssklower len = sizeof(struct rt_msghdr); 45936352Ssklower } 460*52564Ssklower if (cp0 = cp) 461*52564Ssklower cp += len; 462*52564Ssklower for (i = 0; i < RTAX_MAX; i++) { 463*52564Ssklower register struct sockaddr *sa; 464*52564Ssklower 465*52564Ssklower if ((sa = rtinfo->rti_info[i]) == 0) 466*52564Ssklower continue; 467*52564Ssklower rtinfo->rti_addrs |= (1 << i); 468*52564Ssklower dlen = ROUNDUP(sa->sa_len); 469*52564Ssklower if (cp) { 470*52564Ssklower bcopy((caddr_t)sa, cp, (unsigned)dlen); 471*52564Ssklower cp += dlen; 472*52564Ssklower } 47336352Ssklower len += dlen; 47436352Ssklower } 475*52564Ssklower if (cp == 0 && w != NULL && !second_time) { 476*52564Ssklower register struct walkarg *rw = w; 477*52564Ssklower 478*52564Ssklower rw->w_needed += len; 479*52564Ssklower if (rw->w_needed <= 0 && rw->w_where) { 480*52564Ssklower if (rw->w_tmemsize < len) { 481*52564Ssklower if (rw->w_tmem) 482*52564Ssklower free(rw->w_tmem, M_RTABLE); 483*52564Ssklower if (rw->w_tmem = (caddr_t) 484*52564Ssklower malloc(len, M_RTABLE, M_NOWAIT)) 485*52564Ssklower rw->w_tmemsize = len; 486*52564Ssklower } 487*52564Ssklower if (rw->w_tmem) { 488*52564Ssklower cp = rw->w_tmem; 489*52564Ssklower second_time = 1; 490*52564Ssklower goto again; 491*52564Ssklower } else 492*52564Ssklower rw->w_where = 0; 493*52564Ssklower } 49436352Ssklower } 495*52564Ssklower if (cp) { 496*52564Ssklower register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 497*52564Ssklower 498*52564Ssklower rtm->rtm_version = RTM_VERSION; 499*52564Ssklower rtm->rtm_type = type; 500*52564Ssklower rtm->rtm_msglen = len; 50136352Ssklower } 502*52564Ssklower return (len); 503*52564Ssklower } 504*52564Ssklower 505*52564Ssklower /* 506*52564Ssklower * This routine is called to generate a message from the routing 507*52564Ssklower * socket indicating that a redirect has occured, a routing lookup 508*52564Ssklower * has failed, or that a protocol has detected timeouts to a particular 509*52564Ssklower * destination. 510*52564Ssklower */ 511*52564Ssklower rt_missmsg(type, rtinfo, flags, error) 512*52564Ssklower int type, flags, error; 513*52564Ssklower register struct rt_addrinfo *rtinfo; 514*52564Ssklower { 515*52564Ssklower register struct rt_msghdr *rtm; 516*52564Ssklower register struct mbuf *m; 517*52564Ssklower register int i; 518*52564Ssklower struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 519*52564Ssklower 520*52564Ssklower if (route_cb.any_count == 0) 52136352Ssklower return; 522*52564Ssklower m = rt_msg1(type, rtinfo); 523*52564Ssklower if (m == 0) 524*52564Ssklower return; 525*52564Ssklower rtm = mtod(m, struct rt_msghdr *); 526*52564Ssklower rtm->rtm_flags = RTF_DONE | flags; 52737472Ssklower rtm->rtm_errno = error; 528*52564Ssklower rtm->rtm_addrs = rtinfo->rti_addrs; 529*52564Ssklower route_proto.sp_protocol = sa ? sa->sa_family : 0; 53036352Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 53136352Ssklower } 53236352Ssklower 533*52564Ssklower /* 534*52564Ssklower * This routine is called to generate a message from the routing 535*52564Ssklower * socket indicating that the status of a network interface has changed. 536*52564Ssklower */ 537*52564Ssklower rt_ifmsg(ifp) 538*52564Ssklower register struct ifnet *ifp; 539*52564Ssklower { 540*52564Ssklower register struct if_msghdr *ifm; 541*52564Ssklower struct mbuf *m; 542*52564Ssklower struct rt_addrinfo info; 543*52564Ssklower 544*52564Ssklower if (route_cb.any_count == 0) 545*52564Ssklower return; 546*52564Ssklower bzero((caddr_t)&info, sizeof(info)); 547*52564Ssklower m = rt_msg1(RTM_IFINFO, &info); 548*52564Ssklower if (m == 0) 549*52564Ssklower return; 550*52564Ssklower ifm = mtod(m, struct if_msghdr *); 551*52564Ssklower ifm->ifm_index = ifp->if_index; 552*52564Ssklower ifm->ifm_flags = ifp->if_flags; 553*52564Ssklower ifm->ifm_data = ifp->if_data; 554*52564Ssklower ifm->ifm_addrs = 0; 555*52564Ssklower route_proto.sp_protocol = 0; 556*52564Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 557*52564Ssklower } 558*52564Ssklower 559*52564Ssklower /* 560*52564Ssklower * This is called to generate messages from the routing socket 561*52564Ssklower * indicating a network interface has had addresses associated with it. 562*52564Ssklower * if we ever reverse the logic and replace messages TO the routing 563*52564Ssklower * socket indicate a request to configure interfaces, then it will 564*52564Ssklower * be unnecessary as the routing socket will automatically generate 565*52564Ssklower * copies of it. 566*52564Ssklower */ 567*52564Ssklower rt_newaddrmsg(cmd, ifa, error, rt) 568*52564Ssklower int cmd, error; 569*52564Ssklower register struct ifaddr *ifa; 570*52564Ssklower register struct rtentry *rt; 571*52564Ssklower { 572*52564Ssklower struct rt_addrinfo info; 573*52564Ssklower struct sockaddr *sa; 574*52564Ssklower int pass; 575*52564Ssklower struct mbuf *m; 576*52564Ssklower struct ifnet *ifp = ifa->ifa_ifp; 577*52564Ssklower 578*52564Ssklower if (route_cb.any_count == 0) 579*52564Ssklower return; 580*52564Ssklower for (pass = 1; pass < 3; pass++) { 581*52564Ssklower bzero((caddr_t)&info, sizeof(info)); 582*52564Ssklower if ((cmd == RTM_ADD && pass == 1) || 583*52564Ssklower (cmd == RTM_DELETE && pass == 2)) { 584*52564Ssklower register struct ifa_msghdr *ifam; 585*52564Ssklower int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 586*52564Ssklower 587*52564Ssklower ifaaddr = sa = ifa->ifa_addr; 588*52564Ssklower ifpaddr = ifp->if_addrlist->ifa_addr; 589*52564Ssklower netmask = ifa->ifa_netmask; 590*52564Ssklower brdaddr = ifa->ifa_dstaddr; 591*52564Ssklower if ((m = rt_msg1(ncmd, &info)) == NULL) 592*52564Ssklower continue; 593*52564Ssklower ifam = mtod(m, struct ifa_msghdr *); 594*52564Ssklower ifam->ifam_index = ifp->if_index; 595*52564Ssklower ifam->ifam_metric = ifa->ifa_metric; 596*52564Ssklower ifam->ifam_addrs = info.rti_addrs; 597*52564Ssklower } 598*52564Ssklower if ((cmd == RTM_ADD && pass == 2) || 599*52564Ssklower (cmd == RTM_DELETE && pass == 1)) { 600*52564Ssklower register struct rt_msghdr *rtm; 601*52564Ssklower 602*52564Ssklower if (rt == 0) 603*52564Ssklower continue; 604*52564Ssklower netmask = rt_mask(rt); 605*52564Ssklower dst = sa = rt_key(rt); 606*52564Ssklower gate = rt->rt_gateway; 607*52564Ssklower if ((m = rt_msg1(cmd, &info)) == NULL) 608*52564Ssklower continue; 609*52564Ssklower rtm = mtod(m, struct rt_msghdr *); 610*52564Ssklower rtm->rtm_index = ifp->if_index; 611*52564Ssklower rtm->rtm_flags |= rt->rt_flags; 612*52564Ssklower rtm->rtm_errno = error; 613*52564Ssklower rtm->rtm_addrs = info.rti_addrs; 614*52564Ssklower } 615*52564Ssklower route_proto.sp_protocol = sa ? sa->sa_family : 0; 616*52564Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 617*52564Ssklower } 618*52564Ssklower } 619*52564Ssklower 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; 630*52564Ssklower int n, error = 0, size; 631*52564Ssklower struct rt_addrinfo info; 63240446Ssklower 63340446Ssklower if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 63450812Ssklower return 0; 635*52564Ssklower bzero((caddr_t)&info, sizeof(info)); 636*52564Ssklower dst = rt_key(rt); 637*52564Ssklower gate = rt->rt_gateway; 638*52564Ssklower netmask = rt_mask(rt); 639*52564Ssklower genmask = rt->rt_genmask; 640*52564Ssklower size = rt_msg2(RTM_GET, &info, 0, w); 641*52564Ssklower if (w->w_where && w->w_tmem) { 642*52564Ssklower register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 64340446Ssklower 644*52564Ssklower rtm->rtm_flags = rt->rt_flags; 645*52564Ssklower rtm->rtm_use = rt->rt_use; 646*52564Ssklower rtm->rtm_rmx = rt->rt_rmx; 647*52564Ssklower rtm->rtm_index = rt->rt_ifp->if_index; 648*52564Ssklower rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 649*52564Ssklower rtm->rtm_addrs = info.rti_addrs; 650*52564Ssklower if (error = copyout((caddr_t)rtm, w->w_where, size)) 651*52564Ssklower w->w_where = NULL; 652*52564Ssklower else 653*52564Ssklower w->w_where += size; 65440446Ssklower } 655*52564Ssklower return (error); 656*52564Ssklower } 657*52564Ssklower 658*52564Ssklower kinfo_iflist(af, w) 659*52564Ssklower int af; 660*52564Ssklower register struct walkarg *w; 661*52564Ssklower { 662*52564Ssklower register struct ifnet *ifp; 663*52564Ssklower register struct ifaddr *ifa; 664*52564Ssklower struct rt_addrinfo info; 665*52564Ssklower struct sockaddr *sa; 666*52564Ssklower int len, error = 0; 667*52564Ssklower 668*52564Ssklower bzero((caddr_t)&info, sizeof(info)); 669*52564Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 670*52564Ssklower ifa = ifp->if_addrlist; 671*52564Ssklower ifpaddr = ifa->ifa_addr; 672*52564Ssklower len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 673*52564Ssklower ifpaddr = 0; 674*52564Ssklower if (w->w_where && w->w_tmem) { 675*52564Ssklower register struct if_msghdr *ifm; 676*52564Ssklower 677*52564Ssklower ifm = (struct if_msghdr *)w->w_tmem; 678*52564Ssklower ifm->ifm_index = ifp->if_index; 679*52564Ssklower ifm->ifm_flags = ifp->if_flags; 680*52564Ssklower ifm->ifm_data = ifp->if_data; 681*52564Ssklower ifm->ifm_addrs = info.rti_addrs; 682*52564Ssklower if (error = copyout((caddr_t)ifm, w->w_where, len)) 683*52564Ssklower return (error); 684*52564Ssklower w->w_where += len; 685*52564Ssklower } 686*52564Ssklower while (ifa = ifa->ifa_next) { 687*52564Ssklower ifaaddr = ifa->ifa_addr; 688*52564Ssklower netmask = ifa->ifa_netmask; 689*52564Ssklower brdaddr = ifa->ifa_dstaddr; 690*52564Ssklower len = rt_msg2(RTM_NEWADDR, &info, 0, w); 691*52564Ssklower if (w->w_where && w->w_tmem) { 692*52564Ssklower register struct ifa_msghdr *ifam; 693*52564Ssklower 694*52564Ssklower ifam = (struct ifa_msghdr *)w->w_tmem; 695*52564Ssklower ifam->ifam_index = ifa->ifa_ifp->if_index; 696*52564Ssklower ifam->ifam_flags = ifa->ifa_flags; 697*52564Ssklower ifam->ifam_metric = ifa->ifa_metric; 698*52564Ssklower ifam->ifam_addrs = info.rti_addrs; 699*52564Ssklower if (error = copyout(w->w_tmem, w->w_where, len)) 700*52564Ssklower return (error); 701*52564Ssklower w->w_where += len; 702*52564Ssklower } 703*52564Ssklower ifaaddr = netmask = brdaddr = 0; 704*52564Ssklower } 705*52564Ssklower } 70640446Ssklower return (0); 70740446Ssklower } 70840446Ssklower 709*52564Ssklower 71040446Ssklower kinfo_rtable(op, where, given, arg, needed) 71140446Ssklower int op, arg; 71240446Ssklower caddr_t where; 71340446Ssklower int *given, *needed; 71440446Ssklower { 71540446Ssklower register struct radix_node_head *rnh; 716*52564Ssklower int i, s, error = EINVAL; 71740446Ssklower u_char af = ki_af(op); 71840446Ssklower struct walkarg w; 71940446Ssklower 72040446Ssklower Bzero(&w, sizeof(w)); 72140446Ssklower if ((w.w_where = where) && given) 72240446Ssklower w.w_given = *given; 72340446Ssklower w.w_needed = 0 - w.w_given; 72440446Ssklower w.w_arg = arg; 72540446Ssklower w.w_op = op; 72640446Ssklower 72740446Ssklower s = splnet(); 728*52564Ssklower switch (op) { 729*52564Ssklower 730*52564Ssklower case KINFO_RT_DUMP: 731*52564Ssklower case KINFO_RT_FLAGS: 732*52564Ssklower for (i = 1; i <= AF_MAX; i++) 733*52564Ssklower if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 734*52564Ssklower (error = rnh->rnh_walk(rnh->rnh_treetop, 735*52564Ssklower rt_dumpentry, &w))) 736*52564Ssklower break; 737*52564Ssklower break; 738*52564Ssklower 739*52564Ssklower case KINFO_RT_IFLIST: 740*52564Ssklower error = kinfo_iflist(af, &w); 74140446Ssklower } 742*52564Ssklower splx(s); 743*52564Ssklower if (w.w_tmem) 744*52564Ssklower free(w.w_tmem, M_RTABLE); 74540446Ssklower w.w_needed += w.w_given; 74640446Ssklower if (where && given) 74740446Ssklower *given = w.w_where - where; 74840446Ssklower else 74940446Ssklower w.w_needed = (11 * w.w_needed) / 10; 75040446Ssklower *needed = w.w_needed; 75140446Ssklower return (error); 75240446Ssklower } 75340446Ssklower 75440446Ssklower /* 75536352Ssklower * Definitions of protocols supported in the ROUTE domain. 75636352Ssklower */ 75736352Ssklower 75836352Ssklower int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); 75936352Ssklower extern struct domain routedomain; /* or at least forward */ 76036352Ssklower 76136352Ssklower struct protosw routesw[] = { 76236352Ssklower { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 76336352Ssklower raw_input, route_output, raw_ctlinput, 0, 76436352Ssklower route_usrreq, 76536352Ssklower raw_init, 0, 0, 0, 76636352Ssklower } 76736352Ssklower }; 76836352Ssklower 76936352Ssklower int unp_externalize(), unp_dispose(); 77036352Ssklower 77136352Ssklower struct domain routedomain = 77236352Ssklower { PF_ROUTE, "route", 0, 0, 0, 77336352Ssklower routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 774