2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
4 * Copyright Transarc Corporation 1989 - All Rights Reserved *
6 * Permission to use, copy, modify, and distribute this software and its *
7 * documentation for any purpose and without fee is hereby granted, *
8 * provided that the above copyright notice appear in all copies and *
9 * that both that copyright notice and this permission notice appear in *
10 * supporting documentation, and that the name of IBM not be used in *
11 * advertising or publicity pertaining to distribution of the software *
12 * without specific, written prior permission. *
14 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
16 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
17 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
18 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
19 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
20 ****************************************************************************
23 #include <afsconfig.h>
24 #include "../afs/param.h"
29 #include "../rx/rx_kcommon.h"
32 #ifdef RXK_LISTENER_ENV
33 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
34 struct socket *asocket;
35 struct sockaddr_in *addr;
42 struct iovec iov[RX_MAXIOVECS];
46 int haveGlock = ISAFS_GLOCK();
47 /*AFS_STATCNT(osi_NetReceive);*/
49 if (nvecs > RX_MAXIOVECS) {
50 osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
53 for (i = 0 ; i < nvecs ; i++) {
54 iov[i].iov_base = dvec[i].iov_base;
55 iov[i].iov_len = dvec[i].iov_len;
62 u.uio_segflg=UIO_SYSSPACE;
69 code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
73 Debugger("afs NetReceive busted");
81 *alength=*alength-u.uio_resid;
83 if (sa->sa_family == AF_INET) {
84 if (addr) *addr=*(struct sockaddr_in *)sa;
86 printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
92 extern int rxk_ListenerPid;
93 void osi_StopListener(void)
98 p=pfind(rxk_ListenerPid);
104 osi_NetSend(asocket, addr, dvec, nvecs, alength, istack)
105 register struct socket *asocket;
108 register afs_int32 alength;
109 struct sockaddr_in *addr;
112 register afs_int32 code;
116 struct iovec iov[RX_MAXIOVECS];
119 int haveGlock = ISAFS_GLOCK();
121 AFS_STATCNT(osi_NetSend);
122 if (nvecs > RX_MAXIOVECS) {
123 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
126 for (i = 0 ; i < nvecs ; i++) {
127 iov[i].iov_base = dvec[i].iov_base;
128 iov[i].iov_len = dvec[i].iov_len;
135 u.uio_segflg=UIO_SYSSPACE;
139 addr->sin_len=sizeof(struct sockaddr_in);
147 code = sosend(asocket, addr, &u, NULL, NULL, 0, curproc);
151 Debugger("afs NetSend busted");
162 /* This code *almost* works :( */
163 static struct protosw parent_proto; /* udp proto switch */
164 static void rxk_input (struct mbuf *am, int iphlen);
165 static void rxk_fasttimo (void);
167 /* start intercepting basic calls */
169 register struct protosw *tpro, *last;
170 if (rxk_initDone) return 0;
172 last = inetdomain.dom_protoswNPROTOSW;
173 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
174 if (tpro->pr_protocol == IPPROTO_UDP) {
175 #if 0 /* not exported */
176 /* force UDP checksumming on for AFS */
180 memcpy(&parent_proto, tpro, sizeof(parent_proto));
181 tpro->pr_input = rxk_input;
182 tpro->pr_fasttimo = rxk_fasttimo;
184 * don't bother with pr_drain and pr_ctlinput
185 * until we have something to do
190 osi_Panic("inet:no udp");
194 static void rxk_input (struct mbuf *am, int iphlen)
197 register unsigned short *tsp;
200 register struct ip *ti;
201 struct udpiphdr *tvu;
205 struct sockaddr_in taddr;
208 int data_len, comp_sum;
213 /* make sure we have base ip and udp headers in first mbuf */
214 if (iphlen > sizeof (struct ip)) {
215 ip_stripoptions(am, (struct mbuf *)0);
216 iphlen = sizeof (struct ip);
219 if (am->m_len < sizeof(struct udpiphdr)) {
220 am = m_pullup(am, sizeof(struct udpiphdr));
227 ti = mtod(am, struct ip *);
228 /* skip basic ip hdr */
229 tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
231 /* now read the port out */
235 for(tsp=rxk_ports, i=0; i<MAXRXPORTS;i++) {
236 if (*tsp++ == port) {
237 /* checksum the packet */
239 * Make mbuf data length reflect UDP length.
240 * If not enough data to reflect UDP length, drop.
242 tvu = (struct udpiphdr *)ti;
243 tlen = ntohs((u_short)tvu->ui_ulen);
244 if ((int)ti->ip_len != tlen) {
245 if (tlen > (int)ti->ip_len) {
250 m_adj(am, tlen - (int)ti->ip_len);
252 /* deliver packet to rx */
253 taddr.sin_family = AF_INET; /* compute source address */
254 taddr.sin_port = tu->uh_sport;
255 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
256 taddr.sin_len = sizeof(taddr);
257 tvu = (struct udpiphdr *) ti; /* virtual udp structure, for cksum */
258 /* handle the checksum. Note that this code damages the actual ip
259 header (replacing it with the virtual one, which is the same size),
260 so we must ensure we get everything out we need, first */
261 if ( tu->uh_sum != 0) {
262 /* if the checksum is there, always check it. It's crazy not
263 * to, unless you can really be sure that your
264 * underlying network (and interfaces and drivers and
265 * DMA hardware, etc!) is error-free. First, fill
266 * in entire virtual ip header. */
267 memset(tvu->ui_i.ih_x1, 0, 9);
268 tvu->ui_len = tvu->ui_ulen;
269 tlen = ntohs((unsigned short)(tvu->ui_ulen));
270 if (in_cksum(am, sizeof(struct ip) + tlen)) {
271 /* checksum, including cksum field, doesn't come out 0, so
272 this packet is bad */
280 * 28 is IP (20) + UDP (8) header. ulen includes
281 * udp header, and we *don't* tell RX about udp
282 * header either. So, we remove those 8 as well.
284 data_len = ntohs(tu->uh_ulen);
287 if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
288 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
289 /* XXX should just increment counter here.. */
290 printf("rx: truncated UDP packet\n");
291 rxi_FreePacket(phandle);
294 (*rxk_PacketArrivalProc)(phandle, &taddr,
295 rxk_portRocks[i], data_len);
304 /* if we get here, try to deliver packet to udp */
305 if (tproc = parent_proto.pr_input) (*tproc)(am,iphlen);
312 * UDP fast timer to raise events for all but Solaris and NCR.
313 * Called about 5 times per second (at unknown priority?). Must go to
314 * splnet or obtain global lock before touching anything significant.
316 static void rxk_fasttimo (void)
321 /* do rx fasttimo processing here */
322 rxevent_RaiseEvents(&temp);
323 if (tproc = parent_proto.pr_fasttimo) (*tproc)();
326 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
328 * Now, why do we allocate a new buffer when we could theoretically use the one
329 * pointed to by adata? Because PRU_SEND returns after queueing the message,
330 * not after sending it. If the sender changes the data after queueing it,
331 * we'd see the already-queued data change. One attempt to fix this without
332 * adding a copy would be to have this function wait until the datagram is
333 * sent; however this doesn't work well. In particular, if a host is down, and
334 * an ARP fails to that host, this packet will be queued until the ARP request
335 * comes back, which could be hours later. We can't block in this routine that
336 * long, since it prevents RPC timeouts from happening.
338 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
339 * and just queue those. XXX
342 /* set lock on sockbuf sb; can't call sblock since we're at interrupt level
345 register struct sockbuf *sb; {
346 AFS_STATCNT(trysblock);
347 if (sb->sb_flags & SB_LOCK){
348 return -1; /* can't lock socket */
350 sb->sb_flags |= SB_LOCK;
354 /* We only have to do all the mbuf management ourselves if we can be called at
355 interrupt time. in RXK_LISTENER_ENV, we can just call sosend() */
357 osi_NetSend(asocket, addr, dvec, nvec, asize, istack)
358 register struct socket *asocket;
361 register afs_int32 asize;
362 struct sockaddr_in *addr;
365 register struct mbuf *tm, *um;
366 register afs_int32 code;
368 struct mbuf *top = 0;
369 register struct mbuf *m, **mp;
380 AFS_STATCNT(osi_NetSend);
381 /* Actually, the Ultrix way is as good as any for us, so we don't bother with
382 * special mbufs any more. Used to think we could get away with not copying
383 * the data to the interface, but there's no way to tell the caller not to
384 * reuse the buffers after sending, so we lost out on that trick anyway */
386 if (trysblock(&asocket->so_snd)) {
392 tdata = dvec[i].iov_base;
393 tl = dvec[i].iov_len;
397 MGETHDR(m, M_DONTWAIT, MT_DATA);
399 sbunlock(&asocket->so_snd);
405 m->m_pkthdr.rcvif = (struct ifnet *)0;
407 MGET(m, M_DONTWAIT, MT_DATA);
409 /* can't get an mbuf, give up */
410 if (top) m_freem(top); /* free mbuf list we're building */
411 sbunlock(&asocket->so_snd);
416 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
417 * `NBPG', which may have no relation to `CLBYTES'. Also, `CLBYTES'
418 * may be so large that we never use clusters, resulting in far
419 * too many mbufs being used. It is often better to briefly use
420 * a cluster, even if we are only using a portion of it. Since
421 * we are on the xmit side, it shouldn't end up sitting on a queue
422 * for a potentially unbounded time (except perhaps if we are talking
425 if (asize >= 4 * MLEN) { /* try to get cluster mbuf */
426 /* different algorithms for getting cluster mbuf */
427 MCLGET(m, M_DONTWAIT);
428 if ((m->m_flags & M_EXT) == 0)
432 /* now compute usable size */
433 len = MIN(mlen, asize);
434 /* Should I look at MAPPED_MBUFS??? */
437 len = MIN(mlen, asize);
441 top->m_pkthdr.len += len;
442 tpa = mtod(m, caddr_t);
445 memcpy(tpa, tdata, rlen);
455 /* shouldn't come here! */
456 asize = 0; /* so we make progress toward completion */
459 tdata = dvec[i].iov_base;
460 tl = dvec[i].iov_len;
470 tm->m_act = (struct mbuf *) 0;
472 /* setup mbuf corresponding to destination address */
473 um = m_get(M_DONTWAIT, MT_SONAME);
475 if (top) m_freem(top); /* free mbuf chain */
476 sbunlock(&asocket->so_snd);
480 memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
481 addr->sin_len = um->m_len = sizeof(*addr);
482 /* note that udp_usrreq frees funny mbuf. We hold onto data, but mbuf
483 * around it is gone. */
484 /* haveGlock = ISAFS_GLOCK();
488 /* SOCKET_LOCK(asocket); */
489 /* code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0); */
491 if (before) Debugger("afs NetSend before");
493 code = (*asocket->so_proto->pr_usrreqs->pru_send)(asocket, 0, tm,
494 (struct sockaddr *) addr,
496 /* SOCKET_UNLOCK(asocket); */
500 sbunlock(&asocket->so_snd);
505 Debugger("afs NetSend busted");
514 #endif /* AFS_FBSD40_ENV */