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); }
/* 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); }
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; }
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; }
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); }
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; }
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 }
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; }
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; }
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; }
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); }
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; }
/* * 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; }
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); }
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); }
/* * 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); }
/* * 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; }
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; }
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; }
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; }
/* * 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); }