/* * Create a socket that is locally bound to a non-reserve port. For * any failures, -1 is returned which will cause the RPC code to * create the socket. */ int internal_function __get_socket (struct sockaddr_in *saddr) { int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (so < 0) return -1; struct sockaddr_in laddr; socklen_t namelen = sizeof (laddr); laddr.sin_family = AF_INET; laddr.sin_port = 0; laddr.sin_addr.s_addr = htonl (INADDR_ANY); int cc = __bind (so, (struct sockaddr *) &laddr, namelen); if (__glibc_unlikely (cc < 0)) { fail: __close (so); return -1; } cc = __connect (so, (struct sockaddr *) saddr, namelen); if (__glibc_unlikely (cc < 0)) goto fail; return so; }
static int open_socket (void) { int sock = __socket (PF_UNIX, SOCK_STREAM, 0); if (sock < 0) return -1; /* Make socket non-blocking. */ int fl = __fcntl (sock, F_GETFL); if (fl != -1) __fcntl (sock, F_SETFL, fl | O_NONBLOCK); struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy (sun.sun_path, _PATH_NSCDSOCKET); if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0 && errno != EINPROGRESS) goto out; struct pollfd fds[1]; fds[0].fd = sock; fds[0].events = POLLOUT | POLLERR | POLLHUP; if (__poll (fds, 1, 5 * 1000) > 0) /* Success. We do not check for success of the connect call here. If it failed, the following operations will fail. */ return sock; out: close_not_cancel_no_status (sock); return -1; }
/* Open a NETLINK socket. */ int __netlink_open (struct netlink_handle *h) { struct sockaddr_nl nladdr; h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (h->fd < 0) goto out; memset (&nladdr, '\0', sizeof (nladdr)); nladdr.nl_family = AF_NETLINK; if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0) { close_and_out: __netlink_close (h); out: #if __ASSUME_NETLINK_SUPPORT == 0 __no_netlink_support = 1; #endif return -1; } /* Determine the ID the kernel assigned for this netlink connection. It is not necessarily the PID if there is more than one socket open. */ socklen_t addr_len = sizeof (nladdr); if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0) goto close_and_out; h->pid = nladdr.nl_pid; return 0; }
/* * Usage: * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) unix based transporter. * Once *xprt is initialized, it is registered as a transporter * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svcunix_create * binds it to an arbitrary port. The routine then starts a unix * listener on the socket's associated port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * * Since unix streams do buffered io similar to stdio, the caller can specify * how big the send and receive buffers are via the second and third parms; * 0 => use the system default. */ SVCXPRT * svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) { bool_t madesock = FALSE; SVCXPRT *xprt; struct unix_rendezvous *r; struct sockaddr_un addr; socklen_t len = sizeof (struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { perror (_("svc_unix.c - AF_UNIX socket creation problem")); return (SVCXPRT *) NULL; } madesock = TRUE; } memset (&addr, '\0', sizeof (addr)); addr.sun_family = AF_UNIX; len = strlen (path) + 1; memcpy (addr.sun_path, path, len); len += sizeof (addr.sun_family); bind (sock, (struct sockaddr *) &addr, len); if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0 || listen (sock, 2) != 0) { perror (_("svc_unix.c - cannot getsockname or listen")); if (madesock) __close (sock); return (SVCXPRT *) NULL; } r = (struct unix_rendezvous *) mem_alloc (sizeof (*r)); xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { #ifdef USE_IN_LIBIO if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n")); else #endif fputs (_("svcunix_create: out of memory\n"), stderr); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; } r->sendsize = sendsize; r->recvsize = recvsize; xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t) r; xprt->xp_verf = _null_auth; xprt->xp_ops = &svcunix_rendezvous_op; xprt->xp_port = -1; xprt->xp_sock = sock; xprt_register (xprt); return xprt; }
int socket(int domain, int type, int protocol) { int fd; fd = __socket(domain, type, protocol); if (fdleak_record_backtrace) { fdleak_record_backtrace(fd); } return fd; }
/* * Usage: * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) tcp based transporter. * Once *xprt is initialized, it is registered as a transporter * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * If sock<0 then a socket is created, else sock is used. * If the socket, sock is not bound to a port then svctcp_create * binds it to an arbitrary port. The routine then starts a tcp * listener on the socket's associated port. In any (successful) case, * xprt->xp_sock is the registered socket number and xprt->xp_port is the * associated port number. * * Since tcp streams do buffered io similar to stdio, the caller can specify * how big the send and receive buffers are via the second and third parms; * 0 => use the system default. */ SVCXPRT * svctcp_create (int sock, u_int sendsize, u_int recvsize) { bool_t madesock = FALSE; SVCXPRT *xprt; struct tcp_rendezvous *r; struct sockaddr_in addr; socklen_t len = sizeof (struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror (_("svc_tcp.c - tcp socket creation problem")); return (SVCXPRT *) NULL; } madesock = TRUE; } __bzero ((char *) &addr, sizeof (addr)); addr.sin_family = AF_INET; if (bindresvport (sock, &addr)) { addr.sin_port = 0; (void) __bind (sock, (struct sockaddr *) &addr, len); } if ((__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) || (__listen (sock, SOMAXCONN) != 0)) { perror (_("svc_tcp.c - cannot getsockname or listen")); if (madesock) (void) __close (sock); return (SVCXPRT *) NULL; } r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r)); xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; } r->sendsize = sendsize; r->recvsize = recvsize; xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t) r; xprt->xp_verf = _null_auth; xprt->xp_ops = &svctcp_rendezvous_op; xprt->xp_port = ntohs (addr.sin_port); xprt->xp_sock = sock; xprt_register (xprt); return xprt; }
/* * don't use gethostbyname, which would invoke yellow pages * * Avoid loopback interfaces. We return information from a loopback * interface only if there are no other possible interfaces. */ void get_myaddress (struct sockaddr_in *addr) { int s; char buf[BUFSIZ]; struct ifconf ifc; struct ifreq ifreq, *ifr; int len, loopback = 0; if ((s = __socket (AF_INET, SOCK_DGRAM, 0)) < 0) { perror ("get_myaddress: socket"); exit (1); } ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; if (__ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0) { perror (_("get_myaddress: ioctl (get interface configuration)")); exit (1); } again: ifr = ifc.ifc_req; for (len = ifc.ifc_len; len; len -= sizeof ifreq) { ifreq = *ifr; if (__ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0) { perror ("get_myaddress: ioctl"); exit (1); } if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET) && (!(ifreq.ifr_flags & IFF_LOOPBACK) || (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK)))) { *addr = *((struct sockaddr_in *) &ifr->ifr_addr); addr->sin_port = htons (PMAPPORT); __close (s); return; } ifr++; } if (loopback == 0) { loopback = 1; goto again; } __close (s); }
static void internal_function openlog_internal(const char *ident, int logstat, int logfac) { if (ident != NULL) LogTag = ident; LogStat = logstat; if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) LogFacility = logfac; int retry = 0; while (retry < 2) { if (LogFile == -1) { SyslogAddr.sun_family = AF_UNIX; (void)strncpy(SyslogAddr.sun_path, _PATH_LOG, sizeof(SyslogAddr.sun_path)); if (LogStat & LOG_NDELAY) { if ((LogFile = __socket(AF_UNIX, LogType, 0)) == -1) return; (void)__fcntl(LogFile, F_SETFD, 1); } } if (LogFile != -1 && !connected) { int old_errno = errno; if (__connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) { int saved_errno = errno; int fd = LogFile; LogFile = -1; (void)__close(fd); __set_errno (old_errno); if (saved_errno == EPROTOTYPE) { /* retry with the other type: */ LogType = (LogType == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM); ++retry; continue; } } else connected = 1; } break; } }
/* Return a socket of any type. The socket can be used in subsequent ioctl calls to talk to the kernel. */ int internal_function __opensock (void) { /* Cache the last AF that worked, to avoid many redundant calls to socket(). */ static int sock_af = -1; int fd = -1; __libc_lock_define_initialized (static, lock); if (sock_af != -1) { fd = __socket (sock_af, SOCK_DGRAM, 0); if (fd != -1) return fd; } __libc_lock_lock (lock); if (sock_af != -1) fd = __socket (sock_af, SOCK_DGRAM, 0); if (fd == -1) { #ifdef AF_INET fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0); #endif #ifdef AF_INET6 if (fd < 0) fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0); #endif #ifdef AF_IPX if (fd < 0) fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0); #endif #ifdef AF_AX25 if (fd < 0) fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0); #endif #ifdef AF_APPLETALK if (fd < 0) fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0); #endif } __libc_lock_unlock (lock); return fd; }
/* =========================================================================== * TCP Socket Related */ int z_socket_tcp_connect (const char *address, const char *port, struct sockaddr_storage *addr) { struct addrinfo hints; struct addrinfo *info; struct addrinfo *p; int status; int sock; z_memzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((status = getaddrinfo(address, port, &hints, &info)) != 0) { fprintf(stderr, "getaddrinfo(): %s", gai_strerror(status)); return(-1); } sock = -1; for (p = info; p != NULL; p = p->ai_next) { if ((sock = __socket(p, 0, 0)) < 0) { perror("socket()"); continue; } if (connect(sock, p->ai_addr, p->ai_addrlen) < 0) { perror("connect()"); close(sock); sock = -1; continue; } if (addr != NULL) z_memcpy(addr, p->ai_addr, p->ai_addrlen); break; } freeaddrinfo(info); return(sock); }
static int svc_socket (u_long number, int type, int protocol, int reuse) { struct sockaddr_in addr; socklen_t len = sizeof (struct sockaddr_in); int sock, ret; const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp"; if ((sock = __socket (AF_INET, type, protocol)) < 0) { perror (_("svc_socket: socket creation problem")); return sock; } if (reuse) { ret = 1; ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof (ret)); if (ret < 0) { perror (_("svc_socket: socket reuse problem")); return ret; } } memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = htons(getservport(number, proto)); if (bind(sock, (struct sockaddr *) &addr, len) < 0) { perror (_("svc_socket: bind problem")); (void) __close(sock); sock = -1; } return svcsock_nonblock(sock); }
static int __socket_bind (const char *address, const char *port, struct addrinfo *hints, struct sockaddr_storage *addr) { struct addrinfo *info; struct addrinfo *p; int status; int sock; if ((status = getaddrinfo(address, port, hints, &info)) != 0) { fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status)); return(-1); } sock = -1; for (p = info; p != NULL; p = p->ai_next) { if ((sock = __socket(p, 1, 1)) < 0) { perror("socket()"); continue; } if (bind(sock, info->ai_addr, info->ai_addrlen) < 0) { perror("bind()"); close(sock); sock = -1; continue; } if (addr != NULL) z_memcpy(addr, p->ai_addr, p->ai_addrlen); break; } freeaddrinfo(info); return(sock); }
/* * Create a UDP based client handle. * If *sockp<0, *sockp is set to a newly created UPD socket. * If raddr->sin_port is 0 a binder on the remote machine * is consulted for the correct port number. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is initialized to null authentication. * Caller may wish to set this something more useful. * * wait is the amount of time used between retransmitting a call if * no response has been heard; retransmission occurs until the actual * rpc call times out. * * sendsz and recvsz are the maximum allowable packet sizes that can be * sent and received. */ CLIENT * clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *cl; struct cu_data *cu = NULL; struct rpc_msg call_msg; cl = (CLIENT *) mem_alloc (sizeof (CLIENT)); sendsz = ((sendsz + 3) / 4) * 4; recvsz = ((recvsz + 3) / 4) * 4; cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz); if (cl == NULL || cu == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); #ifdef USE_IN_LIBIO if (_IO_fwide (stderr, 0) > 0) (void) __fwprintf (stderr, L"%s", _("clntudp_create: out of memory\n")); else #endif (void) fputs (_("clntudp_create: out of memory\n"), stderr); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; } cu->cu_outbuf = &cu->cu_inbuf[recvsz]; if (raddr->sin_port == 0) { u_short port; if ((port = pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0) { goto fooy; } raddr->sin_port = htons (port); } cl->cl_ops = &udp_ops; cl->cl_private = (caddr_t) cu; cu->cu_raddr = *raddr; cu->cu_rlen = sizeof (cu->cu_raddr); cu->cu_wait = wait; cu->cu_total.tv_sec = -1; cu->cu_total.tv_usec = -1; cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; call_msg.rm_xid = _create_xid (); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg)) { goto fooy; } cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs)); if (*sockp < 0) { int dontblock = 1; *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (*sockp < 0) { struct rpc_createerr *ce = &get_rpc_createerr (); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = errno; goto fooy; } /* attempt to bind to prov port */ (void) bindresvport (*sockp, (struct sockaddr_in *) 0); /* the sockets rpc controls are non-blocking */ (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock); #ifdef IP_RECVERR { int on = 1; setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on)); } #endif cu->cu_closeit = TRUE; } else { cu->cu_closeit = FALSE; } cu->cu_sock = *sockp; cl->cl_auth = authnone_create (); return cl; fooy: if (cu) mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz); if (cl) mem_free ((caddr_t) cl, sizeof (CLIENT)); return (CLIENT *) NULL; }
static int svc_socket (u_long number, int type, int protocol, int reuse) { struct sockaddr_in addr; socklen_t len = sizeof (struct sockaddr_in); int sock, ret; const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp"; if ((sock = __socket (AF_INET, type, protocol)) < 0) { perror (_("svc_socket: socket creation problem")); return sock; } if (reuse) { ret = 1; ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof (ret)); if (ret < 0) { perror (_("svc_socket: socket reuse problem")); return ret; } } memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = htons(getservport(number, proto)); if (bind(sock, (struct sockaddr *) &addr, len) < 0) { perror (_("svc_socket: bind problem")); (void) __close(sock); sock = -1; } if (sock >= 0) { /* This socket might be shared among multiple processes * if mountd is run multi-threaded. So it is safest to * make it non-blocking, else all threads might wake * one will get the data, and the others will block * indefinitely. * In all cases, transaction on this socket are atomic * (accept for TCP, packet-read and packet-write for UDP) * so O_NONBLOCK will not confuse unprepared code causing * it to corrupt messages. * It generally safest to have O_NONBLOCK when doing an accept * as if we get a RST after the SYN and before accept runs, * we can block despite being told there was an acceptable * connection. */ int flags; if ((flags = fcntl(sock, F_GETFL)) < 0) { perror (_("svc_socket: can't get socket flags")); (void) __close (sock); sock = -1; } else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0) { perror (_("svc_socket: can't set socket flags")); (void) __close (sock); sock = -1; } } return sock; }
int res_send(struct SocketBase * libPtr, const char * buf, int buflen, char * answer, int anslen) { register int n; int try, v_circuit, resplen, nscount; int gotsomewhere = 0, connected = 0; int connreset = 0; u_short id, len; char *cp; fd_set dsmask; struct timeval timeout; struct in_addr *ns; struct sockaddr_in host; HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) answer; u_char terrno = ETIMEDOUT; #define JUNK_SIZE 512 char junk[JUNK_SIZE]; /* buffer for trash data */ #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send()\n")); D(bug("[AROSTCP](res_send.c) res_send: using socket %d\n", res_sock)); #endif #ifdef RES_DEBUG printf("res_send()\n"); __p_query(buf, libPtr); #endif /* RES_DEBUG */ v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; id = hp->id; /* * Send request, RETRY times, or until successful */ for (try = 0; try < _res.retry; try++) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Attempt %d\n", try)); #endif nscount = 0; DRES(Printf("Retry #%ld\n",try);) for (ns = _res.nsaddr_list; ns->s_addr; ns++) { nscount++; #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Querying server #%ld address = %s\n", nscount, __inet_ntoa(ns->s_addr, libPtr))); #endif #ifdef RES_DEBUG Printf("Querying server #%ld address = %s\n", nscount, __Inet_NtoA(ns->s_addr, libPtr)); #endif /* RES_DEBUG */ host.sin_len = sizeof(host); host.sin_family = AF_INET; host.sin_port = htons(NAMESERVER_PORT); host.sin_addr.s_addr = ns->s_addr; aligned_bzero_const(&host.sin_zero, sizeof(host.sin_zero)); usevc: if (v_circuit) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Using v_circuit\n")); #endif int truncated = 0; /* * Use virtual circuit; * at most one attempt per server. */ try = _res.retry; if (res_sock < 0) { res_sock = __socket(AF_INET, SOCK_STREAM, 0, libPtr); if (res_sock < 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket!!\n")); terrno = readErrnoValue(libPtr); #endif #ifdef RES_DEBUG Perror("socket (vc)"); #endif /* RES_DEBUG */ continue; } #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: created socket %d\n", res_sock)); #endif if (__connect(res_sock, (struct sockaddr *)&host, sizeof(struct sockaddr), libPtr) < 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Failed to connect\n")); #endif terrno = readErrnoValue(libPtr); #ifdef RES_DEBUG Perror("connect (vc)"); #endif /* RES_DEBUG */ (void) __CloseSocket(res_sock, libPtr); res_sock = -1; continue; } } /* * Send length & message */ len = htons((u_short)buflen); if ((__send(res_sock, (char *)&len, sizeof(len), 0, libPtr) != sizeof(len)) || ((__send(res_sock, (char *)buf, buflen, 0, libPtr) != buflen))) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Failed sending query\n")); #endif terrno = readErrnoValue(libPtr); #ifdef RES_DEBUG Perror("write(vc)"); #endif /* RES_DEBUG */ (void) __CloseSocket(res_sock, libPtr); res_sock = -1; continue; } /* * Receive length & response */ cp = answer; len = sizeof(short); while (len != 0 && (n = __recv(res_sock, (char *)cp, (int)len, 0, libPtr)) > 0) { cp += n; len -= n; } if (n <= 0) { terrno = readErrnoValue(libPtr); #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Failed recieving response\n")); #endif #ifdef RES_DEBUG Perror("read (vc)"); #endif /* RES_DEBUG */ (void) __CloseSocket(res_sock, libPtr); res_sock = -1; /* * A long running process might get its TCP * connection reset if the remote server was * restarted. Requery the server instead of * trying a new one. When there is only one * server, this means that a query might work * instead of failing. We only allow one reset * per query to prevent looping. */ if (terrno == ECONNRESET && !connreset) { connreset = 1; ns--; } continue; } cp = answer; if ((resplen = ntohs(*(u_short *)cp)) > anslen) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Truncated response\n")); #endif #ifdef RES_DEBUG Printf("response truncated\n"); #endif /* RES_DEBUG */ len = anslen; truncated = 1; } else len = resplen; while (len != 0 && (n = __recv(res_sock, (char *)cp, (int)len, 0, libPtr)) > 0) { cp += n; len -= n; } if (n <= 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Error recieving response\n")); #endif terrno = readErrnoValue(libPtr); #ifdef RES_DEBUG Perror("read (vc)"); #endif /* RES_DEBUG */ (void) __CloseSocket(res_sock, libPtr); res_sock = -1; continue; } if (truncated) { /* * Flush rest of answer * so connection stays in synch. */ anhp->tc = 1; len = resplen - anslen; while (len != 0) { n = (len > JUNK_SIZE ? JUNK_SIZE : len); if ((n = __recv(res_sock, junk, n, 0, libPtr)) > 0) len -= n; else break; } } } else { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Using datagrams\n")); #endif /* * Use datagrams. */ if (res_sock < 0) { res_sock = __socket(AF_INET, SOCK_DGRAM, 0, libPtr); if (res_sock < 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket\n")); #endif terrno = readErrnoValue(libPtr); #ifdef RES_DEBUG Perror("socket (dg)"); #endif /* RES_DEBUG */ continue; } } /* * I'm tired of answering this question, so: * On a 4.3BSD+ machine (client and server, * actually), sending to a nameserver datagram * port with no nameserver will cause an * ICMP port unreachable message to be returned. * If our datagram socket is "connected" to the * server, we get an ECONNREFUSED error on the next * socket operation, and select returns if the * error message is received. We can thus detect * the absence of a nameserver without timing out. * If we have sent queries to at least two servers, * however, we don't want to remain connected, * as we wish to receive answers from the first * server to respond. */ #warning "TODO*: see comment here .." /* This piece of code still behaves slightly wrong in case of ECONNREFUSED error. On next retry socket will be in disconnected state and instead of getting ECONNREFUSED again we'll timeout in WaitSelect() and get ETIMEDOUT. However, this is not critical and is queued for future - Pavel Fedin*/ if (try == 0 && nscount == 1) { /* * Don't use connect if we might * still receive a response * from another server. */ if (connected == 0) { if (__connect(res_sock, (struct sockaddr *)&host, sizeof(struct sockaddr), libPtr) < 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Error connecting\n")); #endif #ifdef RES_DEBUG Perror("connect (dg)"); #endif /* RES_DEBUG */ continue; } connected = 1; } if (__send(res_sock, buf, buflen, 0, libPtr) != buflen) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Error sending\n")); #endif #ifdef RES_DEBUG Perror("send (dg)"); #endif /* RES_DEBUG */ continue; } } else { /* * Disconnect if we want to listen * for responses from more than one server. */ if (connected) { (void) __connect(res_sock, &no_addr, sizeof(no_addr), libPtr); connected = 0; } if (__sendto(res_sock, buf, buflen, 0, (struct sockaddr *)&host, sizeof(struct sockaddr), libPtr) != buflen) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: [__sendto] Error\n")); #endif #ifdef RES_DEBUG Perror("sendto (dg)"); #endif /* RES_DEBUG */ continue; } } /* * Wait for reply */ timeout.tv_sec = (_res.retrans << try); if (try > 0) timeout.tv_sec /= nscount; if (timeout.tv_sec <= 0) timeout.tv_sec = 1; timeout.tv_usec = 0; wait: FD_ZERO(&dsmask); FD_SET(res_sock, &dsmask); n = __WaitSelect(res_sock+1, &dsmask, NULL, NULL, &timeout, NULL, libPtr); if (n < 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: [__WaitSelect] Error\n")); #endif #ifdef RES_DEBUG Perror("select"); #endif /* RES_DEBUG */ terrno = readErrnoValue(libPtr); if (terrno == EINTR) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: closing socket\n")); #endif __CloseSocket(res_sock, libPtr); res_sock = -1; return (-1); } continue; } if (n == 0) { /* * timeout */ #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Timeout!\n")); #endif #ifdef RES_DEBUG Printf("timeout\n"); #endif /* RES_DEBUG */ #if 1 || BSD >= 43 gotsomewhere = 1; #endif continue; } if ((resplen = __recv(res_sock, answer, anslen, 0, libPtr)) <= 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Error recieving\n")); #endif #ifdef RES_DEBUG Perror("recv (dg)"); #endif /* RES_DEBUG */ continue; } gotsomewhere = 1; if (id != anhp->id) { /* * response from old query, ignore it */ #ifdef RES_DEBUG Printf("old answer:\n"); __p_query(answer, libPtr); #endif /* RES_DEBUG */ goto wait; } if (!(_res.options & RES_IGNTC) && anhp->tc) { /* * get rest of answer; * use TCP with same server. */ #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Response is truncated\n")); #endif #ifdef RES_DEBUG Printf("truncated answer\n"); #endif /* RES_DEBUG */ (void)__CloseSocket(res_sock, libPtr); res_sock = -1; v_circuit = 1; goto usevc; } } #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Recieved answer\n")); #endif #ifdef RES_DEBUG Printf("got answer:\n"); __p_query(answer, libPtr); #endif /* RES_DEBUG */ /* * If using virtual circuits, we assume that the first server * is preferred * over the rest (i.e. it is on the local * machine) and only keep that one open. * If we have temporarily opened a virtual circuit, * or if we haven't been asked to keep a socket open, * close the socket. */ if ((v_circuit && ((_res.options & RES_USEVC) == 0 || ns->s_addr != 0)) || (_res.options & RES_STAYOPEN) == 0) { #if defined(__AROS__) D(bug("[AROSTCP](res_send.c) res_send: Closing socket\n")); #endif (void) __CloseSocket(res_sock, libPtr); res_sock = -1; } return (resplen); }
/* * Create a UDP based client handle. * If *sockp<0, *sockp is set to a newly created UPD socket. * If raddr->sin_port is 0 a binder on the remote machine * is consulted for the correct port number. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is initialized to null authentication. * Caller may wish to set this something more useful. * * wait is the amount of time used between retransmitting a call if * no response has been heard; retransmission occurs until the actual * rpc call times out. * * sendsz and recvsz are the maximum allowable packet sizes that can be * sent and received. */ CLIENT * __libc_clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp, u_int sendsz, u_int recvsz, int flags) { CLIENT *cl; struct cu_data *cu = NULL; struct rpc_msg call_msg; cl = (CLIENT *) mem_alloc (sizeof (CLIENT)); sendsz = ((sendsz + 3) / 4) * 4; recvsz = ((recvsz + 3) / 4) * 4; cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz); if (cl == NULL || cu == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); (void) __fxprintf (NULL, "%s: %s", "clntudp_create", _("out of memory\n")); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; } cu->cu_outbuf = &cu->cu_inbuf[recvsz]; if (raddr->sin_port == 0) { u_short port; if ((port = pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0) { goto fooy; } raddr->sin_port = htons (port); } cl->cl_ops = (struct clnt_ops *) &udp_ops; cl->cl_private = (caddr_t) cu; cu->cu_raddr = *raddr; cu->cu_rlen = sizeof (cu->cu_raddr); cu->cu_wait = wait; cu->cu_total.tv_sec = -1; cu->cu_total.tv_usec = -1; cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; call_msg.rm_xid = _create_xid (); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg)) { goto fooy; } cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs)); if (*sockp < 0) { #ifdef SOCK_NONBLOCK # ifndef __ASSUME_SOCK_CLOEXEC if (__have_sock_cloexec >= 0) # endif { *sockp = __socket (AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|flags, IPPROTO_UDP); # ifndef __ASSUME_SOCK_CLOEXEC if (__have_sock_cloexec == 0) __have_sock_cloexec = *sockp >= 0 || errno != EINVAL ? 1 : -1; # endif } #endif #ifndef __ASSUME_SOCK_CLOEXEC # ifdef SOCK_CLOEXEC if (__have_sock_cloexec < 0) # endif { *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); # ifdef SOCK_CLOEXEC if (flags & SOCK_CLOEXEC) __fcntl (*sockp, F_SETFD, FD_CLOEXEC); # endif } #endif if (__builtin_expect (*sockp < 0, 0)) { struct rpc_createerr *ce = &get_rpc_createerr (); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = errno; goto fooy; } /* attempt to bind to prov port */ (void) bindresvport (*sockp, (struct sockaddr_in *) 0); #ifndef __ASSUME_SOCK_CLOEXEC # ifdef SOCK_CLOEXEC if (__have_sock_cloexec < 0) # endif { /* the sockets rpc controls are non-blocking */ int dontblock = 1; (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock); } #endif #ifdef IP_RECVERR { int on = 1; __setsockopt (*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on)); } #endif cu->cu_closeit = TRUE; } else { cu->cu_closeit = FALSE; } cu->cu_sock = *sockp; cl->cl_auth = authnone_create (); return cl; fooy: if (cu) mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz); if (cl) mem_free ((caddr_t) cl, sizeof (CLIENT)); return (CLIENT *) NULL; }
/* Create a linked list of `struct ifaddrs' structures, one for each network interface on the host machine. If successful, store the list in *IFAP and return 0. On errors, return -1 and set `errno'. */ int getifaddrs (struct ifaddrs **ifap) { /* This implementation handles only IPv4 interfaces. The various ioctls below will only work on an AF_INET socket. Some different mechanism entirely must be used for IPv6. */ int fd = __socket (AF_INET, SOCK_DGRAM, 0); struct ifreq *ifreqs; int nifs; if (fd < 0) return -1; __ifreq (&ifreqs, &nifs, fd); if (ifreqs == NULL) /* XXX doesn't distinguish error vs none */ { __close (fd); return -1; } /* Now we have the list of interfaces and each one's address. Put it into the expected format and fill in the remaining details. */ if (nifs == 0) *ifap = NULL; else { struct { struct ifaddrs ia; struct sockaddr addr, netmask, broadaddr; char name[IF_NAMESIZE]; } *storage; struct ifreq *ifr; int i; storage = malloc (nifs * sizeof storage[0]); if (storage == NULL) { __close (fd); __if_freereq (ifreqs, nifs); return -1; } i = 0; ifr = ifreqs; do { /* Fill in pointers to the storage we've already allocated. */ storage[i].ia.ifa_next = &storage[i + 1].ia; storage[i].ia.ifa_addr = &storage[i].addr; /* Now copy the information we already have from SIOCGIFCONF. */ storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name, sizeof storage[i].name); storage[i].addr = ifr->ifr_addr; /* The SIOCGIFCONF call filled in only the name and address. Now we must also ask for the other information we need. */ if (__ioctl (fd, SIOCGIFFLAGS, ifr) < 0) break; storage[i].ia.ifa_flags = ifr->ifr_flags; ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFNETMASK, ifr) < 0) storage[i].ia.ifa_netmask = NULL; else { storage[i].ia.ifa_netmask = &storage[i].netmask; storage[i].netmask = ifr->ifr_netmask; } if (ifr->ifr_flags & IFF_BROADCAST) { ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFBRDADDR, ifr) < 0) storage[i].ia.ifa_broadaddr = NULL; { storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; storage[i].broadaddr = ifr->ifr_broadaddr; } } else if (ifr->ifr_flags & IFF_POINTOPOINT) { ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFDSTADDR, ifr) < 0) storage[i].ia.ifa_broadaddr = NULL; else { storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; storage[i].broadaddr = ifr->ifr_dstaddr; } } else storage[i].ia.ifa_broadaddr = NULL; storage[i].ia.ifa_data = NULL; /* Nothing here for now. */ ifr = __if_nextreq (ifr); } while (++i < nifs); if (i < nifs) /* Broke out early on error. */ { __close (fd); free (storage); __if_freereq (ifreqs, nifs); return -1; } storage[i - 1].ia.ifa_next = NULL; *ifap = &storage[0].ia; __close (fd); __if_freereq (ifreqs, nifs); } return 0; }
int socket(int domain, int type, int protocol) { return __socket(domain, type, protocol); }
/* * Create a client handle for a tcp/ip connection. * If *sockp<0, *sockp is set to a newly created TCP socket and it is * connected to raddr. If *sockp non-negative then * raddr is ignored. The rpc/tcp package does buffering * similar to stdio, so the client must pick send and receive buffer sizes,]; * 0 => use the default. * If raddr->sin_port is 0, then a binder on the remote machine is * consulted for the right port number. * NB: *sockp is copied into a private area. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this * something more useful. */ CLIENT * clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *h; struct ct_data *ct; struct rpc_msg call_msg; h = (CLIENT *) mem_alloc (sizeof (*h)); ct = (struct ct_data *) mem_alloc (sizeof (*ct)); if (h == NULL || ct == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; } /* * If no port number given ask the pmap for one */ if (raddr->sin_port == 0) { u_short port; if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0) { mem_free ((caddr_t) ct, sizeof (struct ct_data)); mem_free ((caddr_t) h, sizeof (CLIENT)); return ((CLIENT *) NULL); } raddr->sin_port = htons (port); } /* * If no socket given, open one */ if (*sockp < 0) { *sockp = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); (void) bindresvport (*sockp, (struct sockaddr_in *) 0); if ((*sockp < 0) || (__connect (*sockp, (struct sockaddr *) raddr, sizeof (*raddr)) < 0)) { struct rpc_createerr *ce = &get_rpc_createerr (); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = errno; if (*sockp >= 0) (void) __close (*sockp); goto fooy; } ct->ct_closeit = TRUE; } else { ct->ct_closeit = FALSE; } /* * Set up private data struct */ ct->ct_sock = *sockp; ct->ct_wait.tv_usec = 0; ct->ct_waitset = FALSE; ct->ct_addr = *raddr; /* * Initialize call message */ call_msg.rm_xid = _create_xid (); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = prog; call_msg.rm_call.cb_vers = vers; /* * pre-serialize the static part of the call msg and stash it away */ xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) { if (ct->ct_closeit) { (void) __close (*sockp); } goto fooy; } ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); XDR_DESTROY (&(ct->ct_xdrs)); /* * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, (caddr_t) ct, readtcp, writetcp); h->cl_ops = (struct clnt_ops *) &tcp_ops; h->cl_private = (caddr_t) ct; h->cl_auth = authnone_create (); return h; fooy: /* * Something goofed, free stuff and barf */ mem_free ((caddr_t) ct, sizeof (struct ct_data)); mem_free ((caddr_t) h, sizeof (CLIENT)); return ((CLIENT *) NULL); }
/* Return a socket of any type. The socket can be used in subsequent ioctl calls to talk to the kernel. */ int internal_function __opensock (void) { static int last_family; /* Available socket family we will use. */ static int last_type; static const struct { int family; const char procname[15]; } afs[] = { /* The 2.2 kernels cannot handle ioctl(SIOCGIFCONF) on AF_UNIX sockets. Give the kernel a chance to user inet sockets on old kernels. */ #if __LINUX_KERNEL_VERSION < 132096 { AF_INET, "" }, { AF_UNIX, "net/unix" }, #else { AF_UNIX, "net/unix" }, { AF_INET, "" }, #endif { AF_INET6, "net/if_inet6" }, { AF_AX25, "net/ax25" }, { AF_NETROM, "net/nr" }, { AF_ROSE, "net/rose" }, { AF_IPX, "net/ipx" }, { AF_APPLETALK, "net/appletalk" }, { AF_ECONET, "sys/net/econet" }, { AF_ASH, "sys/net/ash" }, { AF_X25, "net/x25" } }; #define nafs (sizeof (afs) / sizeof (afs[0])) char fname[sizeof "/proc/" + 14]; int result; int has_proc; size_t cnt; /* We already know which family to use from the last call. Use it again. */ if (last_family != 0) { assert (last_type != 0); result = __socket (last_family, last_type, 0); if (result != -1 || errno != EAFNOSUPPORT) /* Maybe the socket type isn't supported anymore (module is unloaded). In this case again try to find the type. */ return result; /* Reset the values. They seem not valid anymore. */ last_family = 0; last_type = 0; } /* Check whether the /proc filesystem is available. */ has_proc = __access ("/proc/net", R_OK) != -1; strcpy (fname, "/proc/"); /* Iterate over the interface families and find one which is available. */ for (cnt = 0; cnt < nafs; ++cnt) { int type = SOCK_DGRAM; if (has_proc && afs[cnt].procname[0] != '\0') { strcpy (fname + 6, afs[cnt].procname); if (__access (fname, R_OK) == -1) /* The /proc entry is not available. I.e., we cannot create a socket of this type (without loading the module). Don't look for it since this might trigger loading the module. */ continue; } if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25) type = SOCK_SEQPACKET; result = __socket (afs[cnt].family, type, 0); if (result != -1) { /* Found an available family. */ last_type = type; last_family = afs[cnt].family; return result; } } /* None of the protocol families is available. It is unclear what kind of error is returned. ENOENT seems like a reasonable choice. */ __set_errno (ENOENT); return -1; }
int rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, struct rpc_timeval *timeout) { int s; struct pollfd fd; int milliseconds; int res; /* RFC 868 says the time is transmitted as a 32-bit value. */ uint32_t thetime; struct sockaddr_in from; int fromlen; int type; if (timeout == NULL) type = SOCK_STREAM; else type = SOCK_DGRAM; s = __socket (AF_INET, type, 0); if (s < 0) return (-1); addrp->sin_family = AF_INET; addrp->sin_port = htons (IPPORT_TIMESERVER); if (type == SOCK_DGRAM) { res = __sendto (s, (char *) &thetime, sizeof (thetime), 0, (struct sockaddr *) addrp, sizeof (*addrp)); if (res < 0) { do_close (s); return -1; } milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); fd.fd = s; fd.events = POLLIN; do res = __poll (&fd, 1, milliseconds); while (res < 0 && errno == EINTR); if (res <= 0) { if (res == 0) __set_errno (ETIMEDOUT); do_close (s); return (-1); } fromlen = sizeof (from); res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0, (struct sockaddr *) &from, &fromlen); do_close (s); if (res < 0) return -1; } else { if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) { do_close (s); return -1; } res = __read (s, (char *) &thetime, sizeof (thetime)); do_close (s); if (res < 0) return (-1); } if (res != sizeof (thetime)) { __set_errno (EIO); return -1; } thetime = ntohl (thetime); timep->tv_sec = thetime - TOFFSET; timep->tv_usec = 0; return 0; }
/* * Create a client handle for a tcp/ip connection. * If *sockp<0, *sockp is set to a newly created TCP socket and it is * connected to raddr. If *sockp non-negative then * raddr is ignored. The rpc/tcp package does buffering * similar to stdio, so the client must pick send and receive buffer sizes,]; * 0 => use the default. * If raddr->sin_port is 0, then a binder on the remote machine is * consulted for the right port number. * NB: *sockp is copied into a private area. * NB: It is the clients responsibility to close *sockp. * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this * something more useful. */ CLIENT * clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *h; struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct)); struct rpc_msg call_msg; int len; h = (CLIENT *) mem_alloc (sizeof (*h)); if (h == NULL || ct == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; } /* * If no socket given, open one */ if (*sockp < 0) { *sockp = __socket (AF_UNIX, SOCK_STREAM, 0); len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1; if (*sockp < 0 || __connect (*sockp, (struct sockaddr *) raddr, len) < 0) { struct rpc_createerr *ce = &get_rpc_createerr (); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = errno; if (*sockp != -1) __close (*sockp); goto fooy; } ct->ct_closeit = TRUE; } else { ct->ct_closeit = FALSE; } /* * Set up private data struct */ ct->ct_sock = *sockp; ct->ct_wait.tv_usec = 0; ct->ct_waitset = FALSE; ct->ct_addr = *raddr; /* * Initialize call message */ call_msg.rm_xid = _create_xid (); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = prog; call_msg.rm_call.cb_vers = vers; /* * pre-serialize the static part of the call msg and stash it away */ xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) { if (ct->ct_closeit) __close (*sockp); goto fooy; } ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); XDR_DESTROY (&(ct->ct_xdrs)); /* * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, (caddr_t) ct, readunix, writeunix); h->cl_ops = (struct clnt_ops *) &unix_ops; h->cl_private = (caddr_t) ct; h->cl_auth = authnone_create (); return h; fooy: /* * Something goofed, free stuff and barf */ mem_free ((caddr_t) ct, sizeof (struct ct_data)); mem_free ((caddr_t) h, sizeof (CLIENT)); return (CLIENT *) NULL; }