2
* Copyright 2000, International Business Machines Corporation and others.
5
* This software has been released under the terms of the IBM Public
6
* License. For details, see the LICENSE file in the top-level source
7
* directory or online at http://www.openafs.org/dl/license10.html
10
#include <afsconfig.h>
11
#include "../afs/param.h"
13
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/rx/DUX/rx_knet.c,v 1.1.1.5 2001/09/11 14:34:29 hartmans Exp $");
16
#include "../rx/rx_kcommon.h"
19
static struct protosw parent_proto; /* udp proto switch */
20
static void rxk_input (struct mbuf *am, int iphlen);
21
static void rxk_fasttimo (void);
23
/* start intercepting basic calls */
25
register struct protosw *tpro, *last;
26
if (rxk_initDone) return 0;
28
last = inetdomain.dom_protoswNPROTOSW;
29
for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
30
if (tpro->pr_protocol == IPPROTO_UDP) {
31
/* force UDP checksumming on for AFS */
34
memcpy(&parent_proto, tpro, sizeof(parent_proto));
35
tpro->pr_input = rxk_input;
36
tpro->pr_fasttimo = rxk_fasttimo;
38
* don't bother with pr_drain and pr_ctlinput
39
* until we have something to do
44
osi_Panic("inet:no udp");
48
static void rxk_input (struct mbuf *am, int iphlen)
51
register unsigned short *tsp;
54
register struct ip *ti;
59
struct sockaddr_in taddr;
62
int data_len, comp_sum;
67
/* make sure we have base ip and udp headers in first mbuf */
68
if (iphlen > sizeof (struct ip)) {
69
ip_stripoptions(am, (struct mbuf *)0, (struct ipoption *)0);
70
iphlen = sizeof (struct ip);
73
if (am->m_len < sizeof(struct udpiphdr)) {
74
am = m_pullup(am, sizeof(struct udpiphdr));
81
ti = mtod(am, struct ip *);
82
/* skip basic ip hdr */
83
tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
85
/* now read the port out */
89
for(tsp=rxk_ports, i=0; i<MAXRXPORTS;i++) {
91
/* checksum the packet */
93
* Make mbuf data length reflect UDP length.
94
* If not enough data to reflect UDP length, drop.
96
tvu = (struct udpiphdr *)ti;
97
tlen = ntohs((u_short)tvu->ui_ulen);
98
if ((int)ti->ip_len != tlen) {
99
if (tlen > (int)ti->ip_len) {
104
m_adj(am, tlen - (int)ti->ip_len);
106
/* deliver packet to rx */
107
taddr.sin_family = AF_INET; /* compute source address */
108
taddr.sin_port = tu->uh_sport;
109
taddr.sin_addr.s_addr = ti->ip_src.s_addr;
110
taddr.sin_len = sizeof(taddr);
111
tvu = (struct udpiphdr *) ti; /* virtual udp structure, for cksum */
112
/* handle the checksum. Note that this code damages the actual ip
113
header (replacing it with the virtual one, which is the same size),
114
so we must ensure we get everything out we need, first */
115
if ( tu->uh_sum != 0) {
116
/* if the checksum is there, always check it. It's crazy not
117
* to, unless you can really be sure that your
118
* underlying network (and interfaces and drivers and
119
* DMA hardware, etc!) is error-free. First, fill
120
* in entire virtual ip header. */
121
tvu->ui_i.fill[0] = 0;
122
tvu->ui_i.fill[1] = 0;
124
tvu->ui_len = tvu->ui_ulen;
125
tlen = ntohs((unsigned short)(tvu->ui_ulen));
126
if (in_cksum(am, sizeof(struct ip) + tlen)) {
127
/* checksum, including cksum field, doesn't come out 0, so
128
this packet is bad */
136
* 28 is IP (20) + UDP (8) header. ulen includes
137
* udp header, and we *don't* tell RX about udp
138
* header either. So, we remove those 8 as well.
140
data_len = ntohs(tu->uh_ulen);
143
if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
144
if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
145
/* XXX should just increment counter here.. */
146
printf("rx: truncated UDP packet\n");
147
rxi_FreePacket(phandle);
150
(*rxk_PacketArrivalProc)(phandle, &taddr,
151
rxk_portRocks[i], data_len);
160
/* if we get here, try to deliver packet to udp */
161
if (tproc = parent_proto.pr_input) (*tproc)(am,iphlen);
168
* UDP fast timer to raise events for all but Solaris and NCR.
169
* Called about 5 times per second (at unknown priority?). Must go to
170
* splnet or obtain global lock before touching anything significant.
172
static void rxk_fasttimo (void)
177
/* do rx fasttimo processing here */
178
rxevent_RaiseEvents(&temp);
179
if (tproc = parent_proto.pr_fasttimo) (*tproc)();
183
/* rx_NetSend - send asize bytes at adata from asocket to host at addr.
185
* Now, why do we allocate a new buffer when we could theoretically use the one
186
* pointed to by adata? Because PRU_SEND returns after queueing the message,
187
* not after sending it. If the sender changes the data after queueing it,
188
* we'd see the already-queued data change. One attempt to fix this without
189
* adding a copy would be to have this function wait until the datagram is
190
* sent; however this doesn't work well. In particular, if a host is down, and
191
* an ARP fails to that host, this packet will be queued until the ARP request
192
* comes back, which could be hours later. We can't block in this routine that
193
* long, since it prevents RPC timeouts from happening.
195
/* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
196
* and just queue those. XXX
199
/* set lock on sockbuf sb; can't call sblock since we're at interrupt level
202
register struct sockbuf *sb; {
203
AFS_STATCNT(trysblock);
204
if (sb->sb_flags & SB_LOCK){
205
return -1; /* can't lock socket */
207
sb->sb_flags |= SB_LOCK;
212
osi_NetSend(asocket, addr, dvec, nvec, asize, istack)
213
register struct socket *asocket;
216
register afs_int32 asize;
217
struct sockaddr_in *addr;
220
register struct mbuf *tm, *um;
221
register afs_int32 code;
223
struct mbuf *top = 0;
224
register struct mbuf *m, **mp;
232
AFS_STATCNT(osi_NetSend);
234
/* Actually, the Ultrix way is as good as any for us, so we don't bother with
235
* special mbufs any more. Used to think we could get away with not copying
236
* the data to the interface, but there's no way to tell the caller not to
237
* reuse the buffers after sending, so we lost out on that trick anyway */
242
tdata = dvec[i].iov_base;
243
tl = dvec[i].iov_len;
247
MGETHDR(m, M_DONTWAIT, MT_DATA);
254
m->m_pkthdr.rcvif = (struct ifnet *)0;
256
MGET(m, M_DONTWAIT, MT_DATA);
258
/* can't get an mbuf, give up */
259
if (top) m_freem(top); /* free mbuf list we're building */
264
* WARNING: the `4 * MLEN' is somewhat dubious. It is better than
265
* `NBPG', which may have no relation to `CLBYTES'. Also, `CLBYTES'
266
* may be so large that we never use clusters, resulting in far
267
* too many mbufs being used. It is often better to briefly use
268
* a cluster, even if we are only using a portion of it. Since
269
* we are on the xmit side, it shouldn't end up sitting on a queue
270
* for a potentially unbounded time (except perhaps if we are talking
273
if (asize >= 4 * MLEN) { /* try to get cluster mbuf */
274
register struct mbuf *p;
276
/* different algorithms for getting cluster mbuf */
277
MCLGET(m, M_DONTWAIT);
278
if ((m->m_flags & M_EXT) == 0)
282
/* now compute usable size */
283
len = MIN(mlen, asize);
284
/* Should I look at MAPPED_MBUFS??? */
287
len = MIN(mlen, asize);
291
top->m_pkthdr.len += len;
292
tpa = mtod(m, caddr_t);
295
memcpy(tpa, tdata, rlen);
305
/* shouldn't come here! */
306
asize = 0; /* so we make progress toward completion */
309
tdata = dvec[i].iov_base;
310
tl = dvec[i].iov_len;
320
tm->m_act = (struct mbuf *) 0;
322
/* setup mbuf corresponding to destination address */
323
um = m_get(M_DONTWAIT, MT_SONAME);
325
if (top) m_freem(top); /* free mbuf chain */
326
/* if this were vfs40, we'd do sbunlock(asocket, &asocket->so_snd), but
327
we don't do the locking at all for vfs40 systems */
331
memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
332
um->m_len = sizeof(*addr);
333
/* note that udp_usrreq frees funny mbuf. We hold onto data, but mbuf
334
* around it is gone. we free address ourselves. */
335
haveGlock = ISAFS_GLOCK();
339
SOCKET_LOCK(asocket);
340
code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0);
341
SOCKET_UNLOCK(asocket);
351
#endif /* AFS_DUX40_ENV */