예제 #1
0
int
kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
{
	struct socket *so;
	struct file *fp;
	cap_rights_t rights;
	int error;

	AUDIT_ARG_FD(fd);
	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
	    &fp, NULL, NULL);
	if (error != 0)
		return (error);
	so = fp->f_data;
#ifdef KTRACE
	if (KTRPOINT(td, KTR_STRUCT))
		ktrsockaddr(sa);
#endif
#ifdef MAC
	error = mac_socket_check_bind(td->td_ucred, so, sa);
	if (error == 0) {
#endif
		if (dirfd == AT_FDCWD)
			error = sobind(so, sa, td);
		else
			error = sobindat(dirfd, so, sa, td);
#ifdef MAC
	}
#endif
	fdrop(fp, td);
	return (error);
}
예제 #2
0
/* ARGSUSED */
int
sys_bind(struct proc *p, void *v, register_t *retval)
{
	struct sys_bind_args /* {
		syscallarg(int) s;
		syscallarg(const struct sockaddr *) name;
		syscallarg(socklen_t) namelen;
	} */ *uap = v;
	struct file *fp;
	struct mbuf *nam;
	int error;

	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
		return (error);
	error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
	    MT_SONAME);
	if (error == 0) {
#ifdef KTRACE
		if (KTRPOINT(p, KTR_STRUCT))
			ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
#endif
		error = sobind(fp->f_data, nam, p);
		m_freem(nam);
	}
	FRELE(fp, p);
	return (error);
}
예제 #3
0
int
bind (int s, struct sockaddr *name, int namelen)
{
	int error;
	int ret = -1;
	struct socket *so;
	struct mbuf *nam;

	rtems_bsdnet_semaphore_obtain ();
	if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
		error = sockargstombuf (&nam, name, namelen, MT_SONAME);
		if (error == 0) {
			error = sobind (so, nam);
			if (error == 0)
				ret = 0;
			else
				errno = error;
			m_freem (nam);
		}
		else {
			errno = error;
		}
	}
	rtems_bsdnet_semaphore_release ();
	return ret;
}
예제 #4
0
static int 
bsd_bind(cyg_file *fp, const sockaddr *sa, socklen_t len)
{
    int error;

    error = sobind((struct socket *)fp->f_data, (sockaddr *)sa, 0);
    return error;
}
예제 #5
0
static int
icl_conn_connect_tcp(struct icl_conn *ic, int domain, int socktype,
    int protocol, struct sockaddr *from_sa, struct sockaddr *to_sa)
{
	struct socket *so;
	int error;
	int interrupted = 0;

	error = socreate(domain, &so, socktype, protocol,
	    curthread->td_ucred, curthread);
	if (error != 0)
		return (error);

	if (from_sa != NULL) {
		error = sobind(so, from_sa, curthread);
		if (error != 0) {
			soclose(so);
			return (error);
		}
	}

	error = soconnect(so, to_sa, curthread);
	if (error != 0) {
		soclose(so);
		return (error);
	}

	SOCK_LOCK(so);
	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
		error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
		    "icl_connect", 0);
		if (error) {
			if (error == EINTR || error == ERESTART)
				interrupted = 1;
			break;
		}
	}
	if (error == 0) {
		error = so->so_error;
		so->so_error = 0;
	}
	SOCK_UNLOCK(so);

	if (error != 0) {
		soclose(so);
		return (error);
	}

	error = icl_conn_handoff_sock(ic, so);
	if (error != 0)
		soclose(so);

	return (error);
}
예제 #6
0
struct socket* listenon(unsigned short port)
{
  struct socket* so = NULL;
  socreate(AF_INET, &so, SOCK_STREAM, 0);
  struct sockaddr_in addr;
  bzero(&addr, sizeof addr);
  addr.sin_len = sizeof addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  struct mbuf* nam = m_devget((caddr_t)&addr, sizeof addr, 0, NULL, NULL);
  sobind(so, nam);
  solisten(so, 5);
  return so;
}
예제 #7
0
errno_t xi_sock_bind(xi_socket_t so, struct sockaddr *to)
{
#ifdef __KPI_SOCKET__
	return sock_bind(so, to);
#else
	thread_funnel_set(network_flock, TRUE);
	errno_t	error;

	error = sobind(so, to);
	
	(void)thread_funnel_set(network_flock, FALSE);

	return error;
#endif
}
예제 #8
0
int
udp_attach(PNATState pData, struct socket *so)
{
    struct sockaddr sa_addr;
    socklen_t socklen = sizeof(struct sockaddr);
    int status;
    int opt = 1;

    AssertReturn(so->so_type == 0, -1);
    so->so_type = IPPROTO_UDP;

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
        goto error;
    fd_nonblock(so->s);

    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;

    status = sobind(pData, so);
    if (status != 0)
        return status;

    /* success, insert in queue */
    so->so_expire = curtime + SO_EXPIRE;

    /* enable broadcast for later use */
    setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));

    status = getsockname(so->s, &sa_addr, &socklen);
    if (status == 0)
    {
        Assert(sa_addr.sa_family == AF_INET);
        so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
        so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
    }

    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);
    return so->s;
