Commit | Line | Data |
---|---|---|
8f57889f C |
1 | /* raw_pup.c 6.1 83/07/29 */ |
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 | } |