1*36352Ssklower /* 2*36352Ssklower * Copyright (c) 1988 Regents of the University of California. 3*36352Ssklower * All rights reserved. 4*36352Ssklower * 5*36352Ssklower * Redistribution and use in source and binary forms are permitted 6*36352Ssklower * provided that the above copyright notice and this paragraph are 7*36352Ssklower * duplicated in all such forms and that any documentation, 8*36352Ssklower * advertising materials, and other materials related to such 9*36352Ssklower * distribution and use acknowledge that the software was developed 10*36352Ssklower * by the University of California, Berkeley. The name of the 11*36352Ssklower * University may not be used to endorse or promote products derived 12*36352Ssklower * from this software without specific prior written permission. 13*36352Ssklower * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*36352Ssklower * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36352Ssklower * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*36352Ssklower * 17*36352Ssklower * @(#)rtsock.c 7.1 (Berkeley) 12/13/88 18*36352Ssklower */ 19*36352Ssklower 20*36352Ssklower #ifndef RTF_UP 21*36352Ssklower #include "param.h" 22*36352Ssklower #include "mbuf.h" 23*36352Ssklower #include "dir.h" 24*36352Ssklower #include "user.h" 25*36352Ssklower #include "proc.h" 26*36352Ssklower #include "socket.h" 27*36352Ssklower #include "socketvar.h" 28*36352Ssklower #include "domain.h" 29*36352Ssklower #include "protosw.h" 30*36352Ssklower #include "errno.h" 31*36352Ssklower 32*36352Ssklower #include "af.h" 33*36352Ssklower #include "route.h" 34*36352Ssklower #include "raw_cb.h" 35*36352Ssklower 36*36352Ssklower #include "../machine/mtpr.h" 37*36352Ssklower #endif 38*36352Ssklower 39*36352Ssklower /*ARGSUSED*/ 40*36352Ssklower route_usrreq(so, req, m, nam, rights, control) 41*36352Ssklower register struct socket *so; 42*36352Ssklower int req; 43*36352Ssklower struct mbuf *m, *nam, *rights, *control; 44*36352Ssklower { 45*36352Ssklower register int error = 0; 46*36352Ssklower register struct rawcb *rp = sotorawcb(so); 47*36352Ssklower if (req == PRU_DETACH && rp) { 48*36352Ssklower int af = rp->rcb_proto.sp_protocol; 49*36352Ssklower if (af == AF_INET) 50*36352Ssklower route_cb.ip_count--; 51*36352Ssklower else if (af == AF_NS) 52*36352Ssklower route_cb.ns_count--; 53*36352Ssklower #ifdef ISO 54*36352Ssklower else if (af == AF_ISO) 55*36352Ssklower route_cb.iso_count--; 56*36352Ssklower #endif 57*36352Ssklower route_cb.any_count--; 58*36352Ssklower } 59*36352Ssklower error = raw_usrreq(so, req, m, nam, rights, control); 60*36352Ssklower rp = sotorawcb(so); 61*36352Ssklower if (error == 0 && req == PRU_ATTACH && rp) { 62*36352Ssklower int af = rp->rcb_proto.sp_protocol; 63*36352Ssklower if (af == AF_INET) 64*36352Ssklower route_cb.ip_count++; 65*36352Ssklower else if (af == AF_NS) 66*36352Ssklower route_cb.ns_count++; 67*36352Ssklower #ifdef ISO 68*36352Ssklower else if (af == AF_ISO) 69*36352Ssklower route_cb.iso_count++; 70*36352Ssklower #endif 71*36352Ssklower rp->rcb_flags |= RAW_FADDR; 72*36352Ssklower route_cb.any_count++; 73*36352Ssklower soisconnected(so); 74*36352Ssklower } 75*36352Ssklower return (error); 76*36352Ssklower } 77*36352Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 78*36352Ssklower 79*36352Ssklower struct sockaddr route_dst = { 0, PF_ROUTE, }; 80*36352Ssklower struct sockaddr route_src = { 0, PF_ROUTE, }; 81*36352Ssklower struct sockproto route_proto = { PF_ROUTE, }; 82*36352Ssklower 83*36352Ssklower route_output(m, so) 84*36352Ssklower register struct mbuf *m; 85*36352Ssklower struct socket *so; 86*36352Ssklower { 87*36352Ssklower register struct rt_msghdr *rtm = 0; 88*36352Ssklower register struct rtentry *rt = 0; 89*36352Ssklower struct mbuf *m0 = m; 90*36352Ssklower struct rtentry *saved_nrt; 91*36352Ssklower struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *author; 92*36352Ssklower struct rt_metrics *rmm = 0; 93*36352Ssklower struct radix_node_head *rnh; 94*36352Ssklower struct radix_node *rn; 95*36352Ssklower caddr_t cp = 0; 96*36352Ssklower int len, error = 0, s; 97*36352Ssklower 98*36352Ssklower #define FLUSH(e) { error = e; goto flush;} 99*36352Ssklower if (m == 0 || (m = m_pullup(m, sizeof(long))) == 0) 100*36352Ssklower FLUSH(ENOBUFS); 101*36352Ssklower if ((m->m_flags & M_PKTHDR) == 0) 102*36352Ssklower return (EOPNOTSUPP); 103*36352Ssklower len = m->m_pkthdr.len; 104*36352Ssklower rtm = mtod(m, struct rt_msghdr *); 105*36352Ssklower if (len < rtm->rtm_msglen) 106*36352Ssklower FLUSH(EINVAL); 107*36352Ssklower R_Malloc(rtm, struct rt_msghdr *, len); 108*36352Ssklower if (rtm == 0) 109*36352Ssklower FLUSH(ENOBUFS); 110*36352Ssklower m_copydata(m, 0, len, (caddr_t)rtm); 111*36352Ssklower if (rtm->rtm_version != 1) 112*36352Ssklower FLUSH(EPROTONOSUPPORT); 113*36352Ssklower rtm->rtm_pid = u.u_procp->p_pid; 114*36352Ssklower cp = (caddr_t) (rtm + 1); 115*36352Ssklower #ifdef notyet 116*36352Ssklower switch (rtm->rtm_type) { 117*36352Ssklower 118*36352Ssklower case RTM_ADD: case RTM_CHANGE: case RTM_GET: 119*36352Ssklower rmm = (struct rt_metrics *)cp ; 120*36352Ssklower cp = (caddr_t) (rmm + 1); 121*36352Ssklower } 122*36352Ssklower #endif 123*36352Ssklower if (rtm->rtm_count > 0) { 124*36352Ssklower dst = (struct sockaddr *)cp; 125*36352Ssklower cp += ROUNDUP(dst->sa_len); 126*36352Ssklower } 127*36352Ssklower if (rtm->rtm_count > 1) { 128*36352Ssklower gate = (struct sockaddr *)cp; 129*36352Ssklower cp += ROUNDUP(gate->sa_len); 130*36352Ssklower } 131*36352Ssklower if (rtm->rtm_count > 2) { 132*36352Ssklower netmask = (struct sockaddr *)cp; 133*36352Ssklower cp += ROUNDUP(netmask->sa_len); 134*36352Ssklower } 135*36352Ssklower if (rtm->rtm_count > 3) { 136*36352Ssklower author = (struct sockaddr *)cp; 137*36352Ssklower } 138*36352Ssklower switch (rtm->rtm_type) { 139*36352Ssklower case RTM_ADD: 140*36352Ssklower error = rtrequest(RTM_ADD, dst, gate, netmask, 141*36352Ssklower rtm->rtm_flags, &saved_nrt); 142*36352Ssklower /* XXX -- add metrics !!! */ 143*36352Ssklower break; 144*36352Ssklower 145*36352Ssklower case RTM_DELETE: 146*36352Ssklower error = rtrequest(RTM_DELETE, dst, gate, netmask, 147*36352Ssklower rtm->rtm_flags, 0); 148*36352Ssklower break; 149*36352Ssklower 150*36352Ssklower case RTM_GET: 151*36352Ssklower case RTM_CHANGE: 152*36352Ssklower case RTM_LOCK: 153*36352Ssklower rt = rtalloc1(dst, 0); 154*36352Ssklower if (rt == 0) 155*36352Ssklower FLUSH(ESRCH); 156*36352Ssklower switch(rtm->rtm_type) { 157*36352Ssklower struct sockaddr *outmask; 158*36352Ssklower 159*36352Ssklower case RTM_GET: 160*36352Ssklower netmask = rt_mask(rt); 161*36352Ssklower len = sizeof(*rtm) + ROUNDUP(rt_key(rt)->sa_len) 162*36352Ssklower + ROUNDUP(rt->rt_gateway->sa_len); 163*36352Ssklower if (netmask) 164*36352Ssklower len + netmask->sa_len; 165*36352Ssklower if (len > rtm->rtm_msglen) { 166*36352Ssklower struct rt_msghdr *new_rtm; 167*36352Ssklower R_Malloc(new_rtm, struct rt_msghdr *, len); 168*36352Ssklower if (new_rtm == 0) 169*36352Ssklower FLUSH(ENOBUFS); 170*36352Ssklower Bcopy(rtm, new_rtm, rtm->rtm_msglen); 171*36352Ssklower Free(rtm); rtm = new_rtm; 172*36352Ssklower gate = (struct sockaddr *) 173*36352Ssklower (ROUNDUP(rt->rt_gateway->sa_len) 174*36352Ssklower + (char *)dst); 175*36352Ssklower Bcopy(&rt->rt_gateway, gate, 176*36352Ssklower rt->rt_gateway->sa_len); 177*36352Ssklower rtm->rtm_flags = rt->rt_flags; 178*36352Ssklower rtm->rtm_count = 2; 179*36352Ssklower if (netmask) { 180*36352Ssklower outmask = (struct sockaddr *) 181*36352Ssklower (ROUNDUP(netmask->sa_len)+(char *)gate); 182*36352Ssklower Bcopy(netmask, outmask, netmask->sa_len); 183*36352Ssklower rtm->rtm_count = 3; 184*36352Ssklower } 185*36352Ssklower } 186*36352Ssklower break; 187*36352Ssklower 188*36352Ssklower case RTM_CHANGE: 189*36352Ssklower if (gate->sa_len > (len = rt->rt_gateway->sa_len)) 190*36352Ssklower FLUSH(EDQUOT); 191*36352Ssklower if (gate->sa_family != rt->rt_gateway->sa_family) 192*36352Ssklower FLUSH(EADDRINUSE); 193*36352Ssklower Bcopy(gate, rt->rt_gateway, len); 194*36352Ssklower rt->rt_gateway->sa_len = len; 195*36352Ssklower 196*36352Ssklower #ifdef notdef 197*36352Ssklower #define metric(f, e) if (rtm->rtm_inits & (f)) rt->rt_m.e = rtm->e; 198*36352Ssklower metric(RTM_RPIPE, rtm_recvpipe); 199*36352Ssklower metric(RTM_SPIPE, rtm_sendpipe); 200*36352Ssklower metric(RTM_SSTHRESH, rtm_ssthresh); 201*36352Ssklower metric(RTM_RTT, rtm_rtt); 202*36352Ssklower metric(RTM_RTTVAR, rtm_rttvar); 203*36352Ssklower metric(RTM_HOPCOUNT, rtm_hopcount); 204*36352Ssklower metric(RTM_MTU, rtm_mtu); 205*36352Ssklower /* 206*36352Ssklower * Fall into 207*36352Ssklower */ 208*36352Ssklower case RTM_LOCKS: 209*36352Ssklower rt->rt_locks |= (rtm->rtm_inits & rtm->rtm_locks); 210*36352Ssklower rt->rt_locks &= ~(rtm->rtm_inits); 211*36352Ssklower break; 212*36352Ssklower #endif 213*36352Ssklower } 214*36352Ssklower goto cleanup; 215*36352Ssklower 216*36352Ssklower default: 217*36352Ssklower FLUSH(EOPNOTSUPP); 218*36352Ssklower } 219*36352Ssklower 220*36352Ssklower flush: 221*36352Ssklower if (rtm) { 222*36352Ssklower if (error) 223*36352Ssklower rtm->rtm_errno = error; 224*36352Ssklower else 225*36352Ssklower rtm->rtm_flags |= RTF_DONE; 226*36352Ssklower } 227*36352Ssklower cleanup: 228*36352Ssklower if (rt) 229*36352Ssklower rtfree(rt); 230*36352Ssklower cp = (caddr_t)rtm; 231*36352Ssklower m_copyback(m = m0, 0, len, cp); 232*36352Ssklower /*if (m->m_pkthdr.len != len) { 233*36352Ssklower m_freem(m); 234*36352Ssklower return (error); 235*36352Ssklower } */ 236*36352Ssklower route_proto.sp_protocol = dst->sa_family; 237*36352Ssklower raw_input(m0, &route_proto, &route_src, &route_dst); 238*36352Ssklower return (error); 239*36352Ssklower } 240*36352Ssklower 241*36352Ssklower /* 242*36352Ssklower * Copy data from a buffer back into the indicated mbuf chain, 243*36352Ssklower * starting "off" bytes from the beginning, extending the mbuf 244*36352Ssklower * chain if necessary. 245*36352Ssklower */ 246*36352Ssklower m_copyback(m0, off, len, cp) 247*36352Ssklower struct mbuf *m0; 248*36352Ssklower register int off; 249*36352Ssklower register int len; 250*36352Ssklower caddr_t cp; 251*36352Ssklower 252*36352Ssklower { 253*36352Ssklower register int mlen; 254*36352Ssklower register struct mbuf *m = m0, *n; 255*36352Ssklower int totlen = 0; 256*36352Ssklower 257*36352Ssklower if (m0 == 0) 258*36352Ssklower return; 259*36352Ssklower while (off >= (mlen = m->m_len)) { 260*36352Ssklower off -= mlen; 261*36352Ssklower totlen += mlen; 262*36352Ssklower if (m->m_next == 0) { 263*36352Ssklower n = m_getclr(M_DONTWAIT, m->m_type); 264*36352Ssklower if (n == 0) 265*36352Ssklower goto out; 266*36352Ssklower n->m_len = min(MLEN, len + off); 267*36352Ssklower m->m_next = n; 268*36352Ssklower } 269*36352Ssklower m = m->m_next; 270*36352Ssklower } 271*36352Ssklower while (len > 0) { 272*36352Ssklower mlen = min (m->m_len - off, len); 273*36352Ssklower bcopy(cp, off + mtod(m, caddr_t), mlen); 274*36352Ssklower cp += mlen; 275*36352Ssklower len -= mlen; 276*36352Ssklower mlen += off; 277*36352Ssklower off = 0; 278*36352Ssklower totlen += mlen; 279*36352Ssklower if (len == 0) 280*36352Ssklower break; 281*36352Ssklower if (m->m_next == 0) { 282*36352Ssklower n = m_get(M_DONTWAIT, m->m_type); 283*36352Ssklower if (n == 0) 284*36352Ssklower break; 285*36352Ssklower n->m_len = min(MLEN, len); 286*36352Ssklower m->m_next = n; 287*36352Ssklower } 288*36352Ssklower m = m->m_next; 289*36352Ssklower } 290*36352Ssklower out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 291*36352Ssklower m->m_pkthdr.len = totlen; 292*36352Ssklower } 293*36352Ssklower 294*36352Ssklower /* 295*36352Ssklower * The miss message and losing message are very similar. 296*36352Ssklower */ 297*36352Ssklower 298*36352Ssklower rt_missmsg(type, dst, gate, mask, src, flags) 299*36352Ssklower register struct sockaddr *dst; 300*36352Ssklower struct sockaddr *gate, *mask, *src; 301*36352Ssklower { 302*36352Ssklower register struct rt_msghdr *rtm; 303*36352Ssklower register struct mbuf *m; 304*36352Ssklower int dlen = ROUNDUP(dst->sa_len); 305*36352Ssklower int len = dlen + sizeof(*rtm); 306*36352Ssklower caddr_t cp = (caddr_t)dst; 307*36352Ssklower 308*36352Ssklower if (route_cb.any_count == 0) 309*36352Ssklower return; 310*36352Ssklower m = m_gethdr(M_DONTWAIT, MT_DATA); 311*36352Ssklower if (m == 0) 312*36352Ssklower return; 313*36352Ssklower m->m_pkthdr.len = m->m_len = min(len, MHLEN); 314*36352Ssklower m->m_pkthdr.rcvif = 0; 315*36352Ssklower rtm = mtod(m, struct rt_msghdr *); 316*36352Ssklower bzero((caddr_t)rtm, sizeof(*rtm)); /*XXX assumes sizeof(*rtm) < MHLEN*/ 317*36352Ssklower rtm->rtm_flags = RTF_DONE | flags; 318*36352Ssklower rtm->rtm_msglen = len; 319*36352Ssklower rtm->rtm_version = 1; 320*36352Ssklower rtm->rtm_type = type; 321*36352Ssklower rtm->rtm_count = 1; 322*36352Ssklower if (type == RTM_OLDADD || type == RTM_OLDDEL) { 323*36352Ssklower int error = (int) src; 324*36352Ssklower src = (struct sockaddr *)0; /* XXXXXXX -- I admit. (KLS) */ 325*36352Ssklower rtm->rtm_pid = u.u_procp->p_pid; 326*36352Ssklower rtm->rtm_errno = error; 327*36352Ssklower if (error) 328*36352Ssklower rtm->rtm_flags &= ~RTF_DONE; 329*36352Ssklower } 330*36352Ssklower m_copyback(m, sizeof (*rtm), dlen, (caddr_t)dst); 331*36352Ssklower if (gate) { 332*36352Ssklower dlen = ROUNDUP(gate->sa_len); 333*36352Ssklower m_copyback(m, len , dlen, (caddr_t)gate); 334*36352Ssklower len += dlen; 335*36352Ssklower rtm->rtm_count++; 336*36352Ssklower } 337*36352Ssklower if (mask) { 338*36352Ssklower dlen = ROUNDUP(mask->sa_len); 339*36352Ssklower m_copyback(m, len , dlen, (caddr_t)mask); 340*36352Ssklower len += dlen; 341*36352Ssklower rtm->rtm_count++; 342*36352Ssklower } 343*36352Ssklower if (src) { 344*36352Ssklower dlen = ROUNDUP(src->sa_len); 345*36352Ssklower m_copyback(m, len , dlen, (caddr_t)src); 346*36352Ssklower len += dlen; 347*36352Ssklower rtm->rtm_count++; 348*36352Ssklower } 349*36352Ssklower if (m->m_pkthdr.len != len) { 350*36352Ssklower m_freem(m); 351*36352Ssklower return; 352*36352Ssklower } 353*36352Ssklower rtm->rtm_msglen = len; 354*36352Ssklower route_proto.sp_protocol = dst->sa_family; 355*36352Ssklower raw_input(m, &route_proto, &route_src, &route_dst); 356*36352Ssklower } 357*36352Ssklower 358*36352Ssklower /* 359*36352Ssklower * Definitions of protocols supported in the ROUTE domain. 360*36352Ssklower */ 361*36352Ssklower 362*36352Ssklower int route_output(); 363*36352Ssklower int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); 364*36352Ssklower extern struct domain routedomain; /* or at least forward */ 365*36352Ssklower 366*36352Ssklower struct protosw routesw[] = { 367*36352Ssklower { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 368*36352Ssklower raw_input, route_output, raw_ctlinput, 0, 369*36352Ssklower route_usrreq, 370*36352Ssklower raw_init, 0, 0, 0, 371*36352Ssklower }, 372*36352Ssklower { 0, 0, 0, 0, 373*36352Ssklower raw_input, 0, raw_ctlinput, 0, 374*36352Ssklower raw_usrreq, 375*36352Ssklower raw_init, 0, 0, 0, 376*36352Ssklower } 377*36352Ssklower }; 378*36352Ssklower 379*36352Ssklower int unp_externalize(), unp_dispose(); 380*36352Ssklower 381*36352Ssklower struct domain routedomain = 382*36352Ssklower { PF_ROUTE, "route", 0, 0, 0, 383*36352Ssklower routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 384