error:
    Log2(("NAT: can't create datagram socket\n"));
    return -1;
}
예제 #9
0
파일: sockio.c 프로젝트: EPiCS/reconos_v2
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len )
{
    struct mbuf *nam;
    int error;

    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);

    if (error)
        return (error);

    error = sobind((struct socket *)fp->f_data, nam);

    m_freem(nam);
    
    return error;
}
예제 #10
0
int
do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
{
	struct socket	*so;
	int		error;

	if ((error = fd_getsock(fd, &so)) != 0) {
		m_freem(nam);
		return (error);
	}
	MCLAIM(nam, so->so_mowner);
	error = sobind(so, nam, l);
	m_freem(nam);
	fd_putfile(fd);
	return error;
}
예제 #11
0
int
nfs_boot_sobind_ipport(struct socket *so, uint16_t port, struct lwp *l)
{
	struct mbuf *m;
	struct sockaddr_in *sin;
	int error;

	m = m_getclr(M_WAIT, MT_SONAME);
	sin = mtod(m, struct sockaddr_in *);
	sin->sin_len = m->m_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port = htons(port);
	error = sobind(so, m, l);
	m_freem(m);
	return (error);
}
예제 #12
0
파일: sockcall.c 프로젝트: fjanssen/Car2X
int
t_bind (long s, 
   struct sockaddr * addr,
   int addrlen)
{
   struct mbuf *     nam;
   struct sockaddr   sa;
   struct sockaddr * sap;
   struct socket *   so;
   int               err;

   so = LONG2SO(s);  /* convert long to socket */
   SOC_CHECK(so);
   DOMAIN_CHECK(so, addrlen);

   so->so_error = 0;
   if (addr == (struct sockaddr *)NULL) 
   {
      MEMSET ((void *)&sa, 0, sizeof(sa));
      addrlen = sizeof(sa);
      sa.sa_family = so->so_domain;
      sap = &sa;
   } else
      sap = addr;

   if ((nam = sockargs (sap, addrlen, MT_SONAME)) == NULL) 
   {
      so->so_error = ENOMEM;
      return SOCKET_ERROR;
   }
   LOCK_NET_RESOURCE(NET_RESID);
   err = sobind (so, nam);
   m_freem(nam);
   UNLOCK_NET_RESOURCE(NET_RESID);
   if (err) 
   {
      so->so_error = err;
      return SOCKET_ERROR;
   }
   return 0;
}
예제 #13
0
/* 
 * Connect to specified server via IP
 */
int
ncp_sock_connect_in(struct ncp_conn *conn) {
	struct sockaddr_in sin;
	struct thread *td = conn->td;
	int addrlen=sizeof(sin), error;

	conn->flags = 0;
	bzero(&sin,addrlen);
	conn->ncp_so = conn->wdg_so = NULL;
	checkbad(socreate(AF_INET, &conn->ncp_so, SOCK_DGRAM, IPPROTO_UDP, td));
	sin.sin_family = AF_INET;
	sin.sin_len = addrlen;
	checkbad(sobind(conn->ncp_so, (struct sockaddr *)&sin, td));
	checkbad(ncp_soconnect(conn->ncp_so,(struct sockaddr*)&conn->li.addr, td));
	if  (!error)
		conn->flags |= NCPFL_SOCONN;
	return error;
bad:
	ncp_sock_disconnect(conn);
	return (error);
}
int waitForMessages(struct sockaddr_in *site_2, struct thread *td) {
	waiting_sockaddr = *site_2;
	struct sockaddr_in *site = &waiting_sockaddr;
	log_info("waiting for messages on %s:%d", inet_ntoa(site->sin_addr), ntohs(site->sin_port));

	int error = 0;
	struct socket *so = NULL;

	error = socreate(AF_INET, &so, SOCK_STREAM, 0, td->td_ucred, td);
	if (error) {
		log_warn("error in socreate in waitForMessages");
		goto bad;
	}
	error = sobind(so, (struct sockaddr *) site, td);
	if (error) {
		log_warn("error in sobind in waitForMessages");
		goto bad;
	}
	error = solisten(so, 5, td);
	if (error) {
		log_warn("error in solisten in waitForMessages");
		goto bad;
	}

	error = kthread_add(accept_loop, so, NULL, &accept_kthread, 0, 0,
			"raymond_accept_loop");
	if (error) {
		log_warn("error creating thread: %d\n", error);
		goto bad;
	}
	return 0;

	bad: // on error
	if (so != NULL)
		soclose(so);
	return error;
}
예제 #15
0
static int
icl_listen_add_tcp(struct icl_listen *il, int domain, int socktype,
    int protocol, struct sockaddr *sa, int portal_id)
{
	struct icl_listen_sock *ils;
	struct socket *so;
	struct sockopt sopt;
	int error, one = 1;

	error = socreate(domain, &so, socktype, protocol,
	    curthread->td_ucred, curthread);
	if (error != 0) {
		ICL_WARN("socreate failed with error %d", error);
		return (error);
	}

	sopt.sopt_dir = SOPT_SET;
	sopt.sopt_level = SOL_SOCKET;
	sopt.sopt_name = SO_REUSEADDR;
	sopt.sopt_val = &one;
	sopt.sopt_valsize = sizeof(one);
	sopt.sopt_td = NULL;
	error = sosetopt(so, &sopt);
	if (error != 0) {
		ICL_WARN("failed to set SO_REUSEADDR with error %d", error);
		soclose(so);
		return (error);
	}

	error = sobind(so, sa, curthread);
	if (error != 0) {
		ICL_WARN("sobind failed with error %d", error);
		soclose(so);
		return (error);
	}

	error = solisten(so, -1, curthread);
	if (error != 0) {
		ICL_WARN("solisten failed with error %d", error);
		soclose(so);
		return (error);
	}

	ils = malloc(sizeof(*ils), M_ICL_PROXY, M_ZERO | M_WAITOK);
	ils->ils_listen = il;
	ils->ils_socket = so;
	ils->ils_id = portal_id;

	error = kthread_add(icl_accept_thread, ils, NULL, NULL, 0, 0, "iclacc");
	if (error != 0) {
		ICL_WARN("kthread_add failed with error %d", error);
		soclose(so);
		free(ils, M_ICL_PROXY);

		return (error);
	}

	sx_xlock(&il->il_lock);
	TAILQ_INSERT_TAIL(&il->il_sockets, ils, ils_next);
	sx_xunlock(&il->il_lock);

	return (0);
}
예제 #16
0
파일: in_dhcp.c 프로젝트: Prajna/xnu
static struct dhcp_context *
dhcp_context_create(struct ifnet * ifp, int max_try,
		    struct proc * procp, int * error_p)
{
    struct dhcp_context	*	context = NULL;
    struct sockaddr_dl *	dl_p;
    struct in_addr		lo_addr;
    struct in_addr		lo_mask;
    int				error;
    struct sockaddr_in		sin;

