예제 #1
0
파일: socket.c 프로젝트: wanggx/Linux1.0
/* 这个和pipe功能有相似之处,pipe是单工的,socketpair是双工的
 * family只能是UNIX域的。
 */
static int
sock_socketpair(int family, int type, int protocol, unsigned long usockvec[2])
{
  int fd1, fd2, i;
  struct socket *sock1, *sock2;
  int er;

  DPRINTF((net_debug,
	"NET: sock_socketpair: family = %d, type = %d, protocol = %d\n",
							family, type, protocol));

  /*
   * Obtain the first socket and check if the underlying protocol
   * supports the socketpair call.
   */
  /* 如果创建失败,则直接返回 */
  if ((fd1 = sock_socket(family, type, protocol)) < 0) return(fd1);
  sock1 = sockfd_lookup(fd1, NULL);
  if (!sock1->ops->socketpair) {
	sys_close(fd1);
	return(-EINVAL);
  }

  /* Now grab another socket and try to connect the two together. */
  if ((fd2 = sock_socket(family, type, protocol)) < 0) {
	sys_close(fd1);
	return(-EINVAL);
  }
  sock2 = sockfd_lookup(fd2, NULL);
  if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
	sys_close(fd1);
	sys_close(fd2);
	return(i);
  }
  sock1->conn = sock2;
  sock2->conn = sock1;
  /* 完成socketpair操作后,则这只套接字的状态为连接状态 */
  sock1->state = SS_CONNECTED;
  sock2->state = SS_CONNECTED;

  er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int));
  if(er)
  	return er;
  put_fs_long(fd1, &usockvec[0]);
  put_fs_long(fd2, &usockvec[1]);

  return(0);
}
예제 #2
0
파일: ipc.c 프로젝트: livebox/livebox2
int ipc_wait_for_server(u16 port)
{
    struct sockaddr_in sa;
    int fd;

    MZERO(sa);
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
    sa.sin_port = port;

    if ((fd = sock_socket(SOCK_STREAM, 0, 0)) < 0)
    {
	rg_error(LERR, "failed creating socket");
	return -1;
    }
    
    /* Try to connect to server infinitely */ 
    while (1)
    {
 	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) >= 0)
	    break;

	/* Sleep for 10ms before trying again */
	usleep(10000);
    }

    /* Once the server accepts the connection, it tries to send the client a
     * sync message. It will fail if we close the socket now. So we keep the
     * socket open until a sync is received, to keep the server happy. */
    ipc_client_sync(fd);

    socket_close(fd);
    
    return 0;
}
예제 #3
0
static int
libcfs_sock_create (cfs_socket_t **sockp, int *fatal,
                    __u32 local_ip, int local_port)
{
        struct sockaddr_in  locaddr;
        cfs_socket_t    *sock;
        int             option;
        int             optlen;
        int             rc;

        /* All errors are fatal except bind failure if the port is in use */
        *fatal = 1;

        sock = _MALLOC(sizeof(cfs_socket_t), M_TEMP, M_WAITOK|M_ZERO);
        if (!sock) {
                CERROR("Can't allocate cfs_socket.\n");
                return -ENOMEM;
        }
        *sockp = sock;
        sock->s_magic = CFS_SOCK_MAGIC;

        rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
                          libcfs_sock_upcall, sock, &C2B_SOCK(sock));
        if (rc != 0) 
                goto out;
        option = 1;
        optlen = sizeof(option);
        rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, 
                              SO_REUSEADDR, &option, optlen);
        if (rc != 0)
                goto out;

        /* can't specify a local port without a local IP */
        LASSERT (local_ip == 0 || local_port != 0);

        if (local_ip != 0 || local_port != 0) {
                bzero (&locaddr, sizeof (locaddr));
                locaddr.sin_len = sizeof(struct sockaddr_in);
                locaddr.sin_family = AF_INET;
                locaddr.sin_port = htons (local_port);
                locaddr.sin_addr.s_addr = (local_ip != 0) ? htonl(local_ip) : INADDR_ANY;
                rc = -sock_bind(C2B_SOCK(sock), (struct sockaddr *)&locaddr);
                if (rc == -EADDRINUSE) {
                        CDEBUG(D_NET, "Port %d already in use\n", local_port);
                        *fatal = 0;
                        goto out;
                }
                if (rc != 0) {
                        CERROR("Error trying to bind to port %d: %d\n",
                               local_port, rc);
                        goto out;
                }
        }
        return 0;
