convert-from-bsd-to-posix-string-and-memory-functions-20010807
[openafs.git] / src / rx / DARWIN / rx_knet.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 #include "../rx/rx_kcommon.h"
16
17 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
18     struct socket *asocket;
19     struct sockaddr_in *addr;
20     struct iovec *dvec;
21     int nvecs;
22     int *alength;
23 {
24     struct uio u;
25     int i;
26     struct iovec iov[RX_MAXIOVECS];
27     struct sockaddr *sa;
28     int code;
29
30     int haveGlock = ISAFS_GLOCK();
31     /*AFS_STATCNT(osi_NetReceive);*/
32
33     if (nvecs > RX_MAXIOVECS) {
34         osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
35     }
36
37     for (i = 0 ; i < nvecs ; i++) {
38         iov[i].iov_base = dvec[i].iov_base;
39         iov[i].iov_len = dvec[i].iov_len;
40     }
41
42     u.uio_iov=&iov[0];
43     u.uio_iovcnt=nvecs;
44     u.uio_offset=0;
45     u.uio_resid=*alength;
46     u.uio_segflg=UIO_SYSSPACE; 
47     u.uio_rw=UIO_READ;
48     u.uio_procp=NULL;  
49
50     if (haveGlock) { 
51         AFS_GUNLOCK();
52     }
53 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
54     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
55 #endif
56     code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
57 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
58     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
59 #endif
60     if (haveGlock) {
61         AFS_GLOCK();
62     }
63     *alength=*alength-u.uio_resid;
64     if (sa) {
65        if (sa->sa_family == AF_INET) {
66           if (addr) *addr=*(struct sockaddr_in *)sa;
67        } else {
68           printf("Unknown socket family %d in NetReceive\n");
69        }
70     }
71     return code;
72 }
73
74 extern int rxk_ListenerPid;
75 void osi_StopListener(void)
76 {
77    struct proc *p;
78
79 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
80     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
81 #endif
82    soclose(rx_socket);
83 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
84     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
85 #endif
86    p=pfind(rxk_ListenerPid); 
87    if (p)
88        psignal(p, SIGUSR1);
89 }
90
91 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
92  *
93  * Now, why do we allocate a new buffer when we could theoretically use the one
94  * pointed to by adata?  Because PRU_SEND returns after queueing the message,
95  * not after sending it.  If the sender changes the data after queueing it,
96  * we'd see the already-queued data change.  One attempt to fix this without
97  * adding a copy would be to have this function wait until the datagram is
98  * sent; however this doesn't work well.  In particular, if a host is down, and
99  * an ARP fails to that host, this packet will be queued until the ARP request
100  * comes back, which could be hours later.  We can't block in this routine that
101  * long, since it prevents RPC timeouts from happening.
102  */
103 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
104  * and just queue those.  XXX
105  */
106
107
108 int 
109 osi_NetSend(asocket, addr, dvec, nvecs, alength, istack)
110      register struct socket *asocket;
111      struct iovec *dvec;
112      int nvecs;
113      register afs_int32 alength;
114      struct sockaddr_in *addr;
115      int istack;
116 {
117     register afs_int32 code;
118     int s;
119     int len;
120     int i;
121     struct iovec iov[RX_MAXIOVECS];
122     char *tdata;
123     struct uio u;
124     struct mbuf *nam;
125     int haveGlock = ISAFS_GLOCK();
126
127     AFS_STATCNT(osi_NetSend);
128     if (nvecs > RX_MAXIOVECS) {
129         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
130     } 
131
132     for (i = 0 ; i < nvecs ; i++) {
133         iov[i].iov_base = dvec[i].iov_base; 
134         iov[i].iov_len = dvec[i].iov_len; 
135     } 
136
137     u.uio_iov=&iov[0];
138     u.uio_iovcnt=nvecs;
139     u.uio_offset=0;
140     u.uio_resid=alength;
141     u.uio_segflg=UIO_SYSSPACE;
142     u.uio_rw=UIO_WRITE;
143     u.uio_procp=NULL;
144     if (haveGlock) {
145         AFS_GUNLOCK();
146     }
147 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
148     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
149 #endif
150     nam=m_get(M_DONTWAIT, MT_SONAME);
151     if (nam == NULL) {
152         code=ENOBUFS;
153         goto bad;
154     }
155     nam->m_len=addr->sin_len=sizeof(struct sockaddr_in);
156     memcpy(mtod(nam, caddr_t), (caddr_t)addr, addr->sin_len);
157     code = sosend(asocket, mtod(nam, struct sockaddr *), &u, NULL, NULL, 0);
158     m_freem(nam);
159 bad:
160 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
161     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
162 #endif
163     if (haveGlock) {
164         AFS_GLOCK();
165     }
166     return code;
167 }