root/source4/lib/socket/socket.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. socket_destructor
  2. socket_tevent_fd_close_fn
  3. socket_create_with_ops
  4. socket_create
  5. socket_connect
  6. socket_connect_complete
  7. socket_listen
  8. socket_accept
  9. socket_recv
  10. socket_recvfrom
  11. socket_send
  12. socket_sendto
  13. socket_pending
  14. socket_set_option
  15. socket_get_peer_name
  16. socket_get_peer_addr
  17. socket_get_my_addr
  18. socket_get_fd
  19. socket_dup
  20. socket_address_from_strings
  21. socket_address_from_sockaddr
  22. socket_address_copy
  23. socket_getops_byname
  24. set_socket_options
  25. socket_set_flags

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    Socket functions
   4    Copyright (C) Andrew Tridgell 1992-1998
   5    Copyright (C) Tim Potter      2000-2001
   6    Copyright (C) Stefan Metzmacher 2004
   7    
   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.
  12    
  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.
  17    
  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/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "lib/socket/socket.h"
  24 #include "system/filesys.h"
  25 #include "system/network.h"
  26 #include "param/param.h"
  27 
  28 /*
  29   auto-close sockets on free
  30 */
  31 static int socket_destructor(struct socket_context *sock)
     /* [<][>][^][v][top][bottom][index][help] */
  32 {
  33         if (sock->ops->fn_close && 
  34             !(sock->flags & SOCKET_FLAG_NOCLOSE)) {
  35                 sock->ops->fn_close(sock);
  36         }
  37         return 0;
  38 }
  39 
  40 _PUBLIC_ void socket_tevent_fd_close_fn(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
  41                                         struct tevent_fd *fde,
  42                                         int fd,
  43                                         void *private_data)
  44 {
  45         /* this might be the socket_wrapper swrap_close() */
  46         close(fd);
  47 }
  48 
  49 _PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
     /* [<][>][^][v][top][bottom][index][help] */
  50                                          struct socket_context **new_sock, 
  51                                          enum socket_type type, uint32_t flags)
  52 {
  53         NTSTATUS status;
  54 
  55         (*new_sock) = talloc(mem_ctx, struct socket_context);
  56         if (!(*new_sock)) {
  57                 return NT_STATUS_NO_MEMORY;
  58         }
  59 
  60         (*new_sock)->type = type;
  61         (*new_sock)->state = SOCKET_STATE_UNDEFINED;
  62         (*new_sock)->flags = flags;
  63 
  64         (*new_sock)->fd = -1;
  65 
  66         (*new_sock)->private_data = NULL;
  67         (*new_sock)->ops = ops;
  68         (*new_sock)->backend_name = NULL;
  69 
  70         status = (*new_sock)->ops->fn_init((*new_sock));
  71         if (!NT_STATUS_IS_OK(status)) {
  72                 talloc_free(*new_sock);
  73                 return status;
  74         }
  75 
  76         /* by enabling "testnonblock" mode, all socket receive and
  77            send calls on non-blocking sockets will randomly recv/send
  78            less data than requested */
  79 
  80         if (!(flags & SOCKET_FLAG_BLOCK) &&
  81             type == SOCKET_TYPE_STREAM &&
  82                 getenv("SOCKET_TESTNONBLOCK") != NULL) {
  83                 (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK;
  84         }
  85 
  86         /* we don't do a connect() on dgram sockets, so need to set
  87            non-blocking at socket create time */
  88         if (!(flags & SOCKET_FLAG_BLOCK) && type == SOCKET_TYPE_DGRAM) {
  89                 set_blocking(socket_get_fd(*new_sock), false);
  90         }
  91 
  92         talloc_set_destructor(*new_sock, socket_destructor);
  93 
  94         return NT_STATUS_OK;
  95 }
  96 
  97 _PUBLIC_ NTSTATUS socket_create(const char *name, enum socket_type type, 
     /* [<][>][^][v][top][bottom][index][help] */
  98                                 struct socket_context **new_sock, uint32_t flags)
  99 {
 100         const struct socket_ops *ops;
 101 
 102         ops = socket_getops_byname(name, type);
 103         if (!ops) {
 104                 return NT_STATUS_INVALID_PARAMETER;
 105         }
 106 
 107         return socket_create_with_ops(NULL, ops, new_sock, type, flags);
 108 }
 109 
 110 _PUBLIC_ NTSTATUS socket_connect(struct socket_context *sock,
     /* [<][>][^][v][top][bottom][index][help] */
 111                                  const struct socket_address *my_address, 
 112                                  const struct socket_address *server_address,
 113                                  uint32_t flags)
 114 {
 115         if (sock == NULL) {
 116                 return NT_STATUS_CONNECTION_DISCONNECTED;
 117         }
 118         if (sock->state != SOCKET_STATE_UNDEFINED) {
 119                 return NT_STATUS_INVALID_PARAMETER;
 120         }
 121 
 122         if (!sock->ops->fn_connect) {
 123                 return NT_STATUS_NOT_IMPLEMENTED;
 124         }
 125 
 126         return sock->ops->fn_connect(sock, my_address, server_address, flags);
 127 }
 128 
 129 _PUBLIC_ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 130 {
 131         if (!sock->ops->fn_connect_complete) {
 132                 return NT_STATUS_NOT_IMPLEMENTED;
 133         }
 134         return sock->ops->fn_connect_complete(sock, flags);
 135 }
 136 
 137 _PUBLIC_ NTSTATUS socket_listen(struct socket_context *sock, 
     /* [<][>][^][v][top][bottom][index][help] */
 138                                 const struct socket_address *my_address, 
 139                                 int queue_size, uint32_t flags)
 140 {
 141         if (sock == NULL) {
 142                 return NT_STATUS_CONNECTION_DISCONNECTED;
 143         }
 144         if (sock->state != SOCKET_STATE_UNDEFINED) {
 145                 return NT_STATUS_INVALID_PARAMETER;
 146         }
 147 
 148         if (!sock->ops->fn_listen) {
 149                 return NT_STATUS_NOT_IMPLEMENTED;
 150         }
 151 
 152         return sock->ops->fn_listen(sock, my_address, queue_size, flags);
 153 }
 154 
 155 _PUBLIC_ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock)
     /* [<][>][^][v][top][bottom][index][help] */
 156 {
 157         NTSTATUS status;
 158 
 159         if (sock == NULL) {
 160                 return NT_STATUS_CONNECTION_DISCONNECTED;
 161         }
 162         if (sock->type != SOCKET_TYPE_STREAM) {
 163                 return NT_STATUS_INVALID_PARAMETER;
 164         }
 165 
 166         if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
 167                 return NT_STATUS_INVALID_PARAMETER;
 168         }
 169 
 170         if (!sock->ops->fn_accept) {
 171                 return NT_STATUS_NOT_IMPLEMENTED;
 172         }
 173 
 174         status = sock->ops->fn_accept(sock, new_sock);
 175 
 176         if (NT_STATUS_IS_OK(status)) {
 177                 talloc_set_destructor(*new_sock, socket_destructor);
 178                 (*new_sock)->flags = 0;
 179         }
 180 
 181         return status;
 182 }
 183 
 184 _PUBLIC_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, 
     /* [<][>][^][v][top][bottom][index][help] */
 185                               size_t wantlen, size_t *nread)
 186 {
 187         if (sock == NULL) {
 188                 return NT_STATUS_CONNECTION_DISCONNECTED;
 189         }
 190         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
 191             sock->state != SOCKET_STATE_SERVER_CONNECTED &&
 192             sock->type  != SOCKET_TYPE_DGRAM) {
 193                 return NT_STATUS_INVALID_PARAMETER;
 194         }
 195 
 196         if (!sock->ops->fn_recv) {
 197                 return NT_STATUS_NOT_IMPLEMENTED;
 198         }
 199 
 200         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) 
 201             && wantlen > 1) {
 202 
 203                 if (random() % 10 == 0) {
 204                         *nread = 0;
 205                         return STATUS_MORE_ENTRIES;
 206                 }
 207                 return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread);
 208         }
 209         return sock->ops->fn_recv(sock, buf, wantlen, nread);
 210 }
 211 
 212 _PUBLIC_ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, 
     /* [<][>][^][v][top][bottom][index][help] */
 213                                   size_t wantlen, size_t *nread, 
 214                                   TALLOC_CTX *mem_ctx, struct socket_address **src_addr)
 215 {
 216         if (sock == NULL) {
 217                 return NT_STATUS_CONNECTION_DISCONNECTED;
 218         }
 219         if (sock->type != SOCKET_TYPE_DGRAM) {
 220                 return NT_STATUS_INVALID_PARAMETER;
 221         }
 222 
 223         if (!sock->ops->fn_recvfrom) {
 224                 return NT_STATUS_NOT_IMPLEMENTED;
 225         }
 226 
 227         return sock->ops->fn_recvfrom(sock, buf, wantlen, nread, 
 228                                       mem_ctx, src_addr);
 229 }
 230 
 231 _PUBLIC_ NTSTATUS socket_send(struct socket_context *sock, 
     /* [<][>][^][v][top][bottom][index][help] */
 232                               const DATA_BLOB *blob, size_t *sendlen)
 233 {
 234         if (sock == NULL) {
 235                 return NT_STATUS_CONNECTION_DISCONNECTED;
 236         }
 237         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
 238             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
 239                 return NT_STATUS_INVALID_PARAMETER;
 240         }
 241 
 242         if (!sock->ops->fn_send) {
 243                 return NT_STATUS_NOT_IMPLEMENTED;
 244         }
 245         
 246         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
 247             && blob->length > 1) {
 248                 DATA_BLOB blob2 = *blob;
 249                 if (random() % 10 == 0) {
 250                         *sendlen = 0;
 251                         return STATUS_MORE_ENTRIES;
 252                 }
 253                 /* The random size sends are incompatible with TLS and SASL
 254                  * sockets, which require re-sends to be consistant */
 255                 if (!(sock->flags & SOCKET_FLAG_ENCRYPT)) {
 256                         blob2.length = 1+(random() % blob2.length);
 257                 } else {
 258                         /* This is particularly stressful on buggy
 259                          * LDAP clients, that don't expect on LDAP
 260                          * packet in many SASL packets */
 261                         blob2.length = 1 + blob2.length/2;
 262                 }
 263                 return sock->ops->fn_send(sock, &blob2, sendlen);
 264         }
 265         return sock->ops->fn_send(sock, blob, sendlen);
 266 }
 267 
 268 
 269 _PUBLIC_ NTSTATUS socket_sendto(struct socket_context *sock, 
     /* [<][>][^][v][top][bottom][index][help] */
 270                                 const DATA_BLOB *blob, size_t *sendlen, 
 271                                 const struct socket_address *dest_addr)
 272 {
 273         if (sock == NULL) {
 274                 return NT_STATUS_CONNECTION_DISCONNECTED;
 275         }
 276         if (sock->type != SOCKET_TYPE_DGRAM) {
 277                 return NT_STATUS_INVALID_PARAMETER;
 278         }
 279 
 280         if (sock->state == SOCKET_STATE_CLIENT_CONNECTED ||
 281             sock->state == SOCKET_STATE_SERVER_CONNECTED) {
 282                 return NT_STATUS_INVALID_PARAMETER;
 283         }
 284 
 285         if (!sock->ops->fn_sendto) {
 286                 return NT_STATUS_NOT_IMPLEMENTED;
 287         }
 288 
 289         return sock->ops->fn_sendto(sock, blob, sendlen, dest_addr);
 290 }
 291 
 292 
 293 /*
 294   ask for the number of bytes in a pending incoming packet
 295 */
 296 _PUBLIC_ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending)
     /* [<][>][^][v][top][bottom][index][help] */
 297 {
 298         if (sock == NULL) {
 299                 return NT_STATUS_CONNECTION_DISCONNECTED;
 300         }
 301         if (!sock->ops->fn_pending) {
 302                 return NT_STATUS_NOT_IMPLEMENTED;
 303         }
 304         return sock->ops->fn_pending(sock, npending);
 305 }
 306 
 307 
 308 _PUBLIC_ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
     /* [<][>][^][v][top][bottom][index][help] */
 309 {
 310         if (sock == NULL) {
 311                 return NT_STATUS_CONNECTION_DISCONNECTED;
 312         }
 313         if (!sock->ops->fn_set_option) {
 314                 return NT_STATUS_NOT_IMPLEMENTED;
 315         }
 316 
 317         return sock->ops->fn_set_option(sock, option, val);
 318 }
 319 
 320 _PUBLIC_ char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 321 {
 322         if (!sock->ops->fn_get_peer_name) {
 323                 return NULL;
 324         }
 325 
 326         return sock->ops->fn_get_peer_name(sock, mem_ctx);
 327 }
 328 
 329 _PUBLIC_ struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 330 {
 331         if (!sock->ops->fn_get_peer_addr) {
 332                 return NULL;
 333         }
 334 
 335         return sock->ops->fn_get_peer_addr(sock, mem_ctx);
 336 }
 337 
 338 _PUBLIC_ struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 339 {
 340         if (!sock->ops->fn_get_my_addr) {
 341                 return NULL;
 342         }
 343 
 344         return sock->ops->fn_get_my_addr(sock, mem_ctx);
 345 }
 346 
 347 _PUBLIC_ int socket_get_fd(struct socket_context *sock)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 349         if (!sock->ops->fn_get_fd) {
 350                 return -1;
 351         }
 352 
 353         return sock->ops->fn_get_fd(sock);
 354 }
 355 
 356 /*
 357   call dup() on a socket, and close the old fd. This is used to change
 358   the fd to the lowest available number, to make select() more
 359   efficient (select speed depends on the maxiumum fd number passed to
 360   it)
 361 */
 362 _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock)
     /* [<][>][^][v][top][bottom][index][help] */
 363 {
 364         int fd;
 365         if (sock->fd == -1) {
 366                 return NT_STATUS_INVALID_HANDLE;
 367         }
 368         fd = dup(sock->fd);
 369         if (fd == -1) {
 370                 return map_nt_error_from_unix(errno);
 371         }
 372         close(sock->fd);
 373         sock->fd = fd;
 374         return NT_STATUS_OK;
 375         
 376 }
 377 
 378 /* Create a new socket_address.  The type must match the socket type.
 379  * The host parameter may be an IP or a hostname 
 380  */
 381 
 382 _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 383                                                             const char *family,
 384                                                             const char *host,
 385                                                             int port)
 386 {
 387         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
 388         if (!addr) {
 389                 return NULL;
 390         }
 391 
 392         addr->family = family;
 393         addr->addr = talloc_strdup(addr, host);
 394         if (!addr->addr) {
 395                 talloc_free(addr);
 396                 return NULL;
 397         }
 398         addr->port = port;
 399         addr->sockaddr = NULL;
 400         addr->sockaddrlen = 0;
 401 
 402         return addr;
 403 }
 404 
 405 /* Create a new socket_address.  Copy the struct sockaddr into the new
 406  * structure.  Used for hooks in the kerberos libraries, where they
 407  * supply only a struct sockaddr */
 408 
 409 _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 410                                                              struct sockaddr *sockaddr, 
 411                                                              size_t sockaddrlen)
 412 {
 413         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
 414         if (!addr) {
 415                 return NULL;
 416         }
 417         addr->family = NULL; 
 418         addr->addr = NULL;
 419         addr->port = 0;
 420         addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen);
 421         if (!addr->sockaddr) {
 422                 talloc_free(addr);
 423                 return NULL;
 424         }
 425         addr->sockaddrlen = sockaddrlen;
 426         return addr;
 427 }
 428 
 429 /* Copy a socket_address structure */
 430 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 431                                            const struct socket_address *oaddr)
 432 {
 433         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
 434         if (!addr) {
 435                 return NULL;
 436         }
 437         addr->family    = oaddr->family;
 438         if (oaddr->addr) {
 439                 addr->addr      = talloc_strdup(addr, oaddr->addr);
 440                 if (!addr->addr) {
 441                         goto nomem;
 442                 }
 443         }
 444         addr->port      = oaddr->port;
 445         if (oaddr->sockaddr) {
 446                 addr->sockaddr = (struct sockaddr *)talloc_memdup(addr,
 447                                                                   oaddr->sockaddr,
 448                                                                   oaddr->sockaddrlen);
 449                 if (!addr->sockaddr) {
 450                         goto nomem;
 451                 }
 452                 addr->sockaddrlen = oaddr->sockaddrlen;
 453         }
 454 
 455         return addr;
 456 
 457 nomem:
 458         talloc_free(addr);
 459         return NULL;
 460 }
 461 
 462 _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum socket_type type)
     /* [<][>][^][v][top][bottom][index][help] */
 463 {
 464         extern const struct socket_ops *socket_ipv4_ops(enum socket_type);
 465         extern const struct socket_ops *socket_ipv6_ops(enum socket_type);
 466         extern const struct socket_ops *socket_unixdom_ops(enum socket_type);
 467 
 468         if (strcmp("ip", family) == 0 || 
 469             strcmp("ipv4", family) == 0) {
 470                 return socket_ipv4_ops(type);
 471         }
 472 
 473 #if HAVE_IPV6
 474         if (strcmp("ipv6", family) == 0) {
 475                 return socket_ipv6_ops(type);
 476         }
 477 #endif
 478 
 479         if (strcmp("unix", family) == 0) {
 480                 return socket_unixdom_ops(type);
 481         }
 482 
 483         return NULL;
 484 }
 485 
 486 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
 487 
 488 static const struct {
 489         const char *name;
 490         int level;
 491         int option;
 492         int value;
 493         int opttype;
 494 } socket_options[] = {
 495   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
 496   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
 497   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
 498 #ifdef TCP_NODELAY
 499   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
 500 #endif
 501 #ifdef IPTOS_LOWDELAY
 502   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
 503 #endif
 504 #ifdef IPTOS_THROUGHPUT
 505   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
 506 #endif
 507 #ifdef SO_REUSEPORT
 508   {"SO_REUSEPORT",      SOL_SOCKET,    SO_REUSEPORT,    0,                 OPT_BOOL},
 509 #endif
 510 #ifdef SO_SNDBUF
 511   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
 512 #endif
 513 #ifdef SO_RCVBUF
 514   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
 515 #endif
 516 #ifdef SO_SNDLOWAT
 517   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
 518 #endif
 519 #ifdef SO_RCVLOWAT
 520   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
 521 #endif
 522 #ifdef SO_SNDTIMEO
 523   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
 524 #endif
 525 #ifdef SO_RCVTIMEO
 526   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
 527 #endif
 528   {NULL,0,0,0,0}};
 529 
 530 
 531 /**
 532  Set user socket options.
 533 **/
 534 _PUBLIC_ void set_socket_options(int fd, const char *options)
     /* [<][>][^][v][top][bottom][index][help] */
 535 {
 536         const char **options_list = (const char **)str_list_make(NULL, options, " \t,");
 537         int j;
 538 
 539         if (!options_list)
 540                 return;
 541 
 542         for (j = 0; options_list[j]; j++) {
 543                 const char *tok = options_list[j];
 544                 int ret=0,i;
 545                 int value = 1;
 546                 char *p;
 547                 bool got_value = false;
 548 
 549                 if ((p = strchr(tok,'='))) {
 550                         *p = 0;
 551                         value = atoi(p+1);
 552                         got_value = true;
 553                 }
 554 
 555                 for (i=0;socket_options[i].name;i++)
 556                         if (strequal(socket_options[i].name,tok))
 557                                 break;
 558 
 559                 if (!socket_options[i].name) {
 560                         DEBUG(0,("Unknown socket option %s\n",tok));
 561                         continue;
 562                 }
 563 
 564                 switch (socket_options[i].opttype) {
 565                 case OPT_BOOL:
 566                 case OPT_INT:
 567                         ret = setsockopt(fd,socket_options[i].level,
 568                                                 socket_options[i].option,(char *)&value,sizeof(int));
 569                         break;
 570 
 571                 case OPT_ON:
 572                         if (got_value)
 573                                 DEBUG(0,("syntax error - %s does not take a value\n",tok));
 574 
 575                         {
 576                                 int on = socket_options[i].value;
 577                                 ret = setsockopt(fd,socket_options[i].level,
 578                                                         socket_options[i].option,(char *)&on,sizeof(int));
 579                         }
 580                         break;    
 581                 }
 582       
 583                 if (ret != 0)
 584                         DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
 585         }
 586 
 587         talloc_free(options_list);
 588 }
 589 
 590 /*
 591   set some flags on a socket 
 592  */
 593 void socket_set_flags(struct socket_context *sock, unsigned flags)
     /* [<][>][^][v][top][bottom][index][help] */
 594 {
 595         sock->flags |= flags;
 596 }

/* [<][>][^][v][top][bottom][index][help] */