death to register
[openafs.git] / src / rx / HPUX / rx_knet.c
1 /* This file is bootstrapped from the RX release cleared by Transarc legal
2    in 1994, available from ftp.dementia.org/pub/rx 
3  */
4
5 #include <afsconfig.h>
6 #include "afs/param.h"
7
8
9 #include "h/types.h"
10 #include "h/param.h"
11 #include "rx/rx_kcommon.h"
12 #include "h/user.h"
13 #include "h/tihdr.h"
14 #include <xti.h>
15
16 /* Define this here, used externally */
17 #ifdef RX_ENABLE_LOCKS
18 lock_t *rx_sleepLock;
19 #endif
20
21 /* rx_kern.c */
22 /*
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
25  */
26
27 /* CKO_PSEUDO : Account for pseudo_header in the checksum               */
28 #ifndef CKO_SUM_MASK
29 #define CKO_SUM_MASK        0xffff      /* sum is in lower 16 bits      */
30 #endif
31
32 #ifndef CKO_PSEUDO
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));             \
39 }
40 #endif
41
42 static struct protosw parent_proto;     /* udp proto switch */
43
44 /* rx_kern.c */
45 static int
46 rxk_fasttimo(void)
47 {
48     int code;
49     int (*tproc) ();
50     struct clock temp;
51
52     SPLVAR;
53     NETPRI;
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)
58         code = (*tproc) ();
59     else
60         code = 0;
61     return code;
62 }
63
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 */
68 int
69 rxk_init()
70 {
71     struct protosw *tpro, *last;
72     if (rxk_initDone)
73         return 0;
74
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        */
79             int udpcksum;
80             udpcksum = 1;
81             memcpy(&parent_proto, tpro, sizeof(parent_proto));
82             tpro->pr_input = rxk_input;
83             tpro->pr_fasttimo = rxk_fasttimo;
84             rxk_initDone = 1;
85             return 0;
86         }
87     }
88     osi_Panic("inet:no udp");
89 }
90
91 /* basic packet handling routine called at splnet from softnet loop */
92 static struct mbuf *
93 rxk_input(struct mbuf *am, struct ifnet *aif)
94 {
95     int (*tproc) ();
96     unsigned short *tsp;
97     int hdr;
98     struct udphdr *tu;
99     struct ip *ti;
100     struct udpiphdr *tvu;
101     int i;
102     char *phandle;
103     afs_int32 code;
104     struct sockaddr_in taddr;
105     int tlen;
106     short port;
107     int data_len;
108     unsigned int comp_sum;
109
110     SPLVAR;
111     NETPRI;
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);
115         USERPRI;
116         if (!am)
117             return NULL;
118     }
119     hdr = (mtod(am, struct ip *))->ip_hl;
120     if (hdr > 5) {
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));
124             USERPRI;
125             if (!am)
126                 return NULL;
127         }
128         ti = mtod(am, struct ip *);     /* recompute, since m_pullup allocates new mbuf */
129         tu = (struct udphdr *)(((char *)ti) + (hdr << 2));      /* skip ip hdr */
130     } else {
131         ti = mtod(am, struct ip *);
132         tu = (struct udphdr *)(((char *)ti) + 20);      /* skip basic ip hdr */
133     }
134     /* now read the port out */
135     port = tu->uh_dport;
136
137     if (port) {
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;
146
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
151                                                  * sum */
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. */
158                     tvu->ui_next = 0;
159                     tvu->ui_prev = 0;
160                     tvu->ui_x1 = 0;
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);
166                     } else {
167                         struct mbuf *m1;
168
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;
172                     }
173                     if (comp_sum) {
174                         /* checksum, including cksum field, doesn't come out 0, so
175                          * this packet is bad */
176                         m_freem(am);
177                         USERPRI;
178                         return (NULL);
179                     }
180                 }
181                 /*
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.
185                  */
186                 data_len = ntohs(tu->uh_ulen);
187                 data_len -= 8;
188
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);
194                     } else
195                         (*rxk_PacketArrivalProc) (phandle, &taddr,
196                                                   portRocks[i], data_len);
197                 } else
198                     m_freem(am);
199                 USERPRI;
200                 return (NULL);
201             }
202         }
203     }
204
205     /* if we get here, try to deliver packet to udp */
206     if (tproc = parent_proto.pr_input) {
207         code = (*tproc) (am, aif);
208         USERPRI;
209         return code;
210     }
211     USERPRI;
212     return (NULL);
213 }
214 #endif /* ! RXK_LISTENER_ENV */
215
216 /* steal decl from sgi_65 */
217 int
218 osi_NetSend(struct socket *asocket, struct sockaddr_in *addr,
219             struct iovec *dvec, int nvec, afs_int32 asize,
220             int istack)
221 {
222     struct uio uio;
223     MBLKP bp;
224     struct iovec temp[RX_MAXWVECS];
225     int code;
226     int size = sizeof(struct sockaddr_in);
227
228     /* Guess based on rxk_NewSocket */
229     bp = allocb((size + SO_MSGOFFSET + 1), BPRI_MED);
230     if (!bp)
231         return ENOBUFS;
232     memcpy((caddr_t) bp->b_rptr + SO_MSGOFFSET, (caddr_t) addr, size);
233     bp->b_wptr = bp->b_rptr + (size + SO_MSGOFFSET + 1);
234
235     memcpy((caddr_t) temp, (caddr_t) dvec, nvec * sizeof(struct iovec));
236
237     /* devresource.hp.com/Drivers/Docs/Refs/11i/ddRef/Chap02R.pdf has details
238      * on use of uio */
239     memset((caddr_t) & uio, 0, sizeof(uio));
240     uio.uio_resid = asize;
241     uio.uio_iov = temp;
242     uio.uio_iovcnt = nvec;
243     uio.uio_seg = UIOSEG_KERNEL;
244
245     code = sosend(asocket, bp, &uio, 0, 0, 0, size);
246     return code;
247 }
248
249 /* pattern from IRIX */
250 #if defined(RXK_LISTENER_ENV)
251 int
252 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
253                int nvecs, int *alength)
254 {
255     int code;
256     struct uio tuio;
257     struct iovec tmpvec[RX_MAXWVECS + 2];
258     int flags = 0;
259     MBLKP bp, sp;
260
261     if (nvecs > RX_MAXWVECS + 2) {
262         osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", nvecs);
263     }
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;
269     tuio.uio_offset = 0;
270     tuio.uio_seg = UIOSEG_KERNEL;
271     tuio.uio_resid = *alength;
272
273     code = soreceive(so, &bp, &tuio, &flags, &sp, (MBLKPP) NULL);
274     if (!code) {
275         *alength = *alength - tuio.uio_resid;
276         if (bp) {
277             memcpy((char *)addr, (char *)bp->b_rptr,
278                    sizeof(struct sockaddr_in));
279         } else {
280             code = -1;
281         }
282     } else {
283         so->so_error = 0;
284     }
285
286     if (bp)
287         freeb(bp);
288     if (sp)
289         freeb(sp);
290     return code;
291 }
292 #endif