r2581: added "hosts allow" and "hosts deny" checking in smbd. I needed this
[nivanova/samba-autobuild/.git] / source4 / lib / socket / socket.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Socket functions
4    Copyright (C) Stefan Metzmacher 2004
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags)
24 {
25         NTSTATUS status;
26
27         (*new_sock) = talloc_p(NULL, struct socket_context);
28         if (!(*new_sock)) {
29                 return NT_STATUS_NO_MEMORY;
30         }
31
32         (*new_sock)->type = type;
33         (*new_sock)->state = SOCKET_STATE_UNDEFINED;
34         (*new_sock)->flags = flags;
35
36         (*new_sock)->fd = -1;
37
38         (*new_sock)->private_data = NULL;
39         (*new_sock)->ops = socket_getops_byname(name, type);
40         if (!(*new_sock)->ops) {
41                 talloc_free((*new_sock));
42                 return NT_STATUS_INVALID_PARAMETER;
43         }
44
45         status = (*new_sock)->ops->init((*new_sock));
46         if (!NT_STATUS_IS_OK(status)) {
47                 talloc_free((*new_sock));
48                 return status;
49         }
50
51         return NT_STATUS_OK;
52 }
53
54 void socket_destroy(struct socket_context *sock)
55 {
56         if (sock->ops->close) {
57                 sock->ops->close(sock);
58         }
59         talloc_free(sock);
60 }
61
62 NTSTATUS socket_connect(struct socket_context *sock,
63                         const char *my_address, int my_port,
64                         const char *server_address, int server_port,
65                         uint32_t flags)
66 {
67         if (sock->type != SOCKET_TYPE_STREAM) {
68                 return NT_STATUS_INVALID_PARAMETER;
69         }
70
71         if (sock->state != SOCKET_STATE_UNDEFINED) {
72                 return NT_STATUS_INVALID_PARAMETER;
73         }
74
75         if (!sock->ops->connect) {
76                 return NT_STATUS_NOT_IMPLEMENTED;
77         }
78
79         return sock->ops->connect(sock, my_address, my_port, server_address, server_port, flags);
80 }
81
82 NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags)
83 {
84         if (sock->type != SOCKET_TYPE_STREAM) {
85                 return NT_STATUS_INVALID_PARAMETER;
86         }
87
88         if (sock->state != SOCKET_STATE_UNDEFINED) {
89                 return NT_STATUS_INVALID_PARAMETER;
90         }
91
92         if (!sock->ops->listen) {
93                 return NT_STATUS_NOT_IMPLEMENTED;
94         }
95
96         return sock->ops->listen(sock, my_address, port, queue_size, flags);
97 }
98
99 NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags)
100 {
101         if (sock->type != SOCKET_TYPE_STREAM) {
102                 return NT_STATUS_INVALID_PARAMETER;
103         }
104
105         if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
106                 return NT_STATUS_INVALID_PARAMETER;
107         }
108
109         if (!sock->ops->accept) {
110                 return NT_STATUS_NOT_IMPLEMENTED;
111         }
112
113         return sock->ops->accept(sock, new_sock, flags);
114 }
115
116 NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
117                         DATA_BLOB *blob, size_t wantlen, uint32_t flags)
118 {
119         if (sock->type != SOCKET_TYPE_STREAM) {
120                 return NT_STATUS_INVALID_PARAMETER;
121         }
122
123         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
124             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
125                 return NT_STATUS_INVALID_PARAMETER;
126         }
127
128         if (!sock->ops->recv) {
129                 return NT_STATUS_NOT_IMPLEMENTED;
130         }
131
132         return sock->ops->recv(sock, mem_ctx, blob, wantlen, flags);
133 }
134
135 NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
136                         const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
137 {
138         if (sock->type != SOCKET_TYPE_STREAM) {
139                 return NT_STATUS_INVALID_PARAMETER;
140         }
141
142         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
143             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
144                 return NT_STATUS_INVALID_PARAMETER;
145         }
146
147         if (!sock->ops->send) {
148                 return NT_STATUS_NOT_IMPLEMENTED;
149         }
150
151         return sock->ops->send(sock, mem_ctx, blob, sendlen, flags);
152 }
153
154 NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
155 {
156         if (!sock->ops->set_option) {
157                 return NT_STATUS_NOT_IMPLEMENTED;
158         }
159
160         return sock->ops->set_option(sock, option, val);
161 }
162
163 char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
164 {
165         if (!sock->ops->get_peer_name) {
166                 return NULL;
167         }
168
169         return sock->ops->get_peer_name(sock, mem_ctx);
170 }
171
172 char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
173 {
174         if (!sock->ops->get_peer_addr) {
175                 return NULL;
176         }
177
178         return sock->ops->get_peer_addr(sock, mem_ctx);
179 }
180
181 int socket_get_peer_port(struct socket_context *sock)
182 {
183         if (!sock->ops->get_peer_port) {
184                 return -1;
185         }
186
187         return sock->ops->get_peer_port(sock);
188 }
189
190 char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
191 {
192         if (!sock->ops->get_my_addr) {
193                 return NULL;
194         }
195
196         return sock->ops->get_my_addr(sock, mem_ctx);
197 }
198
199 int socket_get_my_port(struct socket_context *sock)
200 {
201         if (!sock->ops->get_my_port) {
202                 return -1;
203         }
204
205         return sock->ops->get_my_port(sock);
206 }
207
208 int socket_get_fd(struct socket_context *sock)
209 {
210         if (!sock->ops->get_fd) {
211                 return -1;
212         }
213
214         return sock->ops->get_fd(sock);
215 }
216
217 const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type)
218 {
219         if (strequal("ip", name) || strequal("ipv4", name)) {
220                 return socket_ipv4_ops();
221         }
222
223         return NULL;
224 }