1*6509Ssam /*	raw_pup.c	4.11	82/04/10	*/
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"
126045Swnj #include "../net/if.h"
136040Sroot #include "../errno.h"
145671Ssam 
155671Ssam /*
165671Ssam  * Raw PUP protocol interface.
175671Ssam  */
185671Ssam 
195671Ssam /*
205671Ssam  * Encapsulate packet in PUP header which is supplied by the
215671Ssam  * user.  This is done to allow user to specify PUP identifier.
225671Ssam  */
236045Swnj rpup_output(m, so)
246045Swnj 	register struct mbuf *m;
255671Ssam 	struct socket *so;
265671Ssam {
275671Ssam 	register struct rawcb *rp = sotorawcb(so);
285671Ssam 	register struct pup_header *pup;
29*6509Ssam 	int len, error = 0;
305671Ssam 	struct mbuf *n;
31*6509Ssam 	struct sockaddr_pup *dst;
326027Ssam 	struct ifnet *ifp;
335671Ssam 
345847Sroot COUNT(RPUP_OUTPUT);
355671Ssam 	/*
365671Ssam 	 * Verify user has supplied necessary space
375671Ssam 	 * for the header and check parameters in it.
385671Ssam 	 */
395671Ssam 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct pup_header)) &&
40*6509Ssam 	    (m = m_pullup(m, sizeof(struct pup_header))) == 0) {
41*6509Ssam 		error = EMSGSIZE;	/* XXX */
425671Ssam 		goto bad;
43*6509Ssam 	}
445671Ssam 	pup = mtod(m, struct pup_header *);
45*6509Ssam 	if (pup->pup_type == 0) {
46*6509Ssam 		error = EPERM;		/* XXX */
475671Ssam 		goto bad;
48*6509Ssam 	}
49*6509Ssam 	if (pup->pup_tcontrol && (pup->pup_tcontrol & ~PUP_TRACE)) {
50*6509Ssam 		error = EPERM;		/* XXX */
515671Ssam 		goto bad;
52*6509Ssam 	}
535671Ssam 	for (len = 0, n = m; n; n = n->m_next)
545671Ssam 		len += n->m_len;
555671Ssam 	pup->pup_length = len;
566473Sroot #if vax || pdp11
576473Sroot 	pup->pup_length = htons(pup->pup_length);
586473Sroot #endif
59*6509Ssam 	/* assume user generates PUP checksum. */
60*6509Ssam 	dst = (struct sockaddr_pup *)&rp->rcb_faddr;
61*6509Ssam 	pup->pup_dport = dst->spup_addr;
626339Ssam 	ifp = if_ifonnetof(pup->pup_dnet);
63*6509Ssam 	if (ifp) {
64*6509Ssam 		if (rp->rcb_flags & RAW_LADDR) {
65*6509Ssam 			register struct sockaddr_pup *src;
665671Ssam 
67*6509Ssam 			src = (struct sockaddr_pup *)&rp->rcb_laddr;
68*6509Ssam 			pup->pup_sport = src->spup_addr;
69*6509Ssam 		} else {
70*6509Ssam 			pup->pup_snet = ifp->if_net;
71*6509Ssam 			pup->pup_shost = ifp->if_host[0];
72*6509Ssam 			/* socket is specified by user */
73*6509Ssam 		}
74*6509Ssam 		return ((*ifp->if_output)(ifp, m, (struct sockaddr *)dst));
75*6509Ssam 	}
76*6509Ssam 	error = ENETUNREACH;
775671Ssam bad:
785671Ssam 	m_freem(m);
79*6509Ssam 	return (error);
805671Ssam }
81