    /* get the hardware address from the interface */
    dl_p = link_from_ifnet(ifp);
    if (dl_p == NULL) {
	printf("dhcp: can't get link address\n");
	error = ENXIO;
	goto failed;
    }

    printf("dhcp: h/w addr ");
    link_print(dl_p);
    if (dl_p->sdl_type != IFT_ETHER) {
	printf("dhcp: hardware type %d not supported\n",
	       dl_p->sdl_type);
	error = ENXIO;
	goto failed;
    }

    context = (struct dhcp_context *)kalloc(sizeof(*context));
    if (context == NULL) {
	printf("dhcp: failed to allocate context\n");
	error = ENOMEM;
	goto failed;
    }
    bzero(context, sizeof(*context));

    /* get a socket */
    error = socreate(AF_INET, &context->so, SOCK_DGRAM, 0);
    if (error != 0) {
	printf("dhcp: socreate failed %d\n", error);
	goto failed;
    }

    /* assign 127.0.0.1 to lo0 so that the bind will succeed */
    lo_addr.s_addr = htonl(INADDR_LOOPBACK);
    lo_mask.s_addr = htonl(IN_CLASSA_NET);
    error = inet_aifaddr(context->so, "lo0", &lo_addr, &lo_mask, NULL);
    if (error != 0) {
	printf("dhcp: assigning loopback address failed %d\n", error);
    }

    /* enable reception of DHCP packets before an address is assigned */
    snprintf(context->ifr.ifr_name, 
	     sizeof(context->ifr.ifr_name), "%s%d", ifp->if_name,
	     ifp->if_unit);
    context->ifr.ifr_intval = 1;

    error = ifioctl(context->so, SIOCAUTOADDR, (caddr_t)&context->ifr, procp);
    if (error) {
	printf("dhcp: SIOCAUTOADDR failed: %d\n", error);
	goto failed;
    }
    dprintf(("dhcp: SIOCAUTOADDR done\n"));

    error = ifioctl(context->so, SIOCPROTOATTACH, (caddr_t)&context->ifr, 
		    procp);
    if (error) {
	printf("dhcp: SIOCPROTOATTACH failed: %d\n", error);
	goto failed;
    }
    dprintf(("dhcp: SIOCPROTOATTACH done\n"));
    
    /* bind the socket */
    sin.sin_len = sizeof(sin);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(IPPORT_BOOTPC);
    sin.sin_addr.s_addr = INADDR_ANY;
    error = sobind(context->so, (struct sockaddr *)&sin);
    if (error) {
	printf("dhcp: sobind failed, %d\n", error);
	goto failed;
    }

    /* make it non-blocking I/O */
    socket_lock(context->so, 1);
    context->so->so_state |= SS_NBIO;
    socket_unlock(context->so, 1);

    /* save passed-in information */
    context->max_try = max_try;
    context->dl_p = dl_p;
    context->ifp = ifp;

    /* get a random transaction id */
    context->xid = random();

    return (context);

 failed:
    dhcp_context_free(context, procp);
    *error_p = error;
    return (NULL);
}
예제 #17
0
/*
 * Receive a control message
 */
