1 /* This file is bootstrapped from the RX release cleared by Transarc legal
2 in 1994, available from ftp.dementia.org/pub/rx
11 #include "rx/rx_kcommon.h"
16 /* Define this here, used externally */
17 #ifdef RX_ENABLE_LOCKS
23 * XXX The following is needed since the include file that contains them (<net/cko.h>)
24 * isn't part of a binary distribution!! XXXX
27 /* CKO_PSEUDO : Account for pseudo_header in the checksum */
29 #define CKO_SUM_MASK 0xffff /* sum is in lower 16 bits */
33 #define CKO_PSEUDO(sum, m, hdr) { \
34 (sum) = 0xffff ^ in_3sum( ((struct ipovly *)(hdr))->ih_src.s_addr, \
35 ((struct ipovly *)(hdr))->ih_dst.s_addr, \
36 ((struct ipovly *)(hdr))->ih_len \
37 + (((struct ipovly *)(hdr))->ih_pr<<16) \
38 + ((m)->m_quad[MQ_CKO_IN] & CKO_SUM_MASK)); \
42 static struct protosw parent_proto; /* udp proto switch */
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)
64 /* hybrid of IRIX/knet.c and rx_kern.c */
65 /* XXX should this be listener or !listener? */
66 #if !defined(RXK_LISTENER_ENV)
67 /* start intercepting basic calls */
71 struct protosw *tpro, *last;
75 last = inetdomain.dom_protoswNPROTOSW;
76 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++) {
77 if (tpro->pr_protocol == IPPROTO_UDP) {
78 /* force UDP checksumming on for AFS */
81 memcpy(&parent_proto, tpro, sizeof(parent_proto));
82 tpro->pr_input = rxk_input;
83 tpro->pr_fasttimo = rxk_fasttimo;
88 osi_Panic("inet:no udp");
91 /* basic packet handling routine called at splnet from softnet loop */
93 rxk_input(struct mbuf *am, struct ifnet *aif)
100 struct udpiphdr *tvu;
104 struct sockaddr_in taddr;
108 unsigned int comp_sum;
112 /* make sure we have base ip and udp headers in first mbuf */
113 if (am->m_off > MMAXOFF || am->m_len < 28) {
114 am = m_pullup(am, 28);
119 hdr = (mtod(am, struct ip *))->ip_hl;
121 /* pull up more, the IP hdr is bigger than usual */
122 if (am->m_len < (8 + (hdr << 2))) {
123 am = m_pullup(am, 8 + (hdr << 2));
128 ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
129 tu = (struct udphdr *)(((char *)ti) + (hdr << 2)); /* skip ip hdr */
131 ti = mtod(am, struct ip *);
132 tu = (struct udphdr *)(((char *)ti) + 20); /* skip basic ip hdr */
134 /* now read the port out */
138 for (tsp = ports, i = 0; i < MAXRXPORTS; i++) {
139 if (*tsp++ == port) {
140 /* checksum the packet */
141 ip_stripoptions(ti, NULL); /* get rid of anything we don't need */
142 /* deliver packet to rx */
143 taddr.sin_family = AF_INET; /* compute source address */
144 taddr.sin_port = tu->uh_sport;
145 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
147 /* handle the checksum. Note that this code damages the actual ip
148 * header (replacing it with the virtual one, which is the same
149 * size), so we must ensure we get everything out we need, first */
150 tvu = (struct udpiphdr *)ti; /* virtual udp structure, for ck
152 if (tu->uh_sum != 0) {
153 /* if the checksum is there, always check it. It's crazy not
154 * to, unless you can really be sure that your
155 * underlying network (and interfaces and drivers and
156 * DMA hardware, etc!) is error-free. First, fill
157 * in entire virtual ip header. */
161 tvu->ui_len = tvu->ui_ulen;
162 tlen = ntohs((unsigned short)(tvu->ui_ulen));
163 /* HP: checksum assist for cksum offloading drivers */
164 if (am->m_flags & MF_CKO_IN) {
165 CKO_PSEUDO(comp_sum, am, tvu);
169 comp_sum = in_cksum(am, sizeof(struct ip) + tlen);
170 for (m1 = am; m1; m1 = m1->m_next)
171 m1->m_flags &= ~MF_NOACC;
174 /* checksum, including cksum field, doesn't come out 0, so
175 * this packet is bad */
182 * 28 is IP (20) + UDP (8) header. ulen includes
183 * udp header, and we *don't* tell RX about udp
184 * header either. So, we remove those 8 as well.
186 data_len = ntohs(tu->uh_ulen);
189 if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
190 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
191 /* XXX should just increment counter here.. */
192 printf("rx: truncated UDP packet\n");
193 rxi_FreePacket(phandle);
195 (*rxk_PacketArrivalProc) (phandle, &taddr,
196 portRocks[i], data_len);
205 /* if we get here, try to deliver packet to udp */
206 if (tproc = parent_proto.pr_input) {
207 code = (*tproc) (am, aif);
214 #endif /* ! RXK_LISTENER_ENV */
216 /* steal decl from sgi_65 */
218 osi_NetSend(struct socket *asocket, struct sockaddr_in *addr,
219 struct iovec *dvec, int nvec, afs_int32 asize,
224 struct iovec temp[RX_MAXWVECS];
226 int size = sizeof(struct sockaddr_in);
228 /* Guess based on rxk_NewSocket */
229 bp = allocb((size + SO_MSGOFFSET + 1), BPRI_MED);
232 memcpy((caddr_t) bp->b_rptr + SO_MSGOFFSET, (caddr_t) addr, size);
233 bp->b_wptr = bp->b_rptr + (size + SO_MSGOFFSET + 1);
235 memcpy((caddr_t) temp, (caddr_t) dvec, nvec * sizeof(struct iovec));
237 /* devresource.hp.com/Drivers/Docs/Refs/11i/ddRef/Chap02R.pdf has details
239 memset((caddr_t) & uio, 0, sizeof(uio));
240 uio.uio_resid = asize;
242 uio.uio_iovcnt = nvec;
243 uio.uio_seg = UIOSEG_KERNEL;
245 code = sosend(asocket, bp, &uio, 0, 0, 0, size);
249 /* pattern from IRIX */
250 #if defined(RXK_LISTENER_ENV)
252 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
253 int nvecs, int *alength)
257 struct iovec tmpvec[RX_MAXWVECS + 2];
261 if (nvecs > RX_MAXWVECS + 2) {
262 osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", nvecs);
264 memcpy(tmpvec, (char *)dvec,
265 nvecs /*(RX_MAXWVECS+1) */ * sizeof(struct iovec));
266 tuio.uio_iov = tmpvec;
267 tuio.uio_iovcnt = nvecs;
268 tuio.uio_fpflags = 0;
270 tuio.uio_seg = UIOSEG_KERNEL;
271 tuio.uio_resid = *alength;
273 code = soreceive(so, &bp, &tuio, &flags, &sp, (MBLKPP) NULL);
275 *alength = *alength - tuio.uio_resid;
277 memcpy((char *)addr, (char *)bp->b_rptr,
278 sizeof(struct sockaddr_in));