out:
        if (C2B_SOCK(sock) != NULL) 
                sock_close(C2B_SOCK(sock));
        FREE(sock, M_TEMP);
        return rc;
}
예제 #4
0
파일: socket.c 프로젝트: binsys/doc-linux
static int
sock_socketpair(int family, int type, int protocol, int usockvec[2])
{
	int fd1, fd2, i;
	struct socket *sock1, *sock2;

	PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n",
	       family, type, protocol);

	/*
	 * obtain the first socket and check if the underlying protocol
	 * supports the socketpair call
	 */
	if ((fd1 = sock_socket(family, type, protocol)) < 0)
		return fd1;
	sock1 = sockfd_lookup(fd1, NULL);
	if (!sock1->ops->socketpair) {
		sys_close(fd1);
		return -EINVAL;
	}

	/*
	 * now grab another socket and try to connect the two together
	 */
	if ((fd2 = sock_socket(family, type, protocol)) < 0) {
		sys_close(fd1);
		return -EINVAL;
	}
	sock2 = sockfd_lookup(fd2, NULL);
	if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
		sys_close(fd1);
		sys_close(fd2);
		return i;
	}
	sock1->conn = sock2;
	sock2->conn = sock1;
	sock1->state = SS_CONNECTED;
	sock2->state = SS_CONNECTED;

	verify_area(usockvec, 2 * sizeof(int));
	put_fs_long(fd1, &usockvec[0]);
	put_fs_long(fd2, &usockvec[1]);

	return 0;
}
예제 #5
0
errno_t	xi_sock_socket(int domain, int type, int protocol, sock_upcall callback, void *cookie, xi_socket_t *new_so)
{
#ifdef __KPI_SOCKET__
	return sock_socket(domain, type, protocol, callback, cookie, new_so);
#else
	thread_funnel_set(network_flock, TRUE);
	errno_t	error;
	
	error = socreate(domain, new_so, type, protocol); 
	
	(void)thread_funnel_set(network_flock, FALSE);
	
	return error;
#endif	
}
예제 #6
0
파일: ipc.c 프로젝트: livebox/livebox2
int ipc_listen_ip(u16 port, u32 addr)
{
    int fd;
    
    if ((fd = sock_socket(SOCK_STREAM, addr, port)) < 0)
	return -1;
    /* 5 is a big enough queue length */
    if (listen(fd, 5) < 0)
    {
	rg_error(LERR, "failed ipc listen %m");
	goto Error;
    }
    return fd;

Error:
    socket_close(fd);
    return -1;
}
예제 #7
0
파일: ipc.c 프로젝트: livebox/livebox2
static int __ipc_connect_ip(u16 port, u32 addr, int quiet)
{
    struct sockaddr_in sa;
    int fd = -1;

    while (1)
    {
	if ((fd = sock_socket(SOCK_STREAM, 0, 0)) < 0)
	    return -1;
	
	MZERO(sa);
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = addr;
	sa.sin_port = port;
 	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
	{
	    socket_close(fd);
	    if (!quiet)
		rg_error(LERR, "failed ipc connect %m");
	    return -1;
	}
	/* Linux 2.4 kernel has a bug with localhost connections.
	 * After the server calls listen(), then the client calls
	 * connect() and returns with success immediately, before
	 * the server calls accept()!
	 * Therefore, a SYNC_STR command is used to make sure the connect
	 * succeeded.
	 * This has not been tested on Linux 2.2 whether it too has
	 * this bug. It probably does not exist on VxWorks, since VxWorks
	 * TCP/IP stack is completely different (its BSD based).
	 */
	if (!ipc_client_sync(fd))
	    break;
	socket_close(fd);
	if (!quiet)
	    rg_error(LWARN, "failed ipc connect sync - retrying");
	sys_sleep(1);
    }

    return fd;
}
예제 #8
0
int
libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
{
        struct ifreq    ifr;
        socket_t        so;
        __u32           val;
        int             nob;
        int             rc;

        rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
                          NULL, NULL, &so);
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return rc;
        }

        nob = strnlen(name, IFNAMSIZ);
        if (nob == IFNAMSIZ) {
                CERROR("Interface name %s too long\n", name);
                rc = -EINVAL;
                goto out;
        }

        CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
        bzero(&ifr, sizeof(ifr));
        strcpy(ifr.ifr_name, name);
        rc = -sock_ioctl (so, SIOCGIFFLAGS, &ifr);

        if (rc != 0) {
                CERROR("Can't get flags for interface %s\n", name);
                goto out;
        }
        
        if ((ifr.ifr_flags & IFF_UP) == 0) {
                CDEBUG(D_NET, "Interface %s down\n", name);
                *up = 0;
                *ip = *mask = 0;
                goto out;
        }

        *up = 1;

        bzero(&ifr, sizeof(ifr));
        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        rc = -sock_ioctl(so, SIOCGIFADDR, &ifr);

        if (rc != 0) {
                CERROR("Can't get IP address for interface %s\n", name);
                goto out;
        }
        
        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *ip = ntohl(val);

        bzero(&ifr, sizeof(ifr));
        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        rc = -sock_ioctl(so, SIOCGIFNETMASK, &ifr);

        if (rc != 0) {
                CERROR("Can't get netmask for interface %s\n", name);
                goto out;
        }

        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *mask = ntohl(val);