static int
ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
	struct thread *td = curthread;	/* XXX broken */
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct socket *const so = priv->so;
	struct ng_mesg *resp = NULL;
	int error = 0;
	struct ng_mesg *msg;
	ng_ID_t raddr;

	NGI_GET_MSG(item, msg);
	switch (msg->header.typecookie) {
	case NGM_KSOCKET_COOKIE:
		switch (msg->header.cmd) {
		case NGM_KSOCKET_BIND:
		    {
			struct sockaddr *const sa
			    = (struct sockaddr *)msg->data;

			/* Sanity check */
			if (msg->header.arglen < SADATA_OFFSET
			    || msg->header.arglen < sa->sa_len)
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Bind */
			error = sobind(so, sa, td);
			break;
		    }
		case NGM_KSOCKET_LISTEN:
		    {
			/* Sanity check */
			if (msg->header.arglen != sizeof(int32_t))
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Listen */
			error = solisten(so, *((int32_t *)msg->data), td);
			break;
		    }

		case NGM_KSOCKET_ACCEPT:
		    {
			/* Sanity check */
			if (msg->header.arglen != 0)
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Make sure the socket is capable of accepting */
			if (!(so->so_options & SO_ACCEPTCONN))
				ERROUT(EINVAL);
			if (priv->flags & KSF_ACCEPTING)
				ERROUT(EALREADY);

			error = ng_ksocket_check_accept(priv);
			if (error != 0 && error != EWOULDBLOCK)
				ERROUT(error);

			/*
			 * If a connection is already complete, take it.
			 * Otherwise let the upcall function deal with
			 * the connection when it comes in.
			 */
			priv->response_token = msg->header.token;
			raddr = priv->response_addr = NGI_RETADDR(item);
			if (error == 0) {
				ng_ksocket_finish_accept(priv);
			} else
				priv->flags |= KSF_ACCEPTING;
			break;
		    }

		case NGM_KSOCKET_CONNECT:
		    {
			struct sockaddr *const sa
			    = (struct sockaddr *)msg->data;

			/* Sanity check */
			if (msg->header.arglen < SADATA_OFFSET
			    || msg->header.arglen < sa->sa_len)
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Do connect */
			if ((so->so_state & SS_ISCONNECTING) != 0)
				ERROUT(EALREADY);
			if ((error = soconnect(so, sa, td)) != 0) {
				soclrstate(so, SS_ISCONNECTING);
				ERROUT(error);
			}
			if ((so->so_state & SS_ISCONNECTING) != 0) {
				/* We will notify the sender when we connect */
				priv->response_token = msg->header.token;
				raddr = priv->response_addr = NGI_RETADDR(item);
				priv->flags |= KSF_CONNECTING;
				ERROUT(EINPROGRESS);
			}
			break;
		    }

		case NGM_KSOCKET_GETNAME:
		case NGM_KSOCKET_GETPEERNAME:
		    {
			int (*func)(struct socket *so, struct sockaddr **nam);
			struct sockaddr *sa = NULL;
			int len;

			/* Sanity check */
			if (msg->header.arglen != 0)
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Get function */
			if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) {
				if ((so->so_state
				    & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 
					ERROUT(ENOTCONN);
				func = so->so_proto->pr_usrreqs->pru_peeraddr;
			} else
				func = so->so_proto->pr_usrreqs->pru_sockaddr;

			/* Get local or peer address */
			if ((error = (*func)(so, &sa)) != 0)
				goto bail;
			len = (sa == NULL) ? 0 : sa->sa_len;

			/* Send it back in a response */
			NG_MKRESPONSE(resp, msg, len, M_WAITOK | M_NULLOK);
			if (resp == NULL) {
				error = ENOMEM;
				goto bail;
			}
			bcopy(sa, resp->data, len);

		bail:
			/* Cleanup */
			if (sa != NULL)
				kfree(sa, M_SONAME);
			break;
		    }

		case NGM_KSOCKET_GETOPT:
		    {
			struct ng_ksocket_sockopt *ksopt = 
			    (struct ng_ksocket_sockopt *)msg->data;
			struct sockopt sopt;

			/* Sanity check */
			if (msg->header.arglen != sizeof(*ksopt))
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Get response with room for option value */
			NG_MKRESPONSE(resp, msg, sizeof(*ksopt)
			    + NG_KSOCKET_MAX_OPTLEN, M_WAITOK | M_NULLOK);
			if (resp == NULL)
				ERROUT(ENOMEM);

			/* Get socket option, and put value in the response */
			sopt.sopt_dir = SOPT_GET;
			sopt.sopt_level = ksopt->level;
			sopt.sopt_name = ksopt->name;
			sopt.sopt_td = NULL;
			sopt.sopt_valsize = NG_KSOCKET_MAX_OPTLEN;
			ksopt = (struct ng_ksocket_sockopt *)resp->data;
			sopt.sopt_val = ksopt->value;
			if ((error = sogetopt(so, &sopt)) != 0) {
				NG_FREE_MSG(resp);
				break;
			}

			/* Set actual value length */
			resp->header.arglen = sizeof(*ksopt)
			    + sopt.sopt_valsize;
			break;
		    }

		case NGM_KSOCKET_SETOPT:
		    {
			struct ng_ksocket_sockopt *const ksopt = 
			    (struct ng_ksocket_sockopt *)msg->data;
			const int valsize = msg->header.arglen - sizeof(*ksopt);
			struct sockopt sopt;

			/* Sanity check */
			if (valsize < 0)
				ERROUT(EINVAL);
			if (so == NULL)
				ERROUT(ENXIO);

			/* Set socket option */
			sopt.sopt_dir = SOPT_SET;
			sopt.sopt_level = ksopt->level;
			sopt.sopt_name = ksopt->name;
			sopt.sopt_val = ksopt->value;
			sopt.sopt_valsize = valsize;
			sopt.sopt_td = NULL;
			error = sosetopt(so, &sopt);
			break;
		    }

		default:
			error = EINVAL;
			break;
		}
		break;
	default:
		error = EINVAL;
		break;
	}
done:
	NG_RESPOND_MSG(error, node, item, resp);
	NG_FREE_MSG(msg);
	return (error);
}
예제 #18
0
/*
 * 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.
 * data:	input/output
 * from_p:	output
 */
int
krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
    struct mbuf **data, struct mbuf **from_p, int retries)
{
	struct socket *so;
	struct sockaddr_in *sin;
	struct mbuf *m, *nam, *mhead, *from, *mopt;
	struct rpc_call *call;
	struct rpc_reply *reply;
	struct uio auio;
	int error, rcvflg, timo, secs, len;
	static u_int32_t xid = 0;
	char addr[INET_ADDRSTRLEN];
	int *ip;
	struct timeval tv;

