1*6045Swnj /*	raw_pup.c	4.6	82/03/05	*/
25671Ssam 
35671Ssam #include "../h/param.h"
45671Ssam #include "../h/mbuf.h"
55671Ssam #include "../h/socket.h"
65671Ssam #include "../h/protosw.h"
75671Ssam #include "../h/socketvar.h"
85671Ssam #include "../net/in.h"
95671Ssam #include "../net/in_systm.h"
105671Ssam #include "../net/pup.h"
115671Ssam #include "../net/raw_cb.h"
12*6045Swnj #include "../net/if.h"
136040Sroot #include "../errno.h"
145671Ssam 
155671Ssam /*
165671Ssam  * Raw PUP protocol interface.
175671Ssam  */
185671Ssam 
195671Ssam /*ARGSUSED*/
205847Sroot rpup_ctlinput(m)
215671Ssam 	struct mbuf *m;
225671Ssam {
235847Sroot COUNT(RPUP_CTLINPUT);
245671Ssam }
255671Ssam 
265671Ssam /*
275671Ssam  * Encapsulate packet in PUP header which is supplied by the
285671Ssam  * user.  This is done to allow user to specify PUP identifier.
295671Ssam  */
30*6045Swnj rpup_output(m, so)
31*6045Swnj 	register struct mbuf *m;
325671Ssam 	struct socket *so;
335671Ssam {
345671Ssam 	register struct rawcb *rp = sotorawcb(so);
355671Ssam 	register struct pup_header *pup;
365671Ssam 	int len;
375671Ssam 	struct mbuf *n;
385671Ssam 	struct sockaddr_pup *spup;
396027Ssam 	struct ifnet *ifp;
405671Ssam 
415847Sroot COUNT(RPUP_OUTPUT);
425671Ssam 	/*
435671Ssam 	 * Verify user has supplied necessary space
445671Ssam 	 * for the header and check parameters in it.
455671Ssam 	 */
465671Ssam 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct pup_header)) &&
47*6045Swnj 	    (m = m_pullup(m, sizeof(struct pup_header))) == 0)
485671Ssam 		goto bad;
495671Ssam 	pup = mtod(m, struct pup_header *);
505671Ssam 	if (pup->pup_type == 0)
515671Ssam 		goto bad;
525671Ssam 	if (pup->pup_tcontrol && (pup->pup_tcontrol & ~PUP_TRACE))
535671Ssam 		goto bad;
545671Ssam 	for (len = 0, n = m; n; n = n->m_next)
555671Ssam 		len += n->m_len;
565671Ssam 	pup->pup_length = len;
575671Ssam 	spup = (struct sockaddr_pup *)&rp->rcb_addr;
585671Ssam 	pup->pup_dport = spup->spup_addr;
595671Ssam 
605671Ssam 	/*
615671Ssam 	 * Insure proper source address is included.
625671Ssam 	 */
63*6045Swnj 	spup = (struct sockadrr_pup *)&(rp->rcb_socket->so_addr);
645671Ssam 	pup->pup_sport = spup->spup_addr;
655671Ssam 	/* for now, assume user generates PUP checksum. */
665671Ssam 
676027Ssam 	ifp = if_ifonnetof(&rp->rcb_addr);
686027Ssam 	if (ifp == 0) {
696027Ssam 		ifp = if_gatewayfor(&rp->rcb_addr);
706027Ssam 		if (ifp == 0)
716027Ssam 			goto bad;
726027Ssam 	}
735671Ssam 	return (enoutput((struct ifnet *)rp->rcb_pcb, m, PF_PUP));
745671Ssam 
755671Ssam bad:
765671Ssam 	m_freem(m);
775671Ssam 	return (0);
785671Ssam }
79