1*21486Ssklower /* ns_input.c 6.1 85/05/30 */ 2*21486Ssklower 3*21486Ssklower #include "param.h" 4*21486Ssklower #include "systm.h" 5*21486Ssklower #include "mbuf.h" 6*21486Ssklower #include "domain.h" 7*21486Ssklower #include "protosw.h" 8*21486Ssklower #include "socket.h" 9*21486Ssklower #include "socketvar.h" 10*21486Ssklower #include "errno.h" 11*21486Ssklower #include "time.h" 12*21486Ssklower #include "kernel.h" 13*21486Ssklower 14*21486Ssklower #include "../net/if.h" 15*21486Ssklower #include "../net/route.h" 16*21486Ssklower #include "../net/raw_cb.h" 17*21486Ssklower 18*21486Ssklower #include "ns.h" 19*21486Ssklower #include "ns_if.h" 20*21486Ssklower #include "ns_pcb.h" 21*21486Ssklower #include "idp.h" 22*21486Ssklower #include "idp_var.h" 23*21486Ssklower #include "ns_error.h" 24*21486Ssklower 25*21486Ssklower /* 26*21486Ssklower * NS initialization. 27*21486Ssklower */ 28*21486Ssklower union ns_host ns_thishost; 29*21486Ssklower union ns_host ns_zerohost; 30*21486Ssklower union ns_host ns_broadhost; 31*21486Ssklower 32*21486Ssklower static char allones[] = {-1, -1, -1, -1, -1, -1}; 33*21486Ssklower 34*21486Ssklower struct nspcb nspcb; 35*21486Ssklower struct nspcb nsrawpcb; 36*21486Ssklower 37*21486Ssklower struct ifqueue nsintrq; 38*21486Ssklower int nsqmaxlen = IFQ_MAXLEN; 39*21486Ssklower 40*21486Ssklower int idpcksum = 0; 41*21486Ssklower 42*21486Ssklower ns_init() 43*21486Ssklower { 44*21486Ssklower ns_broadhost = * (union ns_host *) allones; 45*21486Ssklower nspcb.nsp_next = nspcb.nsp_prev = &nspcb; 46*21486Ssklower nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb; 47*21486Ssklower nsintrq.ifq_maxlen = nsqmaxlen; 48*21486Ssklower } 49*21486Ssklower 50*21486Ssklower /* 51*21486Ssklower * Idp input routine. Pass to next level. 52*21486Ssklower */ 53*21486Ssklower int nsintr_getpck = 0; 54*21486Ssklower int nsintr_swtch = 0; 55*21486Ssklower nsintr() 56*21486Ssklower { 57*21486Ssklower register struct idp *idp; 58*21486Ssklower register struct mbuf *m; 59*21486Ssklower struct nspcb *nsp; 60*21486Ssklower struct mbuf *m0; 61*21486Ssklower register int i; 62*21486Ssklower int len, s, error; 63*21486Ssklower char oddpacketp; 64*21486Ssklower 65*21486Ssklower next: 66*21486Ssklower /* 67*21486Ssklower * Get next datagram off input queue and get IDP header 68*21486Ssklower * in first mbuf. 69*21486Ssklower */ 70*21486Ssklower s = splimp(); 71*21486Ssklower IF_DEQUEUE(&nsintrq, m); 72*21486Ssklower splx(s); 73*21486Ssklower nsintr_getpck++; 74*21486Ssklower if (m == 0) 75*21486Ssklower return; 76*21486Ssklower if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) && 77*21486Ssklower (m = m_pullup(m, sizeof (struct idp))) == 0) { 78*21486Ssklower idpstat.idps_toosmall++; 79*21486Ssklower goto next; 80*21486Ssklower } 81*21486Ssklower 82*21486Ssklower /* 83*21486Ssklower * Give any raw listeners a crack at the packet 84*21486Ssklower */ 85*21486Ssklower for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { 86*21486Ssklower struct mbuf *m1 = m_copy(m, 0, M_COPYALL); 87*21486Ssklower if (m1) idp_input(m1, nsp); 88*21486Ssklower } 89*21486Ssklower 90*21486Ssklower idp = mtod(m, struct idp *); 91*21486Ssklower len = ntohs(idp->idp_len); 92*21486Ssklower if (oddpacketp = len & 1) { 93*21486Ssklower len++; /* If this packet is of odd length, 94*21486Ssklower preserve garbage byte for checksum */ 95*21486Ssklower } 96*21486Ssklower 97*21486Ssklower /* 98*21486Ssklower * Check that the amount of data in the buffers 99*21486Ssklower * is as at least much as the IDP header would have us expect. 100*21486Ssklower * Trim mbufs if longer than we expect. 101*21486Ssklower * Drop packet if shorter than we expect. 102*21486Ssklower */ 103*21486Ssklower i = -len; 104*21486Ssklower m0 = m; 105*21486Ssklower for (;;) { 106*21486Ssklower i += m->m_len; 107*21486Ssklower if (m->m_next == 0) 108*21486Ssklower break; 109*21486Ssklower m = m->m_next; 110*21486Ssklower } 111*21486Ssklower if (i != 0) { 112*21486Ssklower if (i < 0) { 113*21486Ssklower idpstat.idps_tooshort++; 114*21486Ssklower m = m0; 115*21486Ssklower goto bad; 116*21486Ssklower } 117*21486Ssklower if (i <= m->m_len) 118*21486Ssklower m->m_len -= i; 119*21486Ssklower else 120*21486Ssklower m_adj(m0, -i); 121*21486Ssklower } 122*21486Ssklower m = m0; 123*21486Ssklower if (idpcksum && ((i = idp->idp_sum)!=0xffff)) { 124*21486Ssklower idp->idp_sum = 0; 125*21486Ssklower if (i != (idp->idp_sum = ns_cksum(m,len))) { 126*21486Ssklower idpstat.idps_badsum++; 127*21486Ssklower if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host)) 128*21486Ssklower error = NS_ERR_BADSUM; 129*21486Ssklower else 130*21486Ssklower error = NS_ERR_BADSUM_T; 131*21486Ssklower ns_error(m, error, 0); 132*21486Ssklower goto next; 133*21486Ssklower } 134*21486Ssklower } 135*21486Ssklower /* 136*21486Ssklower * Is this a directed broadcast? 137*21486Ssklower */ 138*21486Ssklower if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) { 139*21486Ssklower if ((ns_netof(idp->idp_dna)!=ns_netof(idp->idp_sna)) && 140*21486Ssklower (ns_netof(idp->idp_dna)!=-1) && (ns_netof(idp->idp_sna)!=0) 141*21486Ssklower && (ns_netof(idp->idp_dna)!=0)) { 142*21486Ssklower /* 143*21486Ssklower * Look to see if I need to eat this packet as well. 144*21486Ssklower */ 145*21486Ssklower struct ns_ifaddr *ia = 146*21486Ssklower ns_iaonnetof(idp->idp_dna.x_net); 147*21486Ssklower if (ia) { 148*21486Ssklower m = m_copy(m, 0, M_COPYALL); 149*21486Ssklower } else 150*21486Ssklower m = NULL; 151*21486Ssklower idp_forward(idp); 152*21486Ssklower if (m==NULL) 153*21486Ssklower goto next; 154*21486Ssklower idp = mtod(m, struct idp *); 155*21486Ssklower } 156*21486Ssklower /* 157*21486Ssklower * Is this our packet? If not, forward. 158*21486Ssklower */ 159*21486Ssklower } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) { 160*21486Ssklower idp_forward(idp); 161*21486Ssklower goto next; 162*21486Ssklower } 163*21486Ssklower 164*21486Ssklower /* 165*21486Ssklower * Locate pcb for datagram. 166*21486Ssklower */ 167*21486Ssklower nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD); 168*21486Ssklower 169*21486Ssklower 170*21486Ssklower /* 171*21486Ssklower * Switch out to protocol's input routine. 172*21486Ssklower */ 173*21486Ssklower 174*21486Ssklower nsintr_swtch++; 175*21486Ssklower if (nsp) { 176*21486Ssklower if (oddpacketp) { 177*21486Ssklower m_adj(m0, -1); 178*21486Ssklower } 179*21486Ssklower switch (idp->idp_pt) { 180*21486Ssklower case NSPROTO_SPP: 181*21486Ssklower spp_input(m,nsp); 182*21486Ssklower break; 183*21486Ssklower case NSPROTO_ERROR: 184*21486Ssklower ns_err_input(m); 185*21486Ssklower break; 186*21486Ssklower default: 187*21486Ssklower idp_input(m,nsp); 188*21486Ssklower } 189*21486Ssklower } else { 190*21486Ssklower /* don't send ERROR response for multicast packet */ 191*21486Ssklower if (idp->idp_dna.x_host.c_host[0] & 1) 192*21486Ssklower goto bad; 193*21486Ssklower ns_error(m, NS_ERR_NOSOCK, 0); 194*21486Ssklower } 195*21486Ssklower goto next; 196*21486Ssklower 197*21486Ssklower bad: 198*21486Ssklower m_freem(m); 199*21486Ssklower goto next; 200*21486Ssklower } 201*21486Ssklower 202*21486Ssklower u_char nsctlerrmap[PRC_NCMDS] = { 203*21486Ssklower ECONNABORTED, ECONNABORTED, 0, 0, 204*21486Ssklower 0, 0, EHOSTDOWN, EHOSTUNREACH, 205*21486Ssklower ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 206*21486Ssklower EMSGSIZE, 0, 0, 0, 207*21486Ssklower 0, 0, 0, 0 208*21486Ssklower }; 209*21486Ssklower 210*21486Ssklower idp_ctlinput(cmd, arg) 211*21486Ssklower int cmd; 212*21486Ssklower caddr_t arg; 213*21486Ssklower { 214*21486Ssklower struct ns_addr *ns; 215*21486Ssklower int idp_abort(); 216*21486Ssklower int type; 217*21486Ssklower 218*21486Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 219*21486Ssklower return; 220*21486Ssklower if (nsctlerrmap[cmd] == 0) 221*21486Ssklower return; /* XXX */ 222*21486Ssklower type = NS_ERR_UNREACH_HOST; 223*21486Ssklower if (cmd == PRC_IFDOWN) 224*21486Ssklower ns = &((struct sockaddr_ns *)arg)->sns_addr; 225*21486Ssklower else if (cmd == PRC_HOSTDEAD || cmd == PRC_HOSTUNREACH) 226*21486Ssklower ns = (struct ns_addr *)arg; 227*21486Ssklower else { 228*21486Ssklower ns = &((struct ns_errp *)arg)->ns_err_idp.idp_dna; 229*21486Ssklower type = ((struct ns_errp *)arg)->ns_err_num; 230*21486Ssklower type = ntohs(type); 231*21486Ssklower } 232*21486Ssklower switch (type) { 233*21486Ssklower case NS_ERR_UNREACH_HOST: 234*21486Ssklower case NS_ERR_NOSOCK: 235*21486Ssklower ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, 0); 236*21486Ssklower } 237*21486Ssklower } 238*21486Ssklower 239*21486Ssklower int idpprintfs = 0; 240*21486Ssklower int idpforwarding = 1; 241*21486Ssklower /* 242*21486Ssklower * Forward a packet. If some error occurs return the sender 243*21486Ssklower * an error packet. Note we can't always generate a meaningful 244*21486Ssklower * error message because the NS errors don't have a large enough repetoire 245*21486Ssklower * of codes and types. 246*21486Ssklower */ 247*21486Ssklower struct route idp_droute; 248*21486Ssklower struct route idp_sroute; 249*21486Ssklower 250*21486Ssklower idp_forward(idp) 251*21486Ssklower register struct idp *idp; 252*21486Ssklower { 253*21486Ssklower register int error, type, code; 254*21486Ssklower struct mbuf *mopt, *mcopy; 255*21486Ssklower 256*21486Ssklower if (idpprintfs) { 257*21486Ssklower printf("forward: src "); 258*21486Ssklower ns_printhost(&idp->idp_sna); 259*21486Ssklower printf(", dst "); 260*21486Ssklower ns_printhost(&idp->idp_dna); 261*21486Ssklower printf("hop count %d\n", idp->idp_tc); 262*21486Ssklower } 263*21486Ssklower if (idpforwarding == 0) { 264*21486Ssklower /* can't tell difference between net and host */ 265*21486Ssklower type = NS_ERR_UNREACH_HOST, code = 0; 266*21486Ssklower goto senderror; 267*21486Ssklower } 268*21486Ssklower idp->idp_tc++; 269*21486Ssklower if (idp->idp_tc > NS_MAXHOPS) { 270*21486Ssklower type = NS_ERR_TOO_OLD, code = 0; 271*21486Ssklower goto senderror; 272*21486Ssklower } 273*21486Ssklower /* need to adjust checksum */ 274*21486Ssklower if (idp->idp_sum!=0xffff) { 275*21486Ssklower union bytes { 276*21486Ssklower u_char c[4]; 277*21486Ssklower u_short s[2]; 278*21486Ssklower long l; 279*21486Ssklower } x; 280*21486Ssklower register int shift; 281*21486Ssklower x.l = 0; x.c[0] = 1; 282*21486Ssklower shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf; 283*21486Ssklower x.l = idp->idp_sum + (x.l << shift); 284*21486Ssklower x.l = x.s[0] + x.s[1]; 285*21486Ssklower x.l = x.s[0] + x.s[1]; 286*21486Ssklower if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l; 287*21486Ssklower } 288*21486Ssklower mopt = m_get(M_DONTWAIT, MT_DATA); 289*21486Ssklower if (mopt == NULL) { 290*21486Ssklower m_freem(dtom(idp)); 291*21486Ssklower return; 292*21486Ssklower } 293*21486Ssklower 294*21486Ssklower /* 295*21486Ssklower * Save at most 42 bytes of the packet in case 296*21486Ssklower * we need to generate an NS error message to the src. 297*21486Ssklower */ 298*21486Ssklower mcopy = m_copy(dtom(idp), 0, imin(ntohs(idp->idp_len), 42)); 299*21486Ssklower 300*21486Ssklower if ((idp->idp_dna.x_host.c_host[0] & 0x1) == 0) 301*21486Ssklower error = ns_output(dtom(idp), (struct route *)0, NS_FORWARDING); 302*21486Ssklower /* 303*21486Ssklower * Here we are about to forward a broadcast packet, 304*21486Ssklower * so we try to insure that it doesn't go back out 305*21486Ssklower * on the interface it came in on. 306*21486Ssklower */ 307*21486Ssklower else if (idp_do_route(&idp->idp_dna,&idp_droute)) { 308*21486Ssklower if (idp_do_route(&idp->idp_sna,&idp_sroute)) { 309*21486Ssklower struct ifnet *ifp; 310*21486Ssklower 311*21486Ssklower if (idp_droute.ro_rt && 312*21486Ssklower (ifp=idp_droute.ro_rt->rt_ifp) && 313*21486Ssklower idp_sroute.ro_rt && 314*21486Ssklower (ifp!=idp_sroute.ro_rt->rt_ifp)) { 315*21486Ssklower error = ns_output(dtom(idp), &idp_droute, 316*21486Ssklower NS_FORWARDING|NS_ALLOWBROADCAST); 317*21486Ssklower } 318*21486Ssklower idp_undo_route(&idp_sroute); 319*21486Ssklower } 320*21486Ssklower idp_undo_route(&idp_droute); 321*21486Ssklower } 322*21486Ssklower 323*21486Ssklower if (error == 0) { 324*21486Ssklower if (mcopy) 325*21486Ssklower m_freem(mcopy); 326*21486Ssklower return; 327*21486Ssklower } 328*21486Ssklower if (mcopy == NULL) 329*21486Ssklower return; 330*21486Ssklower idp = mtod(mcopy, struct idp *); 331*21486Ssklower type = NS_ERR_UNSPEC_T, code = 0; 332*21486Ssklower switch (error) { 333*21486Ssklower 334*21486Ssklower case ENETUNREACH: 335*21486Ssklower case EHOSTDOWN: 336*21486Ssklower case EHOSTUNREACH: 337*21486Ssklower case ENETDOWN: 338*21486Ssklower case EPERM: 339*21486Ssklower type = NS_ERR_UNREACH_HOST; 340*21486Ssklower break; 341*21486Ssklower 342*21486Ssklower case EMSGSIZE: 343*21486Ssklower type = NS_ERR_TOO_BIG; 344*21486Ssklower code = 576; /* too hard to figure out mtu here */ 345*21486Ssklower break; 346*21486Ssklower 347*21486Ssklower case ENOBUFS: 348*21486Ssklower type = NS_ERR_UNSPEC_T; 349*21486Ssklower break; 350*21486Ssklower } 351*21486Ssklower senderror: 352*21486Ssklower ns_error(dtom(idp), type, code); 353*21486Ssklower } 354*21486Ssklower 355*21486Ssklower idp_do_route(src, ro) 356*21486Ssklower struct ns_addr *src; 357*21486Ssklower struct route *ro; 358*21486Ssklower { 359*21486Ssklower 360*21486Ssklower struct sockaddr_ns *dst; 361*21486Ssklower 362*21486Ssklower bzero((caddr_t)ro, sizeof (*ro)); 363*21486Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 364*21486Ssklower 365*21486Ssklower dst->sns_family = AF_NS; 366*21486Ssklower dst->sns_addr = *src; 367*21486Ssklower rtalloc(ro); 368*21486Ssklower if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { 369*21486Ssklower return(0); 370*21486Ssklower } 371*21486Ssklower ro->ro_rt->rt_use++; 372*21486Ssklower return(1); 373*21486Ssklower } 374*21486Ssklower 375*21486Ssklower idp_undo_route(ro) 376*21486Ssklower register struct route *ro; 377*21486Ssklower { 378*21486Ssklower if (ro->ro_rt) {RTFREE(ro->ro_rt);} 379*21486Ssklower } 380*21486Ssklower ns_watch_output(m) 381*21486Ssklower struct mbuf *m; 382*21486Ssklower { 383*21486Ssklower register struct nspcb *nsp; 384*21486Ssklower /* 385*21486Ssklower * Give any raw listeners a crack at the packet 386*21486Ssklower */ 387*21486Ssklower for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { 388*21486Ssklower struct mbuf *m1 = m_copy(m, 0, M_COPYALL); 389*21486Ssklower if (m1) idp_input(m1, nsp); 390*21486Ssklower } 391*21486Ssklower } 392