	/*
	 * 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;
	from = NULL;

	/*
	 * Create socket and set its receive timeout.
	 */
	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)))
		goto out;

	m = m_get(M_WAIT, MT_SOOPTS);
	tv.tv_sec = 1;
	tv.tv_usec = 0;
	memcpy(mtod(m, struct timeval *), &tv, sizeof tv);
	m->m_len = sizeof(tv);
	if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
		goto out;

	/*
	 * Enable broadcast if necessary.
	 */
	if (from_p) {
		int32_t *on;
		m = m_get(M_WAIT, MT_SOOPTS);
		on = mtod(m, int32_t *);
		m->m_len = sizeof(*on);
		*on = 1;
		if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
			goto out;
	}

	/*
	 * Bind the local endpoint to a reserved port,
	 * because some NFS servers refuse requests from
	 * non-reserved (non-privileged) ports.
	 */
	MGET(mopt, M_WAIT, MT_SOOPTS);
	mopt->m_len = sizeof(int);
	ip = mtod(mopt, int *);
	*ip = IP_PORTRANGE_LOW;
	error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
	if (error)
		goto out;

	MGET(m, M_WAIT, MT_SONAME);
	sin = mtod(m, struct sockaddr_in *);
	sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port = htons(0);
	error = sobind(so, m, &proc0);
	m_freem(m);
	if (error) {
		printf("bind failed\n");
		goto out;
	}

	MGET(mopt, M_WAIT, MT_SOOPTS);
	mopt->m_len = sizeof(int);
	ip = mtod(mopt, int *);
	*ip = IP_PORTRANGE_DEFAULT;
	error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
	if (error)
		goto out;

	/*
	 * Setup socket address for the server.
	 */
	nam = m_get(M_WAIT, MT_SONAME);
	sin = mtod(nam, struct sockaddr_in *);
	bcopy((caddr_t)sa, (caddr_t)sin, (nam->m_len = sa->sin_len));

	/*
	 * Prepend RPC message header.
	 */
	mhead = m_gethdr(M_WAIT, MT_DATA);
	mhead->m_next = *data;
	call = mtod(mhead, struct rpc_call *);
	mhead->m_len = sizeof(*call);
	bzero((caddr_t)call, sizeof(*call));
	/* rpc_call part */
	xid = krpc_get_xid();
	call->rp_xid = txdr_unsigned(xid);
	/* call->rp_direction = 0; */
	call->rp_rpcvers = txdr_unsigned(2);
	call->rp_prog = txdr_unsigned(prog);
	call->rp_vers = txdr_unsigned(vers);
	call->rp_proc = txdr_unsigned(func);
	/* rpc_auth part (auth_unix as root) */
	call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX);
	call->rpc_auth.authlen  = txdr_unsigned(sizeof(struct auth_unix));
	/* rpc_verf part (auth_null) */
	call->rpc_verf.authtype = 0;
	call->rpc_verf.authlen  = 0;

	/*
	 * Setup packet header
	 */
	len = 0;
	m = mhead;
	while (m) {
		len += m->m_len;
		m = m->m_next;
	}
	mhead->m_pkthdr.len = len;
	mhead->m_pkthdr.rcvif = NULL;

	/*
	 * 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.
	 */
	for (timo = 0; retries; retries--) {
		/* Send RPC request (or re-send). */
		m = m_copym(mhead, 0, M_COPYALL, M_WAIT);
		if (m == NULL) {
			error = ENOBUFS;
			goto out;
		}
		error = sosend(so, nam, NULL, m, NULL, 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 %s (0x%x) prog %u\n",
			    inet_ntop(AF_INET, &sin->sin_addr,
				addr, sizeof(addr)),
			    ntohl(sin->sin_addr.s_addr), prog);

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		secs = timo;
		while (secs > 0) {
			if (from) {
				m_freem(from);
				from = NULL;
			}
			if (m) {
				m_freem(m);
				m = NULL;
			}
			auio.uio_resid = len = 1<<16;
			auio.uio_procp = NULL;
			rcvflg = 0;
			error = soreceive(so, &from, &auio, &m, NULL, &rcvflg,
			    0);
			if (error == EWOULDBLOCK) {
				secs--;
				continue;
			}
			if (error)
				goto out;
			len -= auio.uio_resid;

			/* Does the reply contain at least a header? */
			if (len < MIN_REPLY_HDR)
				continue;
			if (m->m_len < MIN_REPLY_HDR)
				continue;
			reply = mtod(m, struct rpc_reply *);

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

			if (reply->rp_xid != txdr_unsigned(xid))
				continue;

			/* Was RPC accepted? (authorization OK) */
			if (reply->rp_astatus != 0) {
				error = fxdr_unsigned(u_int32_t, reply->rp_errno);
				printf("rpc denied, error=%d\n", error);
				continue;
			}

			/* Did the call succeed? */
			if (reply->rp_status != 0) {
				error = fxdr_unsigned(u_int32_t, reply->rp_status);
				printf("rpc denied, status=%d\n", error);
				continue;
			}

			goto gotreply;	/* break two levels */

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

	error = ETIMEDOUT;
	goto out;

 gotreply:

	/*
	 * Get RPC reply header into first mbuf,
	 * get its length, then strip it off.
	 */
	len = sizeof(*reply);
	if (m->m_len < len) {
		m = m_pullup(m, len);
		if (m == NULL) {
			error = ENOBUFS;
			goto out;
		}
	}
	reply = mtod(m, struct rpc_reply *);
	if (reply->rp_auth.authtype != 0) {
		len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen);
		len = (len + 3) & ~3; /* XXX? */
	}
	m_adj(m, len);

	/* result */
	*data = m;
	if (from_p && error == 0) {
		*from_p = from;
		from = NULL;
	}

 out:
	if (nam) m_freem(nam);
	if (mhead) m_freem(mhead);
	if (from) m_freem(from);
	soclose(so);
	return error;
}
예제 #19
0
static int
bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
{
	struct socket *so;
	struct sockaddr_in *sin, dst;
	struct uio auio;
	struct sockopt sopt;
	struct iovec aio;
	int error, on, rcvflg, timo, len;
	time_t atimo;
	time_t rtimo;
	struct timeval tv;
	struct bootpc_ifcontext *ifctx;
	int outstanding;
	int gotrootpath;
	int retry;
	const char *s;

	/*
	 * Create socket and set its recieve timeout.
	 */
	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td);
	if (error != 0)
		goto out0;

	tv.tv_sec = 1;
	tv.tv_usec = 0;
	bzero(&sopt, sizeof(sopt));
	sopt.sopt_dir = SOPT_SET;
	sopt.sopt_level = SOL_SOCKET;
	sopt.sopt_name = SO_RCVTIMEO;
	sopt.sopt_val = &tv;
	sopt.sopt_valsize = sizeof tv;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Enable broadcast.
	 */
	on = 1;
	sopt.sopt_name = SO_BROADCAST;
	sopt.sopt_val = &on;
	sopt.sopt_valsize = sizeof on;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Disable routing.
	 */

	on = 1;
	sopt.sopt_name = SO_DONTROUTE;
	sopt.sopt_val = &on;
	sopt.sopt_valsize = sizeof on;

	error = sosetopt(so, &sopt);
	if (error != 0)
		goto out;

	/*
	 * Bind the local endpoint to a bootp client port.
	 */
	sin = &dst;
	clear_sinaddr(sin);
	sin->sin_port = htons(IPPORT_BOOTPC);
	error = sobind(so, (struct sockaddr *)sin, td);
	if (error != 0) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	sin = &dst;
	clear_sinaddr(sin);
	sin->sin_addr.s_addr = INADDR_BROADCAST;
	sin->sin_port = htons(IPPORT_BOOTPS);

	/*
	 * 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;
	rtimo = 0;
	for (;;) {

		outstanding = 0;
		gotrootpath = 0;

		for (ifctx = gctx->interfaces;
		     ifctx != NULL;
		     ifctx = ifctx->next) {
			if (bootpc_ifctx_isresolved(ifctx) != 0 &&
			    bootpc_tag(&gctx->tmptag, &ifctx->reply,
				       ifctx->replylen,
				       TAG_ROOT) != NULL)
				gotrootpath = 1;
		}

		for (ifctx = gctx->interfaces;
		     ifctx != NULL;
		     ifctx = ifctx->next) {
			ifctx->outstanding = 0;
			if (bootpc_ifctx_isresolved(ifctx)  != 0 &&
			    gotrootpath != 0) {
				continue;
			}
			if (bootpc_ifctx_isfailed(ifctx) != 0)
				continue;

			outstanding++;
			ifctx->outstanding = 1;

			/* Proceed to next step in DHCP negotiation */
			if ((ifctx->state == IF_DHCP_OFFERED &&
			     ifctx->dhcpquerytype != DHCP_REQUEST) ||
			    (ifctx->state == IF_DHCP_UNRESOLVED &&
			     ifctx->dhcpquerytype != DHCP_DISCOVER) ||
			    (ifctx->state == IF_BOOTP_UNRESOLVED &&
			     ifctx->dhcpquerytype != DHCP_NOMSG)) {
				ifctx->sentmsg = 0;
				bootpc_compose_query(ifctx, gctx, td);
			}

			/* Send BOOTP request (or re-send). */

			if (ifctx->sentmsg == 0) {
				switch(ifctx->dhcpquerytype) {
				case DHCP_DISCOVER:
					s = "DHCP Discover";
					break;
				case DHCP_REQUEST:
					s = "DHCP Request";
					break;
				case DHCP_NOMSG:
				default:
					s = "BOOTP Query";
					break;
				}
				printf("Sending %s packet from "
				       "interface %s (%*D)\n",
				       s,
				       ifctx->ireq.ifr_name,
				       ifctx->sdl->sdl_alen,
				       (unsigned char *) LLADDR(ifctx->sdl),
				       ":");
				ifctx->sentmsg = 1;
			}

			aio.iov_base = (caddr_t) &ifctx->call;
			aio.iov_len = sizeof(ifctx->call);

			auio.uio_iov = &aio;
			auio.uio_iovcnt = 1;
			auio.uio_segflg = UIO_SYSSPACE;
			auio.uio_rw = UIO_WRITE;
			auio.uio_offset = 0;
			auio.uio_resid = sizeof(ifctx->call);
			auio.uio_td = td;

			/* Set netmask to 0.0.0.0 */

			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
			clear_sinaddr(sin);
			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
					(caddr_t) &ifctx->ireq, td);
			if (error != 0)
				panic("bootpc_call:"
				      "set if netmask, error=%d",
				      error);

			error = sosend(so, (struct sockaddr *) &dst,
				       &auio, NULL, NULL, 0, td);
			if (error != 0) {
				printf("bootpc_call: sosend: %d state %08x\n",
				       error, (int) so->so_state);
			}

			/* XXX: Is this needed ? */
			pause("bootpw", hz/10);

			/* Set netmask to 255.0.0.0 */

			sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
			clear_sinaddr(sin);
			sin->sin_addr.s_addr = htonl(0xff000000u);
			error = ifioctl(ifctx->so, SIOCSIFNETMASK,
					(caddr_t) &ifctx->ireq, td);
			if (error != 0)
				panic("bootpc_call:"
				      "set if netmask, error=%d",
				      error);

		}

		if (outstanding == 0 &&
		    (rtimo == 0 || time_second >= rtimo)) {
			error = 0;
			goto gotreply;
		}

		/* Determine new timeout. */
		if (timo < MAX_RESEND_DELAY)
			timo++;
		else {
			printf("DHCP/BOOTP timeout for server ");
			print_sin_addr(&dst);
			printf("\n");
		}

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		atimo = timo + time_second;
		while (time_second < atimo) {
			aio.iov_base = (caddr_t) &gctx->reply;
			aio.iov_len = sizeof(gctx->reply);

			auio.uio_iov = &aio;
			auio.uio_iovcnt = 1;
			auio.uio_segflg = UIO_SYSSPACE;
			auio.uio_rw = UIO_READ;
			auio.uio_offset = 0;
			auio.uio_resid = sizeof(gctx->reply);
			auio.uio_td = td;

			rcvflg = 0;
			error = soreceive(so, NULL, &auio,
					  NULL, NULL, &rcvflg);
			gctx->secs = time_second - gctx->starttime;
			for (ifctx = gctx->interfaces;
			     ifctx != NULL;
			     ifctx = ifctx->next) {
				if (bootpc_ifctx_isresolved(ifctx) != 0 ||
				    bootpc_ifctx_isfailed(ifctx) != 0)
					continue;

				ifctx->call.secs = htons(gctx->secs);
			}
			if (error == EWOULDBLOCK)
				continue;
			if (error != 0)
				goto out;
			len = sizeof(gctx->reply) - auio.uio_resid;

			/* Do we have the required number of bytes ? */
			if (len < BOOTP_MIN_LEN)
				continue;
			gctx->replylen = len;

			/* Is it a reply? */
			if (gctx->reply.op != BOOTP_REPLY)
				continue;

			/* Is this an answer to our query */
			for (ifctx = gctx->interfaces;
			     ifctx != NULL;
			     ifctx = ifctx->next) {
				if (gctx->reply.xid != ifctx->call.xid)
					continue;

				/* Same HW address size ? */
				if (gctx->reply.hlen != ifctx->call.hlen)
					continue;

				/* Correct HW address ? */
				if (bcmp(gctx->reply.chaddr,
					 ifctx->call.chaddr,
					 ifctx->call.hlen) != 0)
					continue;

				break;
			}

			if (ifctx != NULL) {
				s =  bootpc_tag(&gctx->tmptag,
						&gctx->reply,
						gctx->replylen,
						TAG_DHCP_MSGTYPE);
				if (s != NULL) {
					switch (*s) {
					case DHCP_OFFER:
						s = "DHCP Offer";
						break;
					case DHCP_ACK:
						s = "DHCP Ack";
						break;
					default:
						s = "DHCP (unexpected)";
						break;
					}
				} else
					s = "BOOTP Reply";

				printf("Received %s packet"
				       " on %s from ",
				       s,
				       ifctx->ireq.ifr_name);
				print_in_addr(gctx->reply.siaddr);
				if (gctx->reply.giaddr.s_addr !=
				    htonl(INADDR_ANY)) {
					printf(" via ");
					print_in_addr(gctx->reply.giaddr);
				}
				if (bootpc_received(gctx, ifctx) != 0) {
					printf(" (accepted)");
					if (ifctx->outstanding) {
						ifctx->outstanding = 0;
						outstanding--;
					}
					/* Network settle delay */
					if (outstanding == 0)
						atimo = time_second +
							BOOTP_SETTLE_DELAY;
				} else
					printf(" (ignored)");
				if (ifctx->gotrootpath) {
					gotrootpath = 1;
					rtimo = time_second +
						BOOTP_SETTLE_DELAY;
					printf(" (got root path)");
				} else
					printf(" (no root path)");
				printf("\n");
			}
		} /* while secs */