out:
        sock_close(so);
        return rc;
}
예제 #9
0
int
libcfs_ipif_enumerate (char ***namesp)
{
        /* Allocate and fill in 'names', returning # interfaces/error */
        char           **names;
        int             toobig;
        int             nalloc;
        int             nfound;
        socket_t        so;
        struct ifreq   *ifr;
        struct ifconf   ifc;
        int             rc;
        int             nob;
        int             i;

        rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
                          NULL, NULL, &so);
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (rc);
        }

        nalloc = 16;    /* first guess at max interfaces */
        toobig = 0;
        for (;;) {
                if (nalloc * sizeof(*ifr) > CFS_PAGE_SIZE) {
                        toobig = 1;
                        nalloc = CFS_PAGE_SIZE/sizeof(*ifr);
                        CWARN("Too many interfaces: only enumerating first %d\n",
                              nalloc);
                }

                LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
                if (ifr == NULL) {
                        CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
                                rc = -ENOMEM;
                        goto out0;
                }
                                
                ifc.ifc_buf = (char *)ifr;
                ifc.ifc_len = nalloc * sizeof(*ifr);
                                        
#if 1
                /*
                 * XXX Liang:
                 * sock_ioctl(..., SIOCGIFCONF, ...) is not supposed to be used in
                 * kernel space because it always try to copy result to userspace. 
                 * So we can't get interfaces name by sock_ioctl(...,SIOCGIFCONF,...).
                 * I've created a bug for Apple, let's wait...
                 */
                nfound = 0;
                for (i = 0; i < 16; i++) {
                        struct ifreq    en;
                        bzero(&en, sizeof(en));
                        snprintf(en.ifr_name, IFNAMSIZ, "en%d", i);
                        rc = -sock_ioctl (so, SIOCGIFFLAGS, &en);
                        if (rc != 0)
                                continue;
                        strcpy(ifr[nfound++].ifr_name, en.ifr_name);
                }

#else           /* NOT in using now */
                rc = -sock_ioctl(so, SIOCGIFCONF, (caddr_t)&ifc);
                                
                if (rc < 0) {
                        CERROR ("Error %d enumerating interfaces\n", rc);
                        goto out1;
                }

                nfound = ifc.ifc_len/sizeof(*ifr);
                LASSERT (nfound <= nalloc);
#endif

                if (nfound < nalloc || toobig)
                        break;

                LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
                nalloc *= 2;
        }
        if (nfound == 0)
                goto out1;

        LIBCFS_ALLOC(names, nfound * sizeof(*names));
        if (names == NULL) {
                rc = -ENOMEM;
                goto out1;
        }
        /* NULL out all names[i] */
        memset (names, 0, nfound * sizeof(*names));

        for (i = 0; i < nfound; i++) {

                nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
                if (nob == IFNAMSIZ) {
                        /* no space for terminating NULL */
                        CERROR("interface name %.*s too long (%d max)\n",
                               nob, ifr[i].ifr_name, IFNAMSIZ);
                        rc = -ENAMETOOLONG;
                        goto out2;
                }

                LIBCFS_ALLOC(names[i], IFNAMSIZ);
                if (names[i] == NULL) {
                        rc = -ENOMEM;
                        goto out2;
                }

                memcpy(names[i], ifr[i].ifr_name, nob);
                names[i][nob] = 0;
        }

        *namesp = names;
        rc = nfound;

out2:
        if (rc < 0)
                libcfs_ipif_free_enumeration(names, nfound);
out1:
        LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
out0:
        sock_close(so);
        return rc;

}
예제 #10
0
파일: krpc_subr.c 프로젝트: argp/xnu
/*
 * Do a remote procedure call (RPC) and wait for its reply.
 * If from_p is non-null, then we are doing broadcast, and
 * the address from whence the response came is saved there.
 */
int
krpc_call(
	struct sockaddr_in *sa,
	u_int sotype, u_int prog, u_int vers, u_int func,
	mbuf_t *data,			/* input/output */
	struct sockaddr_in *from_p)	/* output */
{
	socket_t so;
	struct sockaddr_in *sin;
	mbuf_t m, nam, mhead;
	struct rpc_call *call;
	struct rpc_reply *reply;
	int error, timo, secs;
	size_t len;
	static u_int32_t xid = ~0xFF;
	u_int16_t tport;
	size_t maxpacket = 1<<16;

	/*
	 * Validate address family.
	 * Sorry, this is INET specific...
	 */
	if (sa->sin_family != AF_INET)
		return (EAFNOSUPPORT);

	/* Free at end if not null. */
	nam = mhead = NULL;

	/*
	 * Create socket and set its recieve timeout.
	 */
	if ((error = sock_socket(AF_INET, sotype, 0, 0, 0, &so)))
		goto out1;

	{
		struct timeval tv;

		tv.tv_sec = 1;
		tv.tv_usec = 0;

		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))))
		    goto out;

	}

	/*
	 * Enable broadcast if necessary.
	 */

	if (from_p && (sotype == SOCK_DGRAM)) {
		int on = 1;
		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))))
			goto out;
	}

	/*
	 * Bind the local endpoint to a reserved port,
	 * because some NFS servers refuse requests from
	 * non-reserved (non-privileged) ports.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m)))
		goto out;
	sin = mbuf_data(m);
	bzero(sin, sizeof(*sin));
	mbuf_setlen(m, sizeof(*sin));
	sin->sin_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	tport = IPPORT_RESERVED;
	do {
		tport--;
		sin->sin_port = htons(tport);
		error = sock_bind(so, (struct sockaddr*)sin);
	} while (error == EADDRINUSE &&
			 tport > IPPORT_RESERVED / 2);
	mbuf_freem(m);
	m = NULL;
	if (error) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &nam)))
		goto out;
	sin = mbuf_data(nam);
	mbuf_setlen(nam, sa->sin_len);
	bcopy((caddr_t)sa, (caddr_t)sin, sa->sin_len);

	if (sotype == SOCK_STREAM) {
		struct timeval tv;
		tv.tv_sec = 60;
		tv.tv_usec = 0;
		error = sock_connect(so, mbuf_data(nam), MSG_DONTWAIT);
		if (error && (error != EINPROGRESS))
			goto out;
		error = sock_connectwait(so, &tv);
		if (error) {
			if (error == EINPROGRESS)
				error = ETIMEDOUT;
			printf("krpc_call: error waiting for TCP socket connect: %d\n", error);
			goto out;
		}
	}

	/*
	 * Prepend RPC message header.
	 */
	m = *data;
	*data = NULL;
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: send data w/o pkthdr");
	if (mbuf_pkthdr_len(m) < mbuf_len(m))
		panic("krpc_call: pkthdr.len not set");
