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