Exemple #1
0
/**
 *Creates a nonblocking IPv6 socket
 *@param sin sockaddr_in6 struct. Used for bind(2).
 *@return the FD of the socket or -1 on error.
 */
int
os_getsocket6(const char *if_name, uint16_t port, int bufspace, union olsr_sockaddr *bindto)
{
  struct sockaddr_in6 sin6;
  int on;
  int sock = socket(AF_INET6, SOCK_DGRAM, 0);
  if (sock < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
    olsr_exit(EXIT_FAILURE);
  }
#ifdef IPV6_V6ONLY
  on = 1;
  if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
    OLSR_WARN(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to ipv6 only (%s)\n", strerror(errno));
  }
#endif


  //#ifdef SO_BROADCAST
  /*
     if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof(on)) < 0)
     {
     perror("setsockopt");
     syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
     close(sock);
     return (-1);
     }
   */
  //#endif

#ifdef SO_RCVBUF
  if(bufspace > 0) {
    for (on = bufspace;; on -= 1024) {
      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0) {
        OLSR_DEBUG(LOG_NETWORKING, "Set socket buffer space to %d\n", on);
        break;
      }
      if (on <= 8 * 1024) {
        OLSR_WARN(LOG_NETWORKING, "Could not set a socket buffer space for OLSR PDUs (%s)\n", strerror(errno));
        break;
      }
    }
  }
#endif

  on = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot reuse address for socket for OLSR PDUs (%s)\n", strerror(errno));
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }

  /*
   * we are abusing "on" here. The value is 1 which is our intended
   * hop limit value.
   */
  if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &on, sizeof(on)) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot set multicast hops to 1 for socket for OLSR PDUs (%s)\n", strerror(errno));
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }


  /*
   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
   */

  /* Bind to device */
  if (bind_socket_to_device(sock, if_name) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot bind socket for OLSR PDUs to interface %s: %s (%d)\n", if_name, strerror(errno), errno);
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }

  if (bindto == NULL) {
    memset(&sin6, 0, sizeof(sin6));
    sin6.sin6_family = AF_INET6;
    sin6.sin6_port = htons(port);
    bindto = (union olsr_sockaddr *)&sin6;
  }
  if (bind(sock, &bindto->std, sizeof(*bindto)) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot bind socket for OLSR PDUs (%s)\n", strerror(errno));
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }

  os_socket_set_nonblocking(sock);
  return sock;
}
Exemple #2
0
/**
 *Creates a nonblocking IPv6 socket
 *@param sin sockaddr_in6 struct. Used for bind(2).
 *@return the FD of the socket or -1 on error.
 */
int
getsocket6(int bufspace, struct interface *ifp)
{
  struct sockaddr_in6 sin;
  int on;
  int sock = socket(AF_INET6, SOCK_DGRAM, 0);
  if (sock < 0) {
    perror("socket");
    syslog(LOG_ERR, "socket: %m");
    return (-1);
  }
#ifdef IPV6_V6ONLY
  on = 1;
  if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
    perror("setsockopt(IPV6_V6ONLY)");
    syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
  }
#endif

  //#ifdef SO_BROADCAST
  /*
     if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0)
     {
     perror("setsockopt");
     syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
     close(sock);
     return (-1);
     }
   */
  //#endif

#ifdef SO_RCVBUF
  if(bufspace > 0) {
    for (on = bufspace;; on -= 1024) {
      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0)
        break;
      if (on <= 8 * 1024) {
        perror("setsockopt");
        syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
        break;
      }
    }
  }
#endif

  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    perror("SO_REUSEADDR failed");
    close(sock);
    return (-1);
  }

  /*
   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
   */

  /* Bind to device */
  if (bind_socket_to_device(sock, ifp->int_name) < 0) {
    fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
    syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
    close(sock);
    return -1;
  }

  memset(&sin, 0, sizeof(sin));
  sin.sin6_family = AF_INET6;
  sin.sin6_port = htons(olsr_cnf->olsrport);
  sin.sin6_scope_id = ifp->if_index;

  if(bufspace <= 0) {
    memcpy(&sin.sin6_addr, &ifp->int6_addr.sin6_addr, sizeof(struct in6_addr));
  }

  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    struct ipaddr_str buf;
    OLSR_PRINTF(1, "Error, cannot bind address %s to %s-socket: %s (%d)\n",
        inet_ntop(sin.sin6_family, &sin.sin6_addr, buf.buf, sizeof(buf)),
        bufspace <= 0 ? "transmit" : "receive",
        strerror(errno), errno);
    syslog(LOG_ERR, "bind: %m");
    close(sock);
    return (-1);
  }

  on = fcntl(sock, F_GETFL);
  if (on == -1) {
    syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
  } else {
    if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
      syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
    }
  }
  return sock;
}
Exemple #3
0
/**
 *Creates a nonblocking broadcast socket.
 *@param sa sockaddr struct. Used for bind(2).
 *@return the FD of the socket or -1 on error.
 */