#endif
	len = sizeof(*call);
	if (sotype == SOCK_STREAM)
		len += 4;  /* account for RPC record marker */
	mhead = m;
	if ((error = mbuf_prepend(&mhead, len, MBUF_WAITOK)))
		goto out;
	if ((error = mbuf_pkthdr_setrcvif(mhead, NULL)))
		goto out;

	/*
	 * Fill in the RPC header
	 */
	if (sotype == SOCK_STREAM) {
		/* first, fill in RPC record marker */
		u_int32_t *recmark = mbuf_data(mhead);
		*recmark = htonl(0x80000000 | (mbuf_pkthdr_len(mhead) - 4));
		call = (struct rpc_call *)(recmark + 1);
	} else {
		call = mbuf_data(mhead);
	}
	bzero((caddr_t)call, sizeof(*call));
	xid++;
	call->rp_xid = htonl(xid);
	/* call->rp_direction = 0; */
	call->rp_rpcvers = htonl(2);
	call->rp_prog = htonl(prog);
	call->rp_vers = htonl(vers);
	call->rp_proc = htonl(func);
	/* call->rp_auth = 0; */
	/* call->rp_verf = 0; */

	/*
	 * Send it, repeatedly, until a reply is received,
	 * but delay each re-send by an increasing amount.
	 * If the delay hits the maximum, start complaining.
	 */
	timo = 0;
	for (;;) {
		struct msghdr msg;
		
		/* Send RPC request (or re-send). */
		if ((error = mbuf_copym(mhead, 0, MBUF_COPYALL, MBUF_WAITOK, &m)))
			goto out;
		bzero(&msg, sizeof(msg));
		if (sotype == SOCK_STREAM) {
			msg.msg_name = NULL;
			msg.msg_namelen = 0;
		} else {
			msg.msg_name = mbuf_data(nam);
			msg.msg_namelen = mbuf_len(nam);
		}
		error = sock_sendmbuf(so, &msg, m, 0, 0);
		if (error) {
			printf("krpc_call: sosend: %d\n", error);
			goto out;
		}
		m = NULL;

		/* Determine new timeout. */
		if (timo < MAX_RESEND_DELAY)
			timo++;
            	else
           		printf("RPC timeout for server " IP_FORMAT "\n",
				IP_LIST(&(sin->sin_addr.s_addr)));

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		secs = timo;
		while (secs > 0) {
			size_t readlen;
			
			if (m) {
				mbuf_freem(m);
				m = NULL;
			}
			if (sotype == SOCK_STREAM) {
				int maxretries = 60;
				struct iovec aio;
				aio.iov_base = &len;
				aio.iov_len = sizeof(u_int32_t);
				bzero(&msg, sizeof(msg));
				msg.msg_iov = &aio;
				msg.msg_iovlen = 1;
				do {
				   error = sock_receive(so, &msg, MSG_WAITALL, &readlen);
				   if ((error == EWOULDBLOCK) && (--maxretries <= 0))
					error = ETIMEDOUT;
				} while (error == EWOULDBLOCK);
				if (!error && readlen < aio.iov_len) {
				    /* only log a message if we got a partial word */
				    if (readlen != 0)
					    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
						 readlen, sizeof(u_int32_t), IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
				if (error)
					goto out;
				len = ntohl(len) & ~0x80000000;
				/*
				 * This is SERIOUS! We are out of sync with the sender
				 * and forcing a disconnect/reconnect is all I can do.
				 */
				if (len > maxpacket) {
				    printf("impossible packet length (%ld) from server " IP_FORMAT "\n",
					len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EFBIG;
				    goto out;
				}
				
				do {
				    readlen = len;
				    error = sock_receivembuf(so, NULL, &m, MSG_WAITALL, &readlen);
				} while (error == EWOULDBLOCK);

				if (!error && (len > readlen)) {
				    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
					readlen, len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
			} else {
				len = maxpacket;
				readlen = len;
				bzero(&msg, sizeof(msg));
				msg.msg_name = from_p;
				msg.msg_namelen = (from_p == NULL) ? 0 : sizeof(*from_p);
				error = sock_receivembuf(so, &msg, &m, 0, &readlen);
			}

			if (error == EWOULDBLOCK) {
				secs--;
				continue;
			}
			if (error)
				goto out;
			len = readlen;

			/* Does the reply contain at least a header? */
			if (len < MIN_REPLY_HDR)
				continue;
			if (mbuf_len(m) < MIN_REPLY_HDR)
				continue;
			reply = mbuf_data(m);

			/* Is it the right reply? */
			if (reply->rp_direction != htonl(RPC_REPLY))
				continue;

			if (reply->rp_xid != htonl(xid))
				continue;
			
			/* Was RPC accepted? (authorization OK) */
			if (reply->rp_astatus != 0) {
				error = ntohl(reply->rp_u.rpu_errno);
				printf("rpc denied, error=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_MISMATCH:
					error = ERPCMISMATCH;
					break;
				case RPC_AUTHERR:
					error = EAUTH;
					break;
				}
				goto out;
			}


			if (mbuf_len(m) < REPLY_SIZE) {
				error = RPC_SYSTEM_ERR;
			}
			else {
				error = ntohl(reply->rp_u.rpu_ok.rp_rstatus);
			}

			/* Did the call succeed? */
			if (error != 0) {
				printf("rpc status=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_PROGUNAVAIL:
					error = EPROGUNAVAIL;
					break;
				case RPC_PROGMISMATCH:
					error = EPROGMISMATCH;
					break;
				case RPC_PROCUNAVAIL:
					error = EPROCUNAVAIL;
					break;
				case RPC_GARBAGE:
					error = EINVAL;
					break;
				case RPC_SYSTEM_ERR:
					error = EIO;
					break;
				}
				goto out;
			}

			goto gotreply;	/* break two levels */

		} /* while secs */
	} /* forever send/receive */

	error = ETIMEDOUT;
	goto out;

 gotreply:

	/*
	 * Pull as much as we can into first mbuf, to make
	 * result buffer contiguous.  Note that if the entire
	 * result won't fit into one mbuf, you're out of luck.
	 * XXX - Should not rely on making the entire reply
	 * contiguous (fix callers instead). -gwr
	 */
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: received pkt w/o header?");
#endif
	len = mbuf_pkthdr_len(m);
	if (sotype == SOCK_STREAM)
		len -= 4;  /* the RPC record marker was read separately */
	if (mbuf_len(m) < len) {
		if ((error = mbuf_pullup(&m, len)))
			goto out;
		reply = mbuf_data(m);
	}

	/*
	 * Strip RPC header
	 */
	len = sizeof(*reply);
	if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) {
		len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen);
		len = (len + 3) & ~3; /* XXX? */
	}
	mbuf_adj(m, len);

	/* result */
	*data = m;
 out:
	sock_close(so);
out1:
	if (nam) mbuf_freem(nam);
	if (mhead) mbuf_freem(mhead);
	return error;
}
예제 #11
0
파일: if_utun.c 프로젝트: Bitesher/xnu
static void
utun_cleanup_family(
	ifnet_t				interface,
	protocol_family_t	protocol)
{
	errno_t		result = 0;
	socket_t	pf_socket = NULL;
	ifaddr_t	*addresses = NULL;
	int			i;
	
	if (protocol != PF_INET && protocol != PF_INET6) {
		printf("utun_cleanup_family - invalid protocol family %d\n", protocol);
		return;
	}
	
	/* Create a socket for removing addresses and detaching the protocol */
	result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket);
	if (result != 0) {
		if (result != EAFNOSUPPORT)
			printf("utun_cleanup_family - failed to create %s socket: %d\n",
				protocol == PF_INET ? "IP" : "IPv6", result);
		goto cleanup;
	}
	
        /* always set SS_PRIV, we want to close and detach regardless */
        sock_setpriv(pf_socket, 1);

	result = utun_detach_ip(interface, protocol, pf_socket);
	if (result == 0 || result == ENXIO) {
		/* We are done! We either detached or weren't attached. */
		goto cleanup;
	}
	else if (result != EBUSY) {
		/* Uh, not really sure what happened here... */
		printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result);
		goto cleanup;
	}
	
	/*
	 * At this point, we received an EBUSY error. This means there are
	 * addresses attached. We should detach them and then try again.
	 */
	result = ifnet_get_address_list_family(interface, &addresses, protocol);
	if (result != 0) {
		printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
			ifnet_name(interface), ifnet_unit(interface), 
			protocol == PF_INET ? "PF_INET" : "PF_INET6", result);
		goto cleanup;
	}
	
	for (i = 0; addresses[i] != 0; i++) {
		utun_remove_address(interface, protocol, addresses[i], pf_socket);
	}
	ifnet_free_address_list(addresses);
	addresses = NULL;
	
	/*
	 * The addresses should be gone, we should try the remove again.
	 */
	result = utun_detach_ip(interface, protocol, pf_socket);
	if (result != 0 && result != ENXIO) {
		printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result);
	}
	
