コード例 #1
0
ファイル: sendrecv.c プロジェクト: nodakai/ocaml
value unix_sendto_native(value sock, value buff, value ofs, value len, value flags, value dest)
{
    SOCKET s = Socket_val(sock);
    int flg = convert_flag_list(flags, msg_flag_table);
    int ret;
    intnat numbytes;
    char iobuf[UNIX_BUFFER_SIZE];
    union sock_addr_union addr;
    socklen_param_type addr_len;
    DWORD err = 0;

    get_sockaddr(dest, &addr, &addr_len);
    numbytes = Long_val(len);
    if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE;
    memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes);
    enter_blocking_section();
    ret = sendto(s, iobuf, (int) numbytes, flg, &addr.s_gen, addr_len);
    if (ret == -1) err = WSAGetLastError();
    leave_blocking_section();
    if (ret == -1) {
        win32_maperr(err);
        uerror("sendto", Nothing);
    }
    return Val_int(ret);
}
コード例 #2
0
        void
        udphandler::sendto(const void *msg, int len, std::string host, int port)
        {
                sockaddr_storage saddr;
                if (! get_sockaddr(&saddr, host, port))
                        return;

#ifndef WIN32
                ssize_t sendlen = 0;
                size_t  l = len;
#else
                int sendlen = 0;
                int l = len;
#endif // WIN32

                if (m_domain == PF_INET) {
                        sendlen = ::sendto(m_socket, msg, l, 0,
                                           (sockaddr*)&saddr,
                                           sizeof(sockaddr_in));
                } else if (m_domain == PF_INET6) {
                        sendlen = ::sendto(m_socket, msg, l, 0,
                                           (sockaddr*)&saddr,
                                           sizeof(sockaddr_in6));
                }

#ifndef WIN32
                if (sendlen < 0) {
                        perror("sendto");
                }
#else
                if (sendlen == SOCKET_ERROR) {
                        perror("sendto");
                }
#endif // WIN32
        }
コード例 #3
0
ファイル: tcp.c プロジェクト: alista24ftp/cpsc261
/*
 * Connect to the given port on the given host, returning the connected
 * socket.  If there are any errors, print an error message and exit.
 */
