New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / kernel / core / net / socket.c
blob8c1316d3c1296fdde18c134710b5b49818a27e4e
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)
6 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <net/socket.h>
24 #include <system.h>
25 #include <string.h>
26 #include <select.h>
27 #include <task.h>
28 #include <dev.h>
29 #include <fd.h>
30 #include <errno.h>
32 socket_t socket_list;
34 extern task_t *_curr_task;
36 socket_t *socket_getbyfd (int fd)
38 socket_t *socket;
39 for (socket = socket_list.next; socket != &socket_list; socket = socket->next) {
40 if (socket->fd == fd)
41 return socket;
44 return 0;
47 int socket (int family, int type, int protocol)
49 /* alloc and init context */
50 socket_t *sock = (socket_t *) kmalloc (sizeof (socket_t));
52 if (!sock) {
53 errno_set (ENOMEM);
54 return -1;
57 sock->family = family;
58 sock->type = type;
59 sock->protocol = protocol;
61 fd_t *fd = fd_create (FD_SOCK);
63 if (!fd) {
64 kfree (sock);
65 return -1;
68 sock->fd = fd->id;
70 int ret = 0;
72 switch (sock->family) {
73 case AF_UNSPEC:
74 return -1;
75 case AF_UNIX:
76 ret = net_proto_unix_socket (fd);
77 break;
78 case AF_INET:
79 switch (sock->protocol) {
80 case IPPROTO_TCP:
81 ret = net_proto_tcp_socket (fd);
82 break;
83 case IPPROTO_UDP:
84 ret = net_proto_udp_socket (fd);
85 break;
87 break;
88 case AF_INET6:
89 switch (sock->protocol) {
90 case IPPROTO_TCP:
91 ret = net_proto_tcp6_socket (fd);
92 break;
93 case IPPROTO_UDP:
94 ret = net_proto_udp6_socket (fd);
95 break;
97 break;
98 case AF_RS232:
99 ret = ips_socket (fd);
100 break;
103 if (ret) {
104 kfree (sock);
105 fd_delete (fd);
107 DPRINT (DBG_NET | DBG_SOCKET, "socket () -> %d : ERROR", sock->fd);
108 return -1;
111 /* add into list */
112 sock->next = &socket_list;
113 sock->prev = socket_list.prev;
114 sock->prev->next = sock;
115 sock->next->prev = sock;
117 proc_t *proc = proc_find (_curr_task);
119 /* when it is process */
120 if (proc) {
121 if (proc->task != _curr_task)
122 return;
124 fd->proc = proc;
125 } else {
126 /* it is kernel socket */
127 fd->proc = 0;
130 DPRINT (DBG_NET | DBG_SOCKET, "socket () -> socket: %d", sock->fd);
132 return sock->fd;
135 hostent *gethostbyname (char *hostname)
137 unsigned i = 0;
138 unsigned g = 0;
139 unsigned l = strlen (hostname);
141 /* TODO: make better checking, that it is IPv6 addresss */
142 while (i < l) {
143 if (hostname[i] == ':')
144 g ++;
146 i ++;
149 unsigned target = 0;
150 unsigned short targetv6[8];
152 /* Is it an IPv6 address */
153 if (g == 7) {
154 if (!net_proto_ipv6_convert (targetv6, hostname))
155 return 0;
156 } else {
157 i = 0;
158 g = 0;
160 /* TODO: make better checking, that it is IPv4 addresss */
161 while (i < l) {
162 if (hostname[i] == '.')
163 g ++;
165 i ++;
169 /* it is dns address */
170 if (g != 3) {
171 if (dns_cache_get (hostname, &target, 4) != 1) /* check for ipv4 address */
172 if (dns_send_request (hostname, &target, 4) != 1) {
173 g = 7;
174 if (dns_cache_get (hostname, &targetv6, 16) != 1) { /* check for ipv6 address */
175 if (dns_send_request (hostname, &targetv6, 16) != 1)
176 return 0;
179 } else
180 target = net_proto_ip_convert (hostname);
182 if (!target)
183 return 0;
186 hostent *host = (hostent *) kmalloc (sizeof (hostent));
188 if (!host)
189 return 0;
191 memset (host, 0, sizeof (hostent));
193 /* IPv4 or IPv6 ? */
194 if (g == 7)
195 host->h_length = 16; /* IPv6 - 16 bytes */
196 else
197 host->h_length = 4; /* IPv4 - 4 bytes */
199 host->h_addr = (char *) kmalloc (sizeof (char) * host->h_length);
201 if (!host->h_addr) {
202 kfree (host);
203 return 0;
206 if (g == 7)
207 memcpy (host->h_addr, &targetv6, host->h_length);
208 else
209 memcpy (host->h_addr, &target, host->h_length);
211 return host;
214 int connect (int fd, sockaddr *addr, socklen_t len)
216 DPRINT (DBG_NET | DBG_SOCKET, "connect () -> socket: %d", fd);
217 socket_t *sock = socket_getbyfd (fd);
219 if (!sock)
220 return -1;
222 switch (sock->family) {
223 case AF_UNSPEC:
224 return -1;
225 case AF_UNIX:
226 return net_proto_unix_connect (fd, addr);
227 case AF_INET:
228 switch (sock->protocol) {
229 case IPPROTO_TCP:
230 return net_proto_tcp_connect (fd, (sockaddr_in *) addr);
231 case IPPROTO_UDP:
232 return net_proto_udp_connect (fd, addr);
234 break;
235 case AF_INET6:
236 switch (sock->protocol) {
237 case IPPROTO_TCP:
238 return net_proto_tcp6_connect (fd, (sockaddr_in *) addr);
239 case IPPROTO_UDP:
240 return net_proto_udp6_connect (fd, (sockaddr_in6 *) addr);
242 break;
243 case AF_RS232:
244 return ips_connect (fd, addr);
247 return 0;
250 int send (int fd, char *msg, size_t size, int flags)
252 socket_t *sock = socket_getbyfd (fd);
254 if (!sock)
255 return -1;
257 DPRINT (DBG_NET | DBG_SOCKET, "send (%d) -> %s", fd, msg);
259 switch (sock->family) {
260 case AF_UNSPEC:
261 return -1;
262 case AF_UNIX:
263 return net_proto_unix_send (fd, msg, size);
264 case AF_INET:
265 switch (sock->protocol) {
266 case IPPROTO_TCP:
267 return net_proto_tcp_send (fd, msg, size);
268 case IPPROTO_UDP:
269 return net_proto_udp_send (fd, msg, size);
271 break;
272 case AF_INET6:
273 switch (sock->protocol) {
274 case IPPROTO_TCP:
275 return net_proto_tcp6_send (fd, msg, size);
276 case IPPROTO_UDP:
277 return net_proto_udp6_send (fd, msg, size);
279 break;
280 case AF_RS232:
281 return ips_send (fd, msg, size);
284 return 0;
287 int sendto (int fd, const void *msg, size_t len, int flags, sockaddr *to, socklen_t tolen)
289 socket_t *sock = socket_getbyfd (fd);
291 if (!sock)
292 return -1;
294 DPRINT (DBG_NET | DBG_SOCKET, "sendto (%d) -> %s", fd, msg);
296 switch (sock->protocol) {
297 case IPPROTO_TCP:
298 switch (sock->family) {
299 case AF_UNSPEC:
300 return -1;
301 case AF_UNIX:
302 return -1;
303 case AF_INET:
304 return -1; // net_proto_tcp_sendto (fd, msg, len, to);
305 case AF_INET6:
306 return -1; // net_proto_tcp6_sendto (fd, msg, len, to);
307 case AF_RS232:
308 return -1;
310 break;
311 case IPPROTO_UDP:
312 switch (sock->family) {
313 case AF_UNSPEC:
314 return -1;
315 case AF_UNIX:
316 return -1;
317 case AF_INET:
318 return net_proto_udp_sendto (fd, msg, len, (sockaddr_in *) to);
319 case AF_INET6:
320 return net_proto_udp6_sendto (fd, msg, len, (sockaddr_in6 *) to);
321 case AF_RS232:
322 return -1;
324 break;
327 return 0;
330 int recv (int fd, char *msg, size_t size, int flags)
332 socket_t *sock = socket_getbyfd (fd);
334 if (!sock)
335 return -1;
337 DPRINT (DBG_NET | DBG_SOCKET, "recv (%d)", fd);
339 switch (sock->family) {
340 case AF_UNSPEC:
341 return -1;
342 case AF_UNIX:
343 return net_proto_unix_recv (fd, msg, size);
344 case AF_INET:
345 switch (sock->protocol) {
346 case IPPROTO_TCP:
347 return net_proto_tcp_recv (fd, msg, size);
348 case IPPROTO_UDP:
349 return net_proto_udp_recv (fd, msg, size);
351 break;
352 case AF_INET6:
353 switch (sock->protocol) {
354 case IPPROTO_TCP:
355 return net_proto_tcp6_recv (fd, msg, size);
356 case IPPROTO_UDP:
357 return net_proto_udp6_recv (fd, msg, size);
359 break;
360 case AF_RS232:
361 return ips_recv (fd, msg, size);
364 return -1;
367 int recvfrom (int fd, char *msg, size_t size, int flags, sockaddr *from, socklen_t fromlen)
369 socket_t *sock = socket_getbyfd (fd);
371 if (!sock)
372 return -1;
374 DPRINT (DBG_NET | DBG_SOCKET, "recvfrom (%d)", fd);
376 switch (sock->protocol) {
377 case IPPROTO_TCP:
378 switch (sock->family) {
379 case AF_UNSPEC:
380 return -1;
381 case AF_UNIX:
382 return -1;
383 case AF_INET:
384 return -1; //net_proto_tcp_recvfrom (fd, msg, size, from);
385 case AF_INET6:
386 return -1; //net_proto_tcp6_recvfrom (fd, msg, size, from);
387 case AF_RS232:
388 return -1;
390 break;
391 case IPPROTO_UDP:
392 switch (sock->family) {
393 case AF_UNSPEC:
394 return -1;
395 case AF_UNIX:
396 return -1;
397 case AF_INET:
398 return net_proto_udp_recvfrom (fd, msg, size, (sockaddr_in *) from);
399 case AF_INET6:
400 return net_proto_udp6_recvfrom (fd, msg, size, (sockaddr_in6 *) from);
401 case AF_RS232:
402 return -1;
404 break;
407 return -1;
410 int bind (int fd, sockaddr *addr, socklen_t len)
412 socket_t *sock = socket_getbyfd (fd);
414 if (!sock)
415 return -1;
417 DPRINT (DBG_NET | DBG_SOCKET, "bind (%d)", fd);
419 switch (sock->family) {
420 case AF_UNSPEC:
421 return -1;
422 case AF_UNIX:
423 return net_proto_unix_bind (fd, (sockaddr_in *) addr, len);
424 case AF_INET:
425 switch (sock->protocol) {
426 case IPPROTO_TCP:
427 return net_proto_tcp_bind (fd, (sockaddr_in *) addr, len);
428 case IPPROTO_UDP:
429 return net_proto_udp_bind (fd, (sockaddr_in *) addr, len);
431 break;
432 case AF_INET6:
433 switch (sock->protocol) {
434 case IPPROTO_TCP:
435 return net_proto_tcp6_bind (fd, (sockaddr_in6 *) addr, len);
436 case IPPROTO_UDP:
437 return net_proto_udp6_bind (fd, (sockaddr_in6 *) addr, len);
439 break;
440 case AF_RS232:
441 return ips_bind (fd, addr);
444 return -1;
447 int listen (int fd, int backlog)
449 socket_t *sock = socket_getbyfd (fd);
451 if (!sock)
452 return -1;
454 DPRINT (DBG_NET | DBG_SOCKET, "listen (%d)", fd);
456 switch (sock->family) {
457 case AF_UNSPEC:
459 return -1;
460 case AF_UNIX:
461 return net_proto_unix_listen (fd, backlog);
462 case AF_INET:
463 return net_proto_tcp_listen (fd, backlog);
464 case AF_INET6:
465 return net_proto_tcp6_listen (fd, backlog);
466 case AF_RS232:
467 return ips_listen (fd, backlog);
470 return -1;
473 int accept (int fd, sockaddr *addr, socklen_t *addrlen)
475 socket_t *servsock = socket_getbyfd (fd);
477 if (!servsock)
478 return -1;
480 //DPRINT (DBG_NET | DBG_SOCKET, "accept (%d)", fd);
482 int client = 0;
484 switch (servsock->family) {
485 case AF_UNSPEC:
487 return -1;
488 case AF_UNIX:
489 client = net_proto_unix_accept (fd, (sockaddr_in *) addr, addrlen);
490 break;
491 case AF_INET:
492 client = net_proto_tcp_accept (fd, (sockaddr_in *) addr, addrlen);
493 break;
494 case AF_INET6:
495 client = net_proto_tcp6_accept (fd, (sockaddr_in6 *) addr, addrlen);
496 break;
497 case AF_RS232:
498 client = ips_accept (fd, addr, addrlen);
499 break;
502 if (client <= 0)
503 return client;
505 socket_t *sock;
507 /* alloc and init context */
508 sock = (socket_t *) kmalloc (sizeof (socket_t));
510 if (!sock)
511 return 0;
513 sock->fd = client;
514 sock->family = servsock->family;
515 sock->type = servsock->type;
516 sock->protocol = servsock->protocol;
518 /* add into list */
519 sock->next = &socket_list;
520 sock->prev = socket_list.prev;
521 sock->prev->next = sock;
522 sock->next->prev = sock;
524 return client;
527 int sclose (int fd)
529 socket_t *sock = socket_getbyfd (fd);
531 if (!sock)
532 return -1;
534 DPRINT (DBG_NET | DBG_SOCKET, "close (%d)", fd);
536 /* delete old socket from socket_list */
537 sock->next->prev = sock->prev;
538 sock->prev->next = sock->next;
540 int family = sock->family;
541 int protocol = sock->protocol;
543 kfree (sock);
545 switch (family) {
546 case AF_UNSPEC:
547 return -1;
548 case AF_UNIX:
549 return net_proto_unix_close (fd);
550 case AF_INET:
551 switch (protocol) {
552 case IPPROTO_TCP:
553 return net_proto_tcp_close (fd);
554 case IPPROTO_UDP:
555 return net_proto_udp_close (fd);
557 break;
558 case AF_INET6:
559 switch (protocol) {
560 case IPPROTO_TCP:
561 return net_proto_tcp6_close (fd);
562 case IPPROTO_UDP:
563 return net_proto_udp6_close (fd);
565 break;
566 case AF_RS232:
567 return ips_close (fd);
570 return -1;
573 int sfcntl (int fd, int cmd, long arg)
575 socket_t *sock = socket_getbyfd (fd);
577 if (!sock)
578 return -1;
580 DPRINT (DBG_NET | DBG_SOCKET, "fcntl (%d)", fd);
582 switch (sock->family) {
583 case AF_UNSPEC:
584 return -1;
585 case AF_UNIX:
586 return net_proto_unix_fcntl (fd, cmd, arg);
587 case AF_INET:
588 switch (sock->protocol) {
589 case IPPROTO_TCP:
590 return net_proto_tcp_fcntl (fd, cmd, arg);
591 case IPPROTO_UDP:
592 return net_proto_udp_fcntl (fd, cmd, arg);
594 break;
595 case AF_INET6:
596 switch (sock->protocol) {
597 case IPPROTO_TCP:
598 return net_proto_tcp6_fcntl (fd, cmd, arg);
599 case IPPROTO_UDP:
600 return net_proto_udp6_fcntl (fd, cmd, arg);
602 break;
603 case AF_RS232:
604 return ips_fcntl (fd);
607 return -1;
610 /* socket api select for specified socket */
611 int sselect (int readfd, int writefd, int exceptfd)
613 int fd = -1;
615 if (readfd)
616 fd = readfd;
617 else if (writefd)
618 fd = writefd;
619 else if (exceptfd)
620 fd = exceptfd;
622 socket_t *sock = socket_getbyfd (fd);
624 if (!sock)
625 return -1;
627 switch (sock->family) {
628 /*case AF_UNSPEC:
629 return -1;
630 case AF_UNIX:
631 return net_proto_unix_select (readfd, writefd, exceptfd);*/
632 case AF_INET:
633 switch (sock->protocol) {
634 case IPPROTO_TCP:
635 return net_proto_tcp_select (readfd, writefd, exceptfd);
636 //case IPPROTO_UDP:
637 // return net_proto_udp_select (readfd, writefd, exceptfd);
639 break;
640 case AF_INET6:
641 switch (sock->protocol) {
642 case IPPROTO_TCP:
643 return net_proto_tcp6_select (readfd, writefd, exceptfd);
644 case IPPROTO_UDP:
645 return net_proto_udp6_select (readfd, writefd, exceptfd);
647 break;
648 /*case AF_RS232:
649 return ips_select (readfd, writefd, exceptfd);*/
652 return -1;
655 unsigned int init_socket ()
657 socket_list.next = &socket_list;
658 socket_list.prev = &socket_list;
660 return 1;