/* **************************************************************** * Abre a conexão (parte do servidor) * **************************************************************** */ int tcp_open (int port) { int fd; T_BIND req; INADDR req_addr; if ((fd = t_open (tcpdevname, O_RDWR, (T_INFO *)NULL)) < 0) return (-1); /* * Preenche a estrutura T_BIND */ FILL_INADDR (req_addr, 0, port); FILL_NETBUF (req.addr, &req_addr, sizeof (req_addr)); req.qlen = MAX_LISTEN_QLEN; if (t_bind (fd, &req, (T_BIND *)NULL) < 0) goto bad; if (set_param (fd) < 0) goto bad; listen_port = port; return (fd); bad: t_close (fd); return (-1); } /* end tcp_open */
int local_work(const int port, struct t_call **call) { struct t_bind *req; struct sockaddr_in addr_in; int fd = -1; if ((fd = t_open(DEV_XTI, O_RDWR, NULL)) == -1) error("serwer->t_open", fd); if ((req = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR)) == NULL) error("serwer->t_alloc-bind", fd); req->qlen = 5; req->addr.len = sizeof(addr_in); req->addr.buf = (char *) & addr_in; addr_in.sin_family = AF_INET; addr_in.sin_addr.s_addr = INADDR_ANY; addr_in.sin_port = htons(port); if (t_bind(fd, req, req) < 0) error("serwer->t_bind", fd); if ((*call = (struct t_call *) t_alloc(fd, T_CALL, T_ALL)) == NULL) error("serwer->t_alloc-bind", fd); (*call)->addr.len = sizeof(addr_in); (*call)->udata.maxlen = 0; return fd; }
/* **************************************************************** * Inicia um cliente * **************************************************************** */ int tcp_connect (int port, const char *name) { int fd; T_BIND bind; T_CALL call; INADDR bind_addr, addr; IPADDR remote_ip_addr; if ((fd = t_open (tcpdevname, O_RDWR, (T_INFO *)NULL)) < 0) return (-1); /* * Associa um endereço local. */ FILL_INADDR (bind_addr, 0, 0); FILL_NETBUF (bind.addr, &bind_addr, sizeof (bind_addr)); bind.qlen = 0; /* Não vamos dar "t_listen" nesta conexão */ if (t_bind (fd, &bind, (T_BIND *)NULL) < 0) goto bad; if (set_param (fd) < 0) goto bad; /* * Converte o nome da estação remota em um endereço IP. */ if (name != NOSTR && name[0] != '\0') { remote_ip_addr = t_node_to_addr (fd, name, NULL); if (remote_ip_addr == -1) goto bad; } else { remote_ip_addr = LOCAL_IP_ADDR; } /* * Preenche a estrutura T_CALL: só o membro addr é relevante. */ FILL_INADDR (addr, remote_ip_addr, port); FILL_NETBUF (call.addr, &addr, sizeof (addr)); FILL_NETBUF (call.opt, NULL, 0); FILL_NETBUF (call.udata, NULL, 0); /* * Tenta estabeler a conexão com a estação remota. */ if (t_connect (fd, &call, (T_CALL *)NULL) < 0) goto bad; return (fd); bad: t_close (fd); return (-1); } /* end tcp_connect */
/* * Attempts to bind an address to the network fd 'fd'. If 'reqaddr' is non-NULL, * it attempts to bind to that requested address, else it binds to a kernel * selected address. In the former case, the function returning success * doesn't guarantee that the requested address was bound (the caller needs to * check). If 'retaddr' is non-NULL, the bound address is returned in it. The * 'qlen' parameter is used to set the connection backlog. If the bind * succeeds 0 is returned, else -1. */ static int tlx_bind(int fd, const struct netbuf *reqaddr, struct netbuf *retaddr, int qlen) { struct t_bind breq; struct t_bind bret; debug_msg("Entering tlx_bind: req: %x, ret: %x, qlen: %d", reqaddr, retaddr, qlen); if (retaddr != NULL) { /* caller requests bound address be returned */ bret.addr.buf = retaddr->buf; bret.addr.maxlen = retaddr->maxlen; } if (reqaddr != NULL) { /* caller requests specific address */ breq.addr.buf = reqaddr->buf; breq.addr.len = reqaddr->len; } else { breq.addr.len = 0; } breq.qlen = qlen; if (t_bind(fd, &breq, retaddr != NULL ? &bret : NULL) < 0) return (-1); if (retaddr != NULL) retaddr->len = bret.addr.len; return (0); }
static int TRANS(TLICreateListener)(XtransConnInfo ciptr, struct t_bind *req) { struct t_bind *ret; prmsg(2,"TLICreateListener(%x->%d,%x)\n", ciptr, ciptr->fd, req ); if( (ret=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL ) { prmsg(1, "TLICreateListener: failed to allocate a t_bind\n"); t_free((char *)req,T_BIND); return TRANS_CREATE_LISTENER_FAILED; } if( t_bind(ciptr->fd, req, ret) < 0 ) { prmsg(1, "TLICreateListener: t_bind failed\n"); t_free((char *)req,T_BIND); t_free((char *)ret,T_BIND); return TRANS_CREATE_LISTENER_FAILED; } if( memcmp(req->addr.buf,ret->addr.buf,req->addr.len) != 0 ) { prmsg(1, "TLICreateListener: unable to bind to %x\n", req); t_free((char *)req,T_BIND); t_free((char *)ret,T_BIND); return TRANS_ADDR_IN_USE; } /* * Everything looks good: fill in the XtransConnInfo structure. */ if( (ciptr->addr = malloc(ret->addr.len)) == NULL ) { prmsg(1, "TLICreateListener: Unable to allocate space for the address\n"); t_free((char *)req,T_BIND); t_free((char *)ret, T_BIND); return TRANS_CREATE_LISTENER_FAILED; } ciptr->addrlen=ret->addr.len; memcpy(ciptr->addr,ret->addr.buf,ret->addr.len); t_free((char *)req,T_BIND); t_free((char *)ret, T_BIND); return 0; }
value xti_cots_connect (value device, value addr) { CAMLparam2(device,addr); int fd; char *dev; struct t_call sndcall; char abuf[ABUFLEN]; int k; dev = String_val(device); if ((fd = t_open(dev, O_RDWR, (struct t_info *) NULL)) == -1) { xti_error(-1, "t_open"); } if (t_bind(fd, (struct t_bind *) NULL, (struct t_bind *) NULL) == -1) { xti_error(fd, "t_bind"); } sndcall.opt.buf = NULL; sndcall.opt.len = 0; sndcall.opt.maxlen = 0; sndcall.udata.buf = NULL; sndcall.udata.len = 0; sndcall.udata.maxlen = 0; sndcall.addr.buf = abuf; sndcall.addr.len = 0; sndcall.addr.maxlen = ABUFLEN; sndcall.sequence = 0; if (string_length(addr) > sndcall.addr.maxlen) { t_close(fd); invalid_argument("cots_connect: address too long"); }; sndcall.addr.len = string_length(addr); for (k=0; k<string_length(addr); k++) { sndcall.addr.buf[k] = Byte(addr,k); }; if (t_connect( fd, &sndcall, (struct t_call *) NULL) == -1 ) { xti_error(fd, "t_connect"); } if (ioctl(fd, I_PUSH, "tirdwr") == -1) { int e = errno; t_close(fd); unix_error(e, "ioctl(I_PUSH)", Nothing); } CAMLreturn(Val_int(fd)); }
/* * How to bind to reserved ports. * TLI handle (socket) and port version. */ int bind_resv_port(int td, u_short *pp) { int rc = -1, port; struct t_bind *treq, *tret; struct sockaddr_in *sin; treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!treq) { plog(XLOG_ERROR, "t_alloc req"); return -1; } tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!tret) { t_free((char *) treq, T_BIND); plog(XLOG_ERROR, "t_alloc ret"); return -1; } memset((char *) treq->addr.buf, 0, treq->addr.len); sin = (struct sockaddr_in *) treq->addr.buf; sin->sin_family = AF_INET; treq->qlen = 0; treq->addr.len = treq->addr.maxlen; errno = EADDRINUSE; port = IPPORT_RESERVED; do { --port; sin->sin_port = htons(port); rc = t_bind(td, treq, tret); if (rc < 0) { plog(XLOG_ERROR, "t_bind"); } else { if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0) break; else t_unbind(td); } } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2); if (pp) { if (rc == 0) *pp = port; else plog(XLOG_ERROR, "could not t_bind to any reserved port"); } t_free((char *) tret, T_BIND); t_free((char *) treq, T_BIND); return rc; }
int do_connect(const char *host, const char *serv) { int tfd, i; void *handle; struct t_call tcall; struct t_discon tdiscon; struct netconfig *ncp; struct nd_hostserv hs; struct nd_addrlist *alp; struct netbuf *np; handle = Setnetpath(); hs.h_host = (char *) host; hs.h_serv = (char *) serv; while ( (ncp = getnetpath(handle)) != NULL) { if (strcmp(ncp->nc_netid, "ticotsord") != 0) continue; if (netdir_getbyname(ncp, &hs, &alp) != 0) continue; /* try each server address */ for (i = 0, np = alp->n_addrs; i < alp->n_cnt; i++, np++) { printf("device = %s\n", ncp->nc_device); if ( (tfd = t_open(ncp->nc_device, O_RDWR, NULL)) < 0) err_xti("t_open error for %s", ncp->nc_device); if (t_bind(tfd, NULL, NULL) < 0) err_xti("t_bind error"); tcall.addr.len = np->len; tcall.addr.buf = np->buf; /* pointer copy */ printf("addr.len = %d\n", tcall.addr.len); printf("addr.buf = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", tcall.addr.buf[0], tcall.addr.buf[1], tcall.addr.buf[2], tcall.addr.buf[3], tcall.addr.buf[4], tcall.addr.buf[5], tcall.addr.buf[6], tcall.addr.buf[7], tcall.addr.buf[8], tcall.addr.buf[9], tcall.addr.buf[10]); } netdir_free(alp, ND_ADDRLIST); } endnetpath(handle); return(-1); }
enum proto_accept_error proto_accept_connection(int listener_fd, int *read_fd, int *write_fd, const char **name) { int timeout = server_int_option("name_lookup_timeout", 5); int fd; struct sockaddr_in *addr = (struct sockaddr_in *) call->addr.buf; static Stream *s = 0; if (!s) s = new_stream(100); fd = t_open((void *) "/dev/tcp", O_RDWR, 0); if (fd < 0) { if (t_errno == TSYSERR && errno == EMFILE) return PA_FULL; else { log_ti_error("Opening endpoint for new connection"); return PA_OTHER; } } if (t_bind(fd, 0, 0) < 0) { log_ti_error("Binding endpoint for new connection"); t_close(fd); return PA_OTHER; } if (t_listen(listener_fd, call) < 0) { log_ti_error("Accepting new network connection"); t_close(fd); return PA_OTHER; } if (t_accept(listener_fd, fd, call) < 0) { log_ti_error("Accepting new network connection"); t_close(fd); return PA_OTHER; } if (!set_rw_able(fd)) { t_close(fd); return PA_OTHER; } *read_fd = *write_fd = fd; stream_printf(s, "%s, port %d", lookup_name_from_addr(addr, timeout), (int) ntohs(addr->sin_port)); *name = reset_stream(s); return PA_OKAY; }
int accept_client(int fd, struct t_call *call) { int sd; if ((sd = t_open(DEV_XTI, O_RDWR, NULL)) < 0) error("serwer->accept_client->t_open", fd, sd); if (t_bind(sd, NULL, NULL) < 0) error("serwer->accept_client->t_bind", fd, sd); if (t_accept(fd, sd, call) < 0) { if (t_errno == TLOOK) { if (t_rcvdis(fd, NULL) < 0) error("serwer->accept_client->t_rcvdis", fd, sd); if (t_close(sd) < 0) error("serwer->accept_client->t_close", fd, sd); return -1; } error("t_accept failed", fd, sd); } return(sd); }
CreateWellKnownSockets () { struct t_bind bind_addr; struct netconfig *nconf; struct nd_hostserv service; struct nd_addrlist *servaddrs; char *name, *localHostname(); char bindbuf[15]; int it; if (request_port == 0) return; Debug ("creating UDP stream %d\n", request_port); nconf = getnetconfigent("udp"); if (!nconf) { t_error("getnetconfigent udp"); return; } xdmcpFd = t_open(nconf->nc_device, O_RDWR, NULL); if (xdmcpFd == -1) { LogError ("XDMCP stream creation failed\n"); t_error ("t_open"); return; } name = localHostname (); registerHostname (name, strlen (name)); RegisterCloseOnFork (xdmcpFd); service.h_host = HOST_SELF; sprintf(bindbuf, "%d", request_port); service.h_serv = bindbuf; netdir_getbyname(nconf, &service, &servaddrs); freenetconfigent(nconf); bind_addr.qlen = 5; bind_addr.addr.buf = servaddrs->n_addrs[0].buf; bind_addr.addr.len = servaddrs->n_addrs[0].len; it = t_bind(xdmcpFd, &bind_addr, &bind_addr); netdir_free(servaddrs, ND_ADDRLIST); if (it < 0) { LogError ("error binding STREAMS address %d\n", request_port); t_error("t_bind"); /* also goes to log file */ t_close (xdmcpFd); xdmcpFd = -1; return; } WellKnownSocketsMax = xdmcpFd; FD_SET (xdmcpFd, &WellKnownSocketsMask); chooserFd = t_open ("/dev/tcp", O_RDWR, NULL); Debug ("Created chooser fd %d\n", chooserFd); if (chooserFd == -1) { LogError ("chooser stream creation failed\n"); t_error("t_open chooser"); return; } if (chooserFd > WellKnownSocketsMax) WellKnownSocketsMax = chooserFd; FD_SET (chooserFd, &WellKnownSocketsMask); }
/* * Bind a fd to a privileged IP port. * This is slightly different from the code in netdir_options * because it has a different interface - main thing is that it * needs to know its own address. We also wanted to set the qlen. * t_getname() can be used for those purposes and perhaps job can be done. */ int __rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen, char *fmly) { int res; static in_port_t port, *sinport; struct sockaddr_in6 myaddr; int i; struct t_bind tbindstr, *tres; struct t_info tinfo; extern mutex_t portnum_lock; /* VARIABLES PROTECTED BY portnum_lock: port */ #define STARTPORT 600 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) if (sin == 0 && fmly == 0) { errno = EINVAL; return (-1); } if (geteuid()) { errno = EACCES; return (-1); } if ((i = t_getstate(fd)) != T_UNBND) { if (t_errno == TBADF) errno = EBADF; if (i != -1) errno = EISCONN; return (-1); } if (sin == 0) { sin = (struct sockaddr *)&myaddr; get_myaddress_ipv6(fmly, sin); } if (sin->sa_family == AF_INET) { /* LINTED pointer cast */ sinport = &((struct sockaddr_in *)sin)->sin_port; } else if (sin->sa_family == AF_INET6) { /* LINTED pointer cast */ sinport = &((struct sockaddr_in6 *)sin)->sin6_port; } else { errno = EPFNOSUPPORT; return (-1); } /* Transform sockaddr to netbuf */ if (t_getinfo(fd, &tinfo) == -1) { return (-1); } /* LINTED pointer cast */ tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); if (tres == NULL) return (-1); tbindstr.qlen = qlen; tbindstr.addr.buf = (char *)sin; tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr); /* LINTED pointer cast */ sin = (struct sockaddr *)tbindstr.addr.buf; res = -1; (void) mutex_lock(&portnum_lock); if (port == 0) port = (getpid() % NPORTS) + STARTPORT; for (i = 0; i < NPORTS; i++) { *sinport = htons(port++); if (port > ENDPORT) port = STARTPORT; res = t_bind(fd, &tbindstr, tres); if (res == 0) { if ((tbindstr.addr.len == tres->addr.len) && (memcmp(tbindstr.addr.buf, tres->addr.buf, (int)tres->addr.len) == 0)) break; (void) t_unbind(fd); res = -1; } else if (t_errno != TSYSERR || errno != EADDRINUSE) break; } (void) mutex_unlock(&portnum_lock); if ((portp != NULL) && (res == 0)) *portp = *sinport; (void) t_free((char *)tres, T_BIND); return (res); }
/* * This call attempts to t_accept() an incoming/pending TLI connection. * If it is thwarted by a TLOOK, it is deferred and whatever is on the * file descriptor, removed after a t_look. (Incoming connect indications * get queued for later processing and disconnect indications remove a * a queued connection request if a match found). * Returns -1 on failure, else 0. */ int tlx_accept(const char *fmri, tlx_info_t *tlx_info, struct sockaddr_storage *remote_addr) { tlx_conn_ind_t *conind; struct t_call *call; int fd; int listen_fd = tlx_info->pr_info.listen_fd; debug_msg("Entering tlx_accept: instance: %s", fmri); if ((fd = t_open(tlx_info->dev_name, O_RDWR, NULL)) == -1) { error_msg("t_open: %s", t_strerror(t_errno)); return (-1); } if (tlx_info->pr_info.v6only) { int on = 1; /* restrict to IPv6 communications only */ if (tlx_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) == -1) { (void) t_close(fd); return (-1); } } if (t_bind(fd, NULL, NULL) == -1) { error_msg("t_bind: %s", t_strerror(t_errno)); (void) t_close(fd); return (-1); } /* * Get the next connection indication - first try the pending * queue, then, if none there, get a new one from the file descriptor. */ if ((conind = uu_list_first(tlx_info->conn_ind_queue)) != NULL) { debug_msg("taking con off queue"); call = conind->call; } else if ((call = get_new_conind(listen_fd)) == NULL) { (void) t_close(fd); return (-1); } /* * Accept the connection indication on the newly created endpoint. * If we fail, and it's the result of a tlook, queue the indication * if it isn't already, and go and process the t_look. */ if (t_accept(listen_fd, fd, call) == -1) { if (t_errno == TLOOK) { if (uu_list_first(tlx_info->conn_ind_queue) == NULL) { /* * We are first one to have to defer accepting * and start the pending connections list. */ if (queue_conind(tlx_info->conn_ind_queue, call) == -1) { error_msg(gettext( "Failed to queue connection " "indication for instance %s"), fmri); (void) t_free((char *)call, T_CALL); return (-1); } } (void) process_tlook(fmri, tlx_info); } else { /* non-TLOOK accept failure */ error_msg("%s: %s", "t_accept failed", t_strerror(t_errno)); /* * If we were accepting a queued connection, dequeue * it. */ if (uu_list_first(tlx_info->conn_ind_queue) != NULL) (void) dequeue_conind(tlx_info->conn_ind_queue); (void) t_free((char *)call, T_CALL); } (void) t_close(fd); return (-1); } /* Copy remote address into address parameter */ (void) memcpy(remote_addr, call->addr.buf, MIN(call->addr.len, sizeof (*remote_addr))); /* If we were accepting a queued connection, dequeue it. */ if (uu_list_first(tlx_info->conn_ind_queue) != NULL) (void) dequeue_conind(tlx_info->conn_ind_queue); (void) t_free((char *)call, T_CALL); return (fd); }
/* * Bind to preferred AMQ port. */ static int bind_preferred_amq_port(u_short pref_port, const struct netconfig *ncp, struct t_bind **tretpp) { int td = -1, rc = -1; struct t_bind *treq; struct sockaddr_in *sin, *sin2; extern char *t_errlist[]; extern int t_errno; if (!ncp) { plog(XLOG_ERROR, "null ncp"); return -1; } td = t_open(ncp->nc_device, O_RDWR, (struct t_info *) NULL); if (td < 0) { plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]); return -1; } treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!treq) { plog(XLOG_ERROR, "t_alloc req"); return -1; } *tretpp = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!*tretpp) { t_free((char *) treq, T_BIND); plog(XLOG_ERROR, "t_alloc tretpp"); return -1; } memset((char *) treq->addr.buf, 0, treq->addr.len); sin = (struct sockaddr_in *) treq->addr.buf; sin->sin_family = AF_INET; treq->qlen = 64; /* must be greater than 0 to work for TCP connections */ treq->addr.len = treq->addr.maxlen; if (pref_port > 0) { sin->sin_port = htons(pref_port); sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* XXX: may not be needed */ rc = t_bind(td, treq, *tretpp); if (rc < 0) { plog(XLOG_ERROR, "t_bind return err %d", rc); goto out; } /* check if we got the port we asked for */ sin2 = (struct sockaddr_in *) (*tretpp)->addr.buf; if (sin->sin_port != sin2->sin_port) { plog(XLOG_ERROR, "asked for port %d, got different one (%d)", ntohs(sin->sin_port), ntohs(sin2->sin_port)); t_errno = TNOADDR; /* XXX: is this correct? */ rc = -1; goto out; } if (sin->sin_addr.s_addr != sin2->sin_addr.s_addr) { plog(XLOG_ERROR, "asked for address %x, got different one (%x)", (int) ntohl(sin->sin_addr.s_addr), (int) ntohl(sin2->sin_addr.s_addr)); t_errno = TNOADDR; /* XXX: is this correct? */ rc = -1; goto out; } } out: t_free((char *) treq, T_BIND); return (rc < 0 ? rc : td); }
static int get_tcp_socket( char *machine, /* remote host */ char *service, /* nttp/smtp etc. */ unsigned short port) /* tcp port number */ { int s = -1; int save_errno = 0; struct sockaddr_in sock_in; # ifdef TLI /* Transport Level Interface */ char device[20]; char *env_device; extern int t_errno; extern struct hostent *gethostbyname(); struct hostent *hp; struct t_call *callptr; /* * Create a TCP transport endpoint. */ if ((env_device = getenv("DEV_TCP")) != NULL) /* SCO uses DEV_TCP, most other OS use /dev/tcp */ STRCPY(device, env_device); else strcpy(device, "/dev/tcp"); if ((s = t_open(device, O_RDWR, (struct t_info *) 0)) < 0){ t_error(txt_error_topen); return -EPROTO; } if (t_bind(s, (struct t_bind *) 0, (struct t_bind *) 0) < 0) { t_error("t_bind"); t_close(s); return -EPROTO; } memset((char *) &sock_in, '\0', sizeof(sock_in)); sock_in.sin_family = AF_INET; sock_in.sin_port = htons(port); if (!isdigit((unsigned char)*machine) || # ifdef HAVE_INET_ATON !inet_aton(machine, &sock_in) # else # ifdef HAVE_INET_ADDR (long) (sock_in.sin_addr.s_addr = inet_addr(machine)) == INADDR_NONE) # endif /* HAVE_INET_ADDR */ # endif /* HAVE_INET_ATON */ { if ((hp = gethostbyname(machine)) == NULL) { my_fprintf(stderr, _(txt_gethostbyname), "gethostbyname() ", machine); t_close(s); return -EHOSTUNREACH; } memcpy((char *) &sock_in.sin_addr, hp->h_addr, hp->h_length); } /* * Allocate a t_call structure and initialize it. * Let t_alloc() initialize the addr structure of the t_call structure. */ if ((callptr = (struct t_call *) t_alloc(s, T_CALL, T_ADDR)) == NULL){ t_error("t_alloc"); t_close(s); return -EPROTO; } callptr->addr.maxlen = sizeof(sock_in); callptr->addr.len = sizeof(sock_in); callptr->addr.buf = (char *) &sock_in; callptr->opt.len = 0; /* no options */ callptr->udata.len = 0; /* no user data with connect */ /* * Connect to the server. */ if (t_connect(s, callptr, (struct t_call *) 0) < 0) { save_errno = t_errno; if (save_errno == TLOOK) fprintf(stderr, _(txt_error_server_unavailable)); else t_error("t_connect"); t_free((char *) callptr, T_CALL); t_close(s); return -save_errno; } /* * Now replace the timod module with the tirdwr module so that * standard read() and write() system calls can be used on the * descriptor. */ t_free((char *) callptr, T_CALL); if (ioctl(s, I_POP, (char *) 0) < 0) { perror("I_POP(timod)"); t_close(s); return -EPROTO; } if (ioctl(s, I_PUSH, "tirdwr") < 0) { perror("I_PUSH(tirdwr)"); t_close(s); return -EPROTO; } # else # ifndef EXCELAN struct servent *sp; struct hostent *hp; # ifdef h_addr int x = 0; char **cp; static char *alist[2] = {0, 0}; # endif /* h_addr */ static struct hostent def; static struct in_addr defaddr; static char namebuf[256]; # ifdef HAVE_GETSERVBYNAME if ((sp = (struct servent *) getservbyname(service, "tcp")) == NULL) { my_fprintf(stderr, _(txt_error_unknown_service), service); return -EHOSTUNREACH; } # else sp = my_malloc(sizeof(struct servent)); sp->s_port = htons(IPPORT_NNTP); # endif /* HAVE_GETSERVBYNAME */ /* If not a raw ip address, try nameserver */ if (!isdigit((unsigned char) *machine) || # ifdef HAVE_INET_ATON !inet_aton(machine, &defaddr) # else # ifdef HAVE_INET_ADDR (long) (defaddr.s_addr = (long) inet_addr(machine)) == -1 # endif /* HAVE_INET_ADDR */ # endif /* HAVE_INET_ATON */ ) { hp = gethostbyname(machine); } else { /* Raw ip address, fake */ STRCPY(namebuf, machine); def.h_name = (char *) namebuf; # ifdef h_addr def.h_addr_list = alist; # endif /* h_addr */ def.h_addr = (char *) &defaddr; def.h_length = sizeof(struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } if (hp == NULL) { my_fprintf(stderr, _(txt_gethostbyname), "\n", machine); return -EHOSTUNREACH; } memset((char *) &sock_in, '\0', sizeof(sock_in)); sock_in.sin_family = hp->h_addrtype; sock_in.sin_port = htons(port); /* sock_in.sin_port = sp->s_port; */ # else memset((char *) &sock_in, '\0', sizeof(sock_in)); sock_in.sin_family = AF_INET; # endif /* !EXCELAN */ /* * The following is kinda gross. The name server under 4.3 * returns a list of addresses, each of which should be tried * in turn if the previous one fails. However, 4.2 hostent * structure doesn't have this list of addresses. * Under 4.3, h_addr is a #define to h_addr_list[0]. * We use this to figure out whether to include the NS specific * code... */ # ifdef h_addr /* * Get a socket and initiate connection -- use multiple addresses */ for (cp = hp->h_addr_list; cp && *cp; cp++) { # if defined(__hpux) && defined(SVR4) unsigned long socksize, socksizelen; # endif /* __hpux && SVR4 */ if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { perror("socket"); return -errno; } memcpy((char *) &sock_in.sin_addr, *cp, hp->h_length); # ifdef HAVE_INET_NTOA if (x < 0) my_fprintf(stderr, _(txt_trying), (char *) inet_ntoa(sock_in.sin_addr)); # endif /* HAVE_INET_NTOA */ # if defined(__hpux) && defined(SVR4) /* recommended by [email protected] */ # define HPSOCKSIZE 0x8000 getsockopt(s, SOL_SOCKET, SO_SNDBUF, /* (caddr_t) */ &socksize, /* (caddr_t) */ &socksizelen); if (socksize < HPSOCKSIZE) { socksize = HPSOCKSIZE; setsockopt(s, SOL_SOCKET, SO_SNDBUF, /* (caddr_t) */ &socksize, sizeof(socksize)); } socksize = 0; socksizelen = sizeof(socksize); getsockopt(s, SOL_SOCKET, SO_RCVBUF, /* (caddr_t) */ &socksize, /* (caddr_t) */ &socksizelen); if (socksize < HPSOCKSIZE) { socksize = HPSOCKSIZE; setsockopt(s, SOL_SOCKET, SO_RCVBUF, /* (caddr_t) */ &socksize, sizeof(socksize)); } # endif /* __hpux && SVR4 */ if ((x = connect(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) == 0) break; save_errno = errno; /* Keep for later */ # ifdef HAVE_INET_NTOA my_fprintf(stderr, _(txt_connection_to), (char *) inet_ntoa(sock_in.sin_addr)); perror(""); # endif /* HAVE_INET_NTOA */ (void) s_close(s); } if (x < 0) { my_fprintf(stderr, _(txt_giving_up)); return -save_errno; /* Return the last errno we got */ } # else # ifdef EXCELAN if ((s = socket(SOCK_STREAM, (struct sockproto *) NULL, &sock_in, SO_KEEPALIVE)) < 0) { perror("socket"); return -errno; } /* set up addr for the connect */ memset((char *) &sock_in, '\0', sizeof(sock_in)); sock_in.sin_family = AF_INET; sock_in.sin_port = htons(IPPORT_NNTP); if ((sock_in.sin_addr.s_addr = rhost(&machine)) == -1) { my_fprintf(stderr, _(txt_gethostbyname), "\n", machine); return -1; } /* And connect */ if (connect(s, (struct sockaddr *) &sock_in) < 0) { save_errno = errno; perror("connect"); (void) s_close(s); return -save_errno; } # else if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -errno; } /* And then connect */ memcpy((char *) &sock_in.sin_addr, hp->h_addr, hp->h_length); if (connect(s, (struct sockaddr *) &sock_in, sizeof(sock_in)) < 0) { save_errno = errno; perror("connect"); (void) s_close(s); return -save_errno; } # endif /* !EXCELAN */ # endif /* !h_addr */ # endif /* !TLI */ return s; }
enum error proto_open_connection(Var arglist, int *read_fd, int *write_fd, const char **local_name, const char **remote_name) { /* These are `static' rather than `volatile' because I can't cope with * getting all those nasty little parameter-passing rules right. This * function isn't recursive anyway, so it doesn't matter. */ struct sockaddr_in rec_addr; struct t_bind received; static const char *host_name; static int port; static Timer_ID id; int fd, result; int timeout = server_int_option("name_lookup_timeout", 5); static struct sockaddr_in addr; static Stream *st1 = 0, *st2 = 0; if (!st1) { st1 = new_stream(20); st2 = new_stream(50); } if (arglist.v.list[0].v.num != 2) return E_ARGS; else if (arglist.v.list[1].type != TYPE_STR || arglist.v.list[2].type != TYPE_INT) return E_TYPE; host_name = arglist.v.list[1].v.str; port = arglist.v.list[2].v.num; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = lookup_addr_from_name(host_name, timeout); if (addr.sin_addr.s_addr == 0) return E_INVARG; /* Cast to (void *) here to workaround const-less decls on some systems. */ fd = t_open((void *) "/dev/tcp", O_RDWR, 0); if (fd < 0) { if (t_errno != TSYSERR || errno != EMFILE) log_ti_error("Making endpoint in proto_open_connection"); return E_QUOTA; } received.addr.maxlen = sizeof(rec_addr); received.addr.len = sizeof(rec_addr); received.addr.buf = (void *) &rec_addr; if (t_bind(fd, 0, &received) < 0) { log_ti_error("Binding outbound endpoint"); t_close(fd); return E_QUOTA; } call->addr.maxlen = sizeof(addr); call->addr.len = sizeof(addr); call->addr.buf = (void *) &addr; TRY id = set_timer(server_int_option("outbound_connect_timeout", 5), timeout_proc, 0); result = t_connect(fd, call, 0); cancel_timer(id); EXCEPT(timeout_exception) result = -1; errno = ETIMEDOUT; t_errno = TSYSERR; reenable_timers(); ENDTRY if (result < 0) { t_close(fd); log_ti_error("Connecting in proto_open_connection"); return E_QUOTA; } if (!set_rw_able(fd)) { t_close(fd); return E_QUOTA; } *read_fd = *write_fd = fd; stream_printf(st1, "port %d", (int) ntohs(rec_addr.sin_port)); *local_name = reset_stream(st1); stream_printf(st2, "%s, port %d", host_name, port); *remote_name = reset_stream(st2); return E_NONE; }
enum error proto_make_listener(Var desc, int *fd, Var * canon, const char **name) { struct sockaddr_in req_addr, rec_addr; struct t_bind requested, received; int s, port; static Stream *st = 0; if (!st) st = new_stream(20); if (desc.type != TYPE_INT) return E_TYPE; port = desc.v.num; s = t_open((void *) "/dev/tcp", O_RDWR, 0); if (s < 0) { log_ti_error("Creating listening endpoint"); return E_QUOTA; } req_addr.sin_family = AF_INET; req_addr.sin_addr.s_addr = htonl(INADDR_ANY); req_addr.sin_port = htons(port); requested.addr.maxlen = sizeof(req_addr); requested.addr.len = sizeof(req_addr); requested.addr.buf = (void *) &req_addr; requested.qlen = 5; received.addr.maxlen = sizeof(rec_addr); received.addr.len = sizeof(rec_addr); received.addr.buf = (void *) &rec_addr; if (t_bind(s, &requested, &received) < 0) { enum error e = E_QUOTA; log_ti_error("Binding to listening address"); t_close(s); if (t_errno == TACCES || (t_errno == TSYSERR && errno == EACCES)) e = E_PERM; return e; } else if (port != 0 && rec_addr.sin_port != port) { errlog("Can't bind to requested port!\n"); t_close(s); return E_QUOTA; } if (!call) call = (struct t_call *) t_alloc(s, T_CALL, T_ADDR); if (!call) { log_ti_error("Allocating T_CALL structure"); t_close(s); return E_QUOTA; } canon->type = TYPE_INT; canon->v.num = ntohs(rec_addr.sin_port); stream_printf(st, "port %d", canon->v.num); *name = reset_stream(st); *fd = s; return E_NONE; }
/* * How to bind to reserved ports. * (port-only) version. */ int bind_resv_port2(u_short *pp) { int td, rc = -1, port; struct t_bind *treq, *tret; struct sockaddr_in *sin; extern char *t_errlist[]; extern int t_errno; struct netconfig *nc = (struct netconfig *) NULL; voidp nc_handle; if ((nc_handle = setnetconfig()) == (voidp) NULL) { plog(XLOG_ERROR, "Cannot rewind netconfig: %s", nc_sperror()); return -1; } /* * Search the netconfig table for INET/UDP. * This loop will terminate if there was an error in the /etc/netconfig * file or if you reached the end of the file without finding the udp * device. Either way your machine has probably far more problems (for * example, you cannot have nfs v2 w/o UDP). */ while (1) { if ((nc = getnetconfig(nc_handle)) == (struct netconfig *) NULL) { plog(XLOG_ERROR, "Error accessing getnetconfig: %s", nc_sperror()); endnetconfig(nc_handle); return -1; } if (STREQ(nc->nc_protofmly, NC_INET) && STREQ(nc->nc_proto, NC_UDP)) break; } /* * This is the primary reason for the getnetconfig code above: to get the * correct device name to udp, and t_open a descriptor to be used in * t_bind below. */ td = t_open(nc->nc_device, O_RDWR, (struct t_info *) 0); endnetconfig(nc_handle); if (td < 0) { plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]); return -1; } treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!treq) { plog(XLOG_ERROR, "t_alloc req"); return -1; } tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); if (!tret) { t_free((char *) treq, T_BIND); plog(XLOG_ERROR, "t_alloc ret"); return -1; } memset((char *) treq->addr.buf, 0, treq->addr.len); sin = (struct sockaddr_in *) treq->addr.buf; sin->sin_family = AF_INET; treq->qlen = 0; treq->addr.len = treq->addr.maxlen; errno = EADDRINUSE; port = IPPORT_RESERVED; do { --port; sin->sin_port = htons(port); rc = t_bind(td, treq, tret); if (rc < 0) { plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]); } else { if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0) break; else t_unbind(td); } } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2); if (pp && rc == 0) *pp = port; t_free((char *) tret, T_BIND); t_free((char *) treq, T_BIND); return rc; }
int gtcm_bgn_net(omi_conn_ll *cll) { extern int4 omi_nxact, omi_nerrs, omi_brecv, omi_bsent; omi_fd fd; int i; int save_errno; int rc; #ifdef NET_TCP struct servent *se; unsigned short port; char port_buffer[NI_MAXSERV]; #endif /* defined(NET_TCP) */ #ifdef BSD_TCP struct addrinfo *ai_ptr, hints; const boolean_t reuseaddr = TRUE; int errcode; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP struct t_bind *bind; #endif /* defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ /* The linked list of connections */ cll->head = cll->tail = (omi_conn *)0; /* The statistics */ cll->stats.conn = cll->stats.clos = cll->stats.disc = 0; cll->st_cn.bytes_recv = 0; cll->st_cn.bytes_send = 0; cll->st_cn.start = 0; for (i = 0; i < OMI_OP_MAX; i++) cll->st_cn.xact[i] = 0; for (i = 0; i < OMI_ER_MAX; i++) cll->st_cn.errs[i] = 0; omi_nxact = omi_nerrs = omi_brecv = omi_bsent = 0; /* Fall back on a compile time constant */ if (!omi_service) omi_service = SRVC_NAME; #ifdef NET_TCP /* NET_TCP is defined only when BSD_TCP is defined or SYSV_TCP is defined, but SYSV_TCP is never defined (a bug?) * so we move the code of obtaining port information from service down to #ifdef BSD_TCP */ #ifdef SYSV_TCP GTMASSERT; #endif #endif /* defined(NET_TCP) */ #ifdef BSD_TCP /* Create a socket always tries IPv6 first */ SERVER_HINTS(hints, ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET)); if ((fd = socket(hints.ai_family, SOCK_STREAM, 0)) < 0) { if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { save_errno = errno; return save_errno; } hints.ai_family = AF_INET; } /* Bind an address to the socket */ if (0 != (errcode = getaddrinfo(NULL, omi_service, &hints, &ai_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return errcode; } if (ISDIGIT_ASCII(*omi_service)) port = atoi(omi_service); else { if (0 != (errcode = getnameinfo(ai_ptr->ai_addr, ai_ptr->ai_addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV))) { assert(FALSE); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return errcode; } port = atoi(port_buffer); } /* Reuse a specified address */ if (port && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuseaddr, SIZEOF(reuseaddr)) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } if (bind(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* Initialize the listen queue */ if (listen(fd, 5) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* set up raw socket for use with pinging option */ if (ping_keepalive) psock = init_ping(); /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d, Process ID %d\n", rc_server_id, omi_pid)); #endif if (authenticate) OMI_DBG((omi_debug, "Password verification on OMI connections enabled.\n")); if (!one_conn_per_inaddr) OMI_DBG((omi_debug, "Multiple connections from the same internet address allowed.\n")); if (psock > 0) OMI_DBG((omi_debug, "Keepalive option (-ping) enabled.\n")); return 0; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP GTMASSERT; if ((fd = t_open(SYSV_TCP, O_RDWR, NULL)) < 0) { save_errno = errno; return save_errno; } if (!(bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL))) { save_errno = errno; (void) t_close(fd); return save_errno; } bind->qlen = 5; bind->addr.len = 0; bind->addr.buf = 0; if (t_bind(fd, bind, bind) < 0) { save_errno = errno; (void) t_free(bind, T_BIND); (void) t_close(fd); return save_errno; } /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d\n", rc_server_id)); #endif return 0; #else /* defined(SYSV_TCP) */ cll->nve = FD_INVALID; return -1; #endif /* !defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ }
int qse_nwio_init ( qse_nwio_t* nwio, qse_mmgr_t* mmgr, const qse_nwad_t* nwad, int flags, const qse_nwio_tmout_t* tmout) { qse_skad_t addr; qse_sck_len_t addrlen; int family, type, tmp; QSE_MEMSET (nwio, 0, QSE_SIZEOF(*nwio)); nwio->mmgr = mmgr; nwio->flags = flags; nwio->errnum = QSE_NWIO_ENOERR; if (tmout) nwio->tmout = *tmout; else { nwio->tmout.r.sec = -1; nwio->tmout.w.sec = -1; nwio->tmout.c.sec = -1; nwio->tmout.a.sec = -1; } tmp = qse_nwadtoskad (nwad, &addr); if (tmp <= -1) { nwio->errnum = QSE_NWIO_EINVAL; return -1; } addrlen = tmp; #if defined(SOCK_STREAM) && defined(SOCK_DGRAM) if (flags & QSE_NWIO_TCP) type = SOCK_STREAM; else if (flags & QSE_NWIO_UDP) type = SOCK_DGRAM; else #endif { nwio->errnum = QSE_NWIO_EINVAL; return -1; } family = qse_skadfamily (&addr); #if defined(_WIN32) nwio->handle = socket (family, type, 0); if (nwio->handle == INVALID_SOCKET) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } if ((flags & QSE_NWIO_TCP) && (flags & QSE_NWIO_KEEPALIVE)) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, QSE_SIZEOF(optval)); } if (flags & QSE_NWIO_PASSIVE) { qse_nwio_hnd_t handle; if (flags & QSE_NWIO_REUSEADDR) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, QSE_SIZEOF(optval)); } if (bind (nwio->handle, (struct sockaddr*)&addr, addrlen) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } if (flags & QSE_NWIO_TCP) { if (listen (nwio->handle, 10) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } if (TMOUT_ENABLED(nwio->tmout.a) && wait_for_data (nwio, &nwio->tmout.a, 0) <= -1) goto oops; handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); if (handle == INVALID_SOCKET) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } closesocket (nwio->handle); nwio->handle = handle; } else if (flags & QSE_NWIO_UDP) { nwio->status |= STATUS_UDP_CONNECT; } } else { int xret; if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { unsigned long cmd = 1; if (ioctlsocket(nwio->handle, FIONBIO, &cmd) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } } xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { unsigned long cmd = 0; if ((xret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) || ioctlsocket (nwio->handle, FIONBIO, &cmd) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } if (wait_for_data (nwio, &nwio->tmout.c, 1) <= -1) goto oops; else { int xlen; DWORD xerr; xlen = QSE_SIZEOF(xerr); if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xerr, &xlen) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } else if (xerr != 0) { nwio->errnum = skerr_to_errnum (xerr); goto oops; } } } else { if (xret == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (WSAGetLastError()); goto oops; } } } #elif defined(__OS2__) nwio->handle = socket (family, type, 0); if (nwio->handle <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } if ((flags & QSE_NWIO_TCP) && (flags & QSE_NWIO_KEEPALIVE)) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, QSE_SIZEOF(optval)); } if (flags & QSE_NWIO_PASSIVE) { qse_nwio_hnd_t handle; if (flags & QSE_NWIO_REUSEADDR) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, QSE_SIZEOF(optval)); } if (bind (nwio->handle, (struct sockaddr*)&addr, addrlen) <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } if (flags & QSE_NWIO_TCP) { if (listen (nwio->handle, 10) <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } if (TMOUT_ENABLED(nwio->tmout.a) && wait_for_data (nwio, &nwio->tmout.a, 0) <= -1) goto oops; handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); if (handle <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } soclose (nwio->handle); nwio->handle = handle; } else if (flags & QSE_NWIO_UDP) { nwio->status |= STATUS_UDP_CONNECT; } } else { int xret; if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int noblk = 1; if (ioctl (nwio->handle, FIONBIO, (void*)&noblk, QSE_SIZEOF(noblk)) <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } } xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int noblk = 0; if ((xret <= -1 && sock_errno() != SOCEINPROGRESS) || ioctl (nwio->handle, FIONBIO, (void*)&noblk, QSE_SIZEOF(noblk)) <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } if (wait_for_data (nwio, &nwio->tmout.c, 1) <= -1) goto oops; else { int xlen, xerr; xlen = QSE_SIZEOF(xerr); if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xerr, &xlen) <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } else if (xerr != 0) { nwio->errnum = skerr_to_errnum (xerr); goto oops; } } } else { if (xret <= -1) { nwio->errnum = skerr_to_errnum (sock_errno()); goto oops; } } } #elif defined(__DOS__) nwio->handle = socket (family, type, 0); if (nwio->handle <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if ((flags & QSE_NWIO_TCP) && (flags & QSE_NWIO_KEEPALIVE)) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, QSE_SIZEOF(optval)); } if (flags & QSE_NWIO_PASSIVE) { qse_nwio_hnd_t handle; #if defined(SO_REUSEADDR) if (flags & QSE_NWIO_REUSEADDR) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, QSE_SIZEOF(optval)); } #endif if (bind (nwio->handle, (struct sockaddr*)&addr, addrlen) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (flags & QSE_NWIO_TCP) { if (listen (nwio->handle, 10) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (TMOUT_ENABLED(nwio->tmout.a) && wait_for_data (nwio, &nwio->tmout.a, 0) <= -1) goto oops; handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); if (handle <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } close_s (nwio->handle); nwio->handle = handle; } else if (flags & QSE_NWIO_UDP) { nwio->status |= STATUS_UDP_CONNECT; } } else { int xret; if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int cmd = 1; if (ioctlsocket(nwio->handle, FIONBIO, (char*)&cmd) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (errno); goto oops; } } xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int cmd = 0; if ((xret == SOCKET_ERROR && errno != EWOULDBLOCK) || ioctlsocket (nwio->handle, FIONBIO, (char*)&cmd) == SOCKET_ERROR) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (wait_for_data (nwio, &nwio->tmout.c, 1) <= -1) goto oops; else { int xlen, xerr; xlen = QSE_SIZEOF(xerr); if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xerr, &xlen) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } else if (xerr != 0) { nwio->errnum = skerr_to_errnum (xerr); goto oops; } } } else { if (xret <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } } } #elif defined(USE_TLI) { static const qse_mchar_t* dev_path[2][2] = { { "/dev/tcp", "/dev/inet/tcp" }, { "/dev/udp", "/dev/inet/tcp" } }; int dev_id; if (flags & QSE_NWIO_TCP) dev_id = 0; else { QSE_ASSERT (flags & QSE_NWIO_UDP); dev_id = 1; } nwio->handle = t_open (dev_path[dev_id][0], O_RDWR, QSE_NULL); if (nwio->handle <= -1) { nwio->handle = t_open (dev_path[dev_id][1], O_RDWR, QSE_NULL); if (nwio->handle <= -1) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; } } if (flags & QSE_NWIO_PASSIVE) { /* TODO: */ nwio->errnum = QSE_NWIO_ENOIMPL; goto oops; } else { struct t_call call; /* for connecting */ struct t_bind req, ret; /* for binding */ qse_skad_t reqaddr, retaddr; qse_nwad_t reqnwad; /* call = t_alloc (nwio->handle, T_CALL, T_ADDR); if (!call) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; }*/ qse_clearnwad (&reqnwad, nwad->type); qse_nwadtoskad (&reqnwad, &reqaddr); QSE_MEMSET (&ret, 0, QSE_SIZEOF(req)); req.addr.maxlen = addrlen; req.addr.len = addrlen; req.addr.buf = &reqaddr; QSE_MEMSET (&ret, 0, QSE_SIZEOF(ret)); ret.addr.maxlen = addrlen; ret.addr.len = addrlen; ret.addr.buf = &retaddr; if (t_bind (nwio->handle, &req, &ret) <= -1) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; } /* TODO: should i use t_alloc() and t_free for call, ret, req? */ QSE_MEMSET (&call, 0, QSE_SIZEOF(call)); call.addr.maxlen = addrlen; call.addr.len = addrlen; call.addr.buf = &addr; if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int orgfl; orgfl = fcntl (nwio->handle, F_GETFL, 0); if (orgfl <= -1 || fcntl (nwio->handle, F_SETFL, orgfl | O_NONBLOCK) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (t_connect (nwio->handle, &call, 0) <= -1) { if (t_errno != TNODATA) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; } /* TODO: this doesn't seem to work wel... REDO THE WORK */ if (wait_for_data (nwio, &nwio->tmout.c, 0) <= -1) goto oops; if (t_rcvconnect (nwio->handle, QSE_NULL) <= -1) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; } } if (fcntl (nwio->handle, F_SETFL, orgfl) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } } else { if (t_connect (nwio->handle, &call, 0) <= -1) { nwio->errnum = tlierr_to_errnum (t_errno, errno); goto oops; } } } } #else #if defined(SOCK_CLOEXEC) nwio->handle = socket (family, type | SOCK_CLOEXEC, 0); #else nwio->handle = socket (family, type, 0); #endif if (nwio->handle <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } #if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) { int tmp = fcntl (nwio->handle, F_GETFD); if (tmp >= 0) fcntl (nwio->handle, F_SETFD, tmp | FD_CLOEXEC); } #endif if ((flags & QSE_NWIO_TCP) && (flags & QSE_NWIO_KEEPALIVE)) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, QSE_SIZEOF(optval)); } if (flags & QSE_NWIO_PASSIVE) { qse_nwio_hnd_t handle; #if defined(SO_REUSEADDR) if (flags & QSE_NWIO_REUSEADDR) { int optval = 1; setsockopt (nwio->handle, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, QSE_SIZEOF(optval)); } #endif if (bind (nwio->handle, (struct sockaddr*)&addr, addrlen) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (flags & QSE_NWIO_TCP) { if (listen (nwio->handle, 10) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (TMOUT_ENABLED(nwio->tmout.a) && wait_for_data (nwio, &nwio->tmout.a, 0) <= -1) goto oops; handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); if (handle <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } qse_closesckhnd (nwio->handle); /* close the listening socket */ nwio->handle = handle; /* set the handle to the accepted socket */ } else if (flags & QSE_NWIO_UDP) { nwio->status |= STATUS_UDP_CONNECT; } } else { int xret; if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) { int orgfl; orgfl = fcntl (nwio->handle, F_GETFL, 0); if (orgfl <= -1 || fcntl (nwio->handle, F_SETFL, orgfl | O_NONBLOCK) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); if ((xret <= -1 && errno != EINPROGRESS) || fcntl (nwio->handle, F_SETFL, orgfl) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } if (wait_for_data (nwio, &nwio->tmout.c, 1) <= -1) goto oops; else { qse_sck_len_t xlen; xlen = QSE_SIZEOF(xret); if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xret, &xlen) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } else if (xret != 0) { nwio->errnum = skerr_to_errnum (xret); goto oops; } } } else { xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); if (xret <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; } } } #endif if (flags & QSE_NWIO_TEXT) { int topt = 0; if (flags & QSE_NWIO_IGNOREMBWCERR) topt |= QSE_TIO_IGNOREMBWCERR; if (flags & QSE_NWIO_NOAUTOFLUSH) topt |= QSE_TIO_NOAUTOFLUSH; nwio->tio = qse_tio_open (mmgr, QSE_SIZEOF(qse_nwio_t*), topt); if (nwio->tio == QSE_NULL) { nwio->errnum = QSE_NWIO_ENOMEM; goto oops; } /* store the back-reference to nwio in the extension area.*/ *(qse_nwio_t**)QSE_XTN(nwio->tio) = nwio; if (qse_tio_attachin (nwio->tio, socket_input, QSE_NULL, 4096) <= -1 || qse_tio_attachout (nwio->tio, socket_output, QSE_NULL, 4096) <= -1) { if (nwio->errnum == QSE_NWIO_ENOERR) nwio->errnum = tio_errnum_to_nwio_errnum (nwio->tio); goto oops; } }
static void get_xdmcp_sock(void) { #ifdef STREAMSCONN struct netconfig *nconf; if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) { XdmcpWarning("t_open() of /dev/udp failed"); return; } if (t_bind(xdmcpSocket, NULL, NULL) < 0) { XdmcpWarning("UDP socket creation failed"); t_error("t_bind(xdmcpSocket) failed"); t_close(xdmcpSocket); return; } /* * This part of the code looks contrived. It will actually fit in nicely * when the CLTS part of Xtrans is implemented. */ if ((nconf = getnetconfigent("udp")) == NULL) { XdmcpWarning("UDP socket creation failed: getnetconfigent()"); t_unbind(xdmcpSocket); t_close(xdmcpSocket); return; } if (netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL)) { XdmcpWarning("UDP set broadcast option failed: netdir_options()"); freenetconfigent(nconf); t_unbind(xdmcpSocket); t_close(xdmcpSocket); return; } freenetconfigent(nconf); #else int soopts = 1; #if defined(IPv6) && defined(AF_INET6) if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) XdmcpWarning("INET6 UDP socket creation failed"); #endif if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) XdmcpWarning("UDP socket creation failed"); #ifdef SO_BROADCAST else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *) &soopts, sizeof(soopts)) < 0) XdmcpWarning("UDP set broadcast socket-option failed"); #endif /* SO_BROADCAST */ if (xdmcpSocket >= 0 && xdm_from != NULL) { if (bind(xdmcpSocket, (struct sockaddr *) &FromAddress, FromAddressLen) < 0) { FatalError("Xserver: failed to bind to -from address: %s\n", xdm_from); } } #endif /* STREAMSCONN */ }
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); }
HTCPCONN tcp_ipv6_server_init(unsigned short p_usPort, void * arg ) { gFunctions = (T_PFN_functions *)arg; SOCKTYPE sock = t_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { C_NLOG_ERR("Iniche:tcp_ipv6_server_init: couldn't create ip6 socket"); return NULL; } //add sock in array int i = 0; int isSett = 0; for(;i < MAX_SOCK_NO; i++) { if(g_sockets[i].sock == INVALID_SOCKET) { g_sockets[i].sock = sock; g_sockets[i].indxToListen = -1; isSett = 1; break; } } if(isSett == 0) { t_socketclose(sock); C_NLOG_ERR("Iniche:tcp_ipv6_server_init: couldn't create ip6 socket."); return NULL; } struct sockaddr_in6 tcpsin6; int addrlen = sizeof(tcpsin6); IP6CPY(&tcpsin6.sin6_addr, &in6addr_any); tcpsin6.sin6_port = htons(p_usPort); tcpsin6.sin6_family = AF_INET6; int e = t_bind(g_sockets[i].sock, (struct sockaddr *)&tcpsin6, addrlen); if (e != 0) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: error %d binding tcp listen on port %d",e, p_usPort); return NULL; } int iTmp = 1; e = t_setsockopt(g_sockets[i].sock, SOL_SOCKET, SO_NONBLOCK, (void *)&iTmp, sizeof(iTmp)); if (e == SOCKET_ERROR) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: t_setsockopt() SO_NONBLOCK failed, Err: %d", e); return NULL; } e = t_listen(g_sockets[i].sock,MAX_SOCK_NO); if (e != 0) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: error %d tcp can't listen on port %d",e, p_usPort); return NULL; } C_NLOG_INFO( "Iniche:tcp_ipv6_server_init: TCP server initialized successfully." ); return (HTCPCONN)(g_sockets+i); }
w_rc_t udp_rpc_service::_start() { FUNC(udp_rpc_service::_start); int rpc_socket; int prot; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(port); #ifdef SOLARIS2 rpc_socket = t_open("/dev/udp", O_RDWR, 0); #else rpc_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); #endif if (rpc_socket < 0) { perror("socket"); return RC(errno); } #ifdef SOLARIS2 struct t_bind tb_args; tb_args.addr.maxlen = tb_args.addr.len = sizeof addr; tb_args.addr.buf = (char *)&addr; tb_args.qlen = 0; // Doesn't apply to connection-less transport if (t_bind(rpc_socket, &tb_args, 0) < 0) { // TODO: what is the tli counterpart of SO_REUSEADDR? // TODO: deal with Address-in-use error perror("bind"); return RC(errno); } #else // have to do this before it tries to bind if(ShoreVasLayer.reuseaddr) { set_sock_opt(rpc_socket, SO_REUSEADDR); } if (bind(rpc_socket, (struct sockaddr *)&addr, sizeof (addr)) < 0) { // TODO: deal with Address-in-use error perror("bind"); return RC(errno); } #endif // grot- not an ideal place to put this dassert(sizeof(efs_handle) <= NFS_FHSIZE); svcxprt = svcudp_create(rpc_socket); if (svcxprt == NULL) { // for now: catastrophic("Cannot create RPC/UDP service."); log->log(log_internal, "cannot create udp service\n"); return RC(errno); } #ifdef xxSOLARIS2 rpc_socket = svcxprt->xp_sock; port = svcxprt->xp_port; #else if ((port != 0) && (svcxprt->xp_port != port)) { DBG( << "svcudp_create returns wrong port :" << svcxprt->xp_port << " requested port " << port ) catastrophic("Cannot create RPC/UDP service with correct port."); }
int main(int argc, char *argv[] ) { int length, i; char sendbuffer[4096] ; int tfd; struct t_call *callptr; struct sockaddr_in serv_addr; pname = argv[0]; /* * Create a TCP transport endpoint and bind it. */ if ( (tfd = t_open(DEV_TCP, O_RDWR, 0)) < 0) { printf("client: can't t_open %s........\n", DEV_TCP); exit(1); } if (t_bind(tfd, (struct t_bind *) 0, (struct t_bind *) 0) < 0) { printf("client: t_bind error.....\n"); exit(1); } /* * Fill in the structure "serv_addr" with the address of the * server that we want to connect with. */ bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR); serv_addr.sin_port = htons(SERV_TCP_PORT); /* * Allocate a t_call structure, and initialize it. * Let t_alloc() initialize the addr structure of the t_call structure. */ if ( (callptr = (struct t_call *) t_alloc(tfd, T_CALL, T_ADDR)) == NULL) { printf("client: t_alloc error.......\n"); } callptr->addr.maxlen = sizeof(serv_addr); callptr->addr.len = sizeof(serv_addr); callptr->addr.buf = (char *) &serv_addr; callptr->opt.len = 0; /* no options */ callptr->udata.len = 0; /* no user data with connect */ /* get raw usage data */ if(get_raw_usage_data(sendbuffer, length) != FALSE) { process_client_service(tfd, callptr, sendbuffer, length); } if(*sendbuffer) free(sendbuffer); close(tfd); exit(1); }
static int TRANS(TLITLIBindLocal)(int fd, int family, char *port) { struct sockaddr_un *sunaddr=NULL; struct t_bind *req=NULL; prmsg(2, "TLITLIBindLocal(%d,%d,%s)\n", fd, family, port); if( family == AF_UNIX ) { if( (req=(struct t_bind *)t_alloc(fd,T_BIND,0)) == NULL ) { prmsg(1, "TLITLIBindLocal() failed to allocate a t_bind\n"); return -1; } if( (sunaddr=(struct sockaddr_un *) malloc(sizeof(struct sockaddr_un))) == NULL ) { prmsg(1, "TLITLIBindLocal: failed to allocate a sockaddr_un\n"); t_free((char *)req,T_BIND); return -1; } sunaddr->sun_family=AF_UNIX; #ifdef nuke if( *port == '/' ) { /* A full pathname */ (void) strcpy(sunaddr->sun_path, port); } else { (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port ); } #endif /*NUKE*/ (void) sprintf(sunaddr->sun_path,"%s%d", TLINODENAME, getpid()^time(NULL) ); prmsg(4, "TLITLIBindLocal: binding to %s\n", sunaddr->sun_path); req->addr.buf=(char *)sunaddr; req->addr.len=sizeof(*sunaddr); req->addr.maxlen=sizeof(*sunaddr); } if( t_bind(fd, req, NULL) < 0 ) { prmsg(1, "TLIBindLocal: Unable to bind TLI device to %s\n", port); if (sunaddr) free((char *) sunaddr); if (req) t_free((char *)req,T_BIND); return -1; } return 0; }
/* **************************************************************** * Aguarda pedidos de conexão (servidor) * **************************************************************** */ int tcp_listen (int fd, char *name) { T_CALL call; T_BIND bind; INADDR client_addr, addr[2]; int newfd; char *cp; /* * Preenche a estrutura T_CALL: só o membro addr é relevante. */ FILL_NETBUF (call.addr, &client_addr, sizeof (client_addr)); FILL_NETBUF (call.opt, NULL, 0); FILL_NETBUF (call.udata, NULL, 0); /* * Espera chegar um pedido de conexão. */ if (t_listen (fd, &call) < 0) return (-1); /* * Abre outro "endpoint". */ if ((newfd = t_open (tcpdevname, O_RDWR, (T_INFO *)NULL)) < 0) return (-1); /* * Preenche a estrutura T_BIND. */ if (client_addr.a_addr == LOCAL_IP_ADDR) { /* * A conexão é local: deixa o kernel gerar outro port. */ bind.addr.len = 0; bind.addr.buf = addr; bind.addr.maxlen = sizeof (INADDR); } else { /* * A conexão é remota: respeita o port do "t_listen". */ FILL_INADDR (addr[0], 0, listen_port); FILL_INADDR (addr[1], client_addr.a_addr, client_addr.a_port); FILL_NETBUF (bind.addr, addr, sizeof (addr)); } bind.qlen = 0; /* Não vamos dar "t_listen" nesta conexão */ if (t_bind (newfd, &bind, (T_BIND *)NULL) < 0) goto bad; if (set_param (newfd) < 0) goto bad; /* * Aceita a conexão no novo "endpoint". */ if (t_accept (fd, newfd, &call) < 0) goto bad; if ( name != NOSTR && (cp = t_addr_to_node (fd, client_addr.a_addr)) != NOSTR ) strcpy (name, cp); return (newfd); bad: t_close (newfd); return (-1); } /* end tcp_listen */
/* * This routine is designed to be able to "ping" * a list of hosts and create a list of responding * hosts sorted by response time. * This must be done without any prior * contact with the host - therefore the "ping" * must be to a "well-known" address. The outstanding * candidate here is the address of "rpcbind". * * A response to a ping is no guarantee that the host * is running NFS, has a mount daemon, or exports * the required filesystem. If the subsequent * mount attempt fails then the host will be marked * "ignore" and the host list will be re-pinged * (sans the bad host). This process continues * until a successful mount is achieved or until * there are no hosts left to try. */ enum clnt_stat nfs_cast(struct mapfs *mfs_in, struct mapfs **mfs_out, int timeout) { enum clnt_stat stat; AUTH *sys_auth = authsys_create_default(); XDR xdr_stream; register XDR *xdrs = &xdr_stream; int outlen; int if_inx; int tsec; int flag; int sent, addr_cnt, rcvd, if_cnt; fd_set readfds, mask; register ulong_t xid; /* xid - unique per addr */ register int i; struct rpc_msg msg; struct timeval t, rcv_timeout; char outbuf[UDPMSGSIZE], inbuf[UDPMSGSIZE]; struct t_unitdata t_udata, t_rdata; struct nd_hostserv hs; struct nd_addrlist *retaddrs; struct transp *tr_head; struct transp *trans, *prev_trans; struct addrs *a, *prev_addr; struct tstamps *ts, *prev_ts; NCONF_HANDLE *nc = NULL; struct netconfig *nconf; struct rlimit rl; int dtbsize; struct mapfs *mfs; /* * For each connectionless transport get a list of * host addresses. Any single host may have * addresses on several transports. */ addr_cnt = sent = rcvd = 0; tr_head = NULL; FD_ZERO(&mask); /* * Set the default select size to be the maximum FD_SETSIZE, unless * the current rlimit is lower. */ dtbsize = FD_SETSIZE; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { if (rl.rlim_cur < FD_SETSIZE) dtbsize = rl.rlim_cur; } prev_trans = NULL; prev_addr = NULL; prev_ts = NULL; for (mfs = mfs_in; mfs; mfs = mfs->mfs_next) { if (trace > 2) trace_prt(1, "nfs_cast: host=%s\n", mfs->mfs_host); nc = setnetconfig(); if (nc == NULL) { stat = RPC_CANTSEND; goto done_broad; } while (nconf = getnetconfig(nc)) { if (!(nconf->nc_flag & NC_VISIBLE) || nconf->nc_semantics != NC_TPI_CLTS || (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)) continue; trans = (struct transp *)malloc(sizeof (*trans)); if (trans == NULL) { syslog(LOG_ERR, "no memory"); stat = RPC_CANTSEND; goto done_broad; } (void) memset(trans, 0, sizeof (*trans)); if (tr_head == NULL) tr_head = trans; else prev_trans->tr_next = trans; prev_trans = trans; trans->tr_fd = t_open(nconf->nc_device, O_RDWR, NULL); if (trans->tr_fd < 0) { syslog(LOG_ERR, "nfscast: t_open: %s:%m", nconf->nc_device); stat = RPC_CANTSEND; goto done_broad; } if (t_bind(trans->tr_fd, (struct t_bind *)NULL, (struct t_bind *)NULL) < 0) { syslog(LOG_ERR, "nfscast: t_bind: %m"); stat = RPC_CANTSEND; goto done_broad; } trans->tr_taddr = /* LINTED pointer alignment */ (struct t_bind *)t_alloc(trans->tr_fd, T_BIND, T_ADDR); if (trans->tr_taddr == (struct t_bind *)NULL) { syslog(LOG_ERR, "nfscast: t_alloc: %m"); stat = RPC_SYSTEMERROR; goto done_broad; } trans->tr_device = nconf->nc_device; FD_SET(trans->tr_fd, &mask); if_inx = 0; hs.h_host = mfs->mfs_host; hs.h_serv = "rpcbind"; if (netdir_getbyname(nconf, &hs, &retaddrs) == ND_OK) { /* * If mfs->ignore is previously set for * this map, clear it. Because a host can * have either v6 or v4 address */ if (mfs->mfs_ignore == 1) mfs->mfs_ignore = 0; a = (struct addrs *)malloc(sizeof (*a)); if (a == NULL) { syslog(LOG_ERR, "no memory"); stat = RPC_CANTSEND; goto done_broad; } (void) memset(a, 0, sizeof (*a)); if (trans->tr_addrs == NULL) trans->tr_addrs = a; else prev_addr->addr_next = a; prev_addr = a; a->addr_if_tstamps = NULL; a->addr_mfs = mfs; a->addr_addrs = retaddrs; if_cnt = retaddrs->n_cnt; while (if_cnt--) { ts = (struct tstamps *) malloc(sizeof (*ts)); if (ts == NULL) { syslog(LOG_ERR, "no memory"); stat = RPC_CANTSEND; goto done_broad; } (void) memset(ts, 0, sizeof (*ts)); ts->ts_penalty = mfs->mfs_penalty; if (a->addr_if_tstamps == NULL) a->addr_if_tstamps = ts; else prev_ts->ts_next = ts; prev_ts = ts; ts->ts_inx = if_inx++; addr_cnt++; } break; } else { mfs->mfs_ignore = 1; if (verbose) syslog(LOG_ERR, "%s:%s address not known", mfs->mfs_host, strcmp(nconf->nc_proto, NC_INET)?"IPv6":"IPv4"); } } /* while */ endnetconfig(nc); nc = NULL; } /* for */ if (addr_cnt == 0) { syslog(LOG_ERR, "nfscast: couldn't find addresses"); stat = RPC_CANTSEND; goto done_broad; } (void) gettimeofday(&t, (struct timezone *)0); xid = (getpid() ^ t.tv_sec ^ t.tv_usec) & ~0xFF; t.tv_usec = 0; /* serialize the RPC header */ msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = RPCBPROG; /* * we can not use RPCBVERS here since it doesn't exist in 4.X, * the fix to bug 1139883 has made the 4.X portmapper silent to * version mismatches. This causes the RPC call to the remote * portmapper to simply be ignored if it's not Version 2. */ msg.rm_call.cb_vers = PMAPVERS; msg.rm_call.cb_proc = NULLPROC; if (sys_auth == (AUTH *)NULL) { stat = RPC_SYSTEMERROR; goto done_broad; } msg.rm_call.cb_cred = sys_auth->ah_cred; msg.rm_call.cb_verf = sys_auth->ah_verf; xdrmem_create(xdrs, outbuf, sizeof (outbuf), XDR_ENCODE); if (! xdr_callmsg(xdrs, &msg)) { stat = RPC_CANTENCODEARGS; goto done_broad; } outlen = (int)xdr_getpos(xdrs); xdr_destroy(xdrs); t_udata.opt.len = 0; t_udata.udata.buf = outbuf; t_udata.udata.len = outlen; /* * Basic loop: send packet to all hosts and wait for response(s). * The response timeout grows larger per iteration. * A unique xid is assigned to each address in order to * correctly match the replies. */ for (tsec = 4; timeout > 0; tsec *= 2) { timeout -= tsec; if (timeout <= 0) tsec += timeout; rcv_timeout.tv_sec = tsec; rcv_timeout.tv_usec = 0; sent = 0; for (trans = tr_head; trans; trans = trans->tr_next) { for (a = trans->tr_addrs; a; a = a->addr_next) { struct netbuf *if_netbuf = a->addr_addrs->n_addrs; ts = a->addr_if_tstamps; if_cnt = a->addr_addrs->n_cnt; while (if_cnt--) { /* * xid is the first thing in * preserialized buffer */ /* LINTED pointer alignment */ *((ulong_t *)outbuf) = htonl(xid + ts->ts_inx); (void) gettimeofday(&(ts->ts_timeval), (struct timezone *)0); /* * Check if already received * from a previous iteration. */ if (ts->ts_rcvd) { sent++; ts = ts->ts_next; continue; } t_udata.addr = *if_netbuf++; if (t_sndudata(trans->tr_fd, &t_udata) == 0) { sent++; } ts = ts->ts_next; } } } if (sent == 0) { /* no packets sent ? */ stat = RPC_CANTSEND; goto done_broad; } /* * Have sent all the packets. Now collect the responses... */ rcvd = 0; recv_again: msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.proc = xdr_void; readfds = mask; switch (select(dtbsize, &readfds, (fd_set *)NULL, (fd_set *)NULL, &rcv_timeout)) { case 0: /* Timed out */ /* * If we got at least one response in the * last interval, then don't wait for any * more. In theory we should wait for * the max weighting (penalty) value so * that a very slow server has a chance to * respond but this could take a long time * if the admin has set a high weighting * value. */ if (rcvd > 0) goto done_broad; stat = RPC_TIMEDOUT; continue; case -1: /* some kind of error */ if (errno == EINTR) goto recv_again; syslog(LOG_ERR, "nfscast: select: %m"); if (rcvd == 0) stat = RPC_CANTRECV; goto done_broad; } /* end of select results switch */ for (trans = tr_head; trans; trans = trans->tr_next) { if (FD_ISSET(trans->tr_fd, &readfds)) break; } if (trans == NULL) goto recv_again; try_again: t_rdata.addr = trans->tr_taddr->addr; t_rdata.udata.buf = inbuf; t_rdata.udata.maxlen = sizeof (inbuf); t_rdata.udata.len = 0; t_rdata.opt.len = 0; if (t_rcvudata(trans->tr_fd, &t_rdata, &flag) < 0) { if (errno == EINTR) goto try_again; syslog(LOG_ERR, "nfscast: t_rcvudata: %s:%m", trans->tr_device); stat = RPC_CANTRECV; continue; } if (t_rdata.udata.len < sizeof (ulong_t)) goto recv_again; if (flag & T_MORE) { syslog(LOG_ERR, "nfscast: t_rcvudata: %s: buffer overflow", trans->tr_device); goto recv_again; } /* * see if reply transaction id matches sent id. * If so, decode the results. * Note: received addr is ignored, it could be * different from the send addr if the host has * more than one addr. */ xdrmem_create(xdrs, inbuf, (uint_t)t_rdata.udata.len, XDR_DECODE); if (xdr_replymsg(xdrs, &msg)) { if (msg.rm_reply.rp_stat == MSG_ACCEPTED && (msg.rm_xid & ~0xFF) == xid) { struct addrs *curr_addr; i = msg.rm_xid & 0xFF; for (curr_addr = trans->tr_addrs; curr_addr; curr_addr = curr_addr->addr_next) { for (ts = curr_addr->addr_if_tstamps; ts; ts = ts->ts_next) if (ts->ts_inx == i && !ts->ts_rcvd) { ts->ts_rcvd = 1; calc_resp_time(&ts->ts_timeval); stat = RPC_SUCCESS; rcvd++; break; } } } /* otherwise, we just ignore the errors ... */ } xdrs->x_op = XDR_FREE; msg.acpted_rply.ar_results.proc = xdr_void; (void) xdr_replymsg(xdrs, &msg); XDR_DESTROY(xdrs); if (rcvd == sent) goto done_broad; else goto recv_again; } if (!rcvd) stat = RPC_TIMEDOUT; done_broad: if (rcvd) { *mfs_out = sort_responses(tr_head); stat = RPC_SUCCESS; } if (nc) endnetconfig(nc); free_transports(tr_head); AUTH_DESTROY(sys_auth); return (stat); }
/* **************************************************************** * Domain name resolver * **************************************************************** */ void main (int argc, const char *argv[]) { int opt; #if (0) /*******************************************************/ SERVTB *sp; int index; #endif /*******************************************************/ INADDR server_addr; T_BIND bind; /* * Pequena inicialização */ error_msg_to_log++; /* * Verifica se é SUPERUSUÁRIO */ if (geteuid () != 0) error ("$O usuário efetivo não é SUPERUSUÁRIO"); /* * Analisa as opções * * Sintaxe: * port_daemon [-v] <port_server_addr> ... */ while ((opt = getopt (argc, argv, "v")) != EOF) { switch (opt) { case 'v': /* Verbose */ vflag++; break; default: /* Erro */ putc ('\n', stderr); help (); } /* end switch */ } /* end while */ argv += optind; argc -= optind; #if (0) /*******************************************************/ if (argc == 0) help (); #endif /*******************************************************/ /* * Abre os "endpoint"s */ if ((udp_fd = t_open (udp_dev, O_RDWR, (T_INFO *)NULL)) < 0) error ("$*Não consegui abrir \"%s\"", udp_dev); /* * Obtém a porta local */ server_addr.a_port = PMAP_PORT; server_addr.a_addr = 0; bind.addr.len = sizeof (INADDR); bind.addr.maxlen = sizeof (INADDR); bind.addr.buf = &server_addr; if (t_bind (udp_fd, &bind, &bind) < 0) error ("$*Não consegui dar \"t_bind\" UDP"); send_req (); receive_answer (); #if (0) /*******************************************************/ /* * Cria um filho para enviar os pedidos de DNS. * O pai le os datagramas de resposta. */ if ((pidfilho = thread ()) < 0) error ("$*Não consegui criar um novo processo"); if (pidfilho > 0) pai (); else filho (); /* Não retorna */ #endif /*******************************************************/ } /* end port_mapper */