1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include <net_buffer.h> 11 #include <net_datalink.h> 12 #include <net_protocol.h> 13 #include <net_stack.h> 14 15 #include <KernelExport.h> 16 #include <util/list.h> 17 18 #include <netinet/in.h> 19 #include <netinet/ip.h> 20 #include <new> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <lock.h> 25 #include <util/AutoLock.h> 26 #include <util/khash.h> 27 28 #include <NetBufferUtilities.h> 29 #include <NetUtilities.h> 30 31 #define TRACE_TCP 32 #ifdef TRACE_TCP 33 # define TRACE(x) dprintf x 34 # define TRACE_BLOCK(x) dump_block x 35 #else 36 # define TRACE(x) 37 # define TRACE_BLOCK(x) 38 #endif 39 40 41 #define MAX_HASH_TCP 64 42 43 static net_domain *sDomain; 44 static net_address_module_info *sAddressModule; 45 net_buffer_module_info *sBufferModule; 46 static net_datalink_module_info *sDatalinkModule; 47 static net_stack_module_info *sStackModule; 48 static hash_table *sTCPHash; 49 static benaphore sTCPLock; 50 51 #include "tcp.h" 52 #include "TCPConnection.h" 53 54 55 net_protocol * 56 tcp_init_protocol(net_socket *socket) 57 { 58 socket->protocol = IPPROTO_TCP; 59 TCPConnection *protocol = new (std::nothrow) TCPConnection(socket); 60 if (protocol == NULL) 61 return NULL; 62 63 TRACE(("Created new TCPConnection %p\n", protocol)); 64 return protocol; 65 } 66 67 68 status_t 69 tcp_uninit_protocol(net_protocol *protocol) 70 { 71 delete (TCPConnection *)protocol; 72 return B_OK; 73 } 74 75 76 status_t 77 tcp_open(net_protocol *protocol) 78 { 79 return ((TCPConnection *)protocol)->Open(); 80 } 81 82 83 status_t 84 tcp_close(net_protocol *protocol) 85 { 86 return ((TCPConnection *)protocol)->Close(); 87 } 88 89 90 status_t 91 tcp_free(net_protocol *protocol) 92 { 93 return ((TCPConnection *)protocol)->Free(); 94 } 95 96 97 status_t 98 tcp_connect(net_protocol *protocol, const struct sockaddr *address) 99 { 100 return ((TCPConnection *)protocol)->Connect(address); 101 } 102 103 104 status_t 105 tcp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 106 { 107 return ((TCPConnection *)protocol)->Accept(_acceptedSocket); 108 } 109 110 111 status_t 112 tcp_control(net_protocol *protocol, int level, int option, void *value, 113 size_t *_length) 114 { 115 return protocol->next->module->control(protocol->next, level, option, 116 value, _length); 117 } 118 119 120 status_t 121 tcp_bind(net_protocol *protocol, struct sockaddr *address) 122 { 123 TRACE(("tcp_bind(%p) on address %s\n", protocol, 124 AddressString(sDomain, address, true).Data())); 125 TCPConnection *connection = (TCPConnection *)protocol; 126 return connection->Bind(address); 127 } 128 129 130 status_t 131 tcp_unbind(net_protocol *protocol, struct sockaddr *address) 132 { 133 return ((TCPConnection *)protocol)->Unbind(address); 134 } 135 136 137 status_t 138 tcp_listen(net_protocol *protocol, int count) 139 { 140 return ((TCPConnection *)protocol)->Listen(count); 141 } 142 143 144 status_t 145 tcp_shutdown(net_protocol *protocol, int direction) 146 { 147 return ((TCPConnection *)protocol)->Shutdown(direction); 148 } 149 150 151 status_t 152 tcp_send_data(net_protocol *protocol, net_buffer *buffer) 153 { 154 return protocol->next->module->send_data(protocol->next, buffer); 155 } 156 157 158 status_t 159 tcp_send_routed_data(net_protocol *protocol, struct net_route *route, 160 net_buffer *buffer) 161 { 162 return protocol->next->module->send_routed_data(protocol->next, route, buffer); 163 } 164 165 166 ssize_t 167 tcp_send_avail(net_protocol *protocol) 168 { 169 return ((TCPConnection *)protocol)->SendAvailable(); 170 } 171 172 173 status_t 174 tcp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 175 net_buffer **_buffer) 176 { 177 return ((TCPConnection *)protocol)->ReadData(numBytes, flags, _buffer); 178 } 179 180 181 ssize_t 182 tcp_read_avail(net_protocol *protocol) 183 { 184 return ((TCPConnection *)protocol)->ReadAvailable(); 185 } 186 187 188 struct net_domain * 189 tcp_get_domain(net_protocol *protocol) 190 { 191 return protocol->next->module->get_domain(protocol->next); 192 } 193 194 195 size_t 196 tcp_get_mtu(net_protocol *protocol, const struct sockaddr *address) 197 { 198 return protocol->next->module->get_mtu(protocol->next, address); 199 } 200 201 202 status_t 203 tcp_receive_data(net_buffer *buffer) 204 { 205 return B_ERROR; 206 } 207 208 209 status_t 210 tcp_error(uint32 code, net_buffer *data) 211 { 212 return B_ERROR; 213 } 214 215 216 status_t 217 tcp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code, 218 void *errorData) 219 { 220 return B_ERROR; 221 } 222 223 224 // #pragma mark - 225 226 227 static status_t 228 tcp_init() 229 { 230 status_t status; 231 232 #if 0 233 sDomain = sStackModule->get_domain(AF_INET); 234 sAddressModule = sDomain->address_module; 235 #endif 236 237 status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule); 238 if (status < B_OK) 239 return status; 240 status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&sBufferModule); 241 if (status < B_OK) 242 goto err1; 243 status = get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule); 244 if (status < B_OK) 245 goto err2; 246 247 sTCPHash = hash_init(MAX_HASH_TCP, TCPConnection::HashOffset(), 248 &TCPConnection::Compare, &TCPConnection::Hash); 249 if (sTCPHash == NULL) 250 goto err3; 251 252 status = benaphore_init(&sTCPLock, "TCP Hash Lock"); 253 if (status < B_OK) 254 goto err4; 255 256 status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_IP, 257 "network/protocols/tcp/v1", 258 "network/protocols/ipv4/v1", 259 NULL); 260 if (status < B_OK) 261 goto err5; 262 263 status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP, 264 "network/protocols/tcp/v1", 265 "network/protocols/ipv4/v1", 266 NULL); 267 if (status < B_OK) 268 goto err5; 269 270 status = sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP, 271 "network/protocols/tcp/v1"); 272 if (status < B_OK) 273 goto err5; 274 275 return B_OK; 276 277 err5: 278 benaphore_destroy(&sTCPLock); 279 err4: 280 hash_uninit(sTCPHash); 281 err3: 282 put_module(NET_DATALINK_MODULE_NAME); 283 err2: 284 put_module(NET_BUFFER_MODULE_NAME); 285 err1: 286 put_module(NET_STACK_MODULE_NAME); 287 288 TRACE(("init_tcp() fails with %lx (%s)\n", status, strerror(status))); 289 return status; 290 } 291 292 293 static status_t 294 tcp_uninit() 295 { 296 benaphore_destroy(&sTCPLock); 297 hash_uninit(sTCPHash); 298 put_module(NET_DATALINK_MODULE_NAME); 299 put_module(NET_BUFFER_MODULE_NAME); 300 put_module(NET_STACK_MODULE_NAME); 301 302 return B_OK; 303 } 304 305 306 static status_t 307 tcp_std_ops(int32 op, ...) 308 { 309 switch (op) { 310 case B_MODULE_INIT: 311 return tcp_init(); 312 313 case B_MODULE_UNINIT: 314 return tcp_uninit(); 315 316 default: 317 return B_ERROR; 318 } 319 } 320 321 322 net_protocol_module_info sTCPModule = { 323 { 324 "network/protocols/tcp/v1", 325 0, 326 tcp_std_ops 327 }, 328 tcp_init_protocol, 329 tcp_uninit_protocol, 330 tcp_open, 331 tcp_close, 332 tcp_free, 333 tcp_connect, 334 tcp_accept, 335 tcp_control, 336 tcp_bind, 337 tcp_unbind, 338 tcp_listen, 339 tcp_shutdown, 340 tcp_send_data, 341 tcp_send_routed_data, 342 tcp_send_avail, 343 tcp_read_data, 344 tcp_read_avail, 345 tcp_get_domain, 346 tcp_get_mtu, 347 tcp_receive_data, 348 tcp_error, 349 tcp_error_reply, 350 }; 351 352 module_info *modules[] = { 353 (module_info *)&sTCPModule, 354 NULL 355 }; 356