Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / core / net / socket.c
blob9cddf47072a80a3f689c169bbe1d9d76d0b58ae1
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <net/socket.h>
23 #include <system.h>
24 #include <string.h>
25 #include <task.h>
26 #include <dev.h>
27 #include <fd.h>
28 #include <errno.h>
30 socket_t socket_list;
32 extern task_t *_curr_task;
34 socket_t *socket_getbyfd (int fd)
36 socket_t *socket;
37 for (socket = socket_list.next; socket != &socket_list; socket = socket->next) {
38 if (socket->fd == fd)
39 return socket;
42 return 0;
45 int socket (int family, int type, int protocol)
47 /* alloc and init context */
48 socket_t *sock = (socket_t *) kmalloc (sizeof (socket_t));
50 if (!sock) {
51 errno_set (ENOMEM);
52 return -1;
55 sock->family = family;
56 sock->type = type;
57 sock->protocol = protocol;
59 fd_t *fd = fd_create (FD_SOCK);
61 if (!fd) {
62 kfree (sock);
63 return -1;
66 sock->fd = fd->id;
68 switch (sock->family) {
69 case AF_UNSPEC:
70 return -1;
71 case AF_UNIX:
72 net_proto_unix_socket (fd);
73 break;
74 case AF_INET:
75 switch (sock->protocol) {
76 case IPPROTO_TCP:
77 net_proto_tcp_socket (fd);
78 break;
79 case IPPROTO_UDP:
80 net_proto_udp_socket (fd);
81 break;
83 break;
84 case AF_INET6:
85 switch (sock->protocol) {
86 case IPPROTO_TCP:
87 net_proto_tcp6_socket (fd);
88 break;
89 case IPPROTO_UDP:
90 net_proto_udp6_socket (fd);
91 break;
93 break;
94 case AF_RS232:
95 sock->fd = ips_socket (fd);
96 break;
99 /* add into list */
100 sock->next = &socket_list;
101 sock->prev = socket_list.prev;
102 sock->prev->next = sock;
103 sock->next->prev = sock;
105 proc_t *proc = proc_find (_curr_task);
107 /* when it is process */
108 if (proc) {
109 if (proc->task != _curr_task)
110 return;
112 fd->proc = proc;
113 } else {
114 /* it is kernel socket */
115 fd->proc = 0;
118 DPRINT (DBG_NET | DBG_SOCKET, "socket () -> socket: %d", sock->fd);
120 return sock->fd;
123 hostent *gethostbyname (char *hostname)
125 unsigned i = 0;
126 unsigned g = 0;
127 unsigned l = strlen (hostname);
129 /* TODO: make better checking, that it is IPv6 addresss */
130 while (i < l) {
131 if (hostname[i] == ':')
132 g ++;
134 i ++;
137 unsigned target = 0;
138 unsigned short targetv6[8];
140 /* Is it an IPv6 address */
141 if (g == 7) {
142 if (!net_proto_ipv6_convert (targetv6, hostname))
143 return 0;
144 } else {
145 i = 0;
146 g = 0;
148 /* TODO: make better checking, that it is IPv4 addresss */
149 while (i < l) {
150 if (hostname[i] == '.')
151 g ++;
153 i ++;
157 /* it is dns address */
158 if (g != 3) {
159 if (dns_cache_get (hostname, &target, 4) != 1) /* check for ipv4 address */
160 if (dns_send_request (hostname, &target, 4) != 1) {
161 g = 7;
162 if (dns_cache_get (hostname, &targetv6, 16) != 1) { /* check for ipv6 address */
163 if (dns_send_request (hostname, &targetv6, 16) != 1)
164 return 0;
167 } else
168 target = net_proto_ip_convert (hostname);
170 if (!target)
171 return 0;
174 hostent *host = (hostent *) kmalloc (sizeof (hostent));
176 if (!host)
177 return 0;
179 memset (host, 0, sizeof (hostent));
181 /* IPv4 or IPv6 ? */
182 if (g == 7)
183 host->h_length = 16; /* IPv6 - 16 bytes */
184 else
185 host->h_length = 4; /* IPv4 - 4 bytes */
187 host->h_addr = (char *) kmalloc (sizeof (char) * host->h_length);
189 if (!host->h_addr) {
190 kfree (host);
191 return 0;
194 if (g == 7)
195 memcpy (host->h_addr, &targetv6, host->h_length);
196 else
197 memcpy (host->h_addr, &target, host->h_length);
199 return host;
202 int connect (int fd, sockaddr *addr, socklen_t len)
204 DPRINT (DBG_NET | DBG_SOCKET, "connect () -> socket: %d", fd);
205 socket_t *sock = socket_getbyfd (fd);
207 if (!sock)
208 return -1;
210 switch (sock->family) {
211 case AF_UNSPEC:
212 return -1;
213 case AF_UNIX:
214 return net_proto_unix_connect (fd, addr);
215 case AF_INET:
216 switch (sock->protocol) {
217 case IPPROTO_TCP:
218 return net_proto_tcp_connect (fd, (sockaddr_in *) addr);
219 case IPPROTO_UDP:
220 return net_proto_udp_connect (fd, addr);
222 break;
223 case AF_INET6:
224 switch (sock->protocol) {
225 case IPPROTO_TCP:
226 return net_proto_tcp6_connect (fd, (sockaddr_in *) addr);
227 case IPPROTO_UDP:
228 return net_proto_udp6_connect (fd, (sockaddr_in6 *) addr);
230 break;
231 case AF_RS232:
232 return ips_connect (fd, addr);
235 return 0;
238 int send (int fd, char *msg, size_t size, int flags)
240 socket_t *sock = socket_getbyfd (fd);
242 if (!sock)
243 return -1;
245 DPRINT (DBG_NET | DBG_SOCKET, "send (%d) -> %s", fd, msg);
247 switch (sock->family) {
248 case AF_UNSPEC:
249 return -1;
250 case AF_UNIX:
251 return net_proto_unix_send (fd, msg, size);
252 case AF_INET:
253 switch (sock->protocol) {
254 case IPPROTO_TCP:
255 return net_proto_tcp_send (fd, msg, size);
256 case IPPROTO_UDP:
257 return net_proto_udp_send (fd, msg, size);
259 break;
260 case AF_INET6:
261 switch (sock->protocol) {
262 case IPPROTO_TCP:
263 return net_proto_tcp6_send (fd, msg, size);
264 case IPPROTO_UDP:
265 return net_proto_udp6_send (fd, msg, size);
267 break;
268 case AF_RS232:
269 return ips_send (fd, msg, size);
272 return 0;
275 int sendto (int fd, const void *msg, size_t len, int flags, sockaddr *to, socklen_t tolen)
277 socket_t *sock = socket_getbyfd (fd);
279 if (!sock)
280 return -1;
282 DPRINT (DBG_NET | DBG_SOCKET, "sendto (%d) -> %s", fd, msg);
284 switch (sock->protocol) {
285 case IPPROTO_TCP:
286 switch (sock->family) {
287 case AF_UNSPEC:
288 return -1;
289 case AF_UNIX:
290 return -1;
291 case AF_INET:
292 return -1; // net_proto_tcp_sendto (fd, msg, len, to);
293 case AF_INET6:
294 return -1; // net_proto_tcp6_sendto (fd, msg, len, to);
295 case AF_RS232:
296 return -1;
298 break;
299 case IPPROTO_UDP:
300 switch (sock->family) {
301 case AF_UNSPEC:
302 return -1;
303 case AF_UNIX:
304 return -1;
305 case AF_INET:
306 return net_proto_udp_sendto (fd, msg, len, (sockaddr_in *) to);
307 case AF_INET6:
308 return net_proto_udp6_sendto (fd, msg, len, (sockaddr_in6 *) to);
309 case AF_RS232:
310 return -1;
312 break;
315 return 0;
318 int recv (int fd, char *msg, size_t size, int flags)
320 socket_t *sock = socket_getbyfd (fd);
322 if (!sock)
323 return -1;
325 DPRINT (DBG_NET | DBG_SOCKET, "recv (%d)", fd);
327 switch (sock->family) {
328 case AF_UNSPEC:
329 return -1;
330 case AF_UNIX:
331 return net_proto_unix_recv (fd, msg, size);
332 case AF_INET:
333 switch (sock->protocol) {
334 case IPPROTO_TCP:
335 return net_proto_tcp_recv (fd, msg, size);
336 case IPPROTO_UDP:
337 return net_proto_udp_recv (fd, msg, size);
339 break;
340 case AF_INET6:
341 switch (sock->protocol) {
342 case IPPROTO_TCP:
343 return net_proto_tcp6_recv (fd, msg, size);
344 case IPPROTO_UDP:
345 return net_proto_udp6_recv (fd, msg, size);
347 break;
348 case AF_RS232:
349 return ips_recv (fd, msg, size);
352 return -1;
355 int recvfrom (int fd, char *msg, size_t size, int flags, sockaddr *from, socklen_t fromlen)
357 socket_t *sock = socket_getbyfd (fd);
359 if (!sock)
360 return -1;
362 DPRINT (DBG_NET | DBG_SOCKET, "recvfrom (%d)", fd);
364 switch (sock->protocol) {
365 case IPPROTO_TCP:
366 switch (sock->family) {
367 case AF_UNSPEC:
368 return -1;
369 case AF_UNIX:
370 return -1;
371 case AF_INET:
372 return -1; //net_proto_tcp_recvfrom (fd, msg, size, from);
373 case AF_INET6:
374 return -1; //net_proto_tcp6_recvfrom (fd, msg, size, from);
375 case AF_RS232:
376 return -1;
378 break;
379 case IPPROTO_UDP:
380 switch (sock->family) {
381 case AF_UNSPEC:
382 return -1;
383 case AF_UNIX:
384 return -1;
385 case AF_INET:
386 return net_proto_udp_recvfrom (fd, msg, size, (sockaddr_in *) from);
387 case AF_INET6:
388 return net_proto_udp6_recvfrom (fd, msg, size, (sockaddr_in6 *) from);
389 case AF_RS232:
390 return -1;
392 break;
395 return -1;
398 int bind (int fd, sockaddr *addr, socklen_t len)
400 socket_t *sock = socket_getbyfd (fd);
402 if (!sock)
403 return -1;
405 DPRINT (DBG_NET | DBG_SOCKET, "bind (%d)", fd);
407 switch (sock->family) {
408 case AF_UNSPEC:
409 return -1;
410 case AF_UNIX:
411 return net_proto_unix_bind (fd, (sockaddr_in *) addr, len);
412 case AF_INET:
413 switch (sock->protocol) {
414 case IPPROTO_TCP:
415 return net_proto_tcp_bind (fd, (sockaddr_in *) addr, len);
416 case IPPROTO_UDP:
417 return net_proto_udp_bind (fd, (sockaddr_in *) addr, len);
419 break;
420 case AF_INET6:
421 switch (sock->protocol) {
422 case IPPROTO_TCP:
423 return net_proto_tcp6_bind (fd, (sockaddr_in6 *) addr, len);
424 case IPPROTO_UDP:
425 return net_proto_udp6_bind (fd, (sockaddr_in6 *) addr, len);
427 break;
428 case AF_RS232:
429 return ips_bind (fd, addr);
432 return -1;
435 int listen (int fd, int backlog)
437 socket_t *sock = socket_getbyfd (fd);
439 if (!sock)
440 return -1;
442 DPRINT (DBG_NET | DBG_SOCKET, "listen (%d)", fd);
444 switch (sock->family) {
445 case AF_UNSPEC:
447 return -1;
448 case AF_UNIX:
449 return net_proto_unix_listen (fd, backlog);
450 case AF_INET:
451 return net_proto_tcp_listen (fd, backlog);
452 case AF_INET6:
453 return net_proto_tcp6_listen (fd, backlog);
454 case AF_RS232:
455 return ips_listen (fd, backlog);
458 return -1;
461 int accept (int fd, sockaddr *addr, socklen_t *addrlen)
463 socket_t *servsock = socket_getbyfd (fd);
465 if (!servsock)
466 return -1;
468 //DPRINT (DBG_NET | DBG_SOCKET, "accept (%d)", fd);
470 int client = 0;
472 switch (servsock->family) {
473 case AF_UNSPEC:
475 return -1;
476 case AF_UNIX:
477 client = net_proto_unix_accept (fd, (sockaddr_in *) addr, addrlen);
478 break;
479 case AF_INET:
480 client = net_proto_tcp_accept (fd, (sockaddr_in *) addr, addrlen);
481 break;
482 case AF_INET6:
483 client = net_proto_tcp6_accept (fd, (sockaddr_in6 *) addr, addrlen);
484 break;
485 case AF_RS232:
486 client = ips_accept (fd, addr, addrlen);
487 break;
490 if (client <= 0)
491 return client;
493 socket_t *sock;
495 /* alloc and init context */
496 sock = (socket_t *) kmalloc (sizeof (socket_t));
498 sock->fd = client;
499 sock->family = servsock->family;
500 sock->type = servsock->type;
501 sock->protocol = servsock->protocol;
503 /* add into list */
504 sock->next = &socket_list;
505 sock->prev = socket_list.prev;
506 sock->prev->next = sock;
507 sock->next->prev = sock;
509 return client;
512 int sclose (int fd)
514 socket_t *sock = socket_getbyfd (fd);
516 if (!sock)
517 return -1;
519 DPRINT (DBG_NET | DBG_SOCKET, "close (%d)", fd);
521 /* delete old socket from socket_list */
522 sock->next->prev = sock->prev;
523 sock->prev->next = sock->next;
525 int family = sock->family;
526 int protocol = sock->protocol;
528 kfree (sock);
530 switch (family) {
531 case AF_UNSPEC:
532 return -1;
533 case AF_UNIX:
534 return net_proto_unix_close (fd);
535 case AF_INET:
536 switch (protocol) {
537 case IPPROTO_TCP:
538 return net_proto_tcp_close (fd);
539 case IPPROTO_UDP:
540 return net_proto_udp_close (fd);
542 break;
543 case AF_INET6:
544 switch (protocol) {
545 case IPPROTO_TCP:
546 return net_proto_tcp6_close (fd);
547 case IPPROTO_UDP:
548 return net_proto_udp6_close (fd);
550 break;
551 case AF_RS232:
552 return ips_close (fd);
555 return -1;
558 int sfcntl (int fd, int cmd, long arg)
560 socket_t *sock = socket_getbyfd (fd);
562 if (!sock)
563 return -1;
565 DPRINT (DBG_NET | DBG_SOCKET, "fcntl (%d)", fd);
567 switch (sock->family) {
568 case AF_UNSPEC:
569 return -1;
570 case AF_UNIX:
571 return net_proto_unix_fcntl (fd, cmd, arg);
572 case AF_INET:
573 switch (sock->protocol) {
574 case IPPROTO_TCP:
575 return net_proto_tcp_fcntl (fd, cmd, arg);
576 case IPPROTO_UDP:
577 return net_proto_udp_fcntl (fd, cmd, arg);
579 break;
580 case AF_INET6:
581 switch (sock->protocol) {
582 case IPPROTO_TCP:
583 return net_proto_tcp6_fcntl (fd, cmd, arg);
584 case IPPROTO_UDP:
585 return net_proto_udp6_fcntl (fd, cmd, arg);
587 break;
588 case AF_RS232:
589 return ips_fcntl (fd);
592 return -1;
595 unsigned int init_socket ()
597 socket_list.next = &socket_list;
598 socket_list.prev = &socket_list;
600 return 1;