#ifdef BOOTP_TIMEOUT
		if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
			break;
#endif
		/* Force a retry if halfway in DHCP negotiation */
		retry = 0;
		for (ifctx = gctx->interfaces; ifctx != NULL;
		     ifctx = ifctx->next) {
			if (ifctx->state == IF_DHCP_OFFERED) {
				if (ifctx->dhcpquerytype == DHCP_DISCOVER)
					retry = 1;
				else
					ifctx->state = IF_DHCP_UNRESOLVED;
			}
		}

		if (retry != 0)
			continue;

		if (gotrootpath != 0) {
			gctx->gotrootpath = gotrootpath;
			if (rtimo != 0 && time_second >= rtimo)
				break;
		}
	} /* forever send/receive */

	/*
	 * XXX: These are errors of varying seriousness being silently
	 * ignored
	 */

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
		if (bootpc_ifctx_isresolved(ifctx) == 0) {
			printf("%s timeout for interface %s\n",
			       ifctx->dhcpquerytype != DHCP_NOMSG ?
			       "DHCP" : "BOOTP",
			       ifctx->ireq.ifr_name);
		}
	}
	if (gctx->gotrootpath != 0) {
#if 0
		printf("Got a root path, ignoring remaining timeout\n");
#endif
		error = 0;
		goto out;
	}