int tcp_connect(char *hostname, int port) {
	int skt;
	struct sockaddr_in *my_addr;
	my_addr = malloc(sizeof(struct sockaddr_in));
	
	// create socket
	skt = socket(AF_INET, SOCK_STREAM, 0);
	if(skt<0){
		die0("socket error\n");
	}
	
	// set up sockaddr_in to be local settings (ie. settings on the client computer)
	memset((char *)my_addr, 0, sizeof(*my_addr));
	my_addr->sin_family = AF_INET;
	my_addr->sin_port = htons(0);
	my_addr->sin_addr.s_addr = htonl(INADDR_ANY);
	bzero(&(my_addr->sin_zero),8);
	
	// first bind to LOCAL port	
	printf("Binding to local port...\n");
	if(bind(skt, (struct sockaddr *)my_addr, sizeof(struct sockaddr))<0)
		die0("bind error\n");
	
	// set up to connect to REMOTE PORT
	my_addr = get_sockaddr(hostname, port, (struct sockaddr *)my_addr);
	
	printf("Connecting to port %d...\n", port);
	if(connect(skt, (struct sockaddr *)my_addr, sizeof(struct sockaddr))<0)
		die0("connect error\n");
	printf("connected successfully to %s\n", hostname);

	return skt;
}
コード例 #4
0
ファイル: getnameinfo.c プロジェクト: mzp/coq-for-ipad
CAMLprim value unix_getnameinfo(value vaddr, value vopts)
{
  CAMLparam0();
  CAMLlocal3(vhost, vserv, vres);
  union sock_addr_union addr;
  socklen_param_type addr_len;
  char host[4096];
  char serv[1024];
  int opts, retcode;

  get_sockaddr(vaddr, &addr, &addr_len);
  opts = convert_flag_list(vopts, getnameinfo_flag_table);
  enter_blocking_section();
  retcode =
    getnameinfo((const struct sockaddr *) &addr.s_gen, addr_len,
                host, sizeof(host), serv, sizeof(serv), opts);
  leave_blocking_section();
  if (retcode != 0) raise_not_found(); /* TODO: detailed error reporting? */
  vhost = copy_string(host);
  vserv = copy_string(serv);
  vres = alloc_small(2, 0);
  Field(vres, 0) = vhost;
  Field(vres, 1) = vserv;
  CAMLreturn(vres);
}
コード例 #5
0
ファイル: cliser.c プロジェクト: hardiku/torch-ipc
int cliser_client(lua_State *L) {
#ifdef USE_CUDA
   // sometimes cutorch is loaded late, this is a good spot to try and register...
   Lcliser_CudaInit(L);
#endif
   const char *host;
   const char *port;
   if (lua_type(L, 1) == LUA_TSTRING) {
      host = lua_tostring(L, 1);
      port = lua_tostring(L, 2);
   } else {
      host = DEFAULT_HOST;
      port = lua_tostring(L, 1);
   }
   socklen_t addrlen = sizeof(struct sockaddr);
   struct sockaddr addr;
   int ret = get_sockaddr(L, host, port, &addr, &addrlen);
   if (ret) return ret;
   struct timeval tv;
   gettimeofday(&tv, NULL);
   uint32_t t = tv.tv_sec + DEFAULT_TIMEOUT_SECONDS;
   int sock = -1;
   while (tv.tv_sec < t) {
      ret = socket(PF_INET, SOCK_STREAM, 0);
      if (ret <= 0) return LUA_HANDLE_ERROR(L, errno);
      sock = ret;
      int value = 1;
      ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
      if (ret) break;
      ret = connect(sock, &addr, addrlen);
      if (!ret) break;
      close(sock);
      sleep(1);
      gettimeofday(&tv, NULL);
   }
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   addrlen = sizeof(struct sockaddr);
   struct sockaddr bind_addr;
   ret = getsockname(sock, &bind_addr, &addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   int use_fastpath = can_use_fastpath(L, sock, ((struct sockaddr_in *)&bind_addr)->sin_addr.s_addr, ((struct sockaddr_in *)&addr)->sin_addr.s_addr);
   client_t *client = (client_t *)calloc(1, sizeof(client_t));
   client->sock = sock;
   client->send_rb = ringbuffer_create(SEND_RECV_SIZE);
   client->recv_rb = ringbuffer_create(SEND_RECV_SIZE);
   client->ref_count = 1;
   client->copy_context.use_fastpath = use_fastpath;
   client_t **clientp = (client_t **)lua_newuserdata(L, sizeof(client_t *));
   *clientp = client;
   luaL_getmetatable(L, "ipc.client");
   lua_setmetatable(L, -2);
   return 1;
}
コード例 #6
0
//=============================================================================
int SocketAddress::socket_bind(SOCKET s) const
{
  return ::bind(
    s,
    get_sockaddr(),
    get_sockaddr_size()
  );
}
コード例 #7
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
bool
id_table::set_family(uint16_t id, uint8_t family)
{
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (ss == NULL) {
        return false;
    }
    ss->ss_family = family;
    return true;
}
コード例 #8
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
bool id_table::set_sockaddr(uint16_t id, struct sockaddr* sa, size_t salen)
{
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (ss == NULL) {
        return false;
    } else {
        memcpy(ss, sa, salen);
        return true;
    }
}
コード例 #9
0
ファイル: utpstubs.c プロジェクト: nojb/ocaml-utp
CAMLprim value stub_utp_process_udp (value context, value addr, value buf, value off, value len)
{
  CAMLparam5 (context, addr, buf, off, len);
  union sock_addr_union sock_addr;
  socklen_param_type addr_len;
  int handled;

  get_sockaddr (addr, &sock_addr, &addr_len);
  handled = utp_process_udp (Utp_context_val (context), Caml_ba_data_val (buf) + Int_val (off), Int_val (len), &sock_addr.s_gen, addr_len);
  CAMLreturn (Val_bool (handled));
}
コード例 #10
0
ファイル: bind.c プロジェクト: OCamlPro/OCamlPro-OCaml-Branch
CAMLprim value unix_bind(value socket, value address)
{
  int ret;
  union sock_addr_union addr;
  socklen_param_type addr_len;

  get_sockaddr(address, &addr, &addr_len);
  ret = bind(Int_val(socket), &addr.s_gen, addr_len);
  if (ret == -1) uerror("bind", Nothing);
  return Val_unit;
}
コード例 #11
0
ファイル: utpstubs.c プロジェクト: nojb/ocaml-utp
CAMLprim value stub_utp_connect (value sock, value addr)
{
  CAMLparam2 (sock, addr);
  union sock_addr_union sock_addr;
  socklen_param_type addr_len;
  int res;

  get_sockaddr (addr, &sock_addr, &addr_len);
  res = utp_connect (Utp_socket_val (sock), &sock_addr.s_gen, addr_len);
  if (res < 0) caml_failwith ("utp_connect");
  CAMLreturn (Val_unit);
}
コード例 #12
0
ファイル: sockopt.c プロジェクト: 4og/avango
value skt_bind(value sock_v, value addr_v)
{
    int ret;
    union sock_addr_union addr;
    socklen_param_type addr_len;
    
    get_sockaddr(addr_v, &addr, &addr_len);
    ret = bind(Socket_val(sock_v), (struct sockaddr*) &addr.s_inet, addr_len);
    if (ret == -1) serror("bind");
    SKTTRACE(("bind\n"));
    return Val_unit;
}
コード例 #13
0
ファイル: sockopt.c プロジェクト: 4og/avango
value skt_connect(value sock_v, value address){
    union sock_addr_union addr;
    socklen_param_type addr_len;
    int ret;
    
    get_sockaddr(address, &addr, &addr_len);
    ret = WSAConnect(Socket_val(sock_v), (struct sockaddr*) &addr.s_inet, addr_len,
		     NULL, NULL, NULL, NULL);
    
    if (ret < 0) serror("skt_connect") ;
    SKTTRACE(("skt_connect\n"));
    return Val_unit;
}
コード例 #14
0
ファイル: ext_socket.cpp プロジェクト: hakanertug/hiphop-php
bool f_socket_getsockname(CObjRef socket, VRefParam address,
                          VRefParam port /* = null */) {
  Socket *sock = socket.getTyped<Socket>();

  sockaddr_storage sa_storage;
  socklen_t salen = sizeof(sockaddr_storage);
  struct sockaddr *sa = (struct sockaddr *)&sa_storage;
  if (getsockname(sock->fd(), sa, &salen) < 0) {
    SOCKET_ERROR(sock, "unable to retrieve peer name", errno);
    return false;
  }
  return get_sockaddr(sa, address, port);
}
コード例 #15
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
uint16_t
id_table::get_port(uint16_t id)
{
    uint8_t f = get_family(id);
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (f == AF_INET) {
        return ((struct sockaddr_in*)ss)->sin_port;
    } else if (f == AF_INET6){
        return ((struct sockaddr_in6*)ss)->sin6_port;
    } else {
        return 0;
    }
}
コード例 #16
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
struct in6_addr*
id_table::get_addr6(uint16_t id)
{
    uint8_t f = get_family(id);
    if (f != AF_INET6) {
        return NULL;
    }
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (ss != NULL) {
        return &(((struct sockaddr_in6*)ss)->sin6_addr);
    } else {
        return NULL;
    }
}
コード例 #17
0
ファイル: ext_sockets.cpp プロジェクト: 191919/hhvm
bool HHVM_FUNCTION(socket_getsockname,
                   const Resource& socket,
                   VRefParam address,
                   VRefParam port /* = null */) {
  auto sock = cast<Socket>(socket);

  sockaddr_storage sa_storage;
  socklen_t salen = sizeof(sockaddr_storage);
  struct sockaddr *sa = (struct sockaddr *)&sa_storage;
  if (getsockname(sock->fd(), sa, &salen) < 0) {
    SOCKET_ERROR(sock, "unable to retrieve peer name", errno);
    return false;
  }
  return get_sockaddr(sa, salen, address, port);
}
コード例 #18
0
void run_all(apr_pool_t *pool, int argc, const char * const *argv)
{
    apr_sockaddr_t *sockaddr;

    if (argc != 1) {
        THROW(MESSAGE_ARGUMENT_INVALID);
    }

    DownloadFlowController flow_controller;
    show_line();

    sockaddr = get_sockaddr(pool, DUMMY_ADDRESS);

    run_can_download(&flow_controller, sockaddr);
}
コード例 #19
0
ファイル: bigstring_stubs.c プロジェクト: commonlisp/core
CAMLprim value bigstring_sendto_nonblocking_no_sigpipe_stub(
  value v_fd, value v_pos, value v_len, value v_bstr, value v_addr)
{
  char *bstr = get_bstr(v_bstr, v_pos);
  union sock_addr_union addr;
  socklen_param_type addr_len = sizeof(addr);
  ssize_t ret;
  get_sockaddr(v_addr, &addr, &addr_len);
  ret =
    sendto(
      Int_val(v_fd), bstr, Long_val(v_len),
      nonblocking_no_sigpipe_flag, &addr.s_gen, addr_len);
  if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
    uerror("sendto_nonblocking_no_sigpipe", Nothing);
  return Val_long(ret);
}
コード例 #20
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
bool
id_table::set_addr4(uint16_t id, struct in_addr  addr)
{
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (ss == NULL) {
        return false;
    }
    uint8_t f = ss->ss_family;
    if (f == AF_INET) {
        ((struct sockaddr_in*)ss)->sin_addr = addr;
        return true;
    } if (f == AF_INET6) {
        return false;
    } else {
        return false;
    }
}
コード例 #21
0
ファイル: id_table.hpp プロジェクト: yuma0301/dnsmux.cpp
bool
id_table::set_port(uint16_t id, uint16_t port)
{
    struct sockaddr_storage* ss = get_sockaddr(id);
    if (ss == NULL) {
        return false;
    }
    uint8_t f = ss->ss_family;
    if (f == AF_INET) {
        ((struct sockaddr_in*)ss)->sin_port = port;
        return true;
    } if (f == AF_INET6) {
        ((struct sockaddr_in6*)ss)->sin6_port = port;
        return true;
    } else {
        return false;
    }
}
コード例 #22
0
ファイル: socket_utils.c プロジェクト: muchas/agh-box
int get_client_socket(const char* ip, int port){
    int socket_fd;
    struct in_addr iaddr;
    struct sockaddr_in address;

    socket_fd = get_socket_fd();

    if(inet_aton(ip, &iaddr)==0){
        perror("inet aton failed");
        exit(EXIT_FAILURE);
    }
    address = get_sockaddr(port, iaddr.s_addr);
    if(connect(socket_fd, (struct sockaddr*) &address, sizeof(address))<0){
        perror("Connect failed");
        exit(EXIT_FAILURE);
    }

    return socket_fd;
}
コード例 #23
0
ファイル: cliser.c プロジェクト: hardiku/torch-ipc
int cliser_server(lua_State *L) {
#ifdef USE_CUDA
   // sometimes cutorch is loaded late, this is a good spot to try and register...
   Lcliser_CudaInit(L);
#endif
   const char *host = luaL_optstring(L, 1, DEFAULT_HOST);
   int port = luaL_optinteger(L, 2, 0);
   char port_str[16];
   snprintf(port_str, 16, "%d", port);
   struct sockaddr addr;
   socklen_t addrlen = sizeof(struct sockaddr);
   int ret = get_sockaddr(L, host, port != 0 ? port_str : NULL, &addr, &addrlen);
   if (ret) return ret;
   ret = socket(PF_INET, SOCK_STREAM, 0);
   if (ret <= 0) return LUA_HANDLE_ERROR(L, errno);
   int sock = ret;
   ret = bind(sock, &addr, addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   ret = listen(sock, 1024);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   struct sockaddr_in sin;
   addrlen = sizeof(struct sockaddr_in);
   ret = getsockname(sock, (struct sockaddr *)&sin, &addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   port = ntohs(sin.sin_port);
   server_t *server = (server_t *)lua_newuserdata(L, sizeof(server_t));
   memset(server, 0, sizeof(server_t));
   server->sock = sock;
   server->ip_address = sin.sin_addr.s_addr;
   luaL_getmetatable(L, "ipc.server");
   lua_setmetatable(L, -2);
   lua_pushinteger(L, port);
   return 2;
}
コード例 #24
0
ファイル: client3.c プロジェクト: jlam323/CS3305-Assignment-3
int main(int argc, char *argv[])
{

    int numbytes;
    char sendBuff[MAX_MSG_SIZE];
    char recvBuff[MAX_MSG_SIZE];
    struct sockaddr_in serv_addr; 
    struct hostent *server;
    int rv;
    int a, b, sum;

    if(argc != 3)
    {
        printf("\n Usage: %s hostname port \n",argv[0]);
        return 1;
    } 
  
    struct addrinfo* results = get_sockaddr(argv[1], argv[2]);
    int sockfd = open_connection(results);

    memset(sendBuff, '0',sizeof(sendBuff));
    memset(recvBuff, '0',sizeof(recvBuff));

    a = 5;
    b = 10;

    snprintf(sendBuff, sizeof(sendBuff), "%d %d", a,b);
    write(sockfd, sendBuff, strlen(sendBuff)); 

    numbytes = recv(sockfd,recvBuff,sizeof(recvBuff)-1,0);
    if (numbytes == -1){
      perror("recv");
      exit(1);
    }
  
    recvBuff[numbytes] = '\0';
    sscanf(recvBuff, "%d", &sum);
    printf("received sum is %d\n", sum);
    
    return 0;
}
コード例 #25
0
CAMLprim value unix_sendto_native(value sock, value buff, value ofs, value len,
                                  value flags, value dest)
{
  int ret, cv_flags;
  long numbytes;
  char iobuf[UNIX_BUFFER_SIZE];
  union sock_addr_union addr;
  socklen_param_type addr_len;

  cv_flags = convert_flag_list(flags, msg_flag_table);
  get_sockaddr(dest, &addr, &addr_len);
  numbytes = Long_val(len);
  if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE;
  memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes);
  enter_blocking_section();
  ret = sendto(Int_val(sock), iobuf, (int) numbytes, cv_flags,
               &addr.s_gen, addr_len);
  leave_blocking_section();
  if (ret == -1) uerror("sendto", Nothing);
  return Val_int(ret);
}
コード例 #26
0
ファイル: socket_utils.c プロジェクト: muchas/agh-box
int init_server_socket(int port){
    int socket_fd, result;
    struct sockaddr_in address;

    address = get_sockaddr(port, htonl(INADDR_ANY));
    socket_fd = get_socket_fd();

    result = bind(socket_fd, (struct sockaddr*) &address, sizeof(address));
    if(result != 0){
        perror("Socket binding failed");
        exit(EXIT_FAILURE);
    }

    result = listen(socket_fd, SOMAXCONN);
    if(result != 0){
        perror("Socket listening start failed");
        exit(EXIT_FAILURE);
    }

    return socket_fd;
}
コード例 #27
0
ファイル: krt-iface.c プロジェクト: nabeken/bird
static void
scan_ifs(struct ifreq *r, int cnt)
{
  struct iface i, *pi;
  struct ifa a;
  char *err, *colon;
  unsigned fl;
  ip_addr netmask;
  int l, scope;
  sockaddr *sa;

  if_start_update();
  for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
    {
      int sec = 0;
      bzero(&i, sizeof(i));
      bzero(&a, sizeof(a));
      if (colon = strchr(r->ifr_name, ':'))
	{
	  /* It's an alias -- let's interpret it as a secondary interface address */
	  sec = 1;
	  *colon = 0;
	}
      strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);

      if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue;

      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1);
      if (ipa_nonzero(a.ip))
	{
	  l = ipa_classify(a.ip);
	  if (l < 0 || !(l & IADDR_HOST))
	    {
	      log(L_ERR "%s: Invalid interface address", i.name);
	      a.ip = IPA_NONE;
	    }
	  else
	    {
	      a.scope = l & IADDR_SCOPE_MASK;
	      if (a.scope == SCOPE_HOST)
		i.flags |= IF_LOOPBACK | IF_IGNORE;
	    }
	}

      if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
	{
	  err = "SIOCGIFFLAGS";
	faulty:
	  log(L_ERR "%s(%s): %m", err, i.name);
	bad:
	  i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN;
	  continue;
	}
      fl = r->ifr_flags;
      if (fl & IFF_UP)
	i.flags |= IF_LINK_UP;

      if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
	{ err = "SIOCGIFNETMASK"; goto faulty; }
      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0);
      l = ipa_mklen(netmask);
      if (l < 0 || l == 31)
	{
	  log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask);
	  goto bad;
	}
      a.pxlen = l;

      if (fl & IFF_POINTOPOINT)
	{
	  a.flags |= IA_UNNUMBERED;
	  if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
	    { err = "SIOCGIFDSTADDR"; goto faulty; }
	  get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1);
	  a.prefix = a.opposite;
	  a.pxlen = BITS_PER_IP_ADDRESS;
	}
      else
	a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
      if (fl & IFF_LOOPBACK)
	i.flags |= IF_LOOPBACK | IF_IGNORE;
      if (1
#ifndef CONFIG_ALL_MULTICAST
	  && (fl & IFF_MULTICAST)
#endif
#ifndef CONFIG_UNNUM_MULTICAST
	  && !(a.flags & IA_UNNUMBERED)
#endif
	 )
	i.flags |= IF_MULTICAST;

      scope = ipa_classify(a.ip);
      if (scope < 0)
	{
	  log(L_ERR "%s: Invalid address", i.name);
	  goto bad;
	}
      a.scope = scope & IADDR_SCOPE_MASK;

      if (a.pxlen < 32)
	{
	  a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
	  if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
	    {
	      log(L_ERR "%s: Using network or broadcast address for interface", i.name);
	      goto bad;
	    }
	  if (fl & IFF_BROADCAST)
	    i.flags |= IF_BROADCAST;
	  if (a.pxlen < 30)
	    i.flags |= IF_MULTIACCESS;
	  else
	    a.opposite = ipa_opposite(a.ip, a.pxlen);
	}
      else
	a.brd = a.opposite;
      a.scope = SCOPE_UNIVERSE;

      if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
	{ err = "SIOCGIFMTU"; goto faulty; }
      i.mtu = r->ifr_mtu;

