Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / rx / HPUX / rx_knet.c
1 /* This file is bootstrapped from the RX release cleared by Transarc legal
2 in 1994, available from ftp.dementia.org/pub/rx
3 */
4
5 #include <afsconfig.h>
6 #include "afs/param.h"
7
8
9 #include "h/types.h"
10 #include "h/param.h"
11 #include "rx/rx_kcommon.h"
12 #include "h/user.h"
13 #include "h/tihdr.h"
14 #include <xti.h>
15
16 /* Define this here, used externally */
17 #ifdef RX_ENABLE_LOCKS
18 lock_t *rx_sleepLock;
19 #endif
20
21 /* rx_kern.c */
22 /*
23 * XXX The following is needed since the include file that contains them (<net/cko.h>)
24 * isn't part of a binary distribution!! XXXX
25 */
26
27 /* CKO_PSEUDO : Account for pseudo_header in the checksum */
28 #ifndef CKO_SUM_MASK
29 #define CKO_SUM_MASK 0xffff /* sum is in lower 16 bits */
30 #endif
31
32 #ifndef CKO_PSEUDO
33 #define CKO_PSEUDO(sum, m, hdr) { \
34 (sum) = 0xffff ^ in_3sum( ((struct ipovly *)(hdr))->ih_src.s_addr, \
35 ((struct ipovly *)(hdr))->ih_dst.s_addr, \
36 ((struct ipovly *)(hdr))->ih_len \
37 + (((struct ipovly *)(hdr))->ih_pr<<16) \
38 + ((m)->m_quad[MQ_CKO_IN] & CKO_SUM_MASK)); \
39 }
40 #endif
41
42 static struct protosw parent_proto; /* udp proto switch */
43
44 /* rx_kern.c */
45 static int
46 rxk_fasttimo(void)
47 {
48 int code;
49 int (*tproc) ();
50 struct clock temp;
51
52 SPLVAR;
53 NETPRI;
54 /* do rx fasttimo processing here */
55 rxevent_RaiseEvents(&temp);
56 USERPRI; /* should this be after the call to tproc? */
57 if (tproc = parent_proto.pr_fasttimo)
58 code = (*tproc) ();
59 else
60 code = 0;
61 return code;
62 }
63
64 /* hybrid of IRIX/knet.c and rx_kern.c */
65 /* XXX should this be listener or !listener? */
66 #if !defined(RXK_LISTENER_ENV)
67 /* start intercepting basic calls */
68 int
69 rxk_init()
70 {
71 struct protosw *tpro, *last;
72 if (rxk_initDone)
73 return 0;
74
75 last = inetdomain.dom_protoswNPROTOSW;
76 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++) {
77 if (tpro->pr_protocol == IPPROTO_UDP) {
78 /* force UDP checksumming on for AFS */
79 int udpcksum;
80 udpcksum = 1;
81 memcpy(&parent_proto, tpro, sizeof(parent_proto));
82 tpro->pr_input = rxk_input;
83 tpro->pr_fasttimo = rxk_fasttimo;
84 rxk_initDone = 1;
85 return 0;
86 }
87 }
88 osi_Panic("inet:no udp");
89 }
90
91 /* basic packet handling routine called at splnet from softnet loop */
92 static struct mbuf *
93 rxk_input(struct mbuf *am, struct ifnet *aif)
94 {
95 int (*tproc) ();
96 unsigned short *tsp;
97 int hdr;
98 struct udphdr *tu;
99 struct ip *ti;
100 struct udpiphdr *tvu;
101 int i;
102 char *phandle;
103 afs_int32 code;
104 struct sockaddr_in taddr;
105 int tlen;
106 short port;
107 int data_len;
108 unsigned int comp_sum;
109
110 SPLVAR;
111 NETPRI;
112 /* make sure we have base ip and udp headers in first mbuf */
113 if (am->m_off > MMAXOFF || am->m_len < 28) {
114 am = m_pullup(am, 28);
115 USERPRI;
116 if (!am)
117 return NULL;
118 }
119 hdr = (mtod(am, struct ip *))->ip_hl;
120 if (hdr > 5) {
121 /* pull up more, the IP hdr is bigger than usual */
122 if (am->m_len < (8 + (hdr << 2))) {
123 am = m_pullup(am, 8 + (hdr << 2));
124 USERPRI;
125 if (!am)
126 return NULL;
127 }
128 ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
129 tu = (struct udphdr *)(((char *)ti) + (hdr << 2)); /* skip ip hdr */
130 } else {
131 ti = mtod(am, struct ip *);
132 tu = (struct udphdr *)(((char *)ti) + 20); /* skip basic ip hdr */
133 }
134 /* now read the port out */
135 port = tu->uh_dport;
136
137 if (port) {
138 for (tsp = ports, i = 0; i < MAXRXPORTS; i++) {
139 if (*tsp++ == port) {
140 /* checksum the packet */
141 ip_stripoptions(ti, NULL); /* get rid of anything we don't need */
142 /* deliver packet to rx */
143 taddr.sin_family = AF_INET; /* compute source address */
144 taddr.sin_port = tu->uh_sport;
145 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
146
147 /* handle the checksum. Note that this code damages the actual ip
148 * header (replacing it with the virtual one, which is the same
149 * size), so we must ensure we get everything out we need, first */
150 tvu = (struct udpiphdr *)ti; /* virtual udp structure, for ck
151 * sum */
152 if (tu->uh_sum != 0) {
153 /* if the checksum is there, always check it. It's crazy not
154 * to, unless you can really be sure that your
155 * underlying network (and interfaces and drivers and
156 * DMA hardware, etc!) is error-free. First, fill
157 * in entire virtual ip header. */
158 tvu->ui_next = 0;
159 tvu->ui_prev = 0;
160 tvu->ui_x1 = 0;
161 tvu->ui_len = tvu->ui_ulen;
162 tlen = ntohs((unsigned short)(tvu->ui_ulen));
163 /* HP: checksum assist for cksum offloading drivers */
164 if (am->m_flags & MF_CKO_IN) {
165 CKO_PSEUDO(comp_sum, am, tvu);
166 } else {
167 struct mbuf *m1;
168
169 comp_sum = in_cksum(am, sizeof(struct ip) + tlen);
170 for (m1 = am; m1; m1 = m1->m_next)
171 m1->m_flags &= ~MF_NOACC;
172 }
173 if (comp_sum) {
174 /* checksum, including cksum field, doesn't come out 0, so
175 * this packet is bad */
176 m_freem(am);
177 USERPRI;
178 return (NULL);
179 }
180 }
181 /*
182 * 28 is IP (20) + UDP (8) header. ulen includes
183 * udp header, and we *don't* tell RX about udp
184 * header either. So, we remove those 8 as well.
185 */
186 data_len = ntohs(tu->uh_ulen);
187 data_len -= 8;
188
189 if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
190 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
191 /* XXX should just increment counter here.. */
192 printf("rx: truncated UDP packet\n");
193 rxi_FreePacket(phandle);
194 } else
195 (*rxk_PacketArrivalProc) (phandle, &taddr,
196 portRocks[i], data_len);
197 } else
198 m_freem(am);
199 USERPRI;
200 return (NULL);
201 }
202 }
203 }
204
205 /* if we get here, try to deliver packet to udp */
206 if (tproc = parent_proto.pr_input) {
207 code = (*tproc) (am, aif);
208 USERPRI;
209 return code;
210 }
211 USERPRI;
212 return (NULL);
213 }
214 #endif /* ! RXK_LISTENER_ENV */
215
216 /* steal decl from sgi_65 */
217 int
218 osi_NetSend(struct socket *asocket, struct sockaddr_in *addr,
219 struct iovec *dvec, int nvec, afs_int32 asize,
220 int istack)
221 {
222 struct uio uio;
223 MBLKP bp;
224 struct iovec temp[RX_MAXWVECS];
225 int code;
226 int size = sizeof(struct sockaddr_in);
227
228 memset(&uio, 0, sizeof(uio));
229 memset(&temp, 0, sizeof(temp));
230
231 /* Guess based on rxk_NewSocket */
232 bp = allocb((size + SO_MSGOFFSET + 1), BPRI_MED);
233 if (!bp)
234 return ENOBUFS;
235 memcpy((caddr_t) bp->b_rptr + SO_MSGOFFSET, (caddr_t) addr, size);
236 bp->b_wptr = bp->b_rptr + (size + SO_MSGOFFSET + 1);
237
238 memcpy((caddr_t) temp, (caddr_t) dvec, nvec * sizeof(struct iovec));
239
240 /* devresource.hp.com/Drivers/Docs/Refs/11i/ddRef/Chap02R.pdf has details
241 * on use of uio */
242 memset((caddr_t) & uio, 0, sizeof(uio));
243 uio.uio_resid = asize;
244 uio.uio_iov = temp;
245 uio.uio_iovcnt = nvec;
246 uio.uio_seg = UIOSEG_KERNEL;
247
248 code = sosend(asocket, bp, &uio, 0, 0, 0, size);
249 return code;
250 }
251
252 /* pattern from IRIX */
253 #if defined(RXK_LISTENER_ENV)
254 int
255 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
256 int nvecs, int *alength)
257 {
258 int code;
259 struct uio tuio;
260 struct iovec tmpvec[RX_MAXWVECS + 2];
261 int flags = 0;
262 MBLKP bp, sp;
263
264 memset(&tuio, 0, sizeof(tuio));
265 memset(&tmpvec, 0, sizeof(tempvec));
266
267 if (nvecs > RX_MAXWVECS + 2) {
268 osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", nvecs);
269 }
270 memcpy(tmpvec, (char *)dvec,
271 nvecs /*(RX_MAXWVECS+1) */ * sizeof(struct iovec));
272 tuio.uio_iov = tmpvec;
273 tuio.uio_iovcnt = nvecs;
274 tuio.uio_fpflags = 0;
275 tuio.uio_offset = 0;
276 tuio.uio_seg = UIOSEG_KERNEL;
277 tuio.uio_resid = *alength;
278
279 code = soreceive(so, &bp, &tuio, &flags, &sp, (MBLKPP) NULL);
280 if (!code) {
281 *alength = *alength - tuio.uio_resid;
282 if (bp) {
283 memcpy((char *)addr, (char *)bp->b_rptr,
284 sizeof(struct sockaddr_in));
285 } else {
286 code = -1;
287 }
288 } else {
289 so->so_error = 0;
290 }
291
292 if (bp)
293 freeb(bp);
294 if (sp)
295 freeb(sp);
296 return code;
297 }
298 #endif