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"
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, NULL, NULL);
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(osi_socket asocket, struct sockaddr_in *addr,
213 struct iovec *dvec, int nvec, afs_int32 asize, int istack)
215 register struct mbuf *tm, *um;
216 register afs_int32 code;
218 struct mbuf *top = 0;
219 register struct mbuf *m, **mp;
227 AFS_STATCNT(osi_NetSend);
229 /* Actually, the Ultrix way is as good as any for us, so we don't bother with
230 * special mbufs any more. Used to think we could get away with not copying
231 * the data to the interface, but there's no way to tell the caller not to
232 * reuse the buffers after sending, so we lost out on that trick anyway */
237 tdata = dvec[i].iov_base;
238 tl = dvec[i].iov_len;
242 MGETHDR(m, M_DONTWAIT, MT_DATA);
249 m->m_pkthdr.rcvif = NULL;
251 MGET(m, M_DONTWAIT, MT_DATA);
253 /* can't get an mbuf, give up */
254 if (top) m_freem(top); /* free mbuf list we're building */
259 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
260 * `NBPG', which may have no relation to `CLBYTES'. Also, `CLBYTES'
261 * may be so large that we never use clusters, resulting in far
262 * too many mbufs being used. It is often better to briefly use
263 * a cluster, even if we are only using a portion of it. Since
264 * we are on the xmit side, it shouldn't end up sitting on a queue
265 * for a potentially unbounded time (except perhaps if we are talking
268 if (asize >= 4 * MLEN) { /* try to get cluster mbuf */
269 register struct mbuf *p;
271 /* different algorithms for getting cluster mbuf */
272 MCLGET(m, M_DONTWAIT);
273 if ((m->m_flags & M_EXT) == 0)
277 /* now compute usable size */
278 len = MIN(mlen, asize);
279 /* Should I look at MAPPED_MBUFS??? */
282 len = MIN(mlen, asize);
286 top->m_pkthdr.len += len;
287 tpa = mtod(m, caddr_t);
290 memcpy(tpa, tdata, rlen);
300 /* shouldn't come here! */
301 asize = 0; /* so we make progress toward completion */
304 tdata = dvec[i].iov_base;
305 tl = dvec[i].iov_len;
317 /* setup mbuf corresponding to destination address */
318 um = m_get(M_DONTWAIT, MT_SONAME);
320 if (top) m_freem(top); /* free mbuf chain */
321 /* if this were vfs40, we'd do sbunlock(asocket, &asocket->so_snd), but
322 we don't do the locking at all for vfs40 systems */
326 memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
327 um->m_len = sizeof(*addr);
328 /* note that udp_usrreq frees funny mbuf. We hold onto data, but mbuf
329 * around it is gone. we free address ourselves. */
330 haveGlock = ISAFS_GLOCK();
334 SOCKET_LOCK(asocket);
335 code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0);
336 SOCKET_UNLOCK(asocket);
346 #endif /* AFS_DUX40_ENV */