#ifdef SIOCGIFINDEX
      if (ioctl(if_scan_sock, SIOCGIFINDEX, r) >= 0)
	i.index = r->ifr_ifindex;
      else if (errno != EINVAL)
	DBG("SIOCGIFINDEX failed: %m\n");
      else	/* defined, but not supported by the kernel */
#endif
      /*
       *  The kernel doesn't give us real ifindices, but we still need them
       *  at least for OSPF unnumbered links. So let's make them up ourselves.
       */
      if (pi = if_find_by_name(i.name))
	i.index = pi->index;
      else
	{
	  static int if_index_counter = 1;
	  i.index = if_index_counter++;
	}

      pi = NULL;
      if (sec)
	{
	  a.flags |= IA_SECONDARY;
	  pi = if_find_by_index(i.index);
	}
      if (!pi)
	pi = if_update(&i);
      a.iface = pi;
      ifa_update(&a);
    }
  if_end_update();
}
コード例 #28
0
ファイル: redir.c プロジェクト: Eintler/shadowsocks-libev
int
main(int argc, char **argv)
{
    srand(time(NULL));

    int i, c;
    int pid_flags    = 0;
    int mptcp        = 0;
    int mtu          = 0;
    char *user       = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password   = NULL;
    char *timeout    = NULL;
    char *method     = NULL;
    char *pid_path   = NULL;
    char *conf_path  = NULL;

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    int option_index                    = 0;
    static struct option long_options[] = {
        { "mtu",   required_argument, 0, 0 },
        { "mptcp", no_argument,       0, 0 },
        { "help",  no_argument,       0, 0 },
        {       0,                 0, 0, 0 }
    };

    opterr = 0;

    USE_TTY();

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                mtu = atoi(optarg);
                LOGI("set MTU to %d", mtu);
            } else if (option_index == 1) {
                mptcp = 1;
                LOGI("enable multipath TCP");
            } else if (option_index == 2) {
                usage();
                exit(EXIT_SUCCESS);
            }
            break;
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host   = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path  = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
#ifdef HAVE_SETRLIMIT
        case 'n':
            nofile = atoi(optarg);
            break;
