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 "../afs/param.h"
24 #include <afsconfig.h>
29 #include "../rx/rx_kcommon.h"
32 static struct protosw parent_proto; /* udp proto switch */
33 static void rxk_input (struct mbuf *am, int iphlen);
34 static void rxk_fasttimo (void);
36 /* start intercepting basic calls */
38 register struct protosw *tpro, *last;
39 if (rxk_initDone) return 0;
41 last = inetdomain.dom_protoswNPROTOSW;
42 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
43 if (tpro->pr_protocol == IPPROTO_UDP) {
44 /* force UDP checksumming on for AFS */
47 bcopy(tpro, &parent_proto, sizeof(parent_proto));
48 tpro->pr_input = rxk_input;
49 tpro->pr_fasttimo = rxk_fasttimo;
51 * don't bother with pr_drain and pr_ctlinput
52 * until we have something to do
57 osi_Panic("inet:no udp");
61 static void rxk_input (struct mbuf *am, int iphlen)
64 register unsigned short *tsp;
67 register struct ip *ti;
72 struct sockaddr_in taddr;
75 int data_len, comp_sum;
80 /* make sure we have base ip and udp headers in first mbuf */
81 if (iphlen > sizeof (struct ip)) {
82 ip_stripoptions(am, (struct mbuf *)0);
83 iphlen = sizeof (struct ip);
86 if (am->m_len < sizeof(struct udpiphdr)) {
87 am = m_pullup(am, sizeof(struct udpiphdr));
94 ti = mtod(am, struct ip *);
95 /* skip basic ip hdr */
96 tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
98 /* now read the port out */
102 for(tsp=rxk_ports, i=0; i<MAXRXPORTS;i++) {
103 if (*tsp++ == port) {
104 /* checksum the packet */
106 * Make mbuf data length reflect UDP length.
107 * If not enough data to reflect UDP length, drop.
109 tvu = (struct udpiphdr *)ti;
110 tlen = ntohs((u_short)tvu->ui_ulen);
111 if ((int)ti->ip_len != tlen) {
112 if (tlen > (int)ti->ip_len) {
117 m_adj(am, tlen - (int)ti->ip_len);
119 /* deliver packet to rx */
120 taddr.sin_family = AF_INET; /* compute source address */
121 taddr.sin_port = tu->uh_sport;
122 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
123 taddr.sin_len = sizeof(taddr);
124 tvu = (struct udpiphdr *) ti; /* virtual udp structure, for cksum */
125 /* handle the checksum. Note that this code damages the actual ip
126 header (replacing it with the virtual one, which is the same size),
127 so we must ensure we get everything out we need, first */
128 if ( tu->uh_sum != 0) {
129 /* if the checksum is there, always check it. It's crazy not
130 * to, unless you can really be sure that your
131 * underlying network (and interfaces and drivers and
132 * DMA hardware, etc!) is error-free. First, fill
133 * in entire virtual ip header. */
134 memset(tvu->ui_i.ih_x1, 0, 9);
135 tvu->ui_len = tvu->ui_ulen;
136 tlen = ntohs((unsigned short)(tvu->ui_ulen));
137 if (in_cksum(am, sizeof(struct ip) + tlen)) {
138 /* checksum, including cksum field, doesn't come out 0, so
139 this packet is bad */
147 * 28 is IP (20) + UDP (8) header. ulen includes
148 * udp header, and we *don't* tell RX about udp
149 * header either. So, we remove those 8 as well.
151 data_len = ntohs(tu->uh_ulen);
154 if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
155 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
156 /* XXX should just increment counter here.. */
157 printf("rx: truncated UDP packet\n");
158 rxi_FreePacket(phandle);
161 (*rxk_PacketArrivalProc)(phandle, &taddr,
162 rxk_portRocks[i], data_len);
171 /* if we get here, try to deliver packet to udp */
172 if (tproc = parent_proto.pr_input) (*tproc)(am,iphlen);
179 * UDP fast timer to raise events for all but Solaris and NCR.
180 * Called about 5 times per second (at unknown priority?). Must go to
181 * splnet or obtain global lock before touching anything significant.
183 static void rxk_fasttimo (void)
188 /* do rx fasttimo processing here */
189 rxevent_RaiseEvents(&temp);
190 if (tproc = parent_proto.pr_fasttimo) (*tproc)();
194 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
196 * Now, why do we allocate a new buffer when we could theoretically use the one
197 * pointed to by adata? Because PRU_SEND returns after queueing the message,
198 * not after sending it. If the sender changes the data after queueing it,
199 * we'd see the already-queued data change. One attempt to fix this without
200 * adding a copy would be to have this function wait until the datagram is
201 * sent; however this doesn't work well. In particular, if a host is down, and
202 * an ARP fails to that host, this packet will be queued until the ARP request
203 * comes back, which could be hours later. We can't block in this routine that
204 * long, since it prevents RPC timeouts from happening.
206 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
207 * and just queue those. XXX
210 /* set lock on sockbuf sb; can't call sblock since we're at interrupt level
213 register struct sockbuf *sb; {
214 AFS_STATCNT(trysblock);
215 if (sb->sb_flags & SB_LOCK){
216 return -1; /* can't lock socket */
218 sb->sb_flags |= SB_LOCK;
223 osi_NetSend(asocket, addr, dvec, nvec, asize, istack)
224 register struct socket *asocket;
227 register afs_int32 asize;
228 struct sockaddr_in *addr;
231 register struct mbuf *tm, *um;
232 register afs_int32 code;
234 struct mbuf *top = 0;
235 register struct mbuf *m, **mp;
243 AFS_STATCNT(osi_NetSend);
245 /* Actually, the Ultrix way is as good as any for us, so we don't bother with
246 * special mbufs any more. Used to think we could get away with not copying
247 * the data to the interface, but there's no way to tell the caller not to
248 * reuse the buffers after sending, so we lost out on that trick anyway */
253 tdata = dvec[i].iov_base;
254 tl = dvec[i].iov_len;
258 MGETHDR(m, M_DONTWAIT, MT_DATA);
265 m->m_pkthdr.rcvif = (struct ifnet *)0;
267 MGET(m, M_DONTWAIT, MT_DATA);
269 /* can't get an mbuf, give up */
270 if (top) m_freem(top); /* free mbuf list we're building */
275 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
276 * `NBPG', which may have no relation to `CLBYTES'. Also, `CLBYTES'
277 * may be so large that we never use clusters, resulting in far
278 * too many mbufs being used. It is often better to briefly use
279 * a cluster, even if we are only using a portion of it. Since
280 * we are on the xmit side, it shouldn't end up sitting on a queue
281 * for a potentially unbounded time (except perhaps if we are talking
284 if (asize >= 4 * MLEN) { /* try to get cluster mbuf */
285 register struct mbuf *p;
287 /* different algorithms for getting cluster mbuf */
288 MCLGET(m, M_DONTWAIT);
289 if ((m->m_flags & M_EXT) == 0)
293 /* now compute usable size */
294 len = MIN(mlen, asize);
295 /* Should I look at MAPPED_MBUFS??? */
298 len = MIN(mlen, asize);
302 top->m_pkthdr.len += len;
303 tpa = mtod(m, caddr_t);
306 bcopy(tdata, tpa, rlen);
316 /* shouldn't come here! */
317 asize = 0; /* so we make progress toward completion */
320 tdata = dvec[i].iov_base;
321 tl = dvec[i].iov_len;
331 tm->m_act = (struct mbuf *) 0;
333 /* setup mbuf corresponding to destination address */
334 um = m_get(M_DONTWAIT, MT_SONAME);
336 if (top) m_freem(top); /* free mbuf chain */
337 /* if this were vfs40, we'd do sbunlock(asocket, &asocket->so_snd), but
338 we don't do the locking at all for vfs40 systems */
342 bcopy(addr, mtod(um, caddr_t), sizeof(*addr));
343 um->m_len = sizeof(*addr);
344 /* note that udp_usrreq frees funny mbuf. We hold onto data, but mbuf
345 * around it is gone. we free address ourselves. */
346 /* haveGlock = ISAFS_GLOCK();
350 /* SOCKET_LOCK(asocket); */
351 /* code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0); */
352 code = (*asocket->so_proto->pr_usrreqs->pru_send)(asocket, 0, tm,
353 (struct sockaddr *) addr,
355 /* SOCKET_UNLOCK(asocket); */
365 #endif /* AFS_FBSD40_ENV */