1
/* $Id: sock_linux_kernel.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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() */
26
#include <pj/compat/sprintf.h>
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() */
40
* Address families conversion.
41
* The values here are indexed based on pj_addr_family-0xFF00.
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;
47
const pj_uint16_t PJ_AF_PACKET = AF_PACKET;
49
# error "AF_PACKET undeclared!"
52
const pj_uint16_t PJ_AF_IRDA = AF_IRDA;
54
# error "AF_IRDA undeclared!"
58
* Socket types conversion.
59
* The values here are indexed based on pj_sock_type-0xFF00
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;
67
* Socket level values.
69
const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
71
const pj_uint16_t PJ_SOL_IP = SOL_IP;
73
# error "SOL_IP undeclared!"
76
const pj_uint16_t PJ_SOL_TCP = SOL_TCP;
78
# error "SOL_TCP undeclared!"
81
const pj_uint16_t PJ_SOL_UDP = SOL_UDP;
83
# error "SOL_UDP undeclared!"
86
const pj_uint16_t PJ_SOL_IPV6 = SOL_IPV6;
88
# error "SOL_IPV6 undeclared!"
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;
97
* Convert 16-bit value from network byte order to host byte order.
99
PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
101
return ntohs(netshort);
105
* Convert 16-bit value from host byte order to network byte order.
107
PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
109
return htons(hostshort);
113
* Convert 32-bit value from network byte order to host byte order.
115
PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
117
return ntohl(netlong);
121
* Convert 32-bit value from host byte order to network byte order.
123
PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
125
return htonl(hostlong);
129
* Convert an Internet host address given in network byte order
130
* to string in standard numbers and dots notation.
132
PJ_DEF(char*) pj_inet_ntoa(pj_in_addr in)
134
#define UC(b) (((int)b)&0xff)
139
pj_snprintf(b, sizeof(b), "%d.%d.%d.%d",
140
UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
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.
150
PJ_DEF(int) pj_inet_aton(const pj_str_t *ccp, struct pj_in_addr *addr)
156
unsigned *pp = parts;
160
addr->s_addr = PJ_INADDR_NONE;
162
if (ccp->slen > 15) return 0;
164
pj_memcpy(cp, ccp->ptr, ccp->slen);
165
cp[ccp->slen] = '\0';
170
* Collect number up to ``.''.
171
* Values are specified as for C:
172
* 0x=hex, 0=octal, isdigit=decimal.
174
if (!pj_isdigit((int)c))
179
if (c == 'x' || c == 'X')
180
base = 16, c = *++cp;
186
if (pj_isascii((int)c) && pj_isdigit((int)c)) {
187
val = (val * base) + (c - '0');
189
} else if (base==16 && pj_isascii((int)c) && pj_isxdigit((int)c)) {
191
(c + 10 - (pj_islower((int)c) ? 'a' : 'A'));
201
* a.b.c (with c treated as 16 bits)
202
* a.b (with b treated as 24 bits)
213
* Check for trailing characters.
215
if (c != '\0' && (!pj_isascii((int)c) || !pj_isspace((int)c)))
218
* Concoct the address according to
219
* the number of parts specified.
224
return (0); /* initial nondigit */
225
case 1: /* a -- 32 bits */
227
case 2: /* a.b -- 8.24 bits */
230
val |= parts[0] << 24;
232
case 3: /* a.b.c -- 8.8.16 bits */
235
val |= (parts[0] << 24) | (parts[1] << 16);
237
case 4: /* a.b.c.d -- 8.8.8.8 bits */
240
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
245
addr->s_addr = pj_htonl(val);
250
* Convert address string with numbers and dots to binary IP address.
252
PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
255
pj_inet_aton(cp, &addr);
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
266
PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
267
const pj_str_t *str_addr)
271
pj_assert(str_addr && str_addr->slen < PJ_MAX_HOSTNAME);
273
addr->sin_family = AF_INET;
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) {
279
if (pj_gethostbyname(str_addr, &he) == 0) {
280
addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
282
addr->sin_addr.s_addr = PJ_INADDR_NONE;
288
addr->sin_addr.s_addr = 0;
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.
300
PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
301
const pj_str_t *str_addr,
304
pj_assert(addr && str_addr);
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);
315
PJ_DEF(const pj_str_t*) pj_gethostname(void)
317
static char buf[PJ_MAX_HOSTNAME];
318
static pj_str_t hostname;
322
if (hostname.ptr == NULL) {
325
hostname.slen = strlen(system_utsname.nodename);
326
if (hostname.slen > PJ_MAX_HOSTNAME) {
327
hostname.ptr[0] = '\0';
330
pj_memcpy(hostname.ptr, system_utsname.nodename, hostname.slen);
338
* Get first IP address associated with the hostname.
340
PJ_DEF(pj_in_addr) pj_gethostaddr(void)
343
const pj_str_t *hostname = pj_gethostname();
345
pj_sockaddr_in_set_str_addr(&addr, hostname);
346
return addr.sin_addr;
351
* Create new socket/endpoint for communication and returns a descriptor.
353
PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto,
361
PJ_ASSERT_RETURN(PJ_INVALID_SOCKET == -1 && sock_fd != NULL, PJ_EINVAL);
363
/* Initialize returned socket */
364
*sock_fd = PJ_INVALID_SOCKET;
367
result = sys_socket(af, type, proto);
369
return PJ_RETURN_OS_ERROR((-result));
380
PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sockfd,
381
const pj_sockaddr_t *addr,
389
PJ_ASSERT_RETURN(addr!=NULL && len >= sizeof(struct pj_sockaddr),
395
err = sys_bind(sockfd, (struct sockaddr*)addr, len);
400
return PJ_RETURN_OS_ERROR(-err);
409
PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd,
417
addr.sin_family = PJ_AF_INET;
418
addr.sin_addr.s_addr = pj_htonl(addr32);
419
addr.sin_port = pj_htons(port);
421
return pj_sock_bind(sockfd, &addr, sizeof(pj_sockaddr_in));
427
PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sockfd)
431
err = sys_close(sockfd);
434
return PJ_RETURN_OS_ERROR(-err);
442
PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sockfd,
454
err = sys_getpeername( sockfd, addr, namelen);
459
return PJ_RETURN_OS_ERROR(-err);
467
PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sockfd,
479
err = sys_getsockname( sockfd, addr, namelen );
484
return PJ_RETURN_OS_ERROR(-err);
492
PJ_DEF(pj_status_t) pj_sock_send( pj_sock_t sockfd,
497
return pj_sock_sendto(sockfd, buf, len, flags, NULL, 0);
504
PJ_DEF(pj_status_t) pj_sock_sendto( pj_sock_t sockfd,
508
const pj_sockaddr_t *addr,
519
err = *len = sys_sendto( sockfd, (void*)buff, *len, flags,
520
(void*)addr, addr_len );
528
return PJ_RETURN_OS_ERROR(-err);
535
PJ_DEF(pj_status_t) pj_sock_recv( pj_sock_t sockfd,
540
return pj_sock_recvfrom(sockfd, buf, len, flags, NULL, NULL);
546
PJ_DEF(pj_status_t) pj_sock_recvfrom( pj_sock_t sockfd,
561
err = *size = sys_recvfrom( sockfd, buff, *size, flags, from, fromlen);
569
return PJ_RETURN_OS_ERROR(-err);
576
PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sockfd,
590
err = sys_getsockopt( sockfd, level, optname, optval, optlen);
595
return PJ_RETURN_OS_ERROR(-err);
603
PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,
618
err = sys_setsockopt( sockfd, level, optname, (void*)optval, optlen);
623
return PJ_RETURN_OS_ERROR(-err);
632
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sockfd,
639
err = sys_shutdown(sockfd, how);
642
return PJ_RETURN_OS_ERROR(-err);
648
* Start listening to incoming connections.
650
PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sockfd,
657
err = sys_listen( sockfd, backlog );
660
return PJ_RETURN_OS_ERROR(-err);
668
PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sockfd,
669
const pj_sockaddr_t *addr,
680
err = sys_connect( sockfd, (void*)addr, namelen );
685
return PJ_RETURN_OS_ERROR(-err);
691
* Accept incoming connections
693
PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t sockfd,
694
pj_sock_t *newsockfd,
702
PJ_ASSERT_RETURN(newsockfd != NULL, PJ_EINVAL);
704
err = sys_accept( sockfd, addr, addrlen);
707
*newsockfd = PJ_INVALID_SOCKET;
708
return PJ_RETURN_OS_ERROR(-err);
715
#endif /* PJ_HAS_TCP */
720
* Permission to steal inet_ntoa() and inet_aton() as long as this notice below
724
* Copyright (c) 1983, 1993
725
* The Regents of the University of California. All rights reserved.
727
* Redistribution and use in source and binary forms, with or without
728
* modification, are permitted provided that the following conditions
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.
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