#endif
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        case 'A':
            auth = 1;
            break;
        case '6':
            ipv6first = 1;
            break;
        case '?':
            // The option character is not recognized.
            LOGE("Unrecognized option: %s", optarg);
            opterr = 1;
            break;
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++)
                remote_addr[i] = conf->remote_addr[i];
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (user == NULL) {
            user = conf->user;
        }
        if (auth == 0) {
            auth = conf->auth;
        }
        if (mtu == 0) {
            mtu = conf->mtu;
        }
        if (mptcp == 0) {
            mptcp = conf->mptcp;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (method == NULL) {
        method = "rc4-md5";
    }

    if (timeout == NULL) {
        timeout = "600";
    }

#ifdef HAVE_SETRLIMIT
    /*
     * no need to check the return value here since we will show
     * the user an error message if setrlimit(2) fails
     */
    if (nofile > 1024) {
        if (verbose) {
            LOGI("setting NOFILE to %d", nofile);
        }
        set_nofile(nofile);
    }
#endif

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (ipv6first) {
        LOGI("resolving hostname to IPv6 address first");
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
    signal(SIGINT, signal_cb);
    signal(SIGTERM, signal_cb);

    // Setup keys
    LOGI("initializing ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup proxy context
    listen_ctx_t listen_ctx;
    listen_ctx.remote_num  = remote_num;
    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);
    for (int i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
                     remote_addr[i].port;
        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.method  = m;
    listen_ctx.mptcp   = mptcp;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd == -1) {
            FATAL("bind() error");
        }
        if (listen(listenfd, SOMAXCONN) == -1) {
            FATAL("listen() error");
        }
        setnonblocking(listenfd);

        listen_ctx.fd = listenfd;

        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
        ev_io_start(loop, &listen_ctx.io);
    }

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), mtu, m, auth, listen_ctx.timeout, NULL);
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL && ! run_as(user)) {
        FATAL("failed to switch user");
    }

    if (geteuid() == 0){
        LOGI("running from root user");
    }

    ev_run(loop, 0);

    return 0;
}
コード例 #29
0
ファイル: redir.c プロジェクト: BadaDu/shadowsocks-libev
int main(int argc, char **argv)
{
    int i, c;
    int pid_flags    = 0;
    char *user       = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password   = NULL;
    char *timeout    = NULL;
    char *method     = NULL;
    char *pid_path   = NULL;
    char *conf_path  = NULL;

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    opterr = 0;

    while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:uUvA")) != -1)
        switch (c) {
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host   = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path  = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
#ifdef HAVE_SETRLIMIT
        case 'n':
            nofile = atoi(optarg);
            break;
#endif
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            auth = 1;
            break;
        }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++)
                remote_addr[i] = conf->remote_addr[i];
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (auth == 0) {
            auth = conf->auth;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile > 1024) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) {
        timeout = "60";
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup proxy context
    listen_ctx_t listen_ctx;
    listen_ctx.remote_num  = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *) * remote_num);
    for (int i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
                     remote_addr[i].port;
        struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.method  = m;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd < 0) {
            FATAL("bind() error");
        }
        if (listen(listenfd, SOMAXCONN) == -1) {
            FATAL("listen() error");
        }
        setnonblocking(listenfd);

        listen_ctx.fd = listenfd;

        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
        ev_io_start(loop, &listen_ctx.io);
    }

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, NULL);
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    ev_run(loop, 0);

    return 0;
}
コード例 #30
0
ファイル: local.c プロジェクト: TonyShield/shadowsocks-libev
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    srand(time(NULL));

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    int option_index = 0;
    static struct option long_options[] =
    {
        { "fast-open", no_argument,       0, 0 },
        { "acl",       required_argument, 0, 0 },
        { 0,           0,                 0, 0 }
    };

    opterr = 0;

    USE_TTY();