cleanup:
	if (pf_socket != NULL)
		sock_close(pf_socket);
	
	if (addresses != NULL)
		ifnet_free_address_list(addresses);
}
예제 #12
0
파일: socket.c 프로젝트: wanggx/Linux1.0
/*
 * System call vectors. Since I (RIB) want to rewrite sockets as streams,
 * we have this level of indirection. Not a lot of overhead, since more of
 * the work is done via read/write/select directly.
 */
asmlinkage int
sys_socketcall(int call, unsigned long *args)
{
  int er;
  switch(call) {
	case SYS_SOCKET:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_socket(get_fs_long(args+0),
				   get_fs_long(args+1),
				   get_fs_long(args+2)));
	case SYS_BIND:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_bind(get_fs_long(args+0),
				 (struct sockaddr *)get_fs_long(args+1),
				 get_fs_long(args+2)));
	case SYS_CONNECT:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_connect(get_fs_long(args+0),
				    (struct sockaddr *)get_fs_long(args+1),
				    get_fs_long(args+2)));
	case SYS_LISTEN:
		er=verify_area(VERIFY_READ, args, 2 * sizeof(long));
		if(er)
			return er;
		return(sock_listen(get_fs_long(args+0),
				   get_fs_long(args+1)));
	case SYS_ACCEPT:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_accept(get_fs_long(args+0),
				   (struct sockaddr *)get_fs_long(args+1),
				   (int *)get_fs_long(args+2)));
	case SYS_GETSOCKNAME:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_getsockname(get_fs_long(args+0),
					(struct sockaddr *)get_fs_long(args+1),
					(int *)get_fs_long(args+2)));
	case SYS_GETPEERNAME:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_getpeername(get_fs_long(args+0),
					(struct sockaddr *)get_fs_long(args+1),
					(int *)get_fs_long(args+2)));
	case SYS_SOCKETPAIR:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(long));
		if(er)
			return er;
		return(sock_socketpair(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (unsigned long *)get_fs_long(args+3)));
	case SYS_SEND:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_send(get_fs_long(args+0),
				 (void *)get_fs_long(args+1),
				 get_fs_long(args+2),
				 get_fs_long(args+3)));
	case SYS_SENDTO:
		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_sendto(get_fs_long(args+0),
				   (void *)get_fs_long(args+1),
				   get_fs_long(args+2),
				   get_fs_long(args+3),
				   (struct sockaddr *)get_fs_long(args+4),
				   get_fs_long(args+5)));
	case SYS_RECV:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_recv(get_fs_long(args+0),
				 (void *)get_fs_long(args+1),
				 get_fs_long(args+2),
				 get_fs_long(args+3)));
	case SYS_RECVFROM:
		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_recvfrom(get_fs_long(args+0),
				     (void *)get_fs_long(args+1),
				     get_fs_long(args+2),
				     get_fs_long(args+3),
				     (struct sockaddr *)get_fs_long(args+4),
				     (int *)get_fs_long(args+5)));
	case SYS_SHUTDOWN:
		er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));
		if(er)
			return er;
		return(sock_shutdown(get_fs_long(args+0),
				     get_fs_long(args+1)));
	case SYS_SETSOCKOPT:
		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
		if(er)
			return er;
		return(sock_setsockopt(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (char *)get_fs_long(args+3),
				       get_fs_long(args+4)));
	case SYS_GETSOCKOPT:
		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
		if(er)
			return er;
		return(sock_getsockopt(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (char *)get_fs_long(args+3),
				       (int *)get_fs_long(args+4)));
	default:
		return(-EINVAL);
  }
}
int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* saddrCache)
{
    struct addrinfo* info = nullptr;
    CloudServerAddressType type = CLOUD_SERVER_ADDRESS_TYPE_NONE;
    bool clean = true;

    if (saddrCache && /* protocol == IPPROTO_UDP && */ saddrCache->sa_family != AF_UNSPEC) {
        char tmphost[INET6_ADDRSTRLEN] = {};
        char tmpserv[8] = {};
        if (!netdb_getnameinfo(saddrCache, saddrCache->sa_len, tmphost, sizeof(tmphost),
                               tmpserv, sizeof(tmpserv), AI_NUMERICHOST | AI_NUMERICSERV)) {
            /* There is a cached address, use it, but still pass it to getaddrinfo */
            struct addrinfo hints = {};
            hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG;
            hints.ai_family = saddrCache->sa_family;
            hints.ai_protocol = protocol;
            /* FIXME: */
            hints.ai_socktype = hints.ai_protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;

            if (!netdb_getaddrinfo(tmphost, tmpserv, &hints, &info)) {
                type = CLOUD_SERVER_ADDRESS_TYPE_CACHED;
            }
        }
    }

    if (type == CLOUD_SERVER_ADDRESS_TYPE_NONE) {
        /* Check if we have another address to try from the cached addrinfo list */
        if (s_state.addr && s_state.next) {
            info = s_state.next;
            type = CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO;
        }
    }

    if ((type == CLOUD_SERVER_ADDRESS_TYPE_NONE) && address) {
        /* Use passed ServerAddress */
        switch (address->addr_type) {
            case IP_ADDRESS: {
                struct addrinfo hints = {};
                hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG;
                /* XXX: IPv4-only */
                hints.ai_family = AF_INET;
                hints.ai_protocol = protocol;
                /* FIXME: */
                hints.ai_socktype = hints.ai_protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;

                char tmphost[INET_ADDRSTRLEN] = {};
                char tmpserv[8] = {};

                struct in_addr in = {};
                in.s_addr = htonl(address->ip);
                if (inet_inet_ntop(AF_INET, &in, tmphost, sizeof(tmphost))) {
                    snprintf(tmpserv, sizeof(tmpserv), "%u", address->port);

                    netdb_getaddrinfo(tmphost, tmpserv, &hints, &info);
                    type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
                }
                break;
            }

            case DOMAIN_NAME: {
                struct addrinfo hints = {};
                hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
                hints.ai_protocol = protocol;
                /* FIXME: */
                hints.ai_socktype = hints.ai_protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;

                char tmphost[sizeof(address->domain) + 32] = {};
                char tmpserv[8] = {};
                /* FIXME: this should probably be moved into system_cloud_internal */
                system_string_interpolate(address->domain, tmphost, sizeof(tmphost), system_interpolate_cloud_server_hostname);
                snprintf(tmpserv, sizeof(tmpserv), "%u", address->port);
                LOG(TRACE, "Resolving %s#%s", tmphost, tmpserv);
                netdb_getaddrinfo(tmphost, tmpserv, &hints, &info);
                type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
                break;
            }
        }
    }

    int r = SYSTEM_ERROR_NETWORK;

    if (info == nullptr) {
        LOG(ERROR, "Failed to determine server address");
    }

    LOG(TRACE, "Address type: %d", type);

    for (struct addrinfo* a = info; a != nullptr; a = a->ai_next) {
        /* Iterate over all the addresses and attempt to connect */

        int s = sock_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
        if (s < 0) {
            LOG(ERROR, "Cloud socket failed, family=%d, type=%d, protocol=%d, errno=%d", a->ai_family, a->ai_socktype, a->ai_protocol, errno);
            continue;
        }

        LOG(TRACE, "Cloud socket=%d, family=%d, type=%d, protocol=%d", s, a->ai_family, a->ai_socktype, a->ai_protocol);

        char serverHost[INET6_ADDRSTRLEN] = {};
        uint16_t serverPort = 0;
        switch (a->ai_family) {
            case AF_INET: {
                inet_inet_ntop(a->ai_family, &((sockaddr_in*)a->ai_addr)->sin_addr, serverHost, sizeof(serverHost));
                serverPort = ntohs(((sockaddr_in*)a->ai_addr)->sin_port);
                break;
            }
            case AF_INET6: {
                inet_inet_ntop(a->ai_family, &((sockaddr_in6*)a->ai_addr)->sin6_addr, serverHost, sizeof(serverHost));
                serverPort = ntohs(((sockaddr_in6*)a->ai_addr)->sin6_port);
                break;
            }
        }
        LOG(INFO, "Cloud socket=%d, connecting to %s#%u", s, serverHost, serverPort);

        /* We are using fixed source port only for IPv6 connections */
        if (protocol == IPPROTO_UDP && a->ai_family == AF_INET6) {
            struct sockaddr_storage saddr = {};
            saddr.s2_len = sizeof(saddr);
            saddr.ss_family = a->ai_family;

            /* NOTE: Always binding to 5684 by default */
            switch (a->ai_family) {
                case AF_INET: {
                    ((sockaddr_in*)&saddr)->sin_port = htons(PORT_COAPS);
                    break;
                }
                case AF_INET6: {
                    ((sockaddr_in6*)&saddr)->sin6_port = htons(PORT_COAPS);
                    break;
                }
            }

            const int one = 1;
            if (sock_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
                LOG(ERROR, "Cloud socket=%d, failed to set SO_REUSEADDR, errno=%d", s, errno);
                sock_close(s);
                continue;
            }

            /* Bind socket */
            if (sock_bind(s, (const struct sockaddr*)&saddr, sizeof(saddr))) {
                LOG(ERROR, "Cloud socket=%d, failed to bind, errno=%d");
                sock_close(s);
                continue;
            }
        }

        /* FIXME: timeout for TCP */
        /* NOTE: we do this for UDP sockets as well in order to automagically filter
         * on source address and port */
        r = sock_connect(s, a->ai_addr, a->ai_addrlen);
        if (r) {
            LOG(ERROR, "Cloud socket=%d, failed to connect to %s#%u, errno=%d", s, serverHost, serverPort, errno);
            sock_close(s);
            continue;
        }
        LOG(TRACE, "Cloud socket=%d, connected to %s#%u", s, serverHost, serverPort);

        /* If we got here, we are most likely connected, however keep track of current addrinfo list
         * in order to try the next address if application layer fails to establish the connection
         */
        if (protocol == IPPROTO_UDP &&
            (type == CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO ||
             type == CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO)) {
            if (s_state.addr) {
                /* We are already iterating over a cached addrinfo list */
                s_state.next = a->ai_next;
                if (a->ai_next) {
                    s_state.next = a->ai_next;
                    clean = false;
                } else {
                    info = s_state.addr;
                    s_state.addr = s_state.next = nullptr;
                }
            } else {
                if (a->ai_next) {
                    s_state.addr = info;
                    s_state.next = a->ai_next;
                    clean = false;
                }
            }
        }

        s_state.socket = s;
        if (saddrCache) {
            memcpy(saddrCache, a->ai_addr, a->ai_addrlen);
        }

        unsigned int keepalive = 0;
        system_cloud_get_inet_family_keepalive(a->ai_family, &keepalive);
        system_cloud_set_inet_family_keepalive(a->ai_family, keepalive, 1);

        break;
    }

    if (clean) {
        netdb_freeaddrinfo(info);
    }

    return r;
}
예제 #14
0
파일: sock.c 프로젝트: erumoico/ntripcaster
/*
 * Connect to hostname on specified port and return the created socket.
 * Assert Class: 3
 */