#ifndef BOOTP_NFSROOT
	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
		if (bootpc_ifctx_isresolved(ifctx) != 0) {
			error = 0;
			goto out;
		}
	}
#endif
	error = ETIMEDOUT;
	goto out;

gotreply:
out:
	soclose(so);
out0:
	return error;
}
예제 #20
0
int
bootpc_call(
     struct bootp_packet *call,
     struct bootp_packet *reply,	/* output */
     struct proc *procp)
{
	struct socket *so;
	struct sockaddr_in *sin;
	struct mbuf *m, *nam;
	struct uio auio;
	struct iovec aio;
	int error, rcvflg, timo, secs, len;

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

	/*
	 * Create socket and set its recieve timeout.
	 */
	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)))
		goto out;

	m = m_get(M_WAIT, MT_SOOPTS);
	if (m == NULL) {
		error = ENOBUFS;
		goto out;
	} else {
		struct timeval *tv;
		tv = mtod(m, struct timeval *);
		m->m_len = sizeof(*tv);
		tv->tv_sec = 1;
		tv->tv_usec = 0;
		if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
			goto out;
	}

	/*
	 * Enable broadcast.
	 */
	{
		int *on;
		m = m_get(M_WAIT, MT_SOOPTS);
		if (m == NULL) {
			error = ENOBUFS;
			goto out;
		}
		on = mtod(m, int *);
		m->m_len = sizeof(*on);
		*on = 1;
		if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
			goto out;
	}

	/*
	 * Bind the local endpoint to a bootp client port.
	 */
	m = m_getclr(M_WAIT, MT_SONAME);
	sin = mtod(m, struct sockaddr_in *);
	sin->sin_len = m->m_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port = htons(IPPORT_BOOTPC);
	error = sobind(so, m);
	m_freem(m);
	if (error) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	nam = m_get(M_WAIT, MT_SONAME);
	if (nam == NULL) {
		error = ENOBUFS;
		goto out;
	}
	sin = mtod(nam, struct sockaddr_in *);
	sin-> sin_len = sizeof(*sin);
	sin-> sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_BROADCAST;
	sin->sin_port = htons(IPPORT_BOOTPS);

	nam->m_len = sizeof(*sin);

	/*
	 * 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.
	 */
	for (timo=1; timo <= MAX_RESEND_DELAY; timo++) {
		/* Send BOOTP request (or re-send). */
		
		aio.iov_base = (caddr_t) call;
		aio.iov_len = sizeof(*call);
		
		auio.uio_iov = &aio;
		auio.uio_iovcnt = 1;
		auio.uio_segflg = UIO_SYSSPACE;
		auio.uio_rw = UIO_WRITE;
		auio.uio_offset = 0;
		auio.uio_resid = sizeof(*call);
		auio.uio_procp = procp;
		error = sosend(so, nam, &auio, NULL, NULL, 0);
		if (error) {
			printf("bootpc_call: sosend: %d\n", error);
                        switch (error) {
                        case  ENOBUFS:             /* No buffer space available */
                        case  ENETUNREACH:         /* Network is unreachable */
                        case  ENETDOWN:            /* Network interface is not configured */
                        case  EHOSTDOWN:           /* Host is down */
                        case  EHOSTUNREACH:        /* Host is unreachable */
                        case  EMSGSIZE:            /* Message too long */
                                /* This is a possibly transient error.
                                   We can still receive replies from previous attempts. */
                                break;
                        default:
                              goto out;
                        }
		}

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		secs = timo;
		while (secs > 0) {
			aio.iov_base = (caddr_t) reply;
			aio.iov_len = sizeof(*reply);

			auio.uio_iov = &aio;
			auio.uio_iovcnt = 1;
			auio.uio_segflg = UIO_SYSSPACE;
			auio.uio_rw = UIO_READ;
			auio.uio_offset = 0;
			auio.uio_resid = sizeof(*reply);
			auio.uio_procp = procp;
			
			rcvflg = 0;
			error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg);
			if (error == EWOULDBLOCK) {
				secs--;
				call->secs=htons(ntohs(call->secs)+1);
				continue;
			}
			if (error)
				goto out;
			len = sizeof(*reply) - auio.uio_resid;

			/* Do we have the required number of bytes ? */
			if (len < BOOTP_MIN_LEN)
				continue;

			/* Is it the right reply? */
			if (reply->op != 2)
			  continue;

			if (reply->xid != call->xid)
				continue;

			if (reply->hlen != call->hlen)
			  continue;

			if (bcmp(reply->chaddr,call->chaddr,call->hlen))
			  continue;

			goto gotreply;	/* break two levels */

		} /* while secs */
	} /* send/receive a number of times then return an error */
	{
		uint32_t addr = ntohl(sin->sin_addr.s_addr);
        printf("BOOTP timeout for server %"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32"\n",
               (addr >> 24) & 0xff, (addr >> 16) & 0xff,
               (addr >> 8) & 0xff, addr & 0xff);
	}
	error = ETIMEDOUT;
	goto out;

 gotreply:
 out:
	if (nam) m_freem(nam);
	soclose(so);
	return error;
}
예제 #21
0
static int
libcfs_sock_create (struct socket **sockp, int *fatal,
                    __u32 local_ip, int local_port)
{
        struct sockaddr_in  locaddr;
        struct socket      *so;
        struct sockopt      sopt;
        int                 option;
        int                 rc;
        CFS_DECL_FUNNEL_DATA;

        *fatal = 1;
        CFS_NET_IN;
        rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
        CFS_NET_EX;
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (-rc);
        }
        
        bzero(&sopt, sizeof sopt);
        option = 1;
        sopt.sopt_level = SOL_SOCKET;
        sopt.sopt_name = SO_REUSEADDR;
        sopt.sopt_val = &option;
        sopt.sopt_valsize = sizeof(option);
        CFS_NET_IN;
        rc = sosetopt(so, &sopt);
        if (rc != 0) {
                CFS_NET_EX;
                CERROR ("Can't set sock reuse address: %d\n", rc);
                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 = sobind(so, (struct sockaddr *)&locaddr);
                if (rc == EADDRINUSE) {
                        CFS_NET_EX;
                        CDEBUG(D_NET, "Port %d already in use\n", local_port);
                        *fatal = 0;
                        goto out;
                }
                if (rc != 0) {
                        CFS_NET_EX;
                        CERROR ("Can't bind to local IP Address %u.%u.%u.%u: %d\n",
                        HIPQUAD(local_ip), rc);
                        goto out;
                }
        }
        *sockp = so;
        return 0;