#ifdef ANDROID
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvVA",
                            long_options, &option_index)) != -1) {
#else
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvA",
                            long_options, &option_index)) != -1) {
#endif
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            }
            break;
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            auth = 1;
            break;
#ifdef ANDROID
        case 'V':
            vpn = 1;
            break;
#endif
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }
    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++) {
                remote_addr[i] = conf->remote_addr[i];
            }
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) {
        timeout = "60";
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *) * remote_num);
    for (i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
            remote_addr[i].port;
        struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0) {
        FATAL("bind() error");
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        FATAL("listen() error");
    }
    setnonblocking(listenfd);

    listen_ctx.fd = listenfd;

    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("udprelay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), m, listen_ctx.timeout, iface);
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    for (i = 0; i < remote_num; i++) {
        free(listen_ctx.remote_addr[i]);
    }
    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}

#else

int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    mode = profile.mode;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
    memset(storage, 0, sizeof(struct sockaddr_storage));
    if (get_sockaddr(remote_host, remote_port_str, storage, 1) == -1) {
        return -1;
    }

    // Setup proxy context
    struct ev_loop *loop = EV_DEFAULT;
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *));
    listen_ctx.remote_addr[0] = (struct sockaddr *)storage;
    listen_ctx.timeout = timeout;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        ERROR("bind()");
        return -1;
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        ERROR("listen()");
        return -1;
    }
    setnonblocking(listenfd);

    listen_ctx.fd = listenfd;

    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("udprelay enabled");
        struct sockaddr *addr = (struct sockaddr *)storage;
        init_udprelay(local_addr, local_port_str, addr,
                      get_sockaddr_len(addr), m, timeout, NULL);
    }

    LOGI("listening at %s:%s", local_addr, local_port_str);

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);
    close(listen_ctx.fd);

    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}