89c2f0e044ca690d8f1828edc521ed491c69957d
[asterisk/asterisk.git] / res / pjproject / pjlib / src / pj / sock_linux_kernel.c
1 /* $Id$ */
2 /* 
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19  */
20 #include <pj/sock.h>
21 #include <pj/assert.h>
22 #include <pj/string.h>      /* pj_memcpy()          */
23 #include <pj/os.h>          /* PJ_CHECK_STACK()     */
24 #include <pj/addr_resolv.h> /* pj_gethostbyname()   */
25 #include <pj/ctype.h>
26 #include <pj/compat/sprintf.h>
27 #include <pj/log.h>
28 #include <pj/errno.h>
29
30 /* Linux kernel specific. */
31 #include <linux/socket.h>
32 #include <linux/net.h>
33 //#include <net/sock.h>
34 #include <linux/security.h>
35 #include <linux/syscalls.h>     /* sys_xxx()    */
36 #include <asm/ioctls.h>         /* FIONBIO      */
37 #include <linux/utsname.h>      /* for pj_gethostname() */
38
39 /*
40  * Address families conversion.
41  * The values here are indexed based on pj_addr_family-0xFF00.
42  */
43 const pj_uint16_t PJ_AF_UNIX    = AF_UNIX;
44 const pj_uint16_t PJ_AF_INET    = AF_INET;
45 const pj_uint16_t PJ_AF_INET6   = AF_INET6;
46 #ifdef AF_PACKET
47 const pj_uint16_t PJ_AF_PACKET  = AF_PACKET;
48 #else
49 #  error "AF_PACKET undeclared!"
50 #endif
51 #ifdef AF_IRDA
52 const pj_uint16_t PJ_AF_IRDA    = AF_IRDA;
53 #else
54 #  error "AF_IRDA undeclared!"
55 #endif
56
57 /*
58  * Socket types conversion.
59  * The values here are indexed based on pj_sock_type-0xFF00
60  */
61 const pj_uint16_t PJ_SOCK_STREAM= SOCK_STREAM;
62 const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
63 const pj_uint16_t PJ_SOCK_RAW   = SOCK_RAW;
64 const pj_uint16_t PJ_SOCK_RDM   = SOCK_RDM;
65
66 /*
67  * Socket level values.
68  */
69 const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
70 #ifdef SOL_IP
71 const pj_uint16_t PJ_SOL_IP     = SOL_IP;
72 #else
73 #  error "SOL_IP undeclared!"
74 #endif /* SOL_IP */
75 #if defined(SOL_TCP)
76 const pj_uint16_t PJ_SOL_TCP    = SOL_TCP;
77 #else
78 #  error "SOL_TCP undeclared!"
79 #endif /* SOL_TCP */
80 #ifdef SOL_UDP
81 const pj_uint16_t PJ_SOL_UDP    = SOL_UDP;
82 #else
83 #  error "SOL_UDP undeclared!"
84 #endif
85 #ifdef SOL_IPV6
86 const pj_uint16_t PJ_SOL_IPV6   = SOL_IPV6;
87 #else
88 #  error "SOL_IPV6 undeclared!"
89 #endif
90
91 /* optname values. */
92 const pj_uint16_t PJ_SO_TYPE    = SO_TYPE;
93 const pj_uint16_t PJ_SO_RCVBUF  = SO_RCVBUF;
94 const pj_uint16_t PJ_SO_SNDBUF  = SO_SNDBUF;
95
96 /*
97  * Convert 16-bit value from network byte order to host byte order.
98  */
99 PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
100 {
101     return ntohs(netshort);
102 }
103
104 /*
105  * Convert 16-bit value from host byte order to network byte order.
106  */
107 PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
108 {
109     return htons(hostshort);
110 }
111
112 /*
113  * Convert 32-bit value from network byte order to host byte order.
114  */
115 PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
116 {
117     return ntohl(netlong);
118 }
119
120 /*
121  * Convert 32-bit value from host byte order to network byte order.
122  */
123 PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
124 {
125     return htonl(hostlong);
126 }
127
128 /*
129  * Convert an Internet host address given in network byte order
130  * to string in standard numbers and dots notation.
131  */
132 PJ_DEF(char*) pj_inet_ntoa(pj_in_addr in)
133 {
134 #define UC(b)   (((int)b)&0xff)
135     static char b[18];
136     char *p;
137
138     p = (char *)&in;
139     pj_snprintf(b, sizeof(b), "%d.%d.%d.%d", 
140                UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
141
142     return b;
143 }
144
145 /*
146  * This function converts the Internet host address ccp from the standard
147  * numbers-and-dots notation into binary data and stores it in the structure
148  * that inp points to. 
149  */
150 PJ_DEF(int) pj_inet_aton(const pj_str_t *ccp, struct pj_in_addr *addr)
151 {
152     pj_uint32_t val;
153     int base, n;
154     char c;
155     unsigned parts[4];
156     unsigned *pp = parts;
157     char cp_copy[18];
158     char *cp = cp_copy;
159     
160     addr->s_addr = PJ_INADDR_NONE;
161
162     if (ccp->slen > 15) return 0;
163
164     pj_memcpy(cp, ccp->ptr, ccp->slen);
165     cp[ccp->slen] = '\0';
166
167     c = *cp;
168     for (;;) {
169         /*
170          * Collect number up to ``.''.
171          * Values are specified as for C:
172          * 0x=hex, 0=octal, isdigit=decimal.
173          */
174         if (!pj_isdigit((int)c))
175             return (0);
176         val = 0; base = 10;
177         if (c == '0') {
178             c = *++cp;
179             if (c == 'x' || c == 'X')
180                 base = 16, c = *++cp;
181             else
182                 base = 8;
183         }
184
185         for (;;) {
186             if (pj_isascii((int)c) && pj_isdigit((int)c)) {
187                 val = (val * base) + (c - '0');
188                 c = *++cp;
189             } else if (base==16 && pj_isascii((int)c) && pj_isxdigit((int)c)) {
190                 val = (val << 4) |
191                       (c + 10 - (pj_islower((int)c) ? 'a' : 'A'));
192                 c = *++cp;
193             } else
194                 break;
195         }
196
197         if (c == '.') {
198             /*
199              * Internet format:
200              *  a.b.c.d
201              *  a.b.c   (with c treated as 16 bits)
202              *  a.b     (with b treated as 24 bits)
203              */
204             if (pp >= parts + 3)
205                 return (0);
206             *pp++ = val;
207             c = *++cp;
208         } else
209             break;
210     }
211
212     /*
213      * Check for trailing characters.
214      */
215     if (c != '\0' && (!pj_isascii((int)c) || !pj_isspace((int)c)))
216         return (0);
217     /*
218      * Concoct the address according to
219      * the number of parts specified.
220      */
221     n = pp - parts + 1;
222     switch (n) {
223     case 0:
224         return (0);         /* initial nondigit */
225     case 1:             /* a -- 32 bits */
226         break;
227     case 2:             /* a.b -- 8.24 bits */
228         if (val > 0xffffff)
229             return (0);
230         val |= parts[0] << 24;
231         break;
232     case 3:             /* a.b.c -- 8.8.16 bits */
233         if (val > 0xffff)
234             return (0);
235         val |= (parts[0] << 24) | (parts[1] << 16);
236         break;
237     case 4:             /* a.b.c.d -- 8.8.8.8 bits */
238         if (val > 0xff)
239             return (0);
240         val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
241         break;
242     }
243
244     if (addr)
245         addr->s_addr = pj_htonl(val);
246     return (1);
247 }
248
249 /*
250  * Convert address string with numbers and dots to binary IP address.
251  */ 
252 PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
253 {
254     pj_in_addr addr;
255     pj_inet_aton(cp, &addr);
256     return addr;
257 }
258
259 /*
260  * Set the IP address of an IP socket address from string address, 
261  * with resolving the host if necessary. The string address may be in a
262  * standard numbers and dots notation or may be a hostname. If hostname
263  * is specified, then the function will resolve the host into the IP
264  * address.
265  */
266 PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
267                                                  const pj_str_t *str_addr)
268 {
269     PJ_CHECK_STACK();
270
271     pj_assert(str_addr && str_addr->slen < PJ_MAX_HOSTNAME);
272
273     addr->sin_family = AF_INET;
274
275     if (str_addr && str_addr->slen) {
276         addr->sin_addr = pj_inet_addr(str_addr);
277         if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
278             pj_hostent he;
279             if (pj_gethostbyname(str_addr, &he) == 0) {
280                 addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
281             } else {
282                 addr->sin_addr.s_addr = PJ_INADDR_NONE;
283                 return -1;
284             }
285         }
286
287     } else {
288         addr->sin_addr.s_addr = 0;
289     }
290
291     return PJ_SUCCESS;
292 }
293
294 /*
295  * Set the IP address and port of an IP socket address.
296  * The string address may be in a standard numbers and dots notation or 
297  * may be a hostname. If hostname is specified, then the function will 
298  * resolve the host into the IP address.
299  */
300 PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
301                                          const pj_str_t *str_addr,
302                                          pj_uint16_t port)
303 {
304     pj_assert(addr && str_addr);
305
306     addr->sin_family = PJ_AF_INET;
307     pj_sockaddr_in_set_port(addr, port);
308     return pj_sockaddr_in_set_str_addr(addr, str_addr);
309 }
310
311
312 /*
313  * Get hostname.
314  */
315 PJ_DEF(const pj_str_t*) pj_gethostname(void)
316 {
317     static char buf[PJ_MAX_HOSTNAME];
318     static pj_str_t hostname;
319
320     PJ_CHECK_STACK();
321
322     if (hostname.ptr == NULL) {
323         hostname.ptr = buf;
324         down_read(&uts_sem);
325         hostname.slen = strlen(system_utsname.nodename);
326         if (hostname.slen > PJ_MAX_HOSTNAME) {
327             hostname.ptr[0] = '\0';
328             hostname.slen = 0;
329         } else {
330             pj_memcpy(hostname.ptr, system_utsname.nodename, hostname.slen);
331         }
332         up_read(&uts_sem);
333     }
334     return &hostname;
335 }
336
337 /*
338  * Get first IP address associated with the hostname.
339  */
340 PJ_DEF(pj_in_addr) pj_gethostaddr(void)
341 {
342     pj_sockaddr_in addr;
343     const pj_str_t *hostname = pj_gethostname();
344
345     pj_sockaddr_in_set_str_addr(&addr, hostname);
346     return addr.sin_addr;
347 }
348
349
350 /*
351  * Create new socket/endpoint for communication and returns a descriptor.
352  */
353 PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, 
354                                    pj_sock_t *sock_fd)
355 {
356     long result;
357
358     PJ_CHECK_STACK();
359
360     /* Sanity checks. */
361     PJ_ASSERT_RETURN(PJ_INVALID_SOCKET == -1 && sock_fd != NULL, PJ_EINVAL);
362
363     /* Initialize returned socket */
364     *sock_fd = PJ_INVALID_SOCKET;
365
366     /* Create socket. */
367     result = sys_socket(af, type, proto);
368     if (result < 0) {
369         return PJ_RETURN_OS_ERROR((-result));
370     }
371
372     *sock_fd = result;
373
374     return PJ_SUCCESS;
375 }
376
377 /*
378  * Bind socket.
379  */
380 PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sockfd, 
381                                   const pj_sockaddr_t *addr,
382                                   int len)
383 {
384     long err;
385     mm_segment_t oldfs;
386
387     PJ_CHECK_STACK();
388
389     PJ_ASSERT_RETURN(addr!=NULL && len >= sizeof(struct pj_sockaddr),
390                      PJ_EINVAL);
391
392     oldfs = get_fs();
393     set_fs(KERNEL_DS);
394     
395     err = sys_bind(sockfd, (struct sockaddr*)addr, len);
396
397     set_fs(oldfs);
398
399     if (err)
400         return PJ_RETURN_OS_ERROR(-err);
401     else
402         return PJ_SUCCESS;
403 }
404
405
406 /*
407  * Bind socket.
408  */
409 PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd, 
410                                      pj_uint32_t addr32,
411                                      pj_uint16_t port)
412 {
413     pj_sockaddr_in addr;
414
415     PJ_CHECK_STACK();
416
417     addr.sin_family = PJ_AF_INET;
418     addr.sin_addr.s_addr = pj_htonl(addr32);
419     addr.sin_port = pj_htons(port);
420
421     return pj_sock_bind(sockfd, &addr, sizeof(pj_sockaddr_in));
422 }
423
424 /*
425  * Close socket.
426  */
427 PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sockfd)
428 {
429     long err;
430
431     err = sys_close(sockfd);
432
433     if (err != 0)
434         return PJ_RETURN_OS_ERROR(-err);
435     else
436         return PJ_SUCCESS;
437 }
438
439 /*
440  * Get remote's name.
441  */
442 PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sockfd,
443                                          pj_sockaddr_t *addr,
444                                          int *namelen)
445 {
446     mm_segment_t oldfs;
447     long err;
448
449     PJ_CHECK_STACK();
450
451     oldfs = get_fs();
452     set_fs(KERNEL_DS);
453
454     err = sys_getpeername( sockfd, addr, namelen);
455
456     set_fs(oldfs);
457
458     if (err)
459         return PJ_RETURN_OS_ERROR(-err);
460     else
461         return PJ_SUCCESS;
462 }
463
464 /*
465  * Get socket name.
466  */
467 PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sockfd,
468                                          pj_sockaddr_t *addr,
469                                          int *namelen)
470 {
471     mm_segment_t oldfs;
472     int err;
473
474     PJ_CHECK_STACK();
475
476     oldfs = get_fs();
477     set_fs(KERNEL_DS);
478     
479     err = sys_getsockname( sockfd, addr, namelen );
480
481     set_fs(oldfs);
482
483     if (err)
484         return PJ_RETURN_OS_ERROR(-err);
485     else
486         return PJ_SUCCESS;
487 }
488
489 /*
490  * Send data
491  */
492 PJ_DEF(pj_status_t) pj_sock_send( pj_sock_t sockfd,
493                                   const void *buf,
494                                   pj_ssize_t *len,
495                                   unsigned flags)
496 {
497     return pj_sock_sendto(sockfd, buf, len, flags, NULL, 0);
498 }
499
500
501 /*
502  * Send data.
503  */
504 PJ_DEF(pj_status_t) pj_sock_sendto( pj_sock_t sockfd,
505                                     const void *buff,
506                                     pj_ssize_t *len,
507                                     unsigned flags,
508                                     const pj_sockaddr_t *addr,
509                                     int addr_len)
510 {
511     long err;
512     mm_segment_t oldfs;
513
514     PJ_CHECK_STACK();
515
516     oldfs = get_fs();
517     set_fs(KERNEL_DS);
518     
519     err = *len = sys_sendto( sockfd, (void*)buff, *len, flags, 
520                              (void*)addr, addr_len );
521
522     set_fs(oldfs);
523     
524     if (err >= 0) {
525         return PJ_SUCCESS;
526     }
527     else {
528         return PJ_RETURN_OS_ERROR(-err);
529     }
530 }
531
532 /*
533  * Receive data.
534  */
535 PJ_DEF(pj_status_t) pj_sock_recv( pj_sock_t sockfd,
536                                   void *buf,
537                                   pj_ssize_t *len,
538                                   unsigned flags)
539 {
540     return pj_sock_recvfrom(sockfd, buf, len, flags, NULL, NULL);
541 }
542
543 /*
544  * Receive data.
545  */
546 PJ_DEF(pj_status_t) pj_sock_recvfrom( pj_sock_t sockfd,
547                                       void *buff,
548                                       pj_ssize_t *size,
549                                       unsigned flags,
550                                       pj_sockaddr_t *from,
551                                       int *fromlen)
552 {
553     mm_segment_t oldfs;
554     long err;
555
556     PJ_CHECK_STACK();
557
558     oldfs = get_fs();
559     set_fs(KERNEL_DS);
560
561     err = *size = sys_recvfrom( sockfd, buff, *size, flags, from, fromlen);
562
563     set_fs(oldfs);
564
565     if (err >= 0) {
566         return PJ_SUCCESS;
567     }
568     else {
569         return PJ_RETURN_OS_ERROR(-err);
570     }
571 }
572
573 /*
574  * Get socket option.
575  */
576 PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sockfd,
577                                         pj_uint16_t level,
578                                         pj_uint16_t optname,
579                                         void *optval,
580                                         int *optlen)
581 {
582     mm_segment_t oldfs;
583     long err;
584
585     PJ_CHECK_STACK();
586
587     oldfs = get_fs();
588     set_fs(KERNEL_DS);
589
590     err = sys_getsockopt( sockfd, level, optname, optval, optlen);
591
592     set_fs(oldfs);
593
594     if (err)
595         return PJ_RETURN_OS_ERROR(-err);
596     else
597         return PJ_SUCCESS;
598 }
599
600 /*
601  * Set socket option.
602  */
603 PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
604                                         pj_uint16_t level,
605                                         pj_uint16_t optname,
606                                         const void *optval,
607                                         int optlen)
608 {
609     long err;
610     mm_segment_t oldfs;
611
612     PJ_CHECK_STACK();
613
614
615     oldfs = get_fs();
616     set_fs(KERNEL_DS);
617
618     err = sys_setsockopt( sockfd, level, optname, (void*)optval, optlen);
619
620     set_fs(oldfs);
621
622     if (err)
623         return PJ_RETURN_OS_ERROR(-err);
624     else
625         return PJ_SUCCESS;
626 }
627
628 /*
629  * Shutdown socket.
630  */
631 #if PJ_HAS_TCP
632 PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sockfd,
633                                       int how)
634 {
635     long err;
636
637     PJ_CHECK_STACK();
638
639     err = sys_shutdown(sockfd, how);
640
641     if (err)
642         return PJ_RETURN_OS_ERROR(-err);
643     else
644         return PJ_SUCCESS;
645 }
646
647 /*
648  * Start listening to incoming connections.
649  */
650 PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sockfd,
651                                     int backlog)
652 {
653     long err;
654
655     PJ_CHECK_STACK();
656
657     err = sys_listen( sockfd, backlog );
658
659     if (err)
660         return PJ_RETURN_OS_ERROR(-err);
661     else
662         return PJ_SUCCESS;
663 }
664
665 /*
666  * Connect socket.
667  */
668 PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sockfd,
669                                      const pj_sockaddr_t *addr,
670                                      int namelen)
671 {
672     long err;
673     mm_segment_t oldfs;
674     
675     PJ_CHECK_STACK();
676
677     oldfs = get_fs();
678     set_fs(KERNEL_DS);
679
680     err = sys_connect( sockfd, (void*)addr, namelen );
681
682     set_fs(oldfs);
683
684     if (err)
685         return PJ_RETURN_OS_ERROR(-err);
686     else
687         return PJ_SUCCESS;
688 }
689
690 /*
691  * Accept incoming connections
692  */
693 PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t sockfd,
694                                     pj_sock_t *newsockfd,
695                                     pj_sockaddr_t *addr,
696                                     int *addrlen)
697 {
698     long err;
699
700     PJ_CHECK_STACK();
701
702     PJ_ASSERT_RETURN(newsockfd != NULL, PJ_EINVAL);
703
704     err = sys_accept( sockfd, addr, addrlen);
705
706     if (err < 0) {
707         *newsockfd = PJ_INVALID_SOCKET;
708         return PJ_RETURN_OS_ERROR(-err);
709     }
710     else {
711         *newsockfd = err;
712         return PJ_SUCCESS;
713     }
714 }
715 #endif  /* PJ_HAS_TCP */
716
717
718
719 /*
720  * Permission to steal inet_ntoa() and inet_aton() as long as this notice below
721  * is included:
722  */
723 /*
724  * Copyright (c) 1983, 1993
725  *  The Regents of the University of California.  All rights reserved.
726  *
727  * Redistribution and use in source and binary forms, with or without
728  * modification, are permitted provided that the following conditions
729  * are met:
730  * 1. Redistributions of source code must retain the above copyright
731  *    notice, this list of conditions and the following disclaimer.
732  * 2. Redistributions in binary form must reproduce the above copyright
733  *    notice, this list of conditions and the following disclaimer in the
734  *    documentation and/or other materials provided with the distribution.
735  * 3. All advertising materials mentioning features or use of this software
736  *    must display the following acknowledgement:
737  *  This product includes software developed by the University of
738  *  California, Berkeley and its contributors.
739  * 4. Neither the name of the University nor the names of its contributors
740  *    may be used to endorse or promote products derived from this software
741  *    without specific prior written permission.
742  *
743  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
744  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
745  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
746  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
747  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
748  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
749  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
750  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
751  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
752  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
753  * SUCH DAMAGE.
754  */
755