/** * Sockwatch Module Handler * If you use Sockwatch Module, this should run in the main loop * @ingroup sockwatch_module */ void sockwatch_run(void) { #define WCF_HANDLE(item_v, ret_v) \ do { \ BITCLR(watch_sock[i], item_v); \ watch_cb[i](i, item_v, ret_v); \ } while(0) uint8_t i; int32_t ret; S2E_Packet *value = get_S2E_Packet_pointer(); MQTTPacket_connectData mqttConnectData = MQTTPacket_connectData_initializer; for(i=0; i<TOTAL_SOCK_NUM; i++) { if(watch_sock[i] == 0) continue; if(atci.mqtt_run == 1) { ret = MQTTYield(&mqttClient, mqttConnectData.keepAliveInterval); #ifdef __ATC_MODE_MQTT_DEBUG__ if(ret != SUCCESSS) { printf("MQTT yield error - ret : %d\r\n", ret); } #endif } if(watch_sock[i] & WATCH_SOCK_RECV) { // checked every time when 'connected' state getsockopt(i, SO_RECVBUF, (uint16_t*)&ret); if((uint16_t)ret > 0) WCF_HANDLE(WATCH_SOCK_RECV, RET_OK); } if(watch_sock[i] & WATCH_SOCK_CLS_EVT) { // checked every time when 'connected' state getsockopt(i, SO_STATUS, (uint8_t*)&ret); switch((uint8_t)ret) { case SOCK_CLOSED: WCF_HANDLE(WATCH_SOCK_CLS_EVT, RET_OK); break; case SOCK_CLOSE_WAIT: disconnect(i); //close(i); break; default: break; } } if(watch_sock[i] & WATCH_SOCK_CONN_EVT) { // checked every time when 'listen' state getsockopt(i, SO_STATUS, (uint8_t*)&ret); switch((uint8_t)ret) { case SOCK_ESTABLISHED: WCF_HANDLE(WATCH_SOCK_CONN_EVT, RET_OK); break; default: break; } } if((watch_sock[i] & WATCH_SOCK_MASK_LOW) == 0) continue; // things which occurs occasionally will be checked all together if(watch_sock[i] & WATCH_SOCK_CLS_TRY) { getsockopt(i, SO_STATUS, (uint8_t*)&ret); switch((uint8_t)ret) { case SOCK_LISTEN: close(i); case SOCK_CLOSED: WCF_HANDLE(WATCH_SOCK_CLS_TRY, RET_OK); break; case SOCK_FIN_WAIT: close(i); break; default: ctlsocket(i, CS_GET_INTERRUPT, (uint8_t*)&ret); if((uint8_t)ret & Sn_IR_TIMEOUT){ //ctlsocket(i, CS_CLR_INTERRUPT, (uint8_t*)&ret); close(i); WCF_HANDLE(WATCH_SOCK_CLS_TRY, SOCKERR_TIMEOUT); } disconnect(i); //close(i); break; } } if(watch_sock[i] & WATCH_SOCK_CONN_TRY) { getsockopt(i, SO_STATUS, (uint8_t*)&ret); switch((uint8_t)ret) { case SOCK_ESTABLISHED: WCF_HANDLE(WATCH_SOCK_CONN_TRY, RET_OK); if(atci.mqtt_con == 1) { if(getSn_IR(i) & Sn_IR_CON) { setSn_IR(i,Sn_IR_CON); mqttConnectData.MQTTVersion = 4; mqttConnectData.clientID.cstring = value->module_name; mqttConnectData.username.cstring = value->options.mqtt_user; mqttConnectData.password.cstring = value->options.mqtt_pw; mqttConnectData.willFlag = 0; mqttConnectData.keepAliveInterval = 60; mqttConnectData.cleansession = 1; ret = MQTTConnect(&mqttClient, &mqttConnectData); #ifdef __ATC_MODE_MQTT_DEBUG__ if(ret != SUCCESSS) { printf("MQTT connect error - ret : %d\r\n", ret); } #endif atci.mqtt_con = 0; atci.mqtt_run = 1; } } break; default: ctlsocket(i, CS_GET_INTERRUPT, (uint8_t*)&ret); if((uint8_t)ret & Sn_IR_TIMEOUT){ //ctlsocket(i, CS_CLR_INTERRUPT, (uint8_t*)&ret); close(i); WCF_HANDLE(WATCH_SOCK_CONN_TRY, SOCKERR_TIMEOUT); } break; } } if(watch_sock[i] & WATCH_SOCK_TCP_SEND) { // 블로킹 모드로만 동작함 그러므로 Watch할 필요가 없음 } if(watch_sock[i] & WATCH_SOCK_UDP_SEND) { if(checkAtcUdpSendStatus < 0) { WCF_HANDLE(WATCH_SOCK_UDP_SEND, RET_NOK); } else { WCF_HANDLE(WATCH_SOCK_UDP_SEND, RET_OK); } } } // ToDo: not socket part }
//扫描指定ip的指定port void do_scan(struct sockaddr_in *des_add){ int sock_fd; int result; socklen_t len; struct hostent *hptr; //printf("%s\n",inet_ntoa(des_add->sin_addr)); if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) < 0){ perror("error: socket\n"); return; } //设置为非阻塞模式 int flags = fcntl(sock_fd,F_GETFL,0); fcntl(sock_fd,F_SETFL,flags|O_NONBLOCK); //建立连接 len = sizeof(*des_add); result = connect(sock_fd,(struct sockaddr*)des_add,len); if(result && errno != EINPROGRESS){ close(sock_fd); return; } if(result == 0){ //connect连接成功,恢复套接字阻塞状态 fcntl(sock_fd,F_SETFL,flags); hptr = gethostbyaddr(&(des_add->sin_addr),4,AF_INET); printf("ip:%s\thostname:%s\tport:%d\n",inet_ntoa(des_add->sin_addr),hptr->h_name,ntohs(des_add->sin_port)); close(sock_fd); return; } //连接失败,设置等待或者超时 fd_set rd,wd,ed; FD_ZERO(&rd); FD_SET(sock_fd,&rd); wd = rd; ed = rd; int maxfd = sock_fd; struct timeval tv = {0,3000}; int ret = select(maxfd+1,&rd,&wd,&ed,&tv); int val; if(ret <= 0){ close(sock_fd); return; }else{ if(!FD_ISSET(sock_fd,&rd)&&!FD_ISSET(sock_fd,&wd)){ close(sock_fd); return; } if(getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,&val,&len)<0){ close(sock_fd); return; } if(val!=0){ close(sock_fd); return; } //connect正确返回,恢复阻塞状态 fcntl(sock_fd,F_SETFL,flags); hptr = gethostbyaddr(&(des_add->sin_addr),4,AF_INET); if(hptr == NULL) printf("\t\t\t\t\tip:%s\thostname:unkown\tport:%d\n",inet_ntoa(des_add->sin_addr),ntohs(des_add->sin_port)); else printf("\t\t\t\t\tip:%s\thostname:%s\tport:%d\n",inet_ntoa(des_add->sin_addr),hptr->h_name,ntohs(des_add->sin_port)); close(sock_fd); } }
Connection* ConnectionInit(Connection* connection) { ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; #ifndef AIO4C_WIN32 if ((connection->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { code.error = errno; #else /* AIO4C_WIN32 */ if ((connection->socket = socket(PF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) { code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_SOCKET_ERROR, &code); } #ifndef AIO4C_WIN32 if (fcntl(connection->socket, F_SETFL, O_NONBLOCK) == -1) { code.error = errno; #else /* AIO4C_WIN32 */ unsigned long ioctl = 1; if (ioctlsocket(connection->socket, FIONBIO, &ioctl) == SOCKET_ERROR) { code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_FCNTL_ERROR, &code); } ConnectionState(connection, AIO4C_CONNECTION_STATE_INITIALIZED); return connection; } Connection* ConnectionConnect(Connection* connection) { ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; ConnectionState newState = AIO4C_CONNECTION_STATE_CONNECTING; if (connection->state != AIO4C_CONNECTION_STATE_INITIALIZED) { code.expected = AIO4C_CONNECTION_STATE_INITIALIZED; return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_DEBUG, AIO4C_CONNECTION_STATE_ERROR, &code); } if (connect(connection->socket, AddressGetAddr(connection->address), AddressGetAddrSize(connection->address)) == -1) { #ifndef AIO4C_WIN32 code.error = errno; if (errno == EINPROGRESS) { #else /* AIO4C_WIN32 */ int error = WSAGetLastError(); code.source = AIO4C_ERRNO_SOURCE_WSA; if (error == WSAEINPROGRESS || error == WSAEALREADY || error == WSAEWOULDBLOCK) { #endif /* AIO4C_WIN32 */ newState = AIO4C_CONNECTION_STATE_CONNECTING; } else { return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_CONNECT_ERROR, &code); } } else { newState = AIO4C_CONNECTION_STATE_CONNECTED; } ConnectionState(connection, newState); return connection; } Connection* ConnectionFinishConnect(Connection* connection) { ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; int soError = 0; socklen_t soSize = sizeof(int); #ifdef AIO4C_HAVE_POLL aio4c_poll_t polls[1] = { { .fd = connection->socket, .events = POLLOUT, .revents = 0 } }; #ifndef AIO4C_WIN32 if (poll(polls, 1, -1) == -1) { code.error = errno; #else /* AIO4C_WIN32 */ if (WSAPoll(polls, 1, -1) == SOCKET_ERROR) { code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_POLL_ERROR, &code); } if (polls[0].revents > 0) { #else /* AIO4C_HAVE_POLL */ fd_set writeSet; fd_set errorSet; FD_ZERO(&writeSet); FD_ZERO(&errorSet); FD_SET(connection->socket, &writeSet); FD_SET(connection->socket, &errorSet); #ifndef AIO4C_WIN32 if (select(connection->socket + 1, NULL, &writeSet, &errorSet, NULL) == -1) { code.error = errno; #else /* AIO4C_WIN32 */ if (select(connection->socket + 1, NULL, &writeSet, &errorSet, NULL) == SOCKET_ERROR) { code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_SELECT_ERROR, &code); } if (FD_ISSET(connection->socket, &writeSet) || FD_ISSET(connection->socket, &errorSet)) { #endif /* AIO4C_HAVE_POLL */ #ifndef AIO4C_WIN32 if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, &soError, &soSize) != 0) { code.error = errno; #else /* AI4OC_WIN32 */ if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, (char*)&soError, &soSize) == SOCKET_ERROR) { code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_GETSOCKOPT_ERROR, &code); } if (soError != 0) { #ifndef AIO4C_WIN32 code.error = soError; #else /* AIO4C_WIN32 */ code.source = AIO4C_ERRNO_SOURCE_SOE; code.soError = soError; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_FINISH_CONNECT_ERROR, &code); } } return connection; } Connection* ConnectionRead(Connection* connection) { Buffer* buffer = NULL; ssize_t nbRead = 0; ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; aio4c_byte_t* data = NULL; buffer = connection->readBuffer; if (!BufferHasRemaining(buffer)) { code.buffer = buffer; return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_BUFFER_OVERFLOW_ERROR, &code); } data = BufferGetBytes(buffer); if ((nbRead = recv(connection->socket, (void*)&data[BufferGetPosition(buffer)], BufferRemaining(buffer), 0)) < 0) { #ifndef AIO4C_WIN32 code.error = errno; #else /* AIO4C_WIN32 */ code.source = AIO4C_ERRNO_SOURCE_WSA; #endif /* AIO4C_WIN32 */ return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_ERROR, AIO4C_READ_ERROR, &code); } ProbeSize(AIO4C_PROBE_NETWORK_READ_SIZE, nbRead); if (nbRead == 0) { if (connection->state == AIO4C_CONNECTION_STATE_PENDING_CLOSE) { ConnectionState(connection, AIO4C_CONNECTION_STATE_CLOSED); return connection; } else { return _ConnectionHandleError(connection, AIO4C_LOG_LEVEL_INFO, AIO4C_CONNECTION_DISCONNECTED, &code); } } if (!connection->canRead) { Log(AIO4C_LOG_LEVEL_WARN, "received data on connection %s when reading is not allowed", connection->string); BufferReset(buffer); return connection; } BufferPosition(buffer, BufferGetPosition(buffer) + nbRead); _ConnectionEventHandle(connection, AIO4C_INBOUND_DATA_EVENT); return connection; }
static SOCKET xmlNanoHTTPConnectAttempt(struct sockaddr *addr) { #ifndef HAVE_POLL_H fd_set wfd; #ifdef _WINSOCKAPI_ fd_set xfd; #endif struct timeval tv; #else /* !HAVE_POLL_H */ struct pollfd p; #endif /* !HAVE_POLL_H */ int status; int addrlen; SOCKET s; #ifdef SUPPORT_IP6 if (addr->sa_family == AF_INET6) { s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); addrlen = sizeof(struct sockaddr_in6); } else #endif { s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); addrlen = sizeof(struct sockaddr_in); } if (s == INVALID_SOCKET) { #ifdef DEBUG_HTTP perror("socket"); #endif __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); return INVALID_SOCKET; } #ifdef _WINSOCKAPI_ { u_long one = 1; status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; } #else /* _WINSOCKAPI_ */ #if defined(VMS) { int enable = 1; status = ioctl(s, FIONBIO, &enable); } #else /* VMS */ #if defined(__BEOS__) && !defined(__HAIKU__) { bool noblock = true; status = setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, sizeof(noblock)); } #else /* __BEOS__ */ if ((status = fcntl(s, F_GETFL, 0)) != -1) { #ifdef O_NONBLOCK status |= O_NONBLOCK; #else /* O_NONBLOCK */ #ifdef F_NDELAY status |= F_NDELAY; #endif /* F_NDELAY */ #endif /* !O_NONBLOCK */ status = fcntl(s, F_SETFL, status); } if (status < 0) { #ifdef DEBUG_HTTP perror("nonblocking"); #endif __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); closesocket(s); return INVALID_SOCKET; } #endif /* !__BEOS__ */ #endif /* !VMS */ #endif /* !_WINSOCKAPI_ */ if (connect(s, addr, addrlen) == -1) { switch (socket_errno()) { case EINPROGRESS: case EWOULDBLOCK: break; default: __xmlIOErr(XML_FROM_HTTP, 0, "error connecting to HTTP server"); closesocket(s); return INVALID_SOCKET; } } #ifndef HAVE_POLL_H tv.tv_sec = timeout; tv.tv_usec = 0; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4018) #endif #ifndef _WINSOCKAPI_ if (s > FD_SETSIZE) return INVALID_SOCKET; #endif FD_ZERO(&wfd); FD_SET(s, &wfd); #ifdef _WINSOCKAPI_ FD_ZERO(&xfd); FD_SET(s, &xfd); switch (select(s + 1, NULL, &wfd, &xfd, &tv)) #else switch (select(s + 1, NULL, &wfd, NULL, &tv)) #endif #ifdef _MSC_VER #pragma warning(pop) #endif #else /* !HAVE_POLL_H */ p.fd = s; p.events = POLLOUT; switch (poll(&p, 1, timeout * 1000)) #endif /* !HAVE_POLL_H */ { case 0: /* Time out */ __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); closesocket(s); return INVALID_SOCKET; case -1: /* Ermm.. ?? */ __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); closesocket(s); return INVALID_SOCKET; } #ifndef HAVE_POLL_H if (FD_ISSET(s, &wfd) #ifdef _WINSOCKAPI_ || FD_ISSET(s, &xfd) #endif ) #else /* !HAVE_POLL_H */ if (p.revents == POLLOUT) #endif /* !HAVE_POLL_H */ { XML_SOCKLEN_T len; len = sizeof(status); #ifdef SO_ERROR if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) < 0) { /* Solaris error code */ __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); closesocket(s); return INVALID_SOCKET; } #endif if (status) { __xmlIOErr(XML_FROM_HTTP, 0, "Error connecting to remote host"); closesocket(s); errno = status; return INVALID_SOCKET; } } else { /* pbm */ __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); closesocket(s); return INVALID_SOCKET; } return (s); }
/* system calls which differ in signature across OS's in ways that C++ cannot deal with */ extern int SOCK_getsockopt(int s, int level, int optname, void *optval, GETSOCKOPT_LENGTH_T *optlen) { return getsockopt(s, level, optname, optval, (void *)optlen); }
void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { char tmpfile[256], *err; int dfd, maxtries = 5; int sockerr = 0; socklen_t errlen = sizeof(sockerr); REDIS_NOTUSED(el); REDIS_NOTUSED(privdata); REDIS_NOTUSED(mask); /* If this event fired after the user turned the instance into a master * with SLAVEOF NO ONE we must just return ASAP. */ if (server.repl_state == REDIS_REPL_NONE) { close(fd); return; } /* Check for errors in the socket. */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1) sockerr = errno; if (sockerr) { aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s", strerror(sockerr)); goto error; } /* If we were connecting, it's time to send a non blocking PING, we want to * make sure the master is able to reply before going into the actual * replication process where we have long timeouts in the order of * seconds (in the meantime the slave would block). */ if (server.repl_state == REDIS_REPL_CONNECTING) { redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event."); /* Delete the writable event so that the readable event remains * registered and we can wait for the PONG reply. */ aeDeleteFileEvent(server.el,fd,AE_WRITABLE); server.repl_state = REDIS_REPL_RECEIVE_PONG; /* Send the PING, don't check for errors at all, we have the timeout * that will take care about this. */ syncWrite(fd,"PING\r\n",6,100); return; } /* Receive the PONG command. */ if (server.repl_state == REDIS_REPL_RECEIVE_PONG) { char buf[1024]; /* Delete the readable event, we no longer need it now that there is * the PING reply to read. */ aeDeleteFileEvent(server.el,fd,AE_READABLE); /* Read the reply with explicit timeout. */ buf[0] = '\0'; if (syncReadLine(fd,buf,sizeof(buf), server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING, "I/O error reading PING reply from master: %s", strerror(errno)); goto error; } /* We don't care about the reply, it can be +PONG or an error since * the server requires AUTH. As long as it replies correctly, it's * fine from our point of view. */ if (buf[0] != '-' && buf[0] != '+') { redisLog(REDIS_WARNING,"Unexpected reply to PING from master."); goto error; } else { redisLog(REDIS_NOTICE, "Master replied to PING, replication can continue..."); } } /* AUTH with the master if required. */ if(server.masterauth) { err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL); if (err) { redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err); sdsfree(err); goto error; } } /* Set the slave port, so that Master's INFO command can list the * slave listening port correctly. */ { sds port = sdsfromlonglong(server.port); err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port, NULL); sdsfree(port); /* Ignore the error if any, not all the Redis versions support * REPLCONF listening-port. */ if (err) { redisLog(REDIS_NOTICE,"(non critical): Master does not understand REPLCONF listening-port: %s", err); sdsfree(err); } } /* Issue the SYNC command */ if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) { redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", strerror(errno)); goto error; } /* Prepare a suitable temp file for bulk transfer */ while(maxtries--) { snprintf(tmpfile,256, "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid()); dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); if (dfd != -1) break; sleep(1); } if (dfd == -1) { redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); goto error; } /* Setup the non blocking download of the bulk file. */ if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL) == AE_ERR) { redisLog(REDIS_WARNING,"Can't create readable event for SYNC"); goto error; } server.repl_state = REDIS_REPL_TRANSFER; server.repl_transfer_size = -1; server.repl_transfer_read = 0; server.repl_transfer_last_fsync_off = 0; server.repl_transfer_fd = dfd; server.repl_transfer_lastio = server.unixtime; server.repl_transfer_tmpfile = zstrdup(tmpfile); return; error: close(fd); server.repl_transfer_s = -1; server.repl_state = REDIS_REPL_CONNECT; return; }
/* * Set the date in the machines controlled by timedaemons by communicating the * new date to the local timedaemon. If the timedaemon is in the master state, * it performs the correction on all slaves. If it is in the slave state, it * notifies the master that a correction is needed. * Returns 0 on success. Returns > 0 on failure, setting retval to 2; */ int netsettime(time_t tval) { struct timeval tout; struct servent *sp; struct tsp msg; struct sockaddr_in lsin, dest, from; fd_set ready; long waittime; int s, port, timed_ack, found, lerr; socklen_t length; char hostname[MAXHOSTNAMELEN]; if ((sp = getservbyname("timed", "udp")) == NULL) { warnx("timed/udp: unknown service"); return (retval = 2); } dest.sin_port = sp->s_port; dest.sin_family = AF_INET; dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY); s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { if (errno != EAFNOSUPPORT) warn("timed"); return (retval = 2); } memset(&lsin, 0, sizeof(lsin)); lsin.sin_family = AF_INET; for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { lsin.sin_port = htons((u_short)port); if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0) break; if (errno == EADDRINUSE) continue; if (errno != EADDRNOTAVAIL) warn("bind"); goto bad; } if (port == IPPORT_RESERVED / 2) { warnx("all ports in use"); goto bad; } memset(&msg, 0, sizeof(msg)); msg.tsp_type = TSP_SETDATE; msg.tsp_vers = TSPVERSION; if (gethostname(hostname, sizeof(hostname))) { warn("gethostname"); goto bad; } (void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name)); msg.tsp_seq = htons((u_short)0); msg.tsp_time.tv_sec = htonl((u_long)tval); msg.tsp_time.tv_usec = htonl((u_long)0); length = sizeof(struct sockaddr_in); if (connect(s, (struct sockaddr *)&dest, length) < 0) { warn("connect"); goto bad; } if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) { if (errno != ECONNREFUSED) warn("send"); goto bad; } timed_ack = -1; waittime = WAITACK; loop: tout.tv_sec = waittime; tout.tv_usec = 0; FD_ZERO(&ready); FD_SET(s, &ready); found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); length = sizeof(lerr); if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) { if (lerr != ECONNREFUSED) warnc(lerr, "send (delayed error)"); goto bad; } if (found > 0 && FD_ISSET(s, &ready)) { length = sizeof(struct sockaddr_in); if (recvfrom(s, &msg, sizeof(struct tsp), 0, (struct sockaddr *)&from, &length) < 0) { if (errno != ECONNREFUSED) warn("recvfrom"); goto bad; } msg.tsp_seq = ntohs(msg.tsp_seq); msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); switch (msg.tsp_type) { case TSP_ACK: timed_ack = TSP_ACK; waittime = WAITDATEACK; goto loop; case TSP_DATEACK: (void)close(s); return (0); default: warnx("wrong ack received from timed: %s", tsptype[msg.tsp_type]); timed_ack = -1; break; } } if (timed_ack == -1) warnx("can't reach time daemon, time set locally"); bad: (void)close(s); return (retval = 2); }
static int agent_socket_get_cred(int fd, struct ucred *cred) { socklen_t credlen = sizeof(struct ucred); return getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &credlen); }
static int connect_with_timeout(struct lttcomm_sock *sock) { unsigned long timeout = lttcomm_get_network_timeout(); int ret, flags, connect_ret; struct timespec orig_time, cur_time; ret = fcntl(sock->fd, F_GETFL, 0); if (ret == -1) { PERROR("fcntl"); return -1; } flags = ret; /* Set socket to nonblock */ ret = fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK); if (ret == -1) { PERROR("fcntl"); return -1; } ret = clock_gettime(CLOCK_MONOTONIC, &orig_time); if (ret == -1) { PERROR("clock_gettime"); return -1; } connect_ret = connect(sock->fd, (struct sockaddr *) &sock->sockaddr.addr.sin, sizeof(sock->sockaddr.addr.sin)); if (connect_ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS) { goto error; } else if (!connect_ret) { /* Connect succeeded */ goto success; } /* * Perform poll loop following EINPROGRESS recommendation from * connect(2) man page. */ do { struct pollfd fds; fds.fd = sock->fd; fds.events = POLLOUT; fds.revents = 0; ret = poll(&fds, 1, RECONNECT_DELAY); if (ret < 0) { goto error; } else if (ret > 0) { int optval; socklen_t optval_len = sizeof(optval); if (!(fds.revents & POLLOUT)) { /* Either hup or error */ errno = EPIPE; goto error; } /* got something */ ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &optval, &optval_len); if (ret) { goto error; } if (!optval) { connect_ret = 0; goto success; } else { goto error; } } /* ret == 0: timeout */ ret = clock_gettime(CLOCK_MONOTONIC, &cur_time); if (ret == -1) { PERROR("clock_gettime"); connect_ret = ret; goto error; } } while (time_diff_ms(&cur_time, &orig_time) < timeout); /* Timeout */ errno = ETIMEDOUT; connect_ret = -1; success: /* Restore initial flags */ ret = fcntl(sock->fd, F_SETFL, flags); if (ret == -1) { PERROR("fcntl"); /* Continue anyway */ } error: return connect_ret; }
/* * checks if a socket is connected or not by looking up the ip and port * of the remote host. * Returns 1 if connected and 0 if not. */ int net_is_connected(merlin_node *node) { struct sockaddr_in sain; socklen_t slen; int optval = 0, gsoerr = 0, gsores = 0, gpnres = 0, gpnerr = 0; if (!node || node->sock < 0) return 0; if (node->state == STATE_CONNECTED) return 1; if (node->state != STATE_PENDING) return 0; /* * yes, getpeername() actually has to be here, or getsockopt() * won't return errors when we're not yet connected. It's * important that we read the socket error state though, or * some older kernels will maintain the link in SYN_SENT state * more or less indefinitely, so get all the syscalls taken * care of no matter if they actually work or not. */ errno = 0; slen = sizeof(struct sockaddr_in); gpnres = getpeername(node->sock, (struct sockaddr *)&sain, &slen); gpnerr = errno; slen = sizeof(optval); gsores = getsockopt(node->sock, SOL_SOCKET, SO_ERROR, &optval, &slen); gsoerr = errno; if (!gpnres && !gsores && !optval && !gpnerr && !gsoerr) { node_set_state(node, STATE_CONNECTED, "connect() attempt completed successfully"); return 1; } /* diagnostics first */ ldebug("%s is not connected: gpn/gso: %d:%d/%d:%d; optval: %d", node->name, gpnres, gpnerr, gsores, gsoerr, optval); if (optval) { node_disconnect(node, "connect() to %s node %s failed: %s", node_type(node), node->name, strerror(optval)); return 0; } if (gsores < 0 && gsoerr != ENOTCONN) { node_disconnect(node, "getsockopt(%d) failed for %s node %s: %s", node->sock, node_type(node), node->name, strerror(gsoerr)); } if (gpnres < 0 && gpnerr != ENOTCONN) { lerr("getpeername(%d) failed for %s: %s", node->sock, node->name, strerror(gpnerr)); } /* * if a connection is in progress, we should be getting * ENOTCONN, but we need to give it time to complete * first. 30 seconds should be enough. */ if (node->last_conn_attempt + MERLIN_CONNECT_TIMEOUT < time(NULL)) { node_disconnect(node, "connect() timed out after %d seconds", MERLIN_CONNECT_TIMEOUT); } return 0; }
int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, int sec) { int n, len, error, flags; int fd; struct timeval tv; fd_set rset, wset; struct sockaddr_in csa; if (cs == NULL) cs = &csa; /* first allocate a socket */ cs->sin_family = AF_INET; cs->sin_port = htons (port); fd = socket (cs->sin_family, SOCK_STREAM, 0); if (fd == -1) return (-1); if (!(cs->sin_addr.s_addr = net_resolve (server))) { close (fd); return (-1); } flags = fcntl (fd, F_GETFL, 0); if (flags == -1) { close (fd); return (-1); } n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); if (n == -1) { close (fd); return (-1); } error = 0; n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); if (n < 0) { if (errno != EINPROGRESS) { close (fd); return (-1); } } if (n == 0) goto done; FD_ZERO(&rset); FD_ZERO(&wset); FD_SET(fd, &rset); FD_SET(fd, &wset); tv.tv_sec = sec; tv.tv_usec = 0; n = select(fd + 1, &rset, &wset, NULL, &tv); if (n == 0) { close(fd); errno = ETIMEDOUT; return (-1); } if (n == -1) return (-1); if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { len = sizeof(error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { errno = ETIMEDOUT; return (-1); } if (error == 0) { goto done; } else { errno = error; return (-1); } } } else return (-1); done: n = fcntl(fd, F_SETFL, flags); if (n == -1) return (-1); return (fd); }
static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; int *ip; struct sockaddr *to = NULL; bio_dgram_data *data = NULL; #if defined(IP_MTU_DISCOVER) || defined(IP_MTU) long sockopt_val = 0; unsigned int sockopt_len = 0; #endif #ifdef OPENSSL_SYS_LINUX socklen_t addr_len; union { struct sockaddr sa; struct sockaddr_in s4; #if OPENSSL_USE_IPV6 struct sockaddr_in6 s6; #endif } addr; #endif data = (bio_dgram_data *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: num=0; case BIO_C_FILE_SEEK: ret=0; break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret=0; break; case BIO_C_SET_FD: dgram_clear(b); b->num= *((int *)ptr); b->shutdown=(int)num; b->init=1; break; case BIO_C_GET_FD: if (b->init) { ip=(int *)ptr; if (ip != NULL) *ip=b->num; ret=b->num; } else ret= -1; break; case BIO_CTRL_GET_CLOSE: ret=b->shutdown; break; case BIO_CTRL_SET_CLOSE: b->shutdown=(int)num; break; case BIO_CTRL_PENDING: case BIO_CTRL_WPENDING: ret=0; break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: ret=1; break; case BIO_CTRL_DGRAM_CONNECT: to = (struct sockaddr *)ptr; #if 0 if (connect(b->num, to, sizeof(struct sockaddr)) < 0) { perror("connect"); ret = 0; } else { #endif switch (to->sa_family) { case AF_INET: memcpy(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: memcpy(&data->peer,to,sizeof(data->peer.sa)); break; } #if 0 } #endif break; /* (Linux)kernel sets DF bit on outgoing IP packets */ case BIO_CTRL_DGRAM_MTU_DISCOVER: #ifdef OPENSSL_SYS_LINUX addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: sockopt_val = IP_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) perror("setsockopt"); break; #if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) perror("setsockopt"); break; #endif default: ret = -1; break; } ret = -1; #else break; #endif case BIO_CTRL_DGRAM_QUERY_MTU: #ifdef OPENSSL_SYS_LINUX addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) { ret = 0; } else { /* we assume that the transport protocol is UDP and no * IP options are used. */ data->mtu = sockopt_val - 8 - 20; ret = data->mtu; } break; #if OPENSSL_USE_IPV6 && defined(IPV6_MTU) case AF_INET6: if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) { ret = 0; } else { /* we assume that the transport protocol is UDP and no * IPV6 options are used. */ data->mtu = sockopt_val - 8 - 40; ret = data->mtu; } break; #endif default: ret = 0; break; } #else ret = 0; #endif break; case BIO_CTRL_DGRAM_GET_MTU: return data->mtu; break; case BIO_CTRL_DGRAM_SET_MTU: data->mtu = num; ret = num; break; case BIO_CTRL_DGRAM_SET_CONNECTED: to = (struct sockaddr *)ptr; if ( to != NULL) { data->connected = 1; switch (to->sa_family) { case AF_INET: memcpy(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: memcpy(&data->peer,to,sizeof(data->peer.sa)); break; } } else { data->connected = 0; memset(&(data->peer), 0x00, sizeof(data->peer)); } break; case BIO_CTRL_DGRAM_GET_PEER: switch (data->peer.sa.sa_family) { case AF_INET: ret=sizeof(data->peer.sa_in); break; #if OPENSSL_USE_IPV6 case AF_INET6: ret=sizeof(data->peer.sa_in6); break; #endif default: ret=sizeof(data->peer.sa); break; } if (num==0 || num>ret) num=ret; memcpy(ptr,&data->peer,(ret=num)); break; case BIO_CTRL_DGRAM_SET_PEER: to = (struct sockaddr *) ptr; switch (to->sa_family) { case AF_INET: memcpy(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: memcpy(&data->peer,to,sizeof(data->peer.sa)); break; } break; case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); break; #if defined(SO_RCVTIMEO) case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { struct timeval *tv = (struct timeval *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout)) < 0) { perror("setsockopt"); ret = -1; } } #else if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, sizeof(struct timeval)) < 0) { perror("setsockopt"); ret = -1; } #endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { int timeout, sz = sizeof(timeout); struct timeval *tv = (struct timeval *)ptr; if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } } #else if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, (void *)&ret) < 0) { perror("getsockopt"); ret = -1; } #endif break; #endif #if defined(SO_SNDTIMEO) case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { struct timeval *tv = (struct timeval *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, (void*)&timeout, sizeof(timeout)) < 0) { perror("setsockopt"); ret = -1; } } #else if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, sizeof(struct timeval)) < 0) { perror("setsockopt"); ret = -1; } #endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { int timeout, sz = sizeof(timeout); struct timeval *tv = (struct timeval *)ptr; if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } } #else if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, (void *)&ret) < 0) { perror("getsockopt"); ret = -1; } #endif break; #endif case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: /* fall-through */ case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: #ifdef OPENSSL_SYS_WINDOWS if ( data->_errno == WSAETIMEDOUT) #else if ( data->_errno == EAGAIN) #endif { ret = 1; data->_errno = 0; } else ret = 0; break; #ifdef EMSGSIZE case BIO_CTRL_DGRAM_MTU_EXCEEDED: if ( data->_errno == EMSGSIZE) { ret = 1; data->_errno = 0; } else ret = 0; break; #endif default: ret=0; break; } return(ret); }
JNIEXPORT jint JNICALL Java_com_ghostagent_SoundManagementNative_connect(JNIEnv *env, jobject obj, jint sockfd, jint timeout, jstring address, jint port) { const char *cp; struct sockaddr_in addr; int flags; int ret; fd_set wset; struct timeval tv; int error; socklen_t len; cp = (*env)->GetStringUTFChars(env, address, NULL); if (cp == NULL) return -1; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(cp); (*env)->ReleaseStringUTFChars(env, address, cp); flags = fcntl(sockfd, F_GETFL); if (flags < 0) return -1; if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) return -1; ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == 0) { fcntl(sockfd, F_SETFL, flags); return 0; } if (errno != EINPROGRESS) { fcntl(sockfd, F_SETFL, flags); return -1; } FD_ZERO(&wset); FD_SET(sockfd, &wset); memset(&tv, 0, sizeof(tv)); tv.tv_sec = (time_t)timeout; if (select(sockfd + 1, NULL, &wset, NULL, &tv) <= 0) { fcntl(sockfd, F_SETFL, flags); return -1; } len = sizeof(error); ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len); if (ret < 0 || error != 0) { fcntl(sockfd, F_SETFL, flags); return -1; } fcntl(sockfd, F_SETFL, flags); return 0; }
/** * @brief SSH poll callback. This callback will be used when an event * caught on the socket. * * @param p Poll object this callback belongs to. * @param fd The raw socket. * @param revents The current poll events on the socket. * @param userdata Userdata to be passed to the callback function, * in this case the socket object. * * @return 0 on success, < 0 when the poll object has been removed * from its poll context. */ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s) { ssh_socket s = (ssh_socket)v_s; char buffer[MAX_BUF_SIZE]; ssize_t nread; int rc; int err = 0; socklen_t errlen = sizeof(err); /* Do not do anything if this socket was already closed */ if (!ssh_socket_is_open(s)) { return -1; } SSH_LOG(SSH_LOG_TRACE, "Poll callback on socket %d (%s%s%s), out buffer %d",fd, (revents & POLLIN) ? "POLLIN ":"", (revents & POLLOUT) ? "POLLOUT ":"", (revents & POLLERR) ? "POLLERR":"", ssh_buffer_get_len(s->out_buffer)); if ((revents & POLLERR) || (revents & POLLHUP)) { /* Check if we are in a connecting state */ if (s->state == SSH_SOCKET_CONNECTING) { s->state = SSH_SOCKET_ERROR; rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); if (rc < 0) { err = errno; } s->last_errno = err; ssh_socket_close(s); if (s->callbacks != NULL && s->callbacks->connected != NULL) { s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR, err, s->callbacks->userdata); } return -1; } /* Then we are in a more standard kind of error */ /* force a read to get an explanation */ revents |= POLLIN; } if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) { s->read_wontblock = 1; nread = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer)); if (nread < 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks != NULL && s->callbacks->exception != NULL) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR, s->last_errno, s->callbacks->userdata); } return -2; } if (nread == 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks != NULL && s->callbacks->exception != NULL) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF, 0, s->callbacks->userdata); } return -2; } if (s->session->socket_counter != NULL) { s->session->socket_counter->in_bytes += nread; } /* Bufferize the data and then call the callback */ rc = ssh_buffer_add_data(s->in_buffer, buffer, nread); if (rc < 0) { return -1; } if (s->callbacks != NULL && s->callbacks->data != NULL) { do { nread = s->callbacks->data(ssh_buffer_get(s->in_buffer), ssh_buffer_get_len(s->in_buffer), s->callbacks->userdata); ssh_buffer_pass_bytes(s->in_buffer, nread); } while ((nread > 0) && (s->state == SSH_SOCKET_CONNECTED)); /* p may have been freed, so don't use it * anymore in this function */ p = NULL; } } #ifdef _WIN32 if (revents & POLLOUT || revents & POLLWRNORM) { #else if (revents & POLLOUT) { #endif uint32_t len; /* First, POLLOUT is a sign we may be connected */ if (s->state == SSH_SOCKET_CONNECTING) { SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state"); s->state = SSH_SOCKET_CONNECTED; if (p != NULL) { ssh_poll_set_events(p, POLLOUT | POLLIN); } rc = ssh_socket_set_blocking(ssh_socket_get_fd(s)); if (rc < 0) { return -1; } if (s->callbacks != NULL && s->callbacks->connected != NULL) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0, s->callbacks->userdata); } return 0; } /* So, we can write data */ s->write_wontblock = 1; if (p != NULL) { ssh_poll_remove_events(p, POLLOUT); } /* If buffered data is pending, write it */ len = ssh_buffer_get_len(s->out_buffer); if (len > 0) { ssh_socket_nonblocking_flush(s); } else if (s->callbacks != NULL && s->callbacks->controlflow != NULL) { /* Otherwise advertise the upper level that write can be done */ SSH_LOG(SSH_LOG_TRACE,"sending control flow event"); s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK, s->callbacks->userdata); } /* TODO: Find a way to put back POLLOUT when buffering occurs */ } /* Return -1 if the poll handler disappeared */ if (s->poll_handle == NULL) { return -1; } return 0; } /** @internal * @brief returns the poll handle corresponding to the socket, * creates it if it does not exist. * @returns allocated and initialized ssh_poll_handle object */ ssh_poll_handle ssh_socket_get_poll_handle(ssh_socket s) { if (s->poll_handle) { return s->poll_handle; } s->poll_handle = ssh_poll_new(s->fd,0,ssh_socket_pollcallback,s); return s->poll_handle; } /** \internal * \brief Deletes a socket object */ void ssh_socket_free(ssh_socket s){ if (s == NULL) { return; } ssh_socket_close(s); ssh_buffer_free(s->in_buffer); ssh_buffer_free(s->out_buffer); SAFE_FREE(s); } #ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path) { struct sockaddr_un sunaddr; socket_t fd; sunaddr.sun_family = AF_UNIX; snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == SSH_INVALID_SOCKET) { ssh_set_error(s->session, SSH_FATAL, "Error from socket(AF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); return -1; } if (fcntl(fd, F_SETFD, 1) == -1) { ssh_set_error(s->session, SSH_FATAL, "Error from fcntl(fd, F_SETFD, 1): %s", strerror(errno)); close(fd); return -1; } if (connect(fd, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s", strerror(errno)); close(fd); return -1; } ssh_socket_set_fd(s,fd); return 0; } #endif /** \internal * \brief closes a socket */ void ssh_socket_close(ssh_socket s){ if (ssh_socket_is_open(s)) { #ifdef _WIN32 CLOSE_SOCKET(s->fd); s->last_errno = WSAGetLastError(); #else CLOSE_SOCKET(s->fd); s->last_errno = errno; #endif } if(s->poll_handle != NULL){ ssh_poll_free(s->poll_handle); s->poll_handle=NULL; } s->state = SSH_SOCKET_CLOSED; } /** * @internal * @brief sets the file descriptor of the socket. * @param[out] s ssh_socket to update * @param[in] fd file descriptor to set * @warning this function updates boths the input and output * file descriptors */ void ssh_socket_set_fd(ssh_socket s, socket_t fd) { s->fd = fd; if (s->poll_handle) { ssh_poll_set_fd(s->poll_handle,fd); } else { s->state = SSH_SOCKET_CONNECTING; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLOUT); #ifdef _WIN32 ssh_poll_add_events(ssh_socket_get_poll_handle(s), POLLWRNORM); #endif } }
/** * @brief * Open a connection with a pbs server. * Do not allow TCP to block us if Server host is down * At this point, this does not attempt to find a fail_over Server * * @param[in] server - specifies the server to which to connect * @param[in] tout - timeout value for select * * @return int * @retval >= 0 index to the internal connection table representing the * connection made. * @retval -1 error encountered in getting index */ int pbs_connect_noblk(char *server, int tout) { int out; int i; pbs_socklen_t l; int n; struct timeval tv; fd_set fdset; struct batch_reply *reply; char server_name[PBS_MAXSERVERNAME+1]; unsigned int server_port; struct addrinfo *aip, *pai; struct addrinfo hints; struct sockaddr_in *inp; short int connect_err = 0; struct sockaddr_in sockname; pbs_socklen_t socknamelen; #ifdef WIN32 int non_block = 1; struct sockaddr_in to_sock; struct sockaddr_in from_sock; #endif #ifndef WIN32 int nflg; int oflg; #endif /* initialize the thread context data, if not already initialized */ if (pbs_client_thread_init_thread_context() != 0) return -1; if (pbs_loadconf(0) == 0) return -1; /* get server host and port */ server = PBS_get_server(server, server_name, &server_port); if (server == NULL) { pbs_errno = PBSE_NOSERVER; return -1; } /* Reserve a connection state record */ if (pbs_client_thread_lock_conntable() != 0) return -1; out = -1; for (i=1;i<NCONNECTS;i++) { if (connection[i].ch_inuse) continue; out = i; connection[out].ch_inuse = 1; connection[out].ch_errno = 0; connection[out].ch_socket= -1; connection[out].ch_errtxt = NULL; break; } if (pbs_client_thread_unlock_conntable() != 0) return -1; /* pbs_errno set by the function */ if (out < 0) { pbs_errno = PBSE_NOCONNECTS; return -1; } /* get socket */ #ifdef WIN32 /* the following lousy hack is needed since the socket call needs */ /* SYSTEMROOT env variable properly set! */ if (getenv("SYSTEMROOT") == NULL) { setenv("SYSTEMROOT", "C:\\WINNT", 1); setenv("SystemRoot", "C:\\WINNT", 1); } connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0); if (connection[out].ch_socket < 0) { setenv("SYSTEMROOT", "C:\\WINDOWS", 1); setenv("SystemRoot", "C:\\WINDOWS", 1); connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0); } #else connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0); #endif if (connection[out].ch_socket < 0) { connection[out].ch_inuse = 0; pbs_errno = ERRORNO; return -1; } /* set socket non-blocking */ #ifdef WIN32 if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR) #else oflg = fcntl(connection[out].ch_socket, F_GETFL) & ~O_ACCMODE; nflg = oflg | O_NONBLOCK; if (fcntl(connection[out].ch_socket, F_SETFL, nflg) == -1) #endif goto err; /* and connect... */ strcpy(pbs_server, server); /* set for error messages from commands */ memset(&hints, 0, sizeof(struct addrinfo)); /* * Why do we use AF_UNSPEC rather than AF_INET? Some * implementations of getaddrinfo() will take an IPv6 * address and map it to an IPv4 one if we ask for AF_INET * only. We don't want that - we want only the addresses * that are genuinely, natively, IPv4 so we start with * AF_UNSPEC and filter ai_family below. */ hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (getaddrinfo(server, NULL, &hints, &pai) != 0) { CLOSESOCKET(connection[out].ch_socket); connection[out].ch_inuse = 0; pbs_errno = PBSE_BADHOST; return -1; } for (aip = pai; aip != NULL; aip = aip->ai_next) { /* skip non-IPv4 addresses */ if (aip->ai_family == AF_INET) { inp = (struct sockaddr_in *) aip->ai_addr; break; } } if (aip == NULL) { /* treat no IPv4 addresses as getaddrinfo() failure */ CLOSESOCKET(connection[out].ch_socket); connection[out].ch_inuse = 0; pbs_errno = PBSE_BADHOST; freeaddrinfo(pai); return -1; } else inp->sin_port = htons(server_port); if (connect(connection[out].ch_socket, aip->ai_addr, aip->ai_addrlen) < 0) { connect_err = 1; } if (connect_err == 1) { /* connect attempt failed */ pbs_errno = ERRORNO; switch (pbs_errno) { #ifdef WIN32 case WSAEWOULDBLOCK: #else case EINPROGRESS: case EWOULDBLOCK: #endif while (1) { FD_ZERO(&fdset); FD_SET(connection[out].ch_socket, &fdset); tv.tv_sec = tout; tv.tv_usec = 0; n = select(connection[out].ch_socket+1, NULL, &fdset, NULL, &tv); if (n > 0) { pbs_errno = 0; l = sizeof(pbs_errno); (void)getsockopt(connection[out].ch_socket, SOL_SOCKET, SO_ERROR, &pbs_errno, &l); if (pbs_errno == 0) break; else goto err; } if ((n < 0) && #ifdef WIN32 (ERRORNO == WSAEINTR) #else (ERRORNO == EINTR) #endif ) { continue; } else { goto err; } } break; default: err: CLOSESOCKET(connection[out].ch_socket); connection[out].ch_inuse = 0; freeaddrinfo(pai); return -1; /* cannot connect */ } } freeaddrinfo(pai); /* reset socket blocking */ #ifdef WIN32 non_block = 0; if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR) #else if (fcntl(connection[out].ch_socket, F_SETFL, oflg) < 0) #endif goto err; /* * multiple threads cant get the same connection id above, * so no need to lock this piece of code */ /* setup connection level thread context */ if (pbs_client_thread_init_connect_context(out) != 0) { CLOSESOCKET(connection[out].ch_socket); connection[out].ch_inuse = 0; /* pbs_errno set by the pbs_connect_init_context routine */ return -1; } /* * even though the following is communication with server on * a connection handle, it does not need to be lock since * this connection handle has not be returned back yet to the client * so others threads cannot use it */ /* send "dummy" connect message */ DIS_tcp_setup(connection[out].ch_socket); if ((i = encode_DIS_ReqHdr(connection[out].ch_socket, PBS_BATCH_Connect, pbs_current_user)) || (i = encode_DIS_ReqExtend(connection[out].ch_socket, NULL))) { pbs_errno = PBSE_SYSTEM; return -1; } if (DIS_tcp_wflush(connection[out].ch_socket)) { pbs_errno = PBSE_SYSTEM; return -1; } reply = PBSD_rdrpy(out); PBSD_FreeReply(reply); /*do configured authentication (kerberos, pbs_iff, whatever)*/ /*Get the socket port for engage_authentication()*/ socknamelen = sizeof(sockname); if (getsockname(connection[out].ch_socket, (struct sockaddr *)&sockname, &socknamelen)) return -1; if (engage_authentication(connection[out].ch_socket, server, server_port, &sockname) == -1) { CLOSESOCKET(connection[out].ch_socket); connection[out].ch_inuse = 0; pbs_errno = PBSE_PERM; return -1; } /* setup DIS support routines for following pbs_* calls */ DIS_tcp_setup(connection[out].ch_socket); pbs_tcp_timeout = PBS_DIS_TCP_TIMEOUT_VLONG; /* set for 3 hours */ return out; }
int connect_with_timeout(char *host, int port, int timeout_sec, int timeout_usec, char *account) { int res, valopt; struct sockaddr_in addr; long arg; fd_set myset; struct timeval tv; socklen_t lon; char buffer[181] = {0}; /* Base64 */ char sender[181] = {0}; char receiver[181] = {0}; int rc; // Create socket int soc = socket(AF_INET, SOCK_STREAM, 0); // Set non-blocking arg = fcntl(soc, F_GETFL, NULL); arg |= O_NONBLOCK; fcntl(soc, F_SETFL, arg); // Trying to connect with timeout addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(host); res = connect(soc, (struct sockaddr *)&addr, sizeof(addr)); if (res < 0) { if (errno == EINPROGRESS) { tv.tv_sec = timeout_sec; tv.tv_usec = timeout_usec; FD_ZERO(&myset); FD_SET(soc, &myset); if (select(soc+1, NULL, &myset, NULL, &tv) > 0) { lon = sizeof(int); getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon); if (valopt) { return -2; } } else { return -3; } } else { return -4; } } // Set to blocking mode again... arg = fcntl(soc, F_GETFL, NULL); arg &= (~O_NONBLOCK); fcntl(soc, F_SETFL, arg); rc = Base64Encode(account, sender, BUFFFERLEN); send(soc,sender,181,NULL); recv(soc, buffer, 181, NULL); rc = Base64Decode(buffer, receiver, BUFFFERLEN); printf ("Connect to server: account= %s, buffer = %s\n", account, buffer); if (strcmp(buffer,"Failed")) { return soc; } else { shutdown(soc,2); return -5; } }
static int tcpconn_async_connect(struct socket_info* send_sock, union sockaddr_union* server, char *buf, unsigned len, struct tcp_connection** c, int *ret_fd) { int fd, n; union sockaddr_union my_name; socklen_t my_name_len; struct tcp_connection* con; struct pollfd pf; unsigned int elapsed,to; int err; unsigned int err_len; int poll_err; char *ip; unsigned short port; struct timeval begin; /* create the socket */ fd = socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0); if (fd == -1){ LM_ERR("socket: (%d) %s\n", errno, strerror(errno)); return -1; } if (tcp_init_sock_opt(fd)<0){ LM_ERR("tcp_init_sock_opt failed\n"); goto error; } my_name_len = sockaddru_len(send_sock->su); memcpy( &my_name, &send_sock->su, my_name_len); su_setport( &my_name, 0); if (bind(fd, &my_name.s, my_name_len )!=0) { LM_ERR("bind failed (%d) %s\n", errno,strerror(errno)); goto error; } /* attempt to do connect and see if we do block or not */ poll_err = 0; elapsed = 0; to = hep_async_local_connect_timeout*1000; if (gettimeofday(&(begin), NULL)) { LM_ERR("Failed to get TCP connect start time\n"); goto error; } again: n = connect(fd, &server->s, sockaddru_len(*server)); if (n == -1) { if (errno == EINTR){ elapsed=get_time_diff(&begin); if (elapsed < to) goto again; else { LM_DBG("Local connect attempt failed \n"); goto async_connect; } } if (errno != EINPROGRESS && errno!=EALREADY) { get_su_info(&server->s, ip, port); LM_ERR("[server=%s:%d] (%d) %s\n",ip, port, errno,strerror(errno)); goto error; } } else goto local_connect; /* let's poll for a little */ pf.fd = fd; pf.events = POLLOUT; while(1){ elapsed = get_time_diff(&begin); if (elapsed < to) to -= elapsed; else { LM_DBG("Polling is overdue \n"); goto async_connect; } n = poll(&pf, 1, to/1000); if (n < 0){ if (errno == EINTR) continue; get_su_info(&server->s, ip, port); LM_ERR("poll/select failed:[server=%s:%d] (%d) %s\n", ip, port, errno, strerror(errno)); goto error; } else if (n==0) /* timeout */ continue; if (pf.revents & (POLLERR|POLLHUP|POLLNVAL)){ LM_ERR("poll error: flags %x\n", pf.revents); poll_err=1; } err_len=sizeof(err); getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len); if ((err==0) && (poll_err==0)) goto local_connect; if (err!=EINPROGRESS && err!=EALREADY){ get_su_info(&server->s, ip, port); LM_ERR("failed to retrieve SO_ERROR [server=%s:%d] (%d) %s\n", ip, port, err, strerror(err)); goto error; } } async_connect: LM_DBG("Create connection for async connect\n"); /* create a new dummy connection */ con = tcp_conn_create(fd, server, send_sock, S_CONN_CONNECTING); if (con==NULL) { LM_ERR("tcp_conn_create failed\n"); goto error; } /* attach the write buffer to it */ lock_get(&con->write_lock); if (add_write_chunk(con,buf,len,0) < 0) { LM_ERR("Failed to add the initial write chunk\n"); /* FIXME - seems no more SHM now ... * continue the async connect process ? */ } lock_release(&con->write_lock); /* report an async, in progress connect */ *c = con; return 0; local_connect: con = tcp_conn_create(fd, server, send_sock, S_CONN_OK); if (con==NULL) { LM_ERR("tcp_conn_create failed, closing the socket\n"); goto error; } *c = con; *ret_fd = fd; /* report a local connect */ return 1; error: close(fd); *c = NULL; return -1; }
int main(int argc, char **argv) { struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; int on = 1; socklen_t sa_size; int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif #ifdef ENCRYPTION des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */ #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #ifdef __SYMBIAN32__ if( getConnectionUp() < 0) exit(1); #endif setprogname(argv[0]); progname = *argv; #ifdef ENCRYPTION nclearto = 0; #endif #ifdef _CRAY /* * Get number of pty's before trying to process options, * which may include changing pty range. */ highpty = getnpty(); #endif /* CRAY */ if (argc == 2 && strcmp(argv[1], "--version") == 0) { #ifndef __SYMBIAN32__ print_version(NULL); #endif //__SYMBIAN32__ exit(0); } while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "otp") == 0) { auth_level = 0; require_otp = 1; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATION */ case 'B': /* BFTP mode is not supported any more */ break; case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ case 'h': hostinfo = 0; break; case 'k': /* Linemode is not supported any more */ case 'l': break; case 'n': keepalive = 0; break; #ifdef _CRAY case 'r': { char *strchr(); char *c; /* * Allow the specification of alterations * to the pty search range. It is legal to * specify only one, and not change the * other from its default. */ c = strchr(optarg, '-'); if (c) { *c++ = '\0'; highpty = atoi(c); } if (*optarg != '\0') lowpty = atoi(optarg); if ((lowpty > highpty) || (lowpty < 0) || (highpty > 32767)) { usage(); /* NOT REACHED */ } break; } #endif /* CRAY */ case 'S': #ifdef HAVE_PARSETOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; case 'u': { char *eptr; utmp_len = strtol(optarg, &eptr, 0); if (optarg == eptr) fprintf(stderr, "telnetd: unknown utmp len (%s)\n", optarg); break; } case 'U': registerd_host_only = 1; break; #ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif case 'y': no_warn = 1; break; #ifdef AUTHENTICATION case 'z': log_unauth = 1; break; #endif /* AUTHENTICATION */ case 'L': new_login = optarg; break; default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int port = 0; struct servent *sp; if (argc > 1) { usage (); } else if (argc == 1) { sp = (struct servent*)roken_getservbyname (*argv, "tcp"); if (sp) port = sp->s_port; else port = htons(atoi(*argv)); } else { #ifdef __SYMBIAN32__ port = htons(atoi("23")); #else #ifdef KRB5 port = krb5_getportbyname (NULL, "telnet", "tcp", 23); #else port = k_getportbyname("telnet", "tcp", htons(23)); #endif #endif //__SYMBIAN32__ } mini_inetd (port); } else if (argc > 0) { usage(); /* NOT REACHED */ } #ifdef _SC_CRAY_SECURE_SYS secflag = sysconf(_SC_CRAY_SECURE_SYS); /* * Get socket's security label */ if (secflag) { socklen_t szss = sizeof(ss); int sock_multi; socklen_t szi = sizeof(int); memset(&dv, 0, sizeof(dv)); if (getsysv(&sysv, sizeof(struct sysv)) != 0) fatalperror(net, "getsysv"); /* * Get socket security label and set device values * {security label to be set on ttyp device} */ #ifdef SO_SEC_MULTI /* 8.0 code */ if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, (void *)&ss, &szss) < 0) || (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, (void *)&sock_multi, &szi) < 0)) fatalperror(net, "getsockopt"); else { dv.dv_actlvl = ss.ss_actlabel.lt_level; dv.dv_actcmp = ss.ss_actlabel.lt_compart; if (!sock_multi) { dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; dv.dv_valcmp = dv.dv_actcmp; } else { dv.dv_minlvl = ss.ss_minlabel.lt_level; dv.dv_maxlvl = ss.ss_maxlabel.lt_level; dv.dv_valcmp = ss.ss_maxlabel.lt_compart; } dv.dv_devflg = 0; } #else /* SO_SEC_MULTI */ /* 7.0 code */ if (getsockopt(0, SOL_SOCKET, SO_SECURITY, (void *)&ss, &szss) >= 0) { dv.dv_actlvl = ss.ss_slevel; dv.dv_actcmp = ss.ss_compart; dv.dv_minlvl = ss.ss_minlvl; dv.dv_maxlvl = ss.ss_maxlvl; dv.dv_valcmp = ss.ss_maxcmp; } #endif /* SO_SEC_MULTI */ } #endif /* _SC_CRAY_SECURE_SYS */ roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); sa_size = sizeof (__ss); if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) { fprintf(stderr, "%s: ", progname); perror("getpeername"); _exit(1); } if (keepalive && setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof (on)) < 0) { #ifndef __SYMBIAN32__ syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); #endif ; } #if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT) { # ifdef HAVE_GETTOSBYNAME struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && sa->sa_family == AF_INET && (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = STDIN_FILENO; doit(sa, sa_size); /* NOTREACHED */ return 0; } /* end of main */
void ps_terminal_run_program(int fd_control, char *arguments) { int fd_master, pid_program, exit_status; socklen_t sizeof_credentials; struct ucred credentials; // run the program under the uid of the user that connected to the server sizeof_credentials = sizeof(credentials); if(getsockopt(fd_control, SOL_SOCKET, SO_PEERCRED, &credentials, &sizeof_credentials) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to get uid of controlling user - error [%s]"), strerror(errno)); if (ps_terminal_set_user(credentials.uid) == EXIT_FAILURE) { ps_terminal_send_exitcode(fd_control, EXIT_FAILURE); return; } // create a pseudoterminal fd_master = posix_openpt(O_RDWR | O_NOCTTY); if (fd_master == -1) ps_log(EXIT_FAILURE, LOG_ERROR("posix_openpt() failed -error [%s]"), strerror(errno)); if (grantpt(fd_master) == -1) ps_log(0 /*EXIT_FAILURE*/, LOG_ERROR("grantpt() failed - error [%s]"), strerror(errno)); if (unlockpt(fd_master) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unlockpt() failed - error [%s]"), strerror(errno)); // fork a new process to run the program pid_program=fork(); if (pid_program == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to fork - error [%s]"), strerror(errno)); if (pid_program == 0) { close(fd_control); ps_program_exec(fd_master, arguments); ps_log(EXIT_FAILURE, LOG_ERROR("trespassing error!")); } // TEST for a problem with bash. It seems that bash disables cntl-d (eof) handling // in the pseudo terminal if there is input before it outputs its prompt. This requires // us to use the exit statement in a script that is inside a here-document. The sh shell // does not have this behaviour. Needs further investigation... //sleep(1); ps_terminal_io_loop(fd_control, fd_master); if (waitpid(pid_program, &exit_status, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("waitpid failed - error [%s]"), strerror(errno)); // return status to controller ps_log(0, LOG_INFO("after wait - exit_status [%d]"), exit_status); ps_terminal_send_exitcode(fd_control, exit_status); close(fd_master); close(fd_control); }
int conn_nonb(char *ip,int port,int nsec) { int flags, n, error; //socklen_t len; fd_set rset,wset; struct timeval tval; FD_ZERO(&wset); FD_ZERO(&rset); tval.tv_sec = nsec; tval.tv_usec = 0; //struct servent *sent; int sockfd = socket(AF_INET, SOCK_STREAM, 0); flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); error = 0; if((n=connect(sockfd,(struct sockaddr *)&address,sizeof(address)))<0){ if(errno!=EINPROGRESS) { printf("Connecting error!\n"); return -1; } else if(n==0) { //This case may be happen on localhost? printf("Connecting success! \n"); return 0; } } FD_SET(sockfd,&rset); wset=rset; //usleep(10); int rst = select(sockfd + 1, &rset,&wset,NULL,&tval); switch (rst) { case -1: perror("Select error"); exit(-1); case 0: close(sockfd); //printf("Timed Out!\n"); break; default: if (FD_ISSET(sockfd,&rset)||FD_ISSET(sockfd,&wset)) { int error; socklen_t len = sizeof (error); if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0) { printf ("getsockopt fail,connected fail\n"); return -1; } if(error==0) { //printf ("%d open\n",port); return 0; } } close(sockfd); } return -1; }
void rpc_init(char *name, int prog, int vers, void (*dispatch)(), int defport) { struct sockaddr_in saddr; SVCXPRT *transp; int sock; socklen_t asize; asize = sizeof(saddr); sock = 0; if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0 && saddr.sin_family == AF_INET) { socklen_t ssize = sizeof (int); int fdtype = 0; if (getsockopt(0, SOL_SOCKET, SO_TYPE, (char *)&fdtype, &ssize) == -1) xlog(L_FATAL, "getsockopt failed: %s", strerror(errno)); /* inetd passes a UDP socket or a listening TCP socket. * listen will fail on a connected TCP socket(passed by rsh). */ if (!(fdtype == SOCK_STREAM && listen(0,5) == -1)) { _rpcfdtype = fdtype; _rpcpmstart = 1; } } if (!_rpcpmstart) { pmap_unset(prog, vers); sock = RPC_ANYSOCK; } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { static SVCXPRT *last_transp = NULL; if (_rpcpmstart == 0) { if (last_transp && (!defport || defport == last_transp->xp_port)) { transp = last_transp; goto udp_transport; } if (defport == 0) sock = RPC_ANYSOCK; else if ((sock = makesock(defport, IPPROTO_UDP)) < 0) { xlog(L_FATAL, "%s: cannot make a UDP socket\n", name); } } if (sock == RPC_ANYSOCK) sock = svcudp_socket (prog, 1); transp = svcudp_create(sock); if (transp == NULL) { xlog(L_FATAL, "cannot create udp service."); } udp_transport: if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) { xlog(L_FATAL, "unable to register (%s, %d, udp).", name, vers); } last_transp = transp; } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { static SVCXPRT *last_transp = NULL; if (_rpcpmstart == 0) { if (last_transp && (!defport || defport == last_transp->xp_port)) { transp = last_transp; goto tcp_transport; } if (defport == 0) sock = RPC_ANYSOCK; else if ((sock = makesock(defport, IPPROTO_TCP)) < 0) { xlog(L_FATAL, "%s: cannot make a TCP socket\n", name); } } if (sock == RPC_ANYSOCK) sock = svctcp_socket (prog, 1); transp = svctcp_create(sock, 0, 0); if (transp == NULL) { xlog(L_FATAL, "cannot create tcp service."); } tcp_transport: if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) { xlog(L_FATAL, "unable to register (%s, %d, tcp).", name, vers); } last_transp = transp; } if (_rpcpmstart) { signal (SIGALRM, closedown); alarm (_RPCSVC_CLOSEDOWN); } }
/* we receive a connection acknowledgement from the server, * consisting of nothing more than a status report. If success, * then we initiate authentication method */ static pmix_status_t recv_connect_ack(int sd) { pmix_status_t reply; pmix_status_t rc; struct timeval tv, save; pmix_socklen_t sz; bool sockopt = true; uint32_t u32; char nspace[PMIX_MAX_NSLEN+1]; pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT ACK FROM SERVER"); /* get the current timeout value so we can reset to it */ sz = sizeof(save); if (0 != getsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void*)&save, &sz)) { if (ENOPROTOOPT == errno) { sockopt = false; } else { return PMIX_ERR_UNREACH; } } else { /* set a timeout on the blocking recv so we don't hang */ tv.tv_sec = 2; tv.tv_usec = 0; if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) { pmix_output_verbose(2, pmix_globals.debug_output, "pmix: recv_connect_ack could not setsockopt SO_RCVTIMEO"); return PMIX_ERR_UNREACH; } } /* receive the status reply */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t)); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } reply = ntohl(u32); if (PMIX_PROC_IS_CLIENT) { /* see if they want us to do the handshake */ if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) { PMIX_PSEC_CLIENT_HANDSHAKE(rc, pmix_client_globals.myserver, sd); if (PMIX_SUCCESS != rc) { return rc; } } else if (PMIX_SUCCESS != reply) { return reply; } pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT CONFIRMATION"); /* receive our index into the server's client array */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t)); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } pmix_globals.pindex = ntohl(u32); } else { // we are a tool /* if the status indicates an error, then we are done */ if (PMIX_SUCCESS != reply) { PMIX_ERROR_LOG(reply); return reply; } /* recv our nspace */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&pmix_globals.myid.nspace, PMIX_MAX_NSLEN+1); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } /* our rank is always zero */ pmix_globals.myid.rank = 0; /* get the server's nspace and rank so we can send to it */ pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); pmix_ptl_base_recv_blocking(sd, (char*)nspace, PMIX_MAX_NSLEN+1); pmix_client_globals.myserver->nptr->nspace = strdup(nspace); pmix_client_globals.myserver->info->pname.nspace = strdup(nspace); pmix_ptl_base_recv_blocking(sd, (char*)&(pmix_client_globals.myserver->info->pname.rank), sizeof(int)); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT CONFIRMATION FOR TOOL %s:%d FROM SERVER %s:%d", pmix_globals.myid.nspace, pmix_globals.myid.rank, pmix_client_globals.myserver->info->pname.nspace, pmix_client_globals.myserver->info->pname.rank); /* get the returned status from the security handshake */ pmix_ptl_base_recv_blocking(sd, (char*)&reply, sizeof(pmix_status_t)); if (PMIX_SUCCESS != reply) { /* see if they want us to do the handshake */ if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) { PMIX_PSEC_CLIENT_HANDSHAKE(reply, pmix_client_globals.myserver, sd); if (PMIX_SUCCESS != reply) { return reply; } /* if the handshake succeeded, then fall thru to the next step */ } else { return reply; } } } if (sockopt) { if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &save, sz)) { return PMIX_ERR_UNREACH; } } return PMIX_SUCCESS; }
void *socks_connector_sel(void *p) { fd_set rset, wset; int maxfd = 0, len, so_err; SocksQueue_t *squeue, sq; time_t t; struct timeval tv; socklen_t err_len; for (;;) { if (term_req()) return NULL; FD_ZERO(&rset); FD_ZERO(&wset); MFD_SET(CNF(socksfd[0]), &rset, maxfd); t = time(NULL); for (squeue = socks_queue_; squeue; squeue = squeue->next) { switch (squeue->state) { case SOCKS_NEW: /*if (!squeue->fd) { log_msg(LOG_CRIT, "SOCKS_NEW and fd = %d, but should be 0", squeue->fd); squeue->state = SOCKS_DELETE; continue; }*/ if (t < squeue->restart_time) { log_debug("SOCKS request is scheduled for connection not before %ds", squeue->restart_time - t); continue; } // check and increase retry counter squeue->retry++; if (!squeue->perm && (squeue->retry > SOCKS_MAX_RETRY)) { log_msg(LOG_NOTICE, "temporary request failed %d times and will be removed", squeue->retry - 1); squeue->state = SOCKS_DELETE; continue; } log_debug("creating socket for unconnected SOCKS request"); if ((squeue->fd = socket(CNF(socks_dst)->sin_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0)) == -1) { log_msg(LOG_ERR, "cannot create socket for new SOCKS request: \"%s\"", strerror(errno)); continue; } set_nonblock(squeue->fd); log_debug("queueing fd %d for connect", squeue->fd); squeue->connect_time = t; if (socks_tcp_connect(squeue->fd, (struct sockaddr*) CNF(socks_dst), SOCKADDR_SIZE(CNF(socks_dst))) == -1) { socks_reschedule(squeue); continue; } squeue->state = SOCKS_CONNECTING; MFD_SET(squeue->fd, &wset, maxfd); break; case SOCKS_4AREQ_SENT: MFD_SET(squeue->fd, &rset, maxfd); break; } } // select all file descriptors set_select_timeout(&tv); log_debug("selecting (maxfd = %d)", maxfd); if ((maxfd = select(maxfd + 1, &rset, &wset, NULL, &tv)) == -1) { log_msg(LOG_EMERG, "select encountered error: \"%s\", restarting", strerror(errno)); continue; } log_debug("select returned %d", maxfd); // check socks request pipe if (FD_ISSET(CNF(socksfd[0]), &rset)) { maxfd--; if ((len = read(CNF(socksfd[0]), &sq, sizeof(sq))) == -1) log_msg(LOG_ERR, "failed to read from SOCKS request pipe, fd = %d: \"%s\"", CNF(socksfd[0]), strerror(errno)); if (len < sizeof(sq)) log_msg(LOG_ERR, "read from SOCKS request pipe truncated to %d of %d bytes, ignoring.", len, sizeof(sq)); else { log_debug("received %d bytes on SOCKS request pipe fd %d", len, CNF(socksfd[0])); if (sq.next) { log_debug("output of SOCKS request queue triggered"); socks_output_queue((FILE*) sq.next); } else if (IN6_IS_ADDR_UNSPECIFIED(&sq.addr)) { log_debug("termination request on SOCKS request queue received"); } else { log_debug("SOCKS queuing request received"); socks_enqueue(&sq); } } } // handle all other file descriptors t = time(NULL); for (squeue = socks_queue_; maxfd && squeue; squeue = squeue->next) { // check write set, this is valid after connect() if (FD_ISSET(squeue->fd, &wset)) { maxfd--; if (squeue->state == SOCKS_CONNECTING) { // test if connect() worked log_debug("check socket error"); err_len = sizeof(so_err); if (getsockopt(squeue->fd, SOL_SOCKET, SO_ERROR, &so_err, &err_len) == -1) { log_msg(LOG_ERR, "getsockopt failed: \"%s\", rescheduling request", strerror(errno)); socks_reschedule(squeue); continue; } if (so_err) { log_msg(LOG_ERR, "getsockopt returned %d (\"%s\")", so_err, strerror(so_err)); socks_reschedule(squeue); continue; } // everything seems to be ok, now check request status if (socks_send_request(squeue) == -1) { log_msg(LOG_ERR, "SOCKS request failed"); socks_reschedule(squeue); continue; } // request successfully sent, advance state machine squeue->state = SOCKS_4AREQ_SENT; } else log_debug("unknown state %d in write set", squeue->state); } // check read set, this is valid after write, i.e. receiving SOCKS response if (FD_ISSET(squeue->fd, &rset)) { maxfd--; if (squeue->state == SOCKS_4AREQ_SENT) { if (socks_rec_response(squeue) == -1) { socks_reschedule(squeue); continue; } // success log_debug("activating peer fd %d", squeue->fd); socks_activate_peer(squeue); squeue->state = SOCKS_DELETE; } else log_debug("unknown state %d in read set", squeue->state); } } // delete requests from queue which are marked for deletion for (squeue = socks_queue_; squeue; squeue = squeue->next) if (squeue->state == SOCKS_DELETE) { socks_unqueue(squeue); // restart loop squeue = socks_queue_; if (!squeue) { log_debug("last entry deleted, breaking loop"); break; } } } }
int WdtSocket::getSendBufferSize() const { int size; socklen_t sizeSize = sizeof(size); getsockopt(fd_, SOL_SOCKET, SO_SNDBUF, (void *)&size, &sizeSize); return size; }
static int sendtoxymond(char *recipient, char *message, FILE *respfd, char **respstr, int fullresponse, int timeout) { struct in_addr addr; struct sockaddr_in saddr; int sockfd; fd_set readfds; fd_set writefds; int res, isconnected, wdone, rdone; struct timeval tmo; char *msgptr = message; char *p; char *rcptip = NULL; int rcptport = 0; int connretries = SENDRETRIES; char *httpmessage = NULL; char recvbuf[32768]; int haveseenhttphdrs = 1; int respstrsz = 0; int respstrlen = 0; int result = XYMONSEND_OK; if (dontsendmessages && !respfd && !respstr) { printf("%s\n", message); return XYMONSEND_OK; } setup_transport(recipient); dbgprintf("Recipient listed as '%s'\n", recipient); if (strncmp(recipient, "http://", strlen("http://")) != 0) { /* Standard communications, directly to Xymon daemon */ rcptip = strdup(recipient); rcptport = xymondportnumber; p = strchr(rcptip, ':'); if (p) { *p = '\0'; p++; rcptport = atoi(p); } dbgprintf("Standard protocol on port %d\n", rcptport); } else { char *bufp; char *posturl = NULL; char *posthost = NULL; if (xymonproxyhost == NULL) { char *p; /* * No proxy. "recipient" is "http://host[:port]/url/for/post" * Strip off "http://", and point "posturl" to the part after the hostname. * If a portnumber is present, strip it off and update rcptport. */ rcptip = strdup(recipient+strlen("http://")); rcptport = xymondportnumber; p = strchr(rcptip, '/'); if (p) { posturl = strdup(p); *p = '\0'; } p = strchr(rcptip, ':'); if (p) { *p = '\0'; p++; rcptport = atoi(p); } posthost = strdup(rcptip); dbgprintf("HTTP protocol directly to host %s\n", posthost); } else { char *p; /* * With proxy. The full "recipient" must be in the POST request. */ rcptip = strdup(xymonproxyhost); rcptport = xymonproxyport; posturl = strdup(recipient); p = strchr(recipient + strlen("http://"), '/'); if (p) { *p = '\0'; posthost = strdup(recipient + strlen("http://")); *p = '/'; p = strchr(posthost, ':'); if (p) *p = '\0'; } dbgprintf("HTTP protocol via proxy to host %s\n", posthost); } if ((posturl == NULL) || (posthost == NULL)) { sprintf(errordetails + strlen(errordetails), "Unable to parse HTTP recipient"); if (posturl) xfree(posturl); if (posthost) xfree(posthost); if (rcptip) xfree(rcptip); return XYMONSEND_EBADURL; } bufp = msgptr = httpmessage = malloc(strlen(message)+1024); bufp += sprintf(httpmessage, "POST %s HTTP/1.0\n", posturl); bufp += sprintf(bufp, "MIME-version: 1.0\n"); bufp += sprintf(bufp, "Content-Type: application/octet-stream\n"); bufp += sprintf(bufp, "Content-Length: %d\n", strlen(message)); bufp += sprintf(bufp, "Host: %s\n", posthost); bufp += sprintf(bufp, "\n%s", message); if (posturl) xfree(posturl); if (posthost) xfree(posthost); haveseenhttphdrs = 0; dbgprintf("HTTP message is:\n%s\n", httpmessage); } if (inet_aton(rcptip, &addr) == 0) { /* recipient is not an IP - do DNS lookup */ struct hostent *hent; char hostip[IP_ADDR_STRLEN]; hent = gethostbyname(rcptip); if (hent) { memcpy(&addr, *(hent->h_addr_list), sizeof(struct in_addr)); strcpy(hostip, inet_ntoa(addr)); if (inet_aton(hostip, &addr) == 0) { result = XYMONSEND_EBADIP; goto done; } } else { sprintf(errordetails+strlen(errordetails), "Cannot determine IP address of message recipient %s", rcptip); result = XYMONSEND_EIPUNKNOWN; goto done; } } retry_connect: dbgprintf("Will connect to address %s port %d\n", rcptip, rcptport); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = addr.s_addr; saddr.sin_port = htons(rcptport); /* Get a non-blocking socket */ sockfd = socket(PF_INET, SOCK_STREAM, 0); if (sockfd == -1) { result = XYMONSEND_ENOSOCKET; goto done; } res = fcntl(sockfd, F_SETFL, O_NONBLOCK); if (res != 0) { result = XYMONSEND_ECANNOTDONONBLOCK; goto done; } res = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if ((res == -1) && (errno != EINPROGRESS)) { sprintf(errordetails+strlen(errordetails), "connect to Xymon daemon@%s:%d failed (%s)", rcptip, rcptport, strerror(errno)); result = XYMONSEND_ECONNFAILED; goto done; } rdone = ((respfd == NULL) && (respstr == NULL)); isconnected = wdone = 0; while (!wdone || !rdone) { FD_ZERO(&writefds); FD_ZERO(&readfds); if (!rdone) FD_SET(sockfd, &readfds); if (!wdone) FD_SET(sockfd, &writefds); tmo.tv_sec = timeout; tmo.tv_usec = 0; res = select(sockfd+1, &readfds, &writefds, NULL, (timeout ? &tmo : NULL)); if (res == -1) { sprintf(errordetails+strlen(errordetails), "Select failure while sending to Xymon daemon@%s:%d", rcptip, rcptport); result = XYMONSEND_ESELFAILED; goto done; } else if (res == 0) { /* Timeout! */ shutdown(sockfd, SHUT_RDWR); close(sockfd); if (!isconnected && (connretries > 0)) { dbgprintf("Timeout while talking to Xymon daemon@%s:%d - retrying\n", rcptip, rcptport); connretries--; sleep(1); goto retry_connect; /* Yuck! */ } result = XYMONSEND_ETIMEOUT; goto done; } else { if (!isconnected) { /* Havent seen our connect() status yet - must be now */ int connres; socklen_t connressize = sizeof(connres); res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &connres, &connressize); dbgprintf("Connect status is %d\n", connres); isconnected = (connres == 0); if (!isconnected) { sprintf(errordetails+strlen(errordetails), "Could not connect to Xymon daemon@%s:%d (%s)", rcptip, rcptport, strerror(connres)); result = XYMONSEND_ECONNFAILED; goto done; } } if (!rdone && FD_ISSET(sockfd, &readfds)) { char *outp; int n; n = recv(sockfd, recvbuf, sizeof(recvbuf)-1, 0); if (n > 0) { dbgprintf("Read %d bytes\n", n); recvbuf[n] = '\0'; /* * When running over a HTTP transport, we must strip * off the HTTP headers we get back, so the response * is consistent with what we get from the normal Xymon daemon * transport. * (Non-http transport sets "haveseenhttphdrs" to 1) */ if (!haveseenhttphdrs) { outp = strstr(recvbuf, "\r\n\r\n"); if (outp) { outp += 4; n -= (outp - recvbuf); haveseenhttphdrs = 1; } else n = 0; } else outp = recvbuf; if (n > 0) { if (respfd) { fwrite(outp, n, 1, respfd); } else if (respstr) { char *respend; if (respstrsz == 0) { respstrsz = (n+sizeof(recvbuf)); *respstr = (char *)malloc(respstrsz); } else if ((n+respstrlen) >= respstrsz) { respstrsz += (n+sizeof(recvbuf)); *respstr = (char *)realloc(*respstr, respstrsz); } respend = (*respstr) + respstrlen; memcpy(respend, outp, n); *(respend + n) = '\0'; respstrlen += n; } if (!fullresponse) { rdone = (strchr(outp, '\n') == NULL); } } } else rdone = 1; if (rdone) shutdown(sockfd, SHUT_RD); } if (!wdone && FD_ISSET(sockfd, &writefds)) { /* Send some data */ res = write(sockfd, msgptr, strlen(msgptr)); if (res == -1) { sprintf(errordetails+strlen(errordetails), "Write error while sending message to Xymon daemon@%s:%d", rcptip, rcptport); result = XYMONSEND_EWRITEERROR; goto done; } else { dbgprintf("Sent %d bytes\n", res); msgptr += res; wdone = (strlen(msgptr) == 0); if (wdone) shutdown(sockfd, SHUT_WR); } } } } done: dbgprintf("Closing connection\n"); shutdown(sockfd, SHUT_RDWR); close(sockfd); xfree(rcptip); if (httpmessage) xfree(httpmessage); return result; }
/* * stress_socket_server() * server writer */ static int stress_socket_server( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t pid, const pid_t ppid) { char buf[SOCKET_BUF]; int fd, status; int so_reuseaddr = 1; struct sigaction new_action; socklen_t addr_len = 0; struct sockaddr *addr; uint64_t msgs = 0; int rc = EXIT_SUCCESS; setpgid(pid, pgrp); new_action.sa_handler = handle_socket_sigalrm; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_fail_err(name, "sigaction"); rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { pr_fail_dbg(name, "socket"); rc = EXIT_FAILURE; goto die; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, opt_socket_domain, opt_socket_port, &addr, &addr_len); if (bind(fd, addr, addr_len) < 0) { pr_fail_dbg(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (listen(fd, 10) < 0) { pr_fail_dbg(name, "listen"); rc = EXIT_FAILURE; goto die_close; } do { int sfd = accept(fd, (struct sockaddr *)NULL, NULL); if (sfd >= 0) { size_t i, j; struct sockaddr addr; socklen_t len; int sndbuf; struct msghdr msg; struct iovec vec[sizeof(buf)/16]; #if defined(HAVE_SENDMMSG) struct mmsghdr msgvec[MSGVEC_SIZE]; unsigned int msg_len = 0; #endif #if defined(SOCKET_NODELAY) int one = 1; #endif len = sizeof(addr); if (getsockname(fd, &addr, &len) < 0) { pr_fail_dbg(name, "getsockname"); (void)close(sfd); break; } len = sizeof(sndbuf); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) { pr_fail_dbg(name, "getsockopt"); (void)close(sfd); break; } #if defined(SOCKET_NODELAY) if (opt_flags & OPT_FLAGS_SOCKET_NODELAY) { if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) { pr_inf(stderr, "%s: setsockopt TCP_NODELAY " "failed and disabled, errno=%d (%s)\n", name, errno, strerror(errno)); opt_flags &= ~OPT_FLAGS_SOCKET_NODELAY; } } #endif memset(buf, 'A' + (*counter % 26), sizeof(buf)); switch (opt_socket_opts) { case SOCKET_OPT_SEND: for (i = 16; i < sizeof(buf); i += 16) { ssize_t ret = send(sfd, buf, i, 0); if (ret < 0) { if (errno != EINTR) pr_fail_dbg(name, "send"); break; } else msgs++; } break; case SOCKET_OPT_SENDMSG: for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; } memset(&msg, 0, sizeof(msg)); msg.msg_iov = vec; msg.msg_iovlen = j; if (sendmsg(sfd, &msg, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmsg"); } else msgs += j; break; #if defined(HAVE_SENDMMSG) case SOCKET_OPT_SENDMMSG: memset(msgvec, 0, sizeof(msgvec)); for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; msg_len += i; } for (i = 0; i < MSGVEC_SIZE; i++) { msgvec[i].msg_hdr.msg_iov = vec; msgvec[i].msg_hdr.msg_iovlen = j; } if (sendmmsg(sfd, msgvec, MSGVEC_SIZE, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmmsg"); } else msgs += (MSGVEC_SIZE * j); break; #endif default: /* Should never happen */ pr_err(stderr, "%s: bad option %d\n", name, opt_socket_opts); (void)close(sfd); goto die_close; } if (getpeername(sfd, &addr, &len) < 0) { pr_fail_dbg(name, "getpeername"); } (void)close(sfd); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: (void)close(fd); die: #ifdef AF_UNIX if (opt_socket_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif if (pid) { (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } pr_dbg(stderr, "%s: %" PRIu64 " messages sent\n", name, msgs); return rc; }
static int CreateClientSocket( Tcl_Interp *interp, /* For error reporting; can be NULL. */ TcpState *state) { socklen_t optlen; int async_callback = (state->addr != NULL); int status; int async = state->flags & TCP_ASYNC_CONNECT; if (async_callback) { goto reenter; } for (state->addr = state->addrlist; state->addr != NULL; state->addr = state->addr->ai_next) { status = -1; for (state->myaddr = state->myaddrlist; state->myaddr != NULL; state->myaddr = state->myaddr->ai_next) { int reuseaddr; /* * No need to try combinations of local and remote addresses of * different families. */ if (state->myaddr->ai_family != state->addr->ai_family) { continue; } /* * Close the socket if it is still open from the last unsuccessful * iteration. */ if (state->fds.fd >= 0) { close(state->fds.fd); state->fds.fd = -1; } state->fds.fd = socket(state->addr->ai_family, SOCK_STREAM, 0); if (state->fds.fd < 0) { continue; } /* * Set the close-on-exec flag so that the socket will not get * inherited by child processes. */ fcntl(state->fds.fd, F_SETFD, FD_CLOEXEC); /* * Set kernel space buffering */ TclSockMinimumBuffers(INT2PTR(state->fds.fd), SOCKET_BUFSIZE); if (async) { status = TclUnixSetBlockingMode(state->fds.fd, TCL_MODE_NONBLOCKING); if (status < 0) { continue; } } reuseaddr = 1; (void) setsockopt(state->fds.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr, sizeof(reuseaddr)); status = bind(state->fds.fd, state->myaddr->ai_addr, state->myaddr->ai_addrlen); if (status < 0) { continue; } /* * Attempt to connect. The connect may fail at present with an * EINPROGRESS but at a later time it will complete. The caller * will set up a file handler on the socket if she is interested * in being informed when the connect completes. */ status = connect(state->fds.fd, state->addr->ai_addr, state->addr->ai_addrlen); if (status < 0 && errno == EINPROGRESS) { Tcl_CreateFileHandler(state->fds.fd, TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, state); return TCL_OK; reenter: Tcl_DeleteFileHandler(state->fds.fd); /* * Read the error state from the socket to see if the async * connection has succeeded or failed. As this clears the * error condition, we cache the status in the socket state * struct for later retrieval by [fconfigure -error]. */ optlen = sizeof(int); getsockopt(state->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &status, &optlen); state->status = status; } if (status == 0) { CLEAR_BITS(state->flags, TCP_ASYNC_CONNECT); goto out; } } } out: if (async_callback) { /* * An asynchonous connection has finally succeeded or failed. */ TcpWatchProc(state, state->filehandlers); TclUnixSetBlockingMode(state->fds.fd, state->cachedBlocking); /* * We need to forward the writable event that brought us here, bcasue * upon reading of getsockopt(SO_ERROR), at least some OSes clear the * writable state from the socket, and so a subsequent select() on * behalf of a script level [fileevent] would not fire. It doesn't * hurt that this is also called in the successful case and will save * the event mechanism one roundtrip through select(). */ Tcl_NotifyChannel(state->channel, TCL_WRITABLE); } else if (status != 0) { /* * Failure for either a synchronous connection, or an async one that * failed before it could enter background mode, e.g. because an * invalid -myaddr was given. */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; }
static int TcpGetOptionProc( ClientData instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to retrieve the value * for, or NULL to get all options and their * values. */ Tcl_DString *dsPtr) /* Where to store the computed value; * initialized by caller. */ { TcpState *statePtr = instanceData; size_t len = 0; if (optionName != NULL) { len = strlen(optionName); } if ((len > 1) && (optionName[1] == 'e') && (strncmp(optionName, "-error", len) == 0)) { socklen_t optlen = sizeof(int); int err, ret; if (statePtr->status == 0) { ret = getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen); if (ret < 0) { err = errno; } } else { err = statePtr->status; statePtr->status = 0; } if (err != 0) { Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(err), -1); } return TCL_OK; } if ((len == 0) || ((len > 1) && (optionName[1] == 'p') && (strncmp(optionName, "-peername", len) == 0))) { address peername; socklen_t size = sizeof(peername); if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringStartSublist(dsPtr); } TcpHostPortList(interp, dsPtr, peername, size); if (len) { return TCL_OK; } Tcl_DStringEndSublist(dsPtr); } else { /* * getpeername failed - but if we were asked for all the options * (len==0), don't flag an error at that point because it could be * an fconfigure request on a server socket (which have no peer). * Same must be done on win&mac. */ if (len) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get peername: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } } if ((len == 0) || ((len > 1) && (optionName[1] == 's') && (strncmp(optionName, "-sockname", len) == 0))) { TcpFdList *fds; address sockname; socklen_t size; int found = 0; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sockname"); Tcl_DStringStartSublist(dsPtr); } for (fds = &statePtr->fds; fds != NULL; fds = fds->next) { size = sizeof(sockname); if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) { found = 1; TcpHostPortList(interp, dsPtr, sockname, size); } } if (found) { if (len) { return TCL_OK; } Tcl_DStringEndSublist(dsPtr); } else { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get sockname: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } if (len > 0) { return Tcl_BadChannelOption(interp, optionName, "peername sockname"); } return TCL_OK; }
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout) { int arg, ret; int soopt; socklen_t solen = sizeof(int); int cnt; /* set non-blocking socket */ arg = fcntl(fdpoll->fd, F_GETFL, NULL); if (arg < 0) { uwsgi_error("fcntl()"); return -1; } arg |= O_NONBLOCK; if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) { uwsgi_error("fcntl()"); return -1; } ret = connect(fdpoll->fd, addr, addr_size); if (ret < 0) { /* check what happened */ // in progress ? if (errno == EINPROGRESS) { if (timeout < 1) timeout = 3; fdpoll->events = POLLOUT; cnt = poll(fdpoll, 1, timeout * 1000); /* check for errors */ if (cnt < 0 && errno != EINTR) { uwsgi_error("poll()"); return -1; } /* something hapened on the socket ... */ else if (cnt > 0) { if (getsockopt(fdpoll->fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) { uwsgi_error("getsockopt()"); return -1; } /* is something bad ? */ if (soopt) { return -1; } } /* timeout */ else { return -1; } } else { return -1; } } /* re-set blocking socket */ arg &= (~O_NONBLOCK); if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) { uwsgi_error("fcntl()"); return -1; } return 0; }
static void dgram_adjust_rcv_timeout(BIO *b) { #if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; int sz = sizeof(int); /* Is a timer active? */ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { struct timeval timenow, timeleft; /* Read current socket timeout */ #ifdef OPENSSL_SYS_WINDOWS int timeout; if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); } else { data->socket_timeout.tv_sec = timeout / 1000; data->socket_timeout.tv_usec = (timeout % 1000) * 1000; } #else if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), (void *)&sz) < 0) { perror("getsockopt"); } #endif /* Get current time */ get_current_time(&timenow); /* Calculate time left until timer expires */ memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); timeleft.tv_sec -= timenow.tv_sec; timeleft.tv_usec -= timenow.tv_usec; if (timeleft.tv_usec < 0) { timeleft.tv_sec--; timeleft.tv_usec += 1000000; } if (timeleft.tv_sec < 0) { timeleft.tv_sec = 0; timeleft.tv_usec = 1; } /* Adjust socket timeout if next handhake message timer * will expire earlier. */ if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) || (data->socket_timeout.tv_sec > timeleft.tv_sec) || (data->socket_timeout.tv_sec == timeleft.tv_sec && data->socket_timeout.tv_usec >= timeleft.tv_usec)) { #ifdef OPENSSL_SYS_WINDOWS timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout)) < 0) { perror("setsockopt"); } #else if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft, sizeof(struct timeval)) < 0) { perror("setsockopt"); } #endif } } #endif }