65fef1e09915529375fb6e7a95880d5d808fef02
[openafs.git] / src / rx / OBSD / 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(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
18                    int nvecs, int *alength)
19 {
20     struct uio u;
21     int i, code;
22     struct iovec iov[RX_MAXIOVECS];
23     struct sockaddr *sa;
24
25     int haveGlock = ISAFS_GLOCK();
26
27     if (nvecs > RX_MAXIOVECS)
28         osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
29
30     for (i = 0 ; i < nvecs ; i++) {
31         iov[i].iov_base = dvec[i].iov_base;
32         iov[i].iov_len = dvec[i].iov_len;
33     }
34
35     u.uio_iov = &iov[0];
36     u.uio_iovcnt = nvecs;
37     u.uio_offset = 0;
38     u.uio_resid = *alength;
39     u.uio_segflg = UIO_SYSSPACE;
40     u.uio_rw = UIO_READ;
41     u.uio_procp = NULL;
42
43     if (haveGlock)
44         AFS_GUNLOCK();
45     code = soreceive(asocket, (struct sockaddr_in *) &sa, &u, NULL, NULL, NULL);
46     if (haveGlock)
47         AFS_GLOCK();
48
49     *alength = *alength - u.uio_resid;
50     if (sa != NULL && sa->sa_family == AF_INET && addr != NULL)
51         *addr = *(struct sockaddr_in *)sa;
52
53     return code;
54 }
55
56 extern int rxk_ListenerPid;
57 void osi_StopListener(void)
58 {
59    struct proc *p;
60
61    soclose(rx_socket);
62    p = pfind(rxk_ListenerPid);
63    if (p)
64        psignal(p, SIGUSR1);
65 }
66
67 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
68  *
69  * Now, why do we allocate a new buffer when we could theoretically use the one
70  * pointed to by adata?  Because PRU_SEND returns after queueing the message,
71  * not after sending it.  If the sender changes the data after queueing it,
72  * we'd see the already-queued data change.  One attempt to fix this without
73  * adding a copy would be to have this function wait until the datagram is
74  * sent; however this doesn't work well.  In particular, if a host is down, and
75  * an ARP fails to that host, this packet will be queued until the ARP request
76  * comes back, which could be hours later.  We can't block in this routine that
77  * long, since it prevents RPC timeouts from happening.
78  */
79 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
80  * and just queue those.  XXX
81  */
82
83
84 int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
85                 struct iovec *dvec, int nvecs, afs_int32 alength, int istack)
86 {
87     int i, code;
88     struct iovec iov[RX_MAXIOVECS];
89     struct uio u;
90     struct mbuf *nam;
91     int haveGlock = ISAFS_GLOCK();
92
93     AFS_STATCNT(osi_NetSend);
94     if (nvecs > RX_MAXIOVECS)
95         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
96
97     for (i = 0; i < nvecs; i++) {
98         iov[i].iov_base = dvec[i].iov_base;
99         iov[i].iov_len = dvec[i].iov_len;
100     }
101
102     u.uio_iov = &iov[0];
103     u.uio_iovcnt = nvecs;
104     u.uio_offset = 0;
105     u.uio_resid = alength;
106     u.uio_segflg = UIO_SYSSPACE;
107     u.uio_rw = UIO_WRITE;
108     u.uio_procp = NULL;
109     if (haveGlock)
110         AFS_GUNLOCK();
111
112     nam = m_get(M_DONTWAIT, MT_SONAME);
113     if (nam == NULL) {
114         code = ENOBUFS;
115         goto bad;
116     }
117     nam->m_len = addr->sin_len = sizeof(struct sockaddr_in);
118     memcpy(mtod(nam, caddr_t), (caddr_t)addr, addr->sin_len);
119     code = sosend(asocket, mtod(nam, struct sockaddr_in *), &u, NULL, NULL, 0);
120     m_freem(nam);
121
122 bad:
123     if (haveGlock)
124         AFS_GLOCK();
125
126     return code;
127 }