1*5671Ssam /* raw_pup.c 4.1 82/02/02 */ 2*5671Ssam 3*5671Ssam #include "../h/param.h" 4*5671Ssam #include "../h/mbuf.h" 5*5671Ssam #include "../h/socket.h" 6*5671Ssam #include "../h/protosw.h" 7*5671Ssam #include "../h/socketvar.h" 8*5671Ssam #include "../net/in.h" 9*5671Ssam #include "../net/in_systm.h" 10*5671Ssam #include "../net/pup.h" 11*5671Ssam #include "../net/raw_cb.h" 12*5671Ssam #include "/usr/include/errno.h" 13*5671Ssam 14*5671Ssam /* 15*5671Ssam * Raw PUP protocol interface. 16*5671Ssam */ 17*5671Ssam 18*5671Ssam static struct sockaddr_pup pupaddr = { AF_PUP }; 19*5671Ssam static struct sockproto pupproto = { PF_PUP }; 20*5671Ssam 21*5671Ssam /* 22*5671Ssam * Setup generic address and protocol structures 23*5671Ssam * for raw_input routine, then pass them along with 24*5671Ssam * mbuf chain. 25*5671Ssam */ 26*5671Ssam rawpup_input(m) 27*5671Ssam struct mbuf *m; 28*5671Ssam { 29*5671Ssam register struct pup_header *pup = mtod(m, struct pup_header *); 30*5671Ssam 31*5671Ssam COUNT(RAWPUP_INPUT); 32*5671Ssam pupproto.sp_protocol = pup->pup_type; 33*5671Ssam pupaddr.spup_addr = pup->pup_daddr; 34*5671Ssam raw_input(m, pupproto, pupaddr); 35*5671Ssam } 36*5671Ssam 37*5671Ssam /*ARGSUSED*/ 38*5671Ssam rawpup_ctlinput(m) 39*5671Ssam struct mbuf *m; 40*5671Ssam { 41*5671Ssam COUNT(RAWPUP_CTLINPUT); 42*5671Ssam } 43*5671Ssam 44*5671Ssam /* 45*5671Ssam * Encapsulate packet in PUP header which is supplied by the 46*5671Ssam * user. This is done to allow user to specify PUP identifier. 47*5671Ssam */ 48*5671Ssam rawpup_output(m0, so) 49*5671Ssam struct mbuf *m0; 50*5671Ssam struct socket *so; 51*5671Ssam { 52*5671Ssam register struct rawcb *rp = sotorawcb(so); 53*5671Ssam register struct pup_header *pup; 54*5671Ssam int len; 55*5671Ssam struct mbuf *n; 56*5671Ssam struct sockaddr_pup *spup; 57*5671Ssam 58*5671Ssam COUNT(RAWPUP_OUTPUT); 59*5671Ssam /* 60*5671Ssam * Verify user has supplied necessary space 61*5671Ssam * for the header and check parameters in it. 62*5671Ssam */ 63*5671Ssam if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct pup_header)) && 64*5671Ssam (m = m_pullup(m, sizeof(struct pup_header)) == 0) { 65*5671Ssam goto bad; 66*5671Ssam pup = mtod(m, struct pup_header *); 67*5671Ssam if (pup->pup_type == 0) 68*5671Ssam goto bad; 69*5671Ssam if (pup->pup_tcontrol && (pup->pup_tcontrol & ~PUP_TRACE)) 70*5671Ssam goto bad; 71*5671Ssam for (len = 0, n = m; n; n = n->m_next) 72*5671Ssam len += n->m_len; 73*5671Ssam pup->pup_length = len; 74*5671Ssam spup = (struct sockaddr_pup *)&rp->rcb_addr; 75*5671Ssam pup->pup_dport = spup->spup_addr; 76*5671Ssam 77*5671Ssam /* 78*5671Ssam * Insure proper source address is included. 79*5671Ssam */ 80*5671Ssam spup = (struct sockadrr_pup *)rp->rcb_socket->so_addr; 81*5671Ssam pup->pup_sport = spup->spup_addr; 82*5671Ssam /* for now, assume user generates PUP checksum. */ 83*5671Ssam 84*5671Ssam if (rp->rcb_pcb == 0) /* XXX */ 85*5671Ssam panic("rawpup_output"); 86*5671Ssam return (enoutput((struct ifnet *)rp->rcb_pcb, m, PF_PUP)); 87*5671Ssam 88*5671Ssam bad: 89*5671Ssam m_freem(m); 90*5671Ssam return (0); 91*5671Ssam } 92*5671Ssam 93*5671Ssam /* 94*5671Ssam * Intercept connects and sends to verify interface 95*5671Ssam * exists for destination address. Disconnects are 96*5671Ssam * also looked at to insure pointer is invalidated. 97*5671Ssam */ 98*5671Ssam rawpup_usrreq(so, req, m, addr) 99*5671Ssam struct socket *so; 100*5671Ssam int req; 101*5671Ssam struct mbuf *m; 102*5671Ssam caddr_t addr; 103*5671Ssam { 104*5671Ssam register struct rawcb *rp = sotorawcb(so); 105*5671Ssam 106*5671Ssam COUNT(RAWPUP_USRREQ); 107*5671Ssam if (rp == 0 && req != PRU_ATTACH) 108*5671Ssam return (EINVAL); 109*5671Ssam 110*5671Ssam switch (req) { 111*5671Ssam 112*5671Ssam /* 113*5671Ssam * Verify address has an interface to go with it 114*5671Ssam * and record information for use in output routine. 115*5671Ssam */ 116*5671Ssam case PRU_SEND: 117*5671Ssam case PRU_CONNECT: { 118*5671Ssam register struct sockaddr_pup *spup; 119*5671Ssam register struct ifnet *ifp; 120*5671Ssam 121*5671Ssam spup = (struct sockaddr_pup *)addr; 122*5671Ssam ifp = if_ifonnetof(spup->spup_addr); 123*5671Ssam if (ifp == 0) { 124*5671Ssam ifp = if_gatewayfor(spup->spup_addr); 125*5671Ssam if (ifp == 0) 126*5671Ssam return (EADDRNOTAVAIL); /* XXX */ 127*5671Ssam } 128*5671Ssam rp->rcb_pcb = (caddr_t)ifp; 129*5671Ssam break; 130*5671Ssam } 131*5671Ssam 132*5671Ssam case PRU_DISCONNECT: 133*5671Ssam rp->rcb_pcb = 0; 134*5671Ssam break; 135*5671Ssam 136*5671Ssam case PRU_CONTROL: 137*5671Ssam return (EOPNOTSUPP); 138*5671Ssam } 139*5671Ssam return (raw_usrreq(so, req, m, addr)); 140*5671Ssam } 141