app irc was completely rewrited from base, should be stable now, support multichannel...
[ZeXOS.git] / kernel / core / net / socket.c
blob3a7dced29f84a5cbfae1cb15fb1d794353703664
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <system.h>
22 #include <string.h>
23 #include <net/socket.h>
24 #include <dev.h>
25 #include <task.h>
27 socket_t socket_list;
29 extern fd_t fd_list;
30 extern unsigned int fd_count;
31 extern task_t *_curr_task;
33 socket_t *socket_getbyfd (int fd)
35 socket_t *socket;
36 for (socket = socket_list.next; socket != &socket_list; socket = socket->next) {
37 if (socket->fd == fd)
38 return socket;
41 return 0;
44 int socket (int family, int type, int protocol)
46 socket_t *sock;
48 /* alloc and init context */
49 sock = (socket_t *) kmalloc (sizeof (socket_t));
51 sock->fd = fd_count ++;
52 sock->family = family;
53 sock->type = type;
54 sock->protocol = protocol;
56 switch (sock->protocol) {
57 case IPPROTO_TCP:
58 switch (sock->family) {
59 case AF_UNSPEC:
60 return -1;
61 case AF_UNIX:
63 return -1;
64 case AF_INET:
65 sock->fd = net_proto_tcp_socket ();
66 break;
67 case AF_INET6:
68 sock->fd = net_proto_tcp6_socket ();
69 break;
70 case AF_RS232:
71 sock->fd = ips_socket ();
72 break;
74 break;
75 case IPPROTO_UDP:
76 switch (sock->family) {
77 case AF_UNSPEC:
78 return -1;
79 case AF_UNIX:
81 return -1;
82 case AF_INET:
83 sock->fd = net_proto_udp_socket ();
84 break;
85 case AF_INET6:
86 sock->fd = net_proto_udp6_socket ();
87 break;
88 case AF_RS232:
89 return -1;
91 break;
94 /* add into list */
95 sock->next = &socket_list;
96 sock->prev = socket_list.prev;
97 sock->prev->next = sock;
98 sock->next->prev = sock;
100 fd_t *fd = (fd_t *) kmalloc (sizeof (fd_t));
102 fd->flags = FD_SOCK;
103 fd->id = sock->fd;
105 proc_t *proc = proc_find (_curr_task);
107 if (!proc)
108 return;
110 if (proc->task != _curr_task)
111 return;
113 fd->proc = proc;
115 fd->next = &fd_list;
116 fd->prev = fd_list.prev;
117 fd->prev->next = fd;
118 fd->next->prev = 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 ip addresss */
130 while (i < l) {
131 if (hostname[i] == '.')
132 g ++;
134 i ++;
137 unsigned target = 0;
139 /* it is dns address */
140 if (g != 3) {
141 target = dns_cache_get (hostname);
143 if (!target)
144 target = dns_send_request (hostname);
145 } else
146 target = net_proto_ip_convert (hostname);
148 if (!target)
149 return 0;
151 hostent *host = (hostent *) kmalloc (sizeof (hostent));
153 if (!host)
154 return 0;
156 memset (host, 0, sizeof (hostent));
158 /* 4bytes - unsigned - for ipv4 */
159 host->h_length = 4;
161 host->h_addr = (char *) kmalloc (sizeof (char) * host->h_length);
163 if (!host->h_addr) {
164 kfree (host);
165 return 0;
168 memcpy (host->h_addr, &target, host->h_length);
170 return host;
173 int connect (int fd, sockaddr *addr, socklen_t len)
175 DPRINT ("connect () -> socket: %d\n", fd);
176 socket_t *sock = socket_getbyfd (fd);
178 if (!sock)
179 return -1;
181 switch (sock->protocol) {
182 case IPPROTO_TCP:
183 switch (sock->family) {
184 case AF_UNSPEC:
186 return -1;
187 case AF_UNIX:
189 return -1;
190 case AF_INET:
191 return net_proto_tcp_connect (fd, (sockaddr_in *) addr);
192 case AF_INET6:
193 return net_proto_tcp6_connect (fd, (sockaddr_in6 *) addr);
194 case AF_RS232:
195 return ips_connect (fd, addr);
197 break;
198 case IPPROTO_UDP:
199 switch (sock->family) {
200 case AF_UNSPEC:
202 return -1;
203 case AF_UNIX:
205 return -1;
206 case AF_INET:
207 return net_proto_udp_connect (fd, addr);
208 case AF_INET6:
209 return net_proto_udp6_connect (fd, (sockaddr_in6 *) addr);
210 case AF_RS232:
212 return -1;
214 break;
217 return 1;
220 int send (int fd, char *msg, size_t size, int flags)
222 socket_t *sock = socket_getbyfd (fd);
224 if (!sock)
225 return -1;
227 DPRINT ("send (%d) -> %s\n", fd, msg);
229 switch (sock->protocol) {
230 case IPPROTO_TCP:
231 switch (sock->family) {
232 case AF_UNSPEC:
234 return -1;
235 case AF_UNIX:
237 return -1;
238 case AF_INET:
239 return net_proto_tcp_send (fd, msg, size);
240 case AF_INET6:
241 return net_proto_tcp6_send (fd, msg, size);
242 case AF_RS232:
243 return ips_send (fd, msg, size);
245 break;
246 case IPPROTO_UDP:
247 switch (sock->family) {
248 case AF_UNSPEC:
250 return -1;
251 case AF_UNIX:
253 return -1;
254 case AF_INET:
255 return net_proto_udp_send (fd, msg, size);
256 case AF_INET6:
257 return net_proto_udp6_send (fd, msg, size);
258 case AF_RS232:
260 return -1;
262 break;
265 return 1;
268 int sendto (int fd, const void *msg, size_t len, int flags, sockaddr *to, socklen_t tolen)
270 socket_t *sock = socket_getbyfd (fd);
272 if (!sock)
273 return -1;
275 DPRINT ("sendto (%d) -> %s\n", fd, msg);
277 switch (sock->protocol) {
278 case IPPROTO_TCP:
279 switch (sock->family) {
280 case AF_UNSPEC:
282 return -1;
283 case AF_UNIX:
285 return -1;
286 case AF_INET:
287 return -1; // net_proto_tcp_sendto (fd, msg, len, to);
288 case AF_INET6:
289 return -1; // net_proto_tcp6_sendto (fd, msg, len, to);
290 case AF_RS232:
292 return -1;
294 break;
295 case IPPROTO_UDP:
296 switch (sock->family) {
297 case AF_UNSPEC:
299 return -1;
300 case AF_UNIX:
302 return -1;
303 case AF_INET:
304 return net_proto_udp_sendto (fd, msg, len, (sockaddr_in *) to);
305 case AF_INET6:
306 return net_proto_udp6_sendto (fd, msg, len, (sockaddr_in6 *) to);
307 case AF_RS232:
309 return -1;
311 break;
314 return 1;
317 int recv (int fd, char *msg, size_t size, int flags)
319 socket_t *sock = socket_getbyfd (fd);
321 if (!sock)
322 return -1;
324 DPRINT ("recv (%d)\n", fd);
326 switch (sock->protocol) {
327 case IPPROTO_TCP:
328 switch (sock->family) {
329 case AF_UNSPEC:
331 return -1;
332 case AF_UNIX:
334 return -1;
335 case AF_INET:
336 return net_proto_tcp_recv (fd, msg, size);
337 case AF_INET6:
338 return net_proto_tcp6_recv (fd, msg, size);
339 case AF_RS232:
340 return ips_recv (fd, msg, size);
342 break;
343 case IPPROTO_UDP:
344 switch (sock->family) {
345 case AF_UNSPEC:
347 return -1;
348 case AF_UNIX:
350 return -1;
351 case AF_INET:
352 return net_proto_udp_recv (fd, msg, size);
353 case AF_INET6:
354 return net_proto_udp6_recv (fd, msg, size);
355 case AF_RS232:
357 return -1;
359 break;
362 return 1;
365 int recvfrom (int fd, char *msg, size_t size, int flags, sockaddr *from, socklen_t fromlen)
367 socket_t *sock = socket_getbyfd (fd);
369 if (!sock)
370 return -1;
372 DPRINT ("recvfrom (%d)\n", fd);
374 switch (sock->protocol) {
375 case IPPROTO_TCP:
376 switch (sock->family) {
377 case AF_UNSPEC:
379 return -1;
380 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:
389 return -1;
391 break;
392 case IPPROTO_UDP:
393 switch (sock->family) {
394 case AF_UNSPEC:
396 return -1;
397 case AF_UNIX:
399 return -1;
400 case AF_INET:
401 return net_proto_udp_recvfrom (fd, msg, size, (sockaddr_in *) from);
402 case AF_INET6:
403 return net_proto_udp6_recvfrom (fd, msg, size, (sockaddr_in6 *) from);
404 case AF_RS232:
406 return -1;
408 break;
411 return 1;
414 int bind (int fd, sockaddr *addr, socklen_t len)
416 socket_t *sock = socket_getbyfd (fd);
418 if (!sock)
419 return -1;
421 DPRINT ("bind (%d)\n", fd);
423 switch (sock->protocol) {
424 case IPPROTO_TCP:
425 switch (sock->family) {
426 case AF_UNSPEC:
428 return -1;
429 case AF_UNIX:
431 return -1;
432 case AF_INET:
433 return net_proto_tcp_bind (fd, (sockaddr_in *) addr, len);
434 case AF_INET6:
435 return net_proto_tcp6_bind (fd, (sockaddr_in6 *) addr, len);
436 case AF_RS232:
437 return ips_bind (fd, addr);
439 break;
440 case IPPROTO_UDP:
441 switch (sock->family) {
442 case AF_UNSPEC:
444 return -1;
445 case AF_UNIX:
447 return -1;
448 case AF_INET:
449 return net_proto_udp_bind (fd, (sockaddr_in *) addr, len);
450 case AF_INET6:
451 return net_proto_udp6_bind (fd, (sockaddr_in6 *) addr, len);
452 case AF_RS232:
453 return -1;
455 break;
458 return 1;
461 int listen (int fd, int backlog)
463 socket_t *sock = socket_getbyfd (fd);
465 if (!sock)
466 return -1;
468 DPRINT ("listen (%d)\n", fd);
470 switch (sock->family) {
471 case AF_UNSPEC:
473 return -1;
474 case AF_UNIX:
476 return -1;
477 case AF_INET:
478 return net_proto_tcp_listen (fd, backlog);
479 case AF_INET6:
480 return net_proto_tcp6_listen (fd, backlog);
481 case AF_RS232:
482 return ips_listen (fd, backlog);
485 return 1;
488 int accept (int fd, sockaddr *addr, socklen_t *addrlen)
490 socket_t *servsock = socket_getbyfd (fd);
492 if (!servsock)
493 return -1;
495 DPRINT ("accept (%d)\n", fd);
497 int client = 0;
499 switch (servsock->family) {
500 case AF_UNSPEC:
502 return -1;
503 case AF_UNIX:
505 return -1;
506 case AF_INET:
507 client = net_proto_tcp_accept (fd, (sockaddr_in *) addr, addrlen);
508 break;
509 case AF_INET6:
510 client = net_proto_tcp6_accept (fd, (sockaddr_in6 *) addr, addrlen);
511 break;
512 case AF_RS232:
513 client = ips_accept (fd, addr, addrlen);
514 break;
517 if (client <= 0)
518 return client;
520 socket_t *sock;
522 /* alloc and init context */
523 sock = (socket_t *) kmalloc (sizeof (socket_t));
525 fd_count ++;
526 sock->fd = client;
527 sock->family = servsock->family;
528 sock->type = servsock->type;
529 sock->protocol = servsock->protocol;
531 /* add into list */
532 sock->next = &socket_list;
533 sock->prev = socket_list.prev;
534 sock->prev->next = sock;
535 sock->next->prev = sock;
537 fd_t *fd_client = (fd_t *) kmalloc (sizeof (fd_t));
539 fd_client->flags = FD_SOCK;
540 fd_client->id = sock->fd;
542 fd_client->next = &fd_list;
543 fd_client->prev = fd_list.prev;
544 fd_client->prev->next = fd_client;
545 fd_client->next->prev = fd_client;
547 return client;
550 int sclose (int fd)
552 socket_t *sock = socket_getbyfd (fd);
554 if (!sock)
555 return -1;
557 DPRINT ("close (%d)\n", fd);
559 switch (sock->protocol) {
560 case IPPROTO_TCP:
561 switch (sock->family) {
562 case AF_UNSPEC:
564 return -1;
565 case AF_UNIX:
567 return -1;
568 case AF_INET:
569 return net_proto_tcp_close (fd);
570 case AF_INET6:
571 return net_proto_tcp6_close (fd);
572 case AF_RS232:
573 return ips_close (fd);
575 break;
576 case IPPROTO_UDP:
577 switch (sock->family) {
578 case AF_UNSPEC:
580 return -1;
581 case AF_UNIX:
583 return -1;
584 case AF_INET:
585 return net_proto_udp_close (fd);
586 case AF_INET6:
587 return net_proto_udp6_close (fd);
588 case AF_RS232:
590 return -1;
592 break;
595 return 1;
598 int sfcntl (int fd, int cmd, long arg)
600 socket_t *sock = socket_getbyfd (fd);
602 if (!sock)
603 return -1;
605 DPRINT ("fcntl (%d)\n", fd);
607 switch (sock->protocol) {
608 case IPPROTO_TCP:
609 switch (sock->family) {
610 case AF_UNSPEC:
612 return -1;
613 case AF_UNIX:
615 return -1;
616 case AF_INET:
617 return net_proto_tcp_fcntl (fd, cmd, arg);
618 case AF_INET6:
619 return net_proto_tcp6_fcntl (fd, cmd, arg);
620 case AF_RS232:
621 return ips_fcntl (fd);
623 break;
624 case IPPROTO_UDP:
625 switch (sock->family) {
626 case AF_UNSPEC:
628 return -1;
629 case AF_UNIX:
631 return -1;
632 case AF_INET:
633 return net_proto_udp_fcntl (fd, cmd, arg);
634 case AF_INET6:
635 return net_proto_udp6_fcntl (fd, cmd, arg);
636 case AF_RS232:
638 return -1;
640 break;
645 unsigned int init_socket ()
647 socket_list.next = &socket_list;
648 socket_list.prev = &socket_list;
650 fd_count = 0;
652 return 1;