SVCXPRT * svc_dg_ncreate(int fd, u_int sendsize, u_int recvsize) { SVCXPRT *xprt; struct svc_dg_data *su = NULL; struct __rpc_sockinfo si; struct sockaddr_storage ss; socklen_t slen; uint32_t oflags; if (!__rpc_fd2sockinfo(fd, &si)) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, svc_dg_str, svc_dg_err1); return (NULL); } /* * Find the receive and the send size */ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); if ((sendsize == 0) || (recvsize == 0)) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, svc_dg_str, svc_dg_err2); return (NULL); } xprt = mem_alloc(sizeof (SVCXPRT)); if (xprt == NULL) goto freedata; memset(xprt, 0, sizeof (SVCXPRT)); /* Init SVCXPRT locks, etc */ mutex_init(&xprt->xp_lock, NULL); mutex_init(&xprt->xp_auth_lock, NULL); su = mem_alloc(sizeof (*su)); if (su == NULL) goto freedata; su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4; if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) goto freedata; xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); su->su_cache = NULL; xprt->xp_flags = SVC_XPRT_FLAG_NONE; xprt->xp_refcnt = 1; xprt->xp_fd = fd; xprt->xp_p2 = su; svc_dg_ops(xprt); xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); slen = sizeof ss; if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) goto freedata; __rpc_set_netbuf(&xprt->xp_ltaddr, &ss, slen); switch (ss.ss_family) { case AF_INET: xprt->xp_port = ntohs(((struct sockaddr_in *) &ss)->sin_port); break; #ifdef INET6 case AF_INET6: xprt->xp_port = ntohs(((struct sockaddr_in6 *) &ss)->sin6_port); break; #endif case AF_LOCAL: /* no port */ break; default: break; } /* Enable reception of IP*_PKTINFO control msgs */ svc_dg_enable_pktinfo(fd, &si); /* Make reachable */ xprt->xp_p5 = rpc_dplx_lookup_rec(xprt->xp_fd, RPC_DPLX_FLAG_NONE, &oflags); /* ref+1 */ svc_rqst_init_xprt(xprt); /* Conditional xprt_register */ if (! (__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) xprt_register(xprt); return (xprt); freedata: __warnx(TIRPC_DEBUG_FLAG_SVC_DG, svc_dg_str, __no_mem_str); if (xprt) { if (su) (void) mem_free(su, sizeof (*su)); svc_rqst_finalize_xprt(xprt, SVC_RQST_FLAG_NONE); (void) mem_free(xprt, sizeof (SVCXPRT)); } return (NULL); }
SVCXPRT * svc_dg_ncreatef(const int fd, const u_int sendsz, const u_int recvsz, const uint32_t flags) { SVCXPRT *xprt; struct rpc_dplx_rec *rec; struct svc_dg_xprt *su; struct __rpc_sockinfo si; u_int recvsize; u_int sendsize; u_int xp_flags; int rc; /* atomically find or create shared fd state; ref+1; locked */ xprt = svc_xprt_lookup(fd, svc_dg_xprt_setup); if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d svc_xprt_lookup failed", __func__, fd); return (NULL); } rec = REC_XPRT(xprt); xp_flags = atomic_postset_uint16_t_bits(&xprt->xp_flags, flags | SVC_XPRT_FLAG_INITIALIZED); if ((xp_flags & SVC_XPRT_FLAG_INITIALIZED)) { rpc_dplx_rui(rec); XPRT_TRACE(xprt, __func__, __func__, __LINE__); return (xprt); } if (!__rpc_fd2sockinfo(fd, &si)) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d could not get transport information", __func__, fd); return (NULL); } /* * Find the receive and the send size */ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz); recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz); if ((sendsize == 0) || (recvsize == 0)) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d transport does not support data transfer", __func__, fd); return (NULL); } __rpc_address_setup(&xprt->xp_local); rc = getsockname(fd, xprt->xp_local.nb.buf, &xprt->xp_local.nb.len); if (rc < 0) { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_INITIALIZED); rpc_dplx_rui(rec); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: fd %d getsockname failed (%d)", __func__, fd, rc); return (NULL); } /* * Should be multiple of 4 for XDR. */ su = DG_DR(rec); su->su_dr.sendsz = ((sendsize + 3) / 4) * 4; su->su_dr.recvsz = ((recvsize + 3) / 4) * 4; su->su_dr.maxrec = ((MAX(sendsize, recvsize) + 3) / 4) * 4; /* duplex streams are not used by the rendezvous transport */ xdrmem_create(su->su_dr.ioq.xdrs, NULL, 0, XDR_ENCODE); svc_dg_rendezvous_ops(xprt); /* Enable reception of IP*_PKTINFO control msgs */ svc_dg_enable_pktinfo(fd, &si); /* Conditional register */ if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS) && !(flags & SVC_CREATE_FLAG_XPRT_NOREG)) || (flags & SVC_CREATE_FLAG_XPRT_DOREG)) svc_rqst_evchan_reg(__svc_params->ev_u.evchan.id, xprt, SVC_RQST_FLAG_LOCKED | SVC_RQST_FLAG_CHAN_AFFINITY); /* release */ rpc_dplx_rui(rec); XPRT_TRACE(xprt, __func__, __func__, __LINE__); #if defined(HAVE_BLKIN) __rpc_set_blkin_endpoint(xprt, "svc_dg"); #endif return (xprt); }