pull-prototypes-to-head-20020821
[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 RCSID("$Header$");
9
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"
15 #include <xti.h>
16
17 /* Define this here, used externally */
18 #ifdef RX_ENABLE_LOCKS
19 lock_t *rx_sleepLock;
20 #endif
21
22 /* rx_kern.c */
23 /*
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
26  */
27
28 /* CKO_PSEUDO : Account for pseudo_header in the checksum               */
29 #ifndef CKO_SUM_MASK
30 #define CKO_SUM_MASK        0xffff      /* sum is in lower 16 bits      */
31 #endif
32
33 #ifndef CKO_PSEUDO
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));             \
40 }
41 #endif
42
43 static struct protosw parent_proto;     /* udp proto switch */
44
45 /* rx_kern.c */
46 static int 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) code = (*tproc)();
58     else code = 0;
59     return code;
60 }
61
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 */
66 int
67 rxk_init() {
68     register struct protosw *tpro, *last;
69     if (rxk_initDone) return 0;
70
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        */
75             int udpcksum;
76             udpcksum = 1;
77             memcpy(&parent_proto, tpro, sizeof(parent_proto));
78             tpro->pr_input = rxk_input;
79             tpro->pr_fasttimo = rxk_fasttimo;
80             rxk_initDone = 1;
81             return 0;
82         }
83     }
84     osi_Panic("inet:no udp");
85 }
86
87 /* basic packet handling routine called at splnet from softnet loop */
88 static struct mbuf *rxk_input (register struct mbuf *am, struct ifnet *aif)
89 {
90     int (*tproc)();
91     register unsigned short *tsp;
92     int hdr;
93     struct udphdr *tu;
94     register struct ip *ti;
95     struct udpiphdr *tvu;
96     register int i;
97     char *phandle;
98     afs_int32 code;
99     struct sockaddr_in taddr;
100     int tlen;
101     short port;
102     int data_len;
103     unsigned int comp_sum;
104
105     SPLVAR;
106     NETPRI;
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);
110         USERPRI;
111         if (!am) return NULL;
112     }
113     hdr = (mtod(am, struct ip *))->ip_hl;
114     if (hdr > 5) {
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));
118             USERPRI;
119             if (!am) return NULL;
120         }
121         ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
122         tu = (struct udphdr *)(((char *)ti) + (hdr<<2)); /* skip ip hdr */
123     }
124     else {
125         ti = mtod(am, struct ip *);
126         tu = (struct udphdr *)(((char *)ti) + 20);      /* skip basic ip hdr */
127     }
128     /* now read the port out */
129     port = tu->uh_dport;
130     
131     if (port) {
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;
140                 
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
145                                                    sum */
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. */
152                     tvu->ui_next = 0;
153                     tvu->ui_prev = 0;
154                     tvu->ui_x1 = 0;
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);
160                     } else {
161                         struct mbuf *m1;
162                         
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;
166                     }
167                     if (comp_sum) {
168                         /* checksum, including cksum field, doesn't come out 0, so
169                            this packet is bad */
170                         m_freem(am);
171                         USERPRI;
172                         return(NULL);
173                     }
174                 }
175                 /*
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.
179                  */
180                 data_len = ntohs(tu->uh_ulen);
181                 data_len -= 8;
182                   
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);
188                     }
189                     else 
190                         (*rxk_PacketArrivalProc)(phandle, &taddr,
191                                                  portRocks[i], data_len);
192                 }
193                 else m_freem(am);
194                 USERPRI;
195                 return(NULL);
196             }
197         }
198     }
199
200     /* if we get here, try to deliver packet to udp */
201     if (tproc = parent_proto.pr_input) {
202       code = (*tproc)(am,aif);
203       USERPRI;
204       return code;
205     }
206     USERPRI;
207     return(NULL);
208 }
209 #endif /* ! RXK_LISTENER_ENV */
210
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)
214 {
215     struct uio uio;
216     MBLKP bp;
217     struct iovec temp[RX_MAXWVECS];
218     int code;
219     int size = sizeof(struct sockaddr_in);
220
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);
226
227     memcpy((caddr_t)temp, (caddr_t)dvec, nvec * sizeof(struct iovec));
228     
229     /* devresource.hp.com/Drivers/Docs/Refs/11i/ddRef/Chap02R.pdf has details
230        on use of uio */
231     memset((caddr_t)&uio, 0, sizeof(uio));
232     uio.uio_resid   = asize;
233     uio.uio_iov     = temp;         
234     uio.uio_iovcnt  = nvec;
235     uio.uio_seg     = UIOSEG_KERNEL;
236
237     code = sosend(asocket, bp, &uio, 0, 0, 0, size);
238     return code;
239 }
240
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)
245 {   
246     int          code;
247     struct uio   tuio;
248     struct iovec tmpvec[RX_MAXWVECS+2];
249     int          flags = 0;
250     MBLKP bp, sp;
251
252     if (nvecs > RX_MAXWVECS+2) {
253         osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", nvecs);
254     }
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;
259     tuio.uio_offset  = 0;
260     tuio.uio_seg     = UIOSEG_KERNEL;
261     tuio.uio_resid   = *alength;
262
263     code = soreceive(so, &bp, &tuio, &flags, &sp, (MBLKPP)NULL);
264     if (!code) {
265         *alength = *alength - tuio.uio_resid;
266         if (bp) {
267             memcpy((char*)addr, (char*)bp->b_rptr, sizeof(struct sockaddr_in));
268         } else {
269             code = -1;
270         }
271     } else {
272         so->so_error = 0;
273     }
274
275     if (bp) freeb(bp); 
276     if (sp) freeb(sp);
277     return code;
278 }
279 #endif