static int TRANS(TLIClose)(XtransConnInfo ciptr) { prmsg(2, "TLIClose(%x->%d)\n", ciptr, ciptr->fd); t_unbind(ciptr->fd); return (t_close(ciptr->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; }
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 */ }
/* * 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); }
/* * 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; }