1 /* raw_pup.c 4.20 83/06/30 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/socket.h" 6 #include "../h/protosw.h" 7 #include "../h/socketvar.h" 8 #include "../h/errno.h" 9 10 #include "../net/if.h" 11 #include "../net/route.h" 12 #include "../net/raw_cb.h" 13 14 #include "../netpup/pup.h" 15 16 /* 17 * Raw PUP protocol interface. 18 */ 19 20 struct sockaddr_pup pupsrc = { AF_PUP }; 21 struct sockaddr_pup pupdst = { AF_PUP }; 22 struct sockproto pupproto = { PF_PUP }; 23 /* 24 * Raw PUP input. 25 */ 26 rpup_input(m) 27 struct mbuf *m; 28 { 29 register struct pup_header *pup = mtod(m, struct pup_header *); 30 31 pupproto.sp_protocol = pup->pup_type; 32 bcopy((caddr_t)&pup->pup_dnet, (caddr_t)&pupdst.spup_net, 33 sizeof (struct pupport)); 34 bcopy((caddr_t)&pup->pup_snet, (caddr_t)&pupsrc.spup_net, 35 sizeof (struct pupport)); 36 raw_input(m, &pupproto, (struct sockaddr *)&pupsrc, 37 (struct sockaddr *)&pupdst); 38 } 39 40 /* 41 * Encapsulate packet in PUP header which is supplied by the 42 * user. This is done to allow user to specify PUP identifier. 43 */ 44 rpup_output(m, so) 45 register struct mbuf *m; 46 struct socket *so; 47 { 48 register struct rawcb *rp = sotorawcb(so); 49 register struct pup_header *pup; 50 int len, error = 0; 51 register struct mbuf *n, *last; 52 struct sockaddr_pup *dst; 53 struct ifnet *ifp; 54 u_short *pc; 55 56 /* 57 * Verify user has supplied necessary space 58 * for the header and check parameters in it. 59 */ 60 if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct pup_header)) && 61 (m = m_pullup(m, sizeof(struct pup_header))) == 0) { 62 error = EINVAL; 63 goto bad; 64 } 65 pup = mtod(m, struct pup_header *); 66 if (pup->pup_type == 0 || (pup->pup_tcontrol &~ PUP_TRACE)) { 67 error = EINVAL; 68 goto bad; 69 } 70 for (len = 0, n = last = m; n; last = n, n = n->m_next) 71 len += n->m_len; 72 /* assume user leaves space for checksum */ 73 if ((len & 1) || len < MINPUPSIZ || len > MAXPUPSIZ) { 74 error = EMSGSIZE; 75 goto bad; 76 } 77 pup->pup_length = htons((u_short)len); 78 dst = (struct sockaddr_pup *)&rp->rcb_faddr; 79 bcopy((caddr_t)&dst->spup_net, (caddr_t)&pup->pup_dnet, 80 sizeof (struct pupport)); 81 if (rp->rcb_route.ro_rt == 0) 82 ifp = if_ifonnetof(dst->spup_net); 83 else { 84 rp->rcb_route.ro_rt->rt_use++; 85 ifp = rp->rcb_route.ro_rt->rt_ifp; 86 } 87 if (ifp == 0) { 88 error = ENETUNREACH; 89 goto bad; 90 } 91 if (rp->rcb_flags & RAW_LADDR) { 92 register struct sockaddr_pup *src; 93 94 src = (struct sockaddr_pup *)&rp->rcb_laddr; 95 bcopy((caddr_t)&src->spup_net, (caddr_t)&pup->pup_snet, 96 sizeof (struct pupport)); 97 } else { 98 pup->pup_snet = ifp->if_net; 99 pup->pup_shost = ifp->if_host[0]; 100 /* socket is specified by user */ 101 } 102 /* 103 * Fill in checksum unless user indicates none should be specified. 104 */ 105 pc = (u_short *)(mtod(last, caddr_t) + last->m_len - sizeof (short)); 106 if (*pc != PUP_NOCKSUM) 107 *pc = htons((u_short)pup_cksum(m, len - sizeof (short))); 108 return ((*ifp->if_output)(ifp, m, (struct sockaddr *)dst)); 109 bad: 110 m_freem(m); 111 return (error); 112 } 113