Standardize License information
[openafs.git] / src / rx / LINUX / 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 /*
11  * rx_knet.c - RX kernel send, receive and timer routines.
12  *
13  * Linux implementation.
14  */
15 #include "../afs/param.h"
16 #ifdef AFS_LINUX22_ENV
17 #include "../rx/rx_kcommon.h"
18 #include <asm/uaccess.h>
19
20 /* rxk_NewSocket
21  * open and bind RX socket
22  */
23 struct osi_socket *rxk_NewSocket(short aport)
24 {
25     struct socket *sockp;
26     struct sockaddr_in myaddr;
27     int code;
28
29     
30     code = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sockp);
31     if (code<0)
32         return NULL;
33
34     /* Bind socket */
35     myaddr.sin_family = AF_INET;
36     myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
37     myaddr.sin_port = aport;
38     code = sockp->ops->bind(sockp, (struct sockaddr*)&myaddr, sizeof(myaddr));
39
40     if (code<0) {
41         sock_release(sockp);
42         return NULL;
43     }
44
45     return (struct osi_socket*)sockp;
46 }
47
48
49 /* free socket allocated by osi_NetSocket */
50 int rxk_FreeSocket(asocket)
51     register struct socket *asocket;
52 {
53     AFS_STATCNT(osi_FreeSocket);
54     return 0;
55 }
56
57
58 /* osi_NetSend
59  *
60  * Return codes:
61  * 0 = success
62  * non-zero = failure
63  */
64 int osi_NetSend(struct socket *sop, struct sockaddr_in *to,
65                 struct iovec *iov, int iovcnt, int size, int istack)
66 {
67     KERNEL_SPACE_DECL;
68     struct msghdr msg;
69     int code;
70     struct iovec tmpvec[RX_MAXWVECS+2];
71
72     if (iovcnt > RX_MAXWVECS+2) {
73         osi_Panic("Too many (%d) iovecs passed to osi_NetSend\n", iovcnt);
74     }
75
76     if (iovcnt <= 2) { /* avoid pointless uiomove */
77         tmpvec[0].iov_base = iov[0].iov_base;
78         tmpvec[0].iov_len = size;
79         msg.msg_iovlen = 1;
80     }
81     else {
82         memcpy(tmpvec, iov, iovcnt * sizeof(struct iovec));
83         msg.msg_iovlen = iovcnt;
84     }
85     msg.msg_iov = tmpvec;
86     msg.msg_name = to;
87     msg.msg_namelen = sizeof(*to);
88     msg.msg_control = NULL;
89     msg.msg_controllen = 0;
90     msg.msg_flags = 0;
91
92     TO_USER_SPACE();
93     code = sock_sendmsg(sop, &msg, size);
94     TO_KERNEL_SPACE();
95     return (code<0) ? code : 0;
96 }
97
98
99 /* osi_NetReceive
100  * OS dependent part of kernel RX listener thread.
101  *
102  * Arguments:
103  *      so      socket to receive on, typically rx_socket
104  *      from    pointer to a sockaddr_in. 
105  *      iov     array of iovecs to fill in.
106  *      iovcnt  how many iovecs there are.
107  *      lengthp IN/OUT in: total space available in iovecs. out: size of read.
108  *
109  * Return
110  * 0 if successful
111  * error code (such as EINTER) if not
112  *
113  * Environment
114  *      Note that the maximum number of iovecs is 2 + RX_MAXWVECS. This is
115  *      so we have a little space to look for packets larger than 
116  *      rx_maxReceiveSize.
117  */
118 int rxk_lastSocketError;
119 int rxk_nSocketErrors;
120 int osi_NetReceive(osi_socket so, struct sockaddr_in *from, 
121                    struct iovec *iov, int iovcnt, int *lengthp)
122 {
123     KERNEL_SPACE_DECL;
124     struct msghdr msg;
125     int code;
126     struct iovec tmpvec[RX_MAXWVECS+2];
127     struct socket *sop = (struct socket*)so;
128
129     if (iovcnt > RX_MAXWVECS+2) {
130         osi_Panic("Too many (%d) iovecs passed to osi_NetReceive\n", iovcnt);
131     }
132     memcpy(tmpvec, iov, iovcnt * sizeof(struct iovec));
133     msg.msg_name = from;
134     msg.msg_iov = tmpvec;
135     msg.msg_iovlen = iovcnt;
136     msg.msg_control = NULL;
137     msg.msg_controllen = 0;
138     msg.msg_flags = 0;
139
140     TO_USER_SPACE();
141     code = sock_recvmsg(sop, &msg, *lengthp, 0);
142     TO_KERNEL_SPACE();
143
144     if (code<0) {
145         /* Clear the error before using the socket again.
146          * Oh joy, Linux has hidden header files as well. It appears we can
147          * simply call again and have it clear itself via sock_error().
148          */
149 #ifdef AFS_LINUX22_ENV
150         flush_signals(current); /* We don't want no stinkin' signals. */
151 #else
152         current->signal = 0; /* We don't want no stinkin' signals. */
153 #endif
154         rxk_lastSocketError = code;
155         rxk_nSocketErrors ++ ;
156     }
157     else {
158         *lengthp = code;
159         code = 0;
160     }
161
162     return code;
163 }
164
165 void osi_StopListener(void)
166 {
167     extern int (*sys_killp)();
168     extern int rxk_ListenerPid;
169
170     if (rxk_ListenerPid) {
171         (void) (*sys_killp)(rxk_ListenerPid, 9);
172         rxk_ListenerPid = 0;
173     }
174     sock_release(rx_socket);
175     rx_socket = NULL;
176 }
177
178 #endif /* AFS_LINUX22_ENV */