out:
        CFS_NET_IN;
        soclose(so);
        CFS_NET_EX;
        return -rc;
}
예제 #22
0
/*
 * Connect to specified server via IPX
 */
static int
ncp_sock_connect_ipx(struct ncp_conn *conn)
{
	struct sockaddr_ipx sipx;
	struct ipxpcb *npcb;
	struct thread *td = conn->td;
	int addrlen, error, count;

	sipx.sipx_port = htons(0);

	for (count = 0;;count++) {
		if (count > (IPXPORT_WELLKNOWN-IPXPORT_RESERVED)*2) {
			error = EADDRINUSE;
			goto bad;
		}
		conn->ncp_so = conn->wdg_so = NULL;
		checkbad(socreate(AF_IPX, &conn->ncp_so, SOCK_DGRAM, 0, td->td_ucred, td));
		if (conn->li.opt & NCP_OPT_WDOG)
			checkbad(socreate(AF_IPX, &conn->wdg_so, SOCK_DGRAM, 0, td->td_ucred, td));
		addrlen = sizeof(sipx);
		sipx.sipx_family = AF_IPX;
		ipx_setnullnet(sipx.sipx_addr);
		ipx_setnullhost(sipx.sipx_addr);
		sipx.sipx_len = addrlen;
		error = sobind(conn->ncp_so, (struct sockaddr *)&sipx, td);
		if (error == 0) {
			if ((conn->li.opt & NCP_OPT_WDOG) == 0)
				break;
			sipx.sipx_addr = sotoipxpcb(conn->ncp_so)->ipxp_laddr;
			sipx.sipx_port = htons(ntohs(sipx.sipx_port) + 1);
			ipx_setnullnet(sipx.sipx_addr);
			ipx_setnullhost(sipx.sipx_addr);
			error = sobind(conn->wdg_so, (struct sockaddr *)&sipx, td);
		}
		if (!error) break;
		if (error != EADDRINUSE) goto bad;
		sipx.sipx_port = htons((ntohs(sipx.sipx_port)+4) & 0xfff8);
		soclose(conn->ncp_so);
		if (conn->wdg_so)
			soclose(conn->wdg_so);
	}
	npcb = sotoipxpcb(conn->ncp_so);
	npcb->ipxp_dpt = IPXPROTO_NCP;
	/* IPXrouted must be running, i.e. route must be presented */
	conn->li.ipxaddr.sipx_len = sizeof(struct sockaddr_ipx);
	checkbad(ncp_soconnect(conn->ncp_so, &conn->li.saddr, td));
	if (conn->wdg_so) {
		sotoipxpcb(conn->wdg_so)->ipxp_laddr.x_net = npcb->ipxp_laddr.x_net;
		sotoipxpcb(conn->wdg_so)->ipxp_laddr.x_host= npcb->ipxp_laddr.x_host;
	}
	if (!error) {
		conn->flags |= NCPFL_SOCONN;
	}
#ifdef NCPBURST
	if (ncp_burst_enabled) {
		checkbad(socreate(AF_IPX, &conn->bc_so, SOCK_DGRAM, 0, td));
		bzero(&sipx, sizeof(sipx));
		sipx.sipx_len = sizeof(sipx);
		checkbad(sobind(conn->bc_so, (struct sockaddr *)&sipx, td));
		checkbad(ncp_soconnect(conn->bc_so, &conn->li.saddr, td));
	}
#endif
	if (!error) {
		conn->flags |= NCPFL_SOCONN;
		ncp_sock_checksum(conn, 0);
	}
	return error;
bad:
	ncp_sock_disconnect(conn);
	return (error);
}