int
os_getsocket4(const char *if_name, uint16_t port, int bufspace, union olsr_sockaddr *bindto)
{
  struct sockaddr_in sin4;
  int on;
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
    olsr_exit(EXIT_FAILURE);
  }

  on = 1;
#ifdef SO_BROADCAST
  if (bindto) {
    if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
      OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
      close(sock);
      olsr_exit(EXIT_FAILURE);
    }
  }
#endif

  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot reuse address for OLSR PDUs (%s)\n", strerror(errno));
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }
#ifdef SO_RCVBUF
  if(bufspace > 0) {
    for (on = bufspace;; on -= 1024) {
      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0) {
        OLSR_DEBUG(LOG_NETWORKING, "Set socket buffer space to %d\n", on);
        break;
      }
      if (on <= 8 * 1024) {
        OLSR_WARN(LOG_NETWORKING, "Could not set a socket buffer space for OLSR PDUs (%s)\n", strerror(errno));
        break;
      }
    }
  }
#endif

  /*
   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
   */

  /* Bind to device */
  if (bind_socket_to_device(sock, if_name) < 0) {
    OLSR_ERROR(LOG_NETWORKING, "Cannot bind socket for OLSR PDUs to interface %s: %s (%d)\n", if_name, strerror(errno), errno);
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }

  if (bindto == NULL) {
    memset(&sin4, 0, sizeof(sin4));
    sin4.sin_family = AF_INET;
    sin4.sin_port = htons(port);
    sin4.sin_addr.s_addr = 0;
    bindto = (union olsr_sockaddr *)&sin4;
  }
  if (bind(sock, &bindto->std, sizeof(*bindto)) < 0) {
#if !defined(REMOVE_LOG_ERROR)
    struct ipaddr_str buf;
#endif
    OLSR_ERROR(LOG_NETWORKING, "Could not bind socket for OLSR PDUs to %s/%d: %s (%d)\n",
        inet_ntop(AF_INET, &sin4.sin_addr, buf.buf, sizeof(buf)), port, strerror(errno), errno);
    close(sock);
    olsr_exit(EXIT_FAILURE);
  }

  os_socket_set_nonblocking(sock);
  return sock;
}
Exemple #4
0
/**
 *Creates a nonblocking broadcast socket.
 *@param sa sockaddr struct. Used for bind(2).
 *@return the FD of the socket or -1 on error.
 */
int
getsocket(int bufspace, struct interface *ifp)
{
  struct sockaddr_in sin;
  int on;
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock < 0) {
    perror("socket");
    syslog(LOG_ERR, "socket: %m");
    return -1;
  }

  on = 1;
#ifdef SO_BROADCAST
  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
    perror("setsockopt");
    syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
    close(sock);
    return -1;
  }
#endif

  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    perror("SO_REUSEADDR failed");
    close(sock);
    return -1;
  }
#ifdef SO_RCVBUF
  if(bufspace > 0) {
    for (on = bufspace;; on -= 1024) {
      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0)
        break;
      if (on <= 8 * 1024) {
        perror("setsockopt");
        syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
        break;
      }
    }
  }
#endif

  /*
   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
   */

  /* Bind to device */
  if (bind_socket_to_device(sock, ifp->int_name) < 0) {
    fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
    syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
    close(sock);
    return -1;
  }

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(olsr_cnf->olsrport);

  if(bufspace <= 0) {
    sin.sin_addr.s_addr = ifp->int_addr.sin_addr.s_addr;
  }

  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    perror("bind");
    syslog(LOG_ERR, "bind: %m");
    close(sock);
    return -1;
  }

  on = fcntl(sock, F_GETFL);
  if (on == -1) {
    syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
  } else {
    if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
      syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
    }
  }
  return sock;
}