1*5847Sroot /* raw_imp.c 4.4 82/02/15 */ 25637Sroot 35637Sroot #include "../h/param.h" 45637Sroot #include "../h/mbuf.h" 55637Sroot #include "../h/socket.h" 65637Sroot #include "../h/protosw.h" 75637Sroot #include "../h/socketvar.h" 85637Sroot #include "../net/in.h" 95637Sroot #include "../net/in_systm.h" 105637Sroot #include "../net/if.h" 115637Sroot #include "../net/if_imp.h" 125637Sroot #include "../net/raw_cb.h" 135637Sroot #include "/usr/include/errno.h" 145637Sroot 155637Sroot /* 165637Sroot * Raw interface to IMP. 175637Sroot */ 185637Sroot 195637Sroot /*ARGSUSED*/ 20*5847Sroot rimp_ctlinput(m) 215637Sroot struct mbuf *m; 225637Sroot { 23*5847Sroot COUNT(RIMP_CTLINPUT); 245637Sroot } 255637Sroot 265637Sroot /* 275637Sroot * Generate IMP leader and pass packet to impoutput. 285637Sroot * The user must create a skeletal leader in order to 295637Sroot * communicate message type, message subtype, etc. 305637Sroot * We fill in holes where needed and verify parameters 315637Sroot * supplied by user. 325637Sroot */ 33*5847Sroot rimp_output(m, so) 345637Sroot register struct mbuf *m; 355637Sroot struct socket *so; 365637Sroot { 375637Sroot struct mbuf *n; 385637Sroot int len; 395647Ssam register struct imp_leader *ip; 405637Sroot register struct sockaddr_in *sin; 415637Sroot register struct rawcb *rp = sotorawcb(so); 425772Swnj struct ifnet *ifp; 435772Swnj struct control_leader *cp; 445637Sroot 45*5847Sroot COUNT(RIMP_OUTPUT); 465637Sroot /* 475637Sroot * Verify user has supplied necessary space 485637Sroot * for the leader and check parameters in it. 495637Sroot */ 505772Swnj if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) && 515772Swnj (m = m_pullup(m, sizeof(struct control_leader))) == 0) 525772Swnj return (0); 535772Swnj cp = mtod(m, struct control_leader *); 545772Swnj if (cp->dl_mtype == IMPTYPE_DATA) 555772Swnj if (m->m_len < sizeof(struct imp_leader) && 565772Swnj (m = m_pullup(m, sizeof(struct imp_leader))) == 0) 575772Swnj return (0); 585647Ssam ip = mtod(m, struct imp_leader *); 595647Ssam if (ip->il_format != IMP_NFF) 605637Sroot goto bad; 615647Ssam if (ip->il_link != IMPLINK_IP && 625647Ssam (ip->il_link < IMPLINK_LOWEXPER || ip->il_link > IMPLINK_HIGHEXPER)) 635637Sroot goto bad; 645637Sroot 655637Sroot /* 665637Sroot * Fill in IMP leader -- impoutput refrains from rebuilding 675637Sroot * the leader when it sees the protocol family PF_IMPLINK. 685637Sroot * (message size calculated by walking through mbuf's) 695637Sroot */ 705637Sroot for (len = 0, n = m; n; n = n->m_next) 715637Sroot len += n->m_len; 725772Swnj ip->il_length = htons(len << 3); 735637Sroot sin = (struct sockaddr_in *)&rp->rcb_addr; 745647Ssam ip->il_network = sin->sin_addr.s_net; 755647Ssam ip->il_host = sin->sin_addr.s_host; 765647Ssam ip->il_imp = sin->sin_addr.s_imp; 775772Swnj printf("imp_output: net=%x, host=%x, imp=%x\n", ip->il_network, ip->il_host, 785772Swnj ip->il_impno); 795772Swnj ifp = if_ifonnetof(sin->sin_addr); 805772Swnj if (ifp == 0) { 815772Swnj ifp = if_gatewayfor(sin->sin_addr); 825772Swnj if (ifp == 0) 835772Swnj goto bad; 845772Swnj } 855772Swnj return (impoutput(ifp, m, PF_IMPLINK)); 865637Sroot 875637Sroot bad: 885637Sroot m_freem(m); 895637Sroot return (0); 905637Sroot } 915637Sroot 925637Sroot /* 935637Sroot * Intercept operations required to 945637Sroot * maintain interface pointer used on output. 955637Sroot */ 96*5847Sroot rimp_usrreq(so, req, m, addr) 975637Sroot struct socket *so; 985637Sroot int req; 995637Sroot struct mbuf *m; 1005637Sroot caddr_t addr; 1015637Sroot { 1025637Sroot register struct rawcb *rp = sotorawcb(so); 1035772Swnj register struct sockaddr_in *sin; 1045772Swnj register struct ifnet *ifp; 1055637Sroot 106*5847Sroot COUNT(RIMP_USRREQ); 1075637Sroot if (rp == 0 && req != PRU_ATTACH) 1085637Sroot return (EINVAL); 1095637Sroot 1105637Sroot switch (req) { 1115637Sroot 1125637Sroot /* 1135772Swnj * Verify address has an interface to go with it. 1145637Sroot */ 1155772Swnj case PRU_CONNECT: 1165772Swnj if (rp->rcb_pcb) 1175772Swnj return (EISCONN); 1185637Sroot sin = (struct sockaddr_in *)addr; 1195637Sroot ifp = if_ifonnetof(sin->sin_addr); 1205637Sroot if (ifp == 0) { 1215637Sroot ifp = if_gatewayfor(sin->sin_addr); 1225637Sroot if (ifp == 0) 1235637Sroot return (EADDRNOTAVAIL); /* XXX */ 1245637Sroot } 1255637Sroot rp->rcb_pcb = (caddr_t)ifp; 1265637Sroot break; 1275637Sroot 1285637Sroot case PRU_DISCONNECT: 1295637Sroot rp->rcb_pcb = 0; 1305637Sroot break; 1315637Sroot 1325637Sroot case PRU_CONTROL: 1335637Sroot return (EOPNOTSUPP); 1345637Sroot } 1355637Sroot return (raw_usrreq(so, req, m, addr)); 1365637Sroot } 137