1 /* This file is bootstrapped from the RX release cleared by Transarc legal
2 in 1994, available from ftp.dementia.org/pub/rx
6 #include "../afs/param.h"
10 #include "../h/types.h"
11 #include "../h/param.h"
12 #include "../rx/rx_kcommon.h"
13 #include "../h/user.h"
14 #include "../h/tihdr.h"
17 /* Define this here, used externally */
18 #ifdef RX_ENABLE_LOCKS
24 * XXX The following is needed since the include file that contains them (<net/cko.h>)
25 * isn't part of a binary distribution!! XXXX
28 /* CKO_PSEUDO : Account for pseudo_header in the checksum */
30 #define CKO_SUM_MASK 0xffff /* sum is in lower 16 bits */
34 #define CKO_PSEUDO(sum, m, hdr) { \
35 (sum) = 0xffff ^ in_3sum( ((struct ipovly *)(hdr))->ih_src.s_addr, \
36 ((struct ipovly *)(hdr))->ih_dst.s_addr, \
37 ((struct ipovly *)(hdr))->ih_len \
38 + (((struct ipovly *)(hdr))->ih_pr<<16) \
39 + ((m)->m_quad[MQ_CKO_IN] & CKO_SUM_MASK)); \
43 static struct protosw parent_proto; /* udp proto switch */
46 static int rxk_fasttimo (void)
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) code = (*tproc)();
62 /* hybrid of IRIX/knet.c and rx_kern.c */
63 /* XXX should this be listener or !listener? */
64 #if !defined(RXK_LISTENER_ENV)
65 /* start intercepting basic calls */
68 register struct protosw *tpro, *last;
69 if (rxk_initDone) return 0;
71 last = inetdomain.dom_protoswNPROTOSW;
72 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++) {
73 if (tpro->pr_protocol == IPPROTO_UDP) {
74 /* force UDP checksumming on for AFS */
77 memcpy(&parent_proto, tpro, sizeof(parent_proto));
78 tpro->pr_input = rxk_input;
79 tpro->pr_fasttimo = rxk_fasttimo;
84 osi_Panic("inet:no udp");
87 /* basic packet handling routine called at splnet from softnet loop */
88 static struct mbuf *rxk_input (register struct mbuf *am, struct ifnet *aif)
91 register unsigned short *tsp;
94 register struct ip *ti;
99 struct sockaddr_in taddr;
103 unsigned int comp_sum;
107 /* make sure we have base ip and udp headers in first mbuf */
108 if (am->m_off > MMAXOFF || am->m_len < 28) {
109 am = m_pullup(am, 28);
111 if (!am) return NULL;
113 hdr = (mtod(am, struct ip *))->ip_hl;
115 /* pull up more, the IP hdr is bigger than usual */
116 if (am->m_len < (8 + (hdr<<2))) {
117 am = m_pullup(am, 8+(hdr<<2));
119 if (!am) return NULL;
121 ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
122 tu = (struct udphdr *)(((char *)ti) + (hdr<<2)); /* skip ip hdr */
125 ti = mtod(am, struct ip *);
126 tu = (struct udphdr *)(((char *)ti) + 20); /* skip basic ip hdr */
128 /* now read the port out */
132 for(tsp=ports, i=0; i<MAXRXPORTS;i++) {
133 if (*tsp++ == port) {
134 /* checksum the packet */
135 ip_stripoptions(ti, NULL); /* get rid of anything we don't need */
136 /* deliver packet to rx */
137 taddr.sin_family = AF_INET; /* compute source address */
138 taddr.sin_port = tu->uh_sport;
139 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
141 /* handle the checksum. Note that this code damages the actual ip
142 header (replacing it with the virtual one, which is the same
143 size), so we must ensure we get everything out we need, first */
144 tvu = (struct udpiphdr *) ti; /* virtual udp structure, for ck
146 if ( tu->uh_sum != 0) {
147 /* if the checksum is there, always check it. It's crazy not
148 * to, unless you can really be sure that your
149 * underlying network (and interfaces and drivers and
150 * DMA hardware, etc!) is error-free. First, fill
151 * in entire virtual ip header. */
155 tvu->ui_len = tvu->ui_ulen;
156 tlen = ntohs((unsigned short)(tvu->ui_ulen));
157 /* HP: checksum assist for cksum offloading drivers */
158 if (am->m_flags & MF_CKO_IN) {
159 CKO_PSEUDO(comp_sum, am, tvu);
163 comp_sum = in_cksum(am, sizeof(struct ip) + tlen);
164 for (m1 = am; m1; m1 = m1->m_next)
165 m1->m_flags &= ~MF_NOACC;
168 /* checksum, including cksum field, doesn't come out 0, so
169 this packet is bad */
176 * 28 is IP (20) + UDP (8) header. ulen includes
177 * udp header, and we *don't* tell RX about udp
178 * header either. So, we remove those 8 as well.
180 data_len = ntohs(tu->uh_ulen);
183 if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
184 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
185 /* XXX should just increment counter here.. */
186 printf("rx: truncated UDP packet\n");
187 rxi_FreePacket(phandle);
190 (*rxk_PacketArrivalProc)(phandle, &taddr,
191 portRocks[i], data_len);
200 /* if we get here, try to deliver packet to udp */
201 if (tproc = parent_proto.pr_input) {
202 code = (*tproc)(am,aif);
209 #endif /* ! RXK_LISTENER_ENV */
211 /* steal decl from sgi_65 */
212 int osi_NetSend(register struct socket *asocket, struct sockaddr_in *addr,
213 struct iovec *dvec, int nvec, register afs_int32 asize, int istack)
217 struct iovec temp[RX_MAXWVECS];
219 int size = sizeof(struct sockaddr_in);
221 /* Guess based on rxk_NewSocket */
222 bp = allocb((size+SO_MSGOFFSET+1), BPRI_MED);
223 if (!bp) return ENOBUFS;
224 memcpy((caddr_t)bp->b_rptr+SO_MSGOFFSET, (caddr_t)addr, size);
225 bp->b_wptr = bp->b_rptr + (size+SO_MSGOFFSET+1);
227 memcpy((caddr_t)temp, (caddr_t)dvec, nvec * sizeof(struct iovec));
229 /* devresource.hp.com/Drivers/Docs/Refs/11i/ddRef/Chap02R.pdf has details
231 memset((caddr_t)&uio, 0, sizeof(uio));
232 uio.uio_resid = asize;
234 uio.uio_iovcnt = nvec;
235 uio.uio_seg = UIOSEG_KERNEL;
237 code = sosend(asocket, bp, &uio, 0, 0, 0, size);
241 /* pattern from IRIX */
242 #if defined(RXK_LISTENER_ENV)
243 int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
244 int nvecs, int *alength)
248 struct iovec tmpvec[RX_MAXWVECS+2];
252 if (nvecs > RX_MAXWVECS+2) {
253 osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", nvecs);
255 memcpy(tmpvec, (char*)dvec, nvecs/*(RX_MAXWVECS+1)*/ * sizeof(struct iovec));
256 tuio.uio_iov = tmpvec;
257 tuio.uio_iovcnt = nvecs;
258 tuio.uio_fpflags = 0;
260 tuio.uio_seg = UIOSEG_KERNEL;
261 tuio.uio_resid = *alength;
263 code = soreceive(so, &bp, &tuio, &flags, &sp, (MBLKPP)NULL);
265 *alength = *alength - tuio.uio_resid;
267 memcpy((char*)addr, (char*)bp->b_rptr, sizeof(struct sockaddr_in));