~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib/src/pj/sock_linux_kernel.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: sock_linux_kernel.c 3553 2011-05-05 06:14:19Z nanang $ */
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
 
 */