static int setopt(int fd, int level, int name, int value) { struct t_optmgmt req, resp; struct { struct opthdr opt; int value; } reqbuf; reqbuf.opt.level = level; reqbuf.opt.name = name; reqbuf.opt.len = sizeof (int); reqbuf.value = value; req.flags = T_NEGOTIATE; req.opt.len = sizeof (reqbuf); req.opt.buf = (char *)&reqbuf; resp.flags = 0; resp.opt.buf = (char *)&reqbuf; resp.opt.maxlen = sizeof (reqbuf); if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) { t_error("t_optmgmt"); return (-1); } return (0); }
static int get_opt(int fd, int level, int name) { struct t_optmgmt req, res; struct { struct opthdr opt; int value; } reqbuf; reqbuf.opt.level = level; reqbuf.opt.name = name; reqbuf.opt.len = sizeof (int); reqbuf.value = 0; req.flags = T_CURRENT; req.opt.len = sizeof (reqbuf); req.opt.buf = (char *)&reqbuf; res.flags = 0; res.opt.buf = (char *)&reqbuf; res.opt.maxlen = sizeof (reqbuf); if (t_optmgmt(fd, &req, &res) < 0 || res.flags != T_SUCCESS) { t_error("t_optmgmt"); return (-1); } return (reqbuf.value); }
/* **************************************************************** * Modifica algumas características da conexão * **************************************************************** */ static int set_param (int fd) { T_OPTMGMT req_optmgmt, ret_optmgmt; TCP_OPTIONS options; /* * Obtém os valores em USO */ memset (&options, 0, sizeof (TCP_OPTIONS)); req_optmgmt.flags = T_CHECK; req_optmgmt.opt.buf = &options; req_optmgmt.opt.len = sizeof (TCP_OPTIONS); ret_optmgmt.opt.buf = &options; ret_optmgmt.opt.maxlen = sizeof (TCP_OPTIONS); if (t_optmgmt (fd, &req_optmgmt, &ret_optmgmt) < 0) return (-1); /* * Negocia o "max_wait" e "max_silence" */ req_optmgmt.flags = T_NEGOTIATE; options.max_wait = 0; /* Sem limite */ options.max_silence = 0; /* Sem limite */ /*** req_optmgmt.opt.buf = &options; ***/ /*** req_optmgmt.opt.len = sizeof (TCP_OPTIONS); ***/ /*** ret_optmgmt.opt.buf = &options; ***/ /*** ret_optmgmt.opt.maxlen = sizeof (TCP_OPTIONS); ***/ if (t_optmgmt (fd, &req_optmgmt, &ret_optmgmt) < 0) return (-1); return (0); } /* end set_param */
int xti_getopt(int fd, int level, int name, void *optval, socklen_t *optlenp) { int rc, len; struct t_optmgmt *req, *ret; struct t_opthdr *topt; req = T_alloc(fd, T_OPTMGMT, T_ALL); ret = T_alloc(fd, T_OPTMGMT, T_ALL); if (req->opt.maxlen == 0) err_quit("xti_getopt: opt.maxlen == 0"); topt = (struct t_opthdr *) req->opt.buf; topt->level = level; topt->name = name; topt->len = sizeof(struct t_opthdr); /* just a t_opthdr{} */ req->opt.len = topt->len; req->flags = T_CURRENT; if (t_optmgmt(fd, req, ret) < 0) { T_free(req, T_OPTMGMT); T_free(ret, T_OPTMGMT); return(-1); } rc = ret->flags; if (rc == T_SUCCESS || rc == T_READONLY) { /*4copy back value and length */ topt = (struct t_opthdr *) ret->opt.buf; len = topt->len - sizeof(struct t_opthdr); len = min(len, *optlenp); memcpy(optval, topt+1, len); *optlenp = len; } T_free(req, T_OPTMGMT); T_free(ret, T_OPTMGMT); if (rc == T_SUCCESS || rc == T_READONLY) return(0); return(-1); /* T_NOTSUPPORT */ }
static int tlx_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { struct t_optmgmt request, reply; struct { struct opthdr sockopt; char data[256]; } optbuf; debug_msg("Entering tlx_setsockopt, " "fd: %d, level: %d, optname: %d, optval: %x, optlen: %d", fd, level, optname, optval, optlen); if (optlen > sizeof (optbuf.data)) { error_msg(gettext("t_optmgmt request too long")); return (-1); } optbuf.sockopt.level = level; optbuf.sockopt.name = optname; optbuf.sockopt.len = optlen; (void) memcpy(optbuf.data, optval, optlen); request.opt.len = sizeof (struct opthdr) + optlen; request.opt.buf = (char *)&optbuf; request.flags = T_NEGOTIATE; reply.opt.maxlen = sizeof (struct opthdr) + optlen; reply.opt.buf = (char *)&optbuf; reply.flags = 0; if ((t_optmgmt(fd, &request, &reply) == -1) || (reply.flags != T_SUCCESS)) { error_msg("t_optmgmt: %s", t_strerror(t_errno)); return (-1); } return (0); }
void xti_set_ulong_opt(int fd, const char *str, u_long level, u_long name) { struct t_opthdr *topt; topt = (struct t_opthdr *) req->opt.buf; topt->level = level; topt->name = name; topt->len = sizeof(struct t_opthdr); req->opt.len = topt->len; req->flags = T_CURRENT; printf("%s: ", str); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error\n"); } else { topt = (struct t_opthdr *) ret->opt.buf; if (topt->status == T_SUCCESS || topt->status == T_READONLY) printf("%lu\n", *((u_long *) (topt + 1))); else printf("status = %ld\n", topt->status); } }
void xti_def_uchar_opt(int fd, const char *str, t_scalar_t level, t_scalar_t name) { struct t_opthdr *topt; topt = (struct t_opthdr *) req->opt.buf; topt->level = level; topt->name = name; topt->len = sizeof(struct t_opthdr); req->opt.len = topt->len; req->flags = T_DEFAULT; printf("%s: ", str); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error\n"); } else { topt = (struct t_opthdr *) ret->opt.buf; printf("len = %d, ", topt->len); if (topt->status == T_SUCCESS || topt->status == T_READONLY) printf("%u\n", *((u_char *) (topt + 1))); else printf("status = %ld\n", topt->status); } }
{ struct { struct t_opthdr hdr; char optval[64]; } opt; struct t_optmgmt opts = { { .maxlen = sizeof(opt), .len = optlen, .buf = opt.optval, } , T_NEGOTIATE, }; int retval; retval = t_optmgmt(s, &opts, &opts); if (retval == -1) { switch (t_errno) { case TBADF: errno = EBADF; break; default: case TBADFLAG: case TBADOPT: case TBUFOVFLW: case TNOTSUPPORT: case TOUTSTATE: errno = EINVAL; break; case TPROTO: errno = EPROTO;
int nfslib_bindit(struct netconfig *nconf, struct netbuf **addr, struct nd_hostserv *hs, int backlog) { int fd; struct t_bind *ntb; struct t_bind tb; struct nd_addrlist *addrlist; struct t_optmgmt req, resp; struct opthdr *opt; char reqbuf[128]; bool_t use_any = FALSE; bool_t gzone = TRUE; if ((fd = nfslib_transport_open(nconf)) == -1) { syslog(LOG_ERR, "cannot establish transport service over %s", nconf->nc_device); return (-1); } addrlist = (struct nd_addrlist *)NULL; /* nfs4_callback service does not used a fieed port number */ if (strcmp(hs->h_serv, "nfs4_callback") == 0) { tb.addr.maxlen = 0; tb.addr.len = 0; tb.addr.buf = 0; use_any = TRUE; gzone = (getzoneid() == GLOBAL_ZONEID); } else if (netdir_getbyname(nconf, hs, &addrlist) != 0) { syslog(LOG_ERR, "Cannot get address for transport %s host %s service %s", nconf->nc_netid, hs->h_host, hs->h_serv); (void) t_close(fd); return (-1); } if (strcmp(nconf->nc_proto, "tcp") == 0) { /* * If we're running over TCP, then set the * SO_REUSEADDR option so that we can bind * to our preferred address even if previously * left connections exist in FIN_WAIT states. * This is somewhat bogus, but otherwise you have * to wait 2 minutes to restart after killing it. */ if (reuseaddr(fd) == -1) { syslog(LOG_WARNING, "couldn't set SO_REUSEADDR option on transport"); } } else if (strcmp(nconf->nc_proto, "udp") == 0) { /* * In order to run MLP on UDP, we need to handle creds. */ if (recvucred(fd) == -1) { syslog(LOG_WARNING, "couldn't set SO_RECVUCRED option on transport"); } } /* * Make non global zone nfs4_callback port MLP */ if (use_any && is_system_labeled() && !gzone) { if (anonmlp(fd) == -1) { /* * failing to set this option means nfs4_callback * could fail silently later. So fail it with * with an error message now. */ syslog(LOG_ERR, "couldn't set SO_ANON_MLP option on transport"); (void) t_close(fd); return (-1); } } if (nconf->nc_semantics == NC_TPI_CLTS) tb.qlen = 0; else tb.qlen = backlog; /* LINTED pointer alignment */ ntb = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL); if (ntb == (struct t_bind *)NULL) { syslog(LOG_ERR, "t_alloc failed: t_errno %d, %m", t_errno); (void) t_close(fd); netdir_free((void *)addrlist, ND_ADDRLIST); return (-1); } /* * XXX - what about the space tb->addr.buf points to? This should * be either a memcpy() to/from the buf fields, or t_alloc(fd,T_BIND,) * should't be called with T_ALL. */ if (addrlist) tb.addr = *(addrlist->n_addrs); /* structure copy */ if (t_bind(fd, &tb, ntb) == -1) { syslog(LOG_ERR, "t_bind failed: t_errno %d, %m", t_errno); (void) t_free((char *)ntb, T_BIND); netdir_free((void *)addrlist, ND_ADDRLIST); (void) t_close(fd); return (-1); } /* make sure we bound to the right address */ if (use_any == FALSE && (tb.addr.len != ntb->addr.len || memcmp(tb.addr.buf, ntb->addr.buf, tb.addr.len) != 0)) { syslog(LOG_ERR, "t_bind to wrong address"); (void) t_free((char *)ntb, T_BIND); netdir_free((void *)addrlist, ND_ADDRLIST); (void) t_close(fd); return (-1); } /* * Call nfs4svc_setport so that the kernel can be * informed what port number the daemon is listing * for incoming connection requests. */ if ((nconf->nc_semantics == NC_TPI_COTS || nconf->nc_semantics == NC_TPI_COTS_ORD) && Mysvc4 != NULL) (*Mysvc4)(fd, NULL, nconf, NFS4_SETPORT, &ntb->addr); *addr = &ntb->addr; netdir_free((void *)addrlist, ND_ADDRLIST); if (strcmp(nconf->nc_proto, "tcp") == 0) { /* * Disable the Nagle algorithm on TCP connections. * Connections accepted from this listener will * inherit the listener options. */ /* LINTED pointer alignment */ opt = (struct opthdr *)reqbuf; opt->level = IPPROTO_TCP; opt->name = TCP_NODELAY; opt->len = sizeof (int); /* LINTED pointer alignment */ *(int *)((char *)opt + sizeof (*opt)) = 1; req.flags = T_NEGOTIATE; req.opt.len = sizeof (*opt) + opt->len; req.opt.buf = (char *)opt; resp.flags = 0; resp.opt.buf = reqbuf; resp.opt.maxlen = sizeof (reqbuf); if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) { syslog(LOG_ERR, "couldn't set NODELAY option for proto %s: t_errno = %d, %m", nconf->nc_proto, t_errno); } nfslib_set_sockbuf(fd); } return (fd); }
void xti_set_uchar_opt(int fd, const char *str, u_long level, u_long name, u_int val) { struct t_opthdr *topt; /* first check that option is supported */ topt = (struct t_opthdr *) req->opt.buf; topt->level = level; topt->name = name; topt->len = sizeof(struct t_opthdr); /* just the header, no value */ req->opt.len = topt->len; req->flags = T_CHECK; printf("%s: check: ", str); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error %d", t_errno); } else { if (ret->opt.len >= sizeof(struct t_opthdr)) { topt = (struct t_opthdr *) ret->opt.buf; printf("%s", xti_flag_str(topt->status)); } else printf("*ret->opt.len = %d", ret->opt.len); } /* get default value of option */ /* ret is "const", so it was not changed by t_optmgmt() */ topt = (struct t_opthdr *) req->opt.buf; topt->status = 0; req->flags = T_DEFAULT; printf("; default: "); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error %d", t_errno); } else { topt = (struct t_opthdr *) ret->opt.buf; printf("(ret->opt.len = %d, len = %d) ", ret->opt.len, topt->len); if (topt->status == T_SUCCESS || topt->status == T_READONLY) printf("%u", *((u_char *) (topt + 1))); else printf("status = %ld", topt->status); } /* now change value */ topt = (struct t_opthdr *) req->opt.buf; topt->status = 0; topt->len += sizeof(u_long); req->opt.len = topt->len; *((u_long *) (topt + 1)) = val; req->flags = T_NEGOTIATE; printf("; negotiated: "); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error %d", t_errno); } else { topt = (struct t_opthdr *) ret->opt.buf; if (topt->status == T_SUCCESS) printf("T_SUCCESS"); else if (topt->status == T_PARTSUCCESS) printf("T_PARTSUCCESS"); else if (topt->status == T_READONLY) printf("T_READONLY"); else if (topt->status == T_FAILURE) printf("T_FAILURE"); else if (topt->status == T_NOTSUPPORT) printf("T_NOTSUPPORT"); else printf("status = %ld\n", topt->status); } topt = (struct t_opthdr *) req->opt.buf; topt->len -= sizeof(u_long); req->opt.len = topt->len; req->flags = T_CURRENT; printf("; current: "); if (t_optmgmt(fd, req, ret) == -1) { printf("t_optmgmt error %d", t_errno); } else { topt = (struct t_opthdr *) ret->opt.buf; if (topt->status == T_SUCCESS || topt->status == T_READONLY) printf("%u", *((u_long *) (topt + 1))); else printf("status = %ld", topt->status); } printf("\n"); }