SOCKET sock_connect_wto(const char *hostname, const int port,
			const int timeout)
{
	SOCKET sockfd;
	struct sockaddr_in sin, server;
	struct hostent *host;
	struct hostent hostinfo;
	char buf[BUFSIZE];
	int error;

	if (!hostname || !hostname[0]) {
		write_log(LOG_DEFAULT,
			  "ERROR: sock_connect() called with NULL or empty hostname");
		return INVALID_SOCKET;
	} else if (port <= 0) {
		write_log(LOG_DEFAULT,
			  "ERROR: sock_connect() called with invalid port number");
		return INVALID_SOCKET;
	}

	sockfd = sock_socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd == INVALID_SOCKET) {
		sock_close(sockfd);
		return INVALID_SOCKET;
	}

	if (info.myhostname != NULL) {
		struct sockaddr_in localsin;
		memset(&localsin, 0, sizeof (struct sockaddr_in));

		xa_debug(2, "DEBUG: Trying to bind to %s", info.myhostname);

		localsin.sin_addr = localaddr;
		localsin.sin_family = AF_INET;
		localsin.sin_port = 0;

		if (bind
		    (sockfd, (struct sockaddr *) &localsin,
		     sizeof (localsin)) == SOCKET_ERROR) {
			xa_debug(2, "DEBUG: Unable to bind", info.myhostname);
			write_log(LOG_DEFAULT,
				  "ERROR: Bind to local address %s failed",
				  info.myhostname);
			sock_close(sockfd);
			return INVALID_SOCKET;
		}
	}

	memset(&sin, 0, sizeof (sin));
	memset(&server, 0, sizeof (struct sockaddr_in));

	if (isdigit((int) hostname[0])
	    && isdigit((int) hostname[ice_strlen(hostname) - 1])) {
		if (inet_aton(hostname, (struct in_addr *) &sin.sin_addr) ==
		    0) {
			write_log(LOG_DEFAULT, "ERROR: Invalid ip number %s",
				  hostname);
			sock_close(sockfd);
			return INVALID_SOCKET;
		}
		memcpy(&server.sin_addr, &sin.sin_addr, sizeof (sin));
	} else {
		host =
			ice_gethostbyname(hostname, &hostinfo, buf, BUFSIZE,
					  &error);
		if (host == NULL) {
			xa_debug(1, "DEBUG: gethostbyname %s failed",
				 hostname);
			sock_close(sockfd);
			ice_clean_hostent();
			return INVALID_SOCKET;
		}
		memcpy(&server.sin_addr, host->h_addr, host->h_length);
		ice_clean_hostent();
	}

	server.sin_family = AF_INET;
	server.sin_port = htons(port);

	{
		char buf[50];

		makeasciihost(&server.sin_addr, buf);
		xa_debug(1, "Trying to connect to %s:%d", buf, port);
	}

	if (timeout > 0) {
		fd_set wfds;
		struct timeval tv;
		int retval;
		int val;
		socklen_t valsize = sizeof (int);

		xa_debug(3,
			 "DEBUG: sock_connect(): doing a connection w/ timeout");

		FD_ZERO(&wfds);
		FD_SET(sockfd, &wfds);
		tv.tv_sec = timeout;
		tv.tv_usec = 0;

		sock_set_blocking(sockfd, SOCK_NONBLOCK);
		retval = connect(sockfd, (struct sockaddr *) &server, sizeof (server));
		if (retval == 0) {
			xa_debug(3, "DEBUG: sock_connect(): non blocking connect returned 0!");
			sock_set_blocking(sockfd, SOCK_BLOCK);
			return sockfd;
		} else {
#ifdef _WIN32
			if (WSAGetLastError() == WSAEINPROGRESS) {
#else
			if (!is_recoverable(errno)) {
#endif
				xa_debug(3, "DEBUG: sock_connect(): connect didn't return EINPROGRESS!, was: %d", errno);
				sock_close(sockfd);
				return SOCKET_ERROR;
			}
		}

		if (select(sockfd + 1, NULL, &wfds, NULL, &tv)) {
			retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
					    (void *) &val,
					    (socklen_t *) & valsize);
			if ((retval == 0) && (val == 0)) {
				sock_set_blocking(sockfd, SOCK_BLOCK);
				return sockfd;
			} else {
				xa_debug(3,
					 "DEBUG: sock_connect(): getsockopt returned %i, val = %i, valsize = %i, errno = %i!",
					 retval, val, valsize, errno);
				sock_close(sockfd);
				return SOCKET_ERROR;
			}
		} else {
			xa_debug(3,
				 "DEBUG: sock_connect(): select returned 0");
			sock_close(sockfd);
			return SOCKET_ERROR;
		}
	} else {
		if (connect
예제 #15
0
파일: sock.c 프로젝트: erumoico/ntripcaster
/*
 * Create a socket for all incoming requests on specified port.
 * If info.myhostname is NULL, bind it to INADDR_ANY (all available interfaces).
 * If info.myhostname is not NULL, resolv it (if needed), and bind to that.
 * Return the socket for bound socket, or INVALID_SOCKET if failed.
 * Assert Class: 3
 */
SOCKET sock_get_server_socket(const int port)
{
	struct sockaddr_in sin;
	int sin_len, error;
	SOCKET sockfd;

	if (port < 0) {
		write_log(LOG_DEFAULT,
			  "ERROR: Invalid port number %d. Cannot listen for requests, this is bad!",
			  port);
		return INVALID_SOCKET;
	}

	xa_debug (2, "DEBUG: Getting socket for port %d", port);

	/*
	 * get socket descriptor 
	 */
	sockfd = sock_socket (AF_INET, SOCK_STREAM, 0);
	if (sockfd == INVALID_SOCKET)
		return INVALID_SOCKET;

	/*
	 * Setup socket 
	 */
#ifdef HAVE_SETSOCKOPT
	{
		int tmp = 1;

		if (setsockopt
		    (sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &tmp,
		     sizeof (tmp)) != 0)
			write_log(LOG_DEFAULT,
				  "ERROR: setsockopt() failed to set SO_REUSEADDR flag. (mostly harmless)");
	}
#endif

	/*
	 * setup sockaddr structure 
	 */
	sin_len = sizeof (sin);
	memset(&sin, 0, sin_len);
	sin.sin_family = AF_INET;

	if (info.myhostname != NULL && info.myhostname[0]) {
		if (isdigit((int) info.myhostname[0])
		    && isdigit((int) info.
			       myhostname[ice_strlen(info.myhostname) - 1])) {
			if (inet_aton
			    (info.myhostname,
			     (struct in_addr *) &localaddr) == 0) {
				write_log(LOG_DEFAULT,
					  "ERROR: Invalid ip number %s, will die now",
					  info.myhostname);
				clean_shutdown(&info);
			}
			sin.sin_addr.s_addr = localaddr.s_addr;
		} else {
			struct hostent *hostinfoptr, hostinfo;
			char buf[BUFSIZE];
			int error;

			hostinfoptr =
				ice_gethostbyname(info.myhostname, &hostinfo,
						  buf, BUFSIZE, &error);
			if (hostinfoptr == NULL) {
				write_log(LOG_DEFAULT,
					  "Unknown host %s, that's it for me!",
					  info.myhostname);
				ice_clean_hostent();
				clean_shutdown(&info);
			}
			sin.sin_addr.s_addr = localaddr.s_addr;
			memcpy((void *) &localaddr, hostinfoptr->h_addr,
			       sizeof (localaddr));
			ice_clean_hostent();
		}
	} else {
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	}

	sin.sin_port = htons(port);

	/*
	 * bind socket to port 
	 */
	error = bind(sockfd, (struct sockaddr *) &sin, sin_len);
	if (error == SOCKET_ERROR) {
		write_log(LOG_DEFAULT,
			  "Bind to socket on port %d failed. Shutting down now.",
			  port);
		clean_shutdown(&info);
	}

	return sockfd;
}