void SM_Util::check_log ( void ) { std::ifstream *inFile = new std::ifstream( sm_logPath.c_str(), std::ios::binary ); long sm_size = SM_Util::fileLen( inFile ); inFile->close(); delete inFile; /* reset log */ if( sm_size >= MAX_LOG_BYTES ) { std::ofstream outFile( sm_logPath.c_str(), std::ios::trunc | std::ios::binary ); outFile.close(); } msg_out( "\n-- SIMPLEMAN --\n\n" ); }
int auth_pwd_server(int s) { u_char buf[512]; int r, len; char user[256]; char pass[256]; struct sockaddr_storage client; char client_ip[NI_MAXHOST]; int error = 0; int code = 0; r = timerd_read(s, buf, sizeof(buf), TIMEOUTSEC, MSG_PEEK); if ( r < 2 ) { return(-1); } if (buf[0] != 0x01) { /* current username/password auth version */ /* error in version */ return(-1); } len = buf[1]; if (len < 1 || len > 255) { /* invalid username len */ return(-1); } /* read username */ r = timerd_read(s, buf, 2+len, TIMEOUTSEC, 0); if (r < 2+len) { /* read error */ return(-1); } strncpy(user, (char *)&buf[2], len); user[len] = '\0'; /* get passwd */ r = timerd_read(s, buf, sizeof(buf), TIMEOUTSEC, MSG_PEEK); if ( r < 1 ) { return(-1); } len = buf[0]; if (len < 1 || len > 255) { /* invalid password len */ return(-1); } /* read passwd */ r = timerd_read(s, buf, 1+len, TIMEOUTSEC, 0); if (r < 1+len) { /* read error */ return(-1); } strncpy(pass, (char *)&buf[1], len); pass[len] = '\0'; /* do authentication */ r = checkpasswd(user, pass); /* logging */ len = sizeof(struct sockaddr_storage); if (getpeername(s, (struct sockaddr *)&client, (socklen_t *)&len) != 0) { client_ip[0] = '\0'; } else { error = getnameinfo((struct sockaddr *)&client, len, client_ip, sizeof(client_ip), NULL, 0, NI_NUMERICHOST); if (error) { client_ip[0] = '\0'; } } msg_out(norm, "%s 5-U/P_AUTH %s %s.", client_ip, user, r == 0 ? "accepted" : "denied"); /* erace uname and passwd storage */ memset(user, 0, sizeof(user)); memset(pass, 0, sizeof(pass)); code = ( r == 0 ? 0 : -1 ); /* reply to client */ buf[0] = 0x01; /* sub negotiation version */ buf[1] = code & 0xff; /* grant or not */ r = timerd_write(s, buf, 2, TIMEOUTSEC); if (r < 2) { /* write error */ return(-1); } return(code); /* access granted or not */ }
void QNE::performTask() { msg->to_start(); IEErrorList errlist; uint32 bytes_read; IE *ie = QSPEC_IEManager::instance()->deserialize(*msg, cat_qspec_pdu, IE::protocol_v1, errlist, bytes_read, true); qspec_pdu *qspec = dynamic_cast<qspec_pdu *>(ie); //cout << *ie << "\n"; if ( qspec == NULL ) { cout << "Parsing failed." << endl; exit(1); } /* * We only support QSPEC type 12. */ if ( qspec->get_qspec_type() != 12 ) { cout << "only supporting QSPEC type 12 right now" << endl; } qspec_object *desired = qspec->get_object(ot_qos_desired); if ( ! desired ) { cout << "Incomplete QSPEC\n"; return; } // The RMF would give us that information. t_mod our_t_mod(2048000.0, 576.0, 100000.0, 40); uint32 our_latency = 1000; /* * Examine QoS Desired. */ t_mod *bw = dynamic_cast<t_mod *>( desired->get_parameter(t_mod::PARAM_ID1)); float max_t_mod_rate = bw->get_rate(); path_latency *latency = dynamic_cast<path_latency *>( desired->get_parameter(path_latency::PARAM_ID)); uint32 max_latency = latency->get_value(); /* * Examine QoS Minimum. */ qspec_object *minimum = qspec->get_object(ot_qos_desired); float min_t_mod_rate; uint32 min_latency; if ( minimum ) { t_mod *min_bw = dynamic_cast<t_mod *>( minimum->get_parameter(t_mod::PARAM_ID1)); min_t_mod_rate = min_bw->get_rate(); path_latency *min_lat = dynamic_cast<path_latency *>( minimum->get_parameter(path_latency::PARAM_ID)); min_latency = min_lat->get_value(); } else { min_t_mod_rate = max_t_mod_rate; min_latency = max_latency; } /* * Update QoS Available. */ qspec_object *available = qspec->get_object(ot_qos_available); uint32 accumulated_latency = 0; if ( available ) { t_mod *avail_bw = dynamic_cast<t_mod *>( available->get_parameter(t_mod::PARAM_ID1)); avail_bw->set_rate(min(our_t_mod.get_rate(), avail_bw->get_rate())); path_latency *avail_lat = dynamic_cast<path_latency *>( available->get_parameter(path_latency::PARAM_ID)); accumulated_latency = avail_lat->get_value() + our_latency; avail_lat->set_value(accumulated_latency); } /* * Check if we can fulfill the request. */ if ( our_t_mod.get_rate() < min_t_mod_rate ) { cout << "Not enough bandwidth to fulfill request\n"; return; } if ( accumulated_latency > max_latency ) { cout << "Can't fulfill request. Path latency too high\n"; return; } //cout << *ie << "\n"; /* * Serialize the modified QSPEC. */ NetMsg msg_out(1024); // this will contain our QSPEC uint32 bytes_written; // the number of bytes written try { qspec->serialize(msg_out, IE::protocol_v1, bytes_written); msg_out.truncate(bytes_written); } catch ( IEError err ) { std::cout << "Error: " << err.what() << "\n"; exit(1); } // Now send msg_out to the next QNE ... }
int serv_loop() { int cs, ss = 0; struct sockaddr_storage cl; fd_set readable; int i, n, len; char cl_addr[NI_MAXHOST]; char cl_name[NI_MAXHOST]; int error; pid_t pid; #ifdef USE_THREAD if (threading) { blocksignal(SIGHUP); blocksignal(SIGINT); blocksignal(SIGUSR1); } #endif for (;;) { readable = allsock; MUTEX_LOCK(mutex_select); n = select(maxsock+1, &readable, 0, 0, 0); if (n <= 0) { if (n < 0 && errno != EINTR) { msg_out(warn, "select: %m"); } MUTEX_UNLOCK(mutex_select); continue; } #ifdef USE_THREAD if ( ! threading ) { #endif /* handle any queued signal flags */ if (FD_ISSET(sig_queue[0], &readable)) { if (ioctl(sig_queue[0], FIONREAD, &i) != 0) { msg_out(crit, "ioctl: %m"); exit(-1); } while (--i >= 0) { char c; if (read(sig_queue[0], &c, 1) != 1) { msg_out(crit, "read: %m"); exit(-1); } switch(c) { case 'H': /* sighup */ reload(); break; case 'C': /* sigchld */ reapchild(); break; case 'T': /* sigterm */ cleanup(); break; default: break; } } } #ifdef USE_THREAD } #endif for ( i = 0; i < serv_sock_ind; i++ ) { if (FD_ISSET(serv_sock[i], &readable)) { n--; break; } } if ( n < 0 || i >= serv_sock_ind ) { MUTEX_UNLOCK(mutex_select); continue; } len = sizeof(struct sockaddr_storage); cs = accept(serv_sock[i], (struct sockaddr *)&cl, (socklen_t *)&len); if (cs < 0) { if (errno == EINTR #ifdef SOLARIS || errno == EPROTO #endif || errno == EWOULDBLOCK || errno == ECONNABORTED) { ; /* ignore */ } else { /* real accept error */ msg_out(warn, "accept: %m"); } MUTEX_UNLOCK(mutex_select); continue; } MUTEX_UNLOCK(mutex_select); #ifdef USE_THREAD if ( !threading ) { #endif if (max_child > 0 && cur_child >= max_child) { msg_out(warn, "child: cur %d; exeedeing max(%d)", cur_child, max_child); close(cs); continue; } #ifdef USE_THREAD } #endif error = getnameinfo((struct sockaddr *)&cl, len, cl_addr, sizeof(cl_addr), NULL, 0, NI_NUMERICHOST); if (resolv_client) { error = getnameinfo((struct sockaddr *)&cl, len, cl_name, sizeof(cl_name), NULL, 0, 0); msg_out(norm, "%s[%s] connected", cl_name, cl_addr); } else { msg_out(norm, "%s connected", cl_addr); strncpy(cl_name, cl_addr, sizeof(cl_name)); } i = validate_access(cl_addr, cl_name); if (i < 1) { /* access denied */ close(cs); continue; } set_blocking(cs); #ifdef USE_THREAD if (!threading ) { #endif blocksignal(SIGHUP); blocksignal(SIGCHLD); pid = fork(); switch (pid) { case -1: /* fork child failed */ printf("\nfork failed\n"); break; case 0: /* i am child */ for ( i = 0; i < serv_sock_ind; i++ ) { close(serv_sock[i]); } setsignal(SIGCHLD, SIG_DFL); setsignal(SIGHUP, SIG_DFL); releasesignal(SIGCHLD); releasesignal(SIGHUP); ss = proto_socks(cs); if ( ss == -1 ) { close(cs); /* may already be closed */ exit(1); } printf("\nrelaying\n"); relay(cs, ss); exit(0); default: /* may be parent */ printf("\nadding proc\n"); proclist_add(pid); break; } close(cs); releasesignal(SIGHUP); releasesignal(SIGCHLD); #ifdef USE_THREAD } else { ss = proto_socks(cs); if ( ss == -1 ) { close(cs); /* may already be closed */ continue; } relay(cs, ss); } #endif } }
void udp_relay(int cs, int ss, struct sockaddr_storage *udp) { fd_set sockfd, ctlfd; struct sockaddr_storage sender; struct timeval timeout; uint8_t buf[65535]; // BIG!! uint8_t outbuf[65535]; // BIG!! ssize_t recvlen = 0; socklen_t addrlen = 0; struct socks_udpmsg *udpmsg = NULL; int is_clientmsg = 0; int learn_client = 0; #ifdef IPHONE_OS pthread_mutex_lock(&stat_lock); stat_connections++; pthread_mutex_unlock(&stat_lock); #endif sender.ss_family = udp->ss_family; if (udp->ss_family == AF_INET6) { struct sockaddr_in6 *udp_ip6 = NULL; udp_ip6 = (struct sockaddr_in6*)udp; if (udp_ip6->sin6_port == 0) learn_client = 1; } else { struct sockaddr_in *udp_ip4 = NULL; udp_ip4 = (struct sockaddr_in*)udp; if (udp_ip4->sin_port == 0) learn_client = 1; } errno = 0; for (;;) { FD_ZERO(&ctlfd); FD_SET(cs, &ctlfd); timeout.tv_sec = 0; timeout.tv_usec = 100; if (select(cs + 1, &ctlfd, NULL, NULL, &timeout) == 1) { char c; if (recv(cs, &c, 1, MSG_PEEK | MSG_DONTWAIT) == 0) { msg_out(norm, "UDP: control channel closed\n"); break; } } FD_ZERO(&sockfd); FD_SET(ss, &sockfd); timeout.tv_sec = 0; timeout.tv_usec = 100; if (select(ss + 1, &sockfd, NULL, NULL, &timeout) == 0) continue; bzero(buf, sizeof(buf)); bzero(&sender, sizeof(struct sockaddr_storage)); if (sender.ss_family == AF_INET6) addrlen = sizeof(struct sockaddr_in6); else addrlen = sizeof(struct sockaddr_in); recvlen = recvfrom(ss, buf, sizeof(buf), 0, (struct sockaddr*)&sender, &addrlen); if (recvlen <= 0) { msg_out(warn, "UDP: recvfrom() - %s\n", strerror(errno)); break; } /* validate request - who sent it? */ udpmsg = (struct socks_udpmsg*)buf; is_clientmsg = 0; if (udpmsg->rsv == 0) { switch (udpmsg->atyp) { case S5ATIPV4: { struct sockaddr_in *udp_ip4 = (struct sockaddr_in*)udp; struct sockaddr_in *sender_ip4 = (struct sockaddr_in*)&sender; if (bcmp(&sender_ip4->sin_addr.s_addr, &udp_ip4->sin_addr.s_addr, sizeof(udp_ip4->sin_addr)) == 0) is_clientmsg = 1; } break; case S5ATIPV6: { struct sockaddr_in6 *udp_ip6 = (struct sockaddr_in6*)udp; struct sockaddr_in6 *sender_ip6 = (struct sockaddr_in6*)&sender; // if (sender_ip6->sin6_port == udp_ip6->sin6_port) if (bcmp(sender_ip6->sin6_addr.s6_addr, udp_ip6->sin6_addr.s6_addr, sizeof(udp_ip6->sin6_addr.s6_addr)) == 0) is_clientmsg = 1; } break; default: break; } } if (is_clientmsg == 1) { /* looks like our client sent it */ if (udpmsg->atyp == S5ATIPV4) { struct sockaddr_in remote; bzero(&remote, sizeof(remote)); remote.sin_addr.s_addr = udpmsg->_addr._ip4.addr; remote.sin_port = udpmsg->_addr._ip4.port; remote.sin_family = AF_INET; remote.sin_len = sizeof(remote); addrlen = sizeof(remote); if (learn_client == 1) { msg_out(norm, "UDP: client is sending on port %d\n", ntohs(((struct sockaddr_in*)&sender)->sin_port)); ((struct sockaddr_in*)udp)->sin_port = ((struct sockaddr_in*)&sender)->sin_port; learn_client = 0; } if (sendto(ss, &buf[SOCKS_UDPMSG_V4_SIZE(udpmsg)], recvlen - SOCKS_UDPMSG_V4_SIZE(udpmsg), 0, (struct sockaddr*)&remote, addrlen) < 0) { msg_out(crit, "UDP: error sending IPv4 request to server\n"); break; } } else { struct sockaddr_in6 remote; bzero(&remote, sizeof(remote)); remote.sin6_addr = udpmsg->_addr._ip6.addr; remote.sin6_port = udpmsg->_addr._ip6.port; remote.sin6_family = AF_INET6; remote.sin6_len = sizeof(remote); addrlen = sizeof(remote); if (learn_client == 1) { msg_out(norm, "UDP: client is sending on port %d\n", ntohs(((struct sockaddr_in6*)&sender)->sin6_port)); ((struct sockaddr_in6*)udp)->sin6_port = ((struct sockaddr_in6*)&sender)->sin6_port; learn_client = 0; } if (sendto(ss, &buf[SOCKS_UDPMSG_V6_SIZE(udpmsg)], recvlen - SOCKS_UDPMSG_V6_SIZE(udpmsg), 0, (struct sockaddr*)&remote, addrlen) < 0) { msg_out(crit, "UDP: error sending IPv6 request to server\n"); break; } } } else { /* possible server response */ /* TODO: Is it neccessary to distinguish IPv4/v6 ? */ bzero(&outbuf, sizeof(outbuf)); udpmsg = (struct socks_udpmsg*)outbuf; if (sender.ss_family == AF_INET6) { struct sockaddr_in6 remote; struct sockaddr_in6 *udp_ip6 = NULL; struct sockaddr_in6 *sender_ip6 = NULL; bzero(&remote, sizeof(remote)); udp_ip6 = (struct sockaddr_in6*)udp; sender_ip6 = (struct sockaddr_in6*)&sender; udpmsg->rsv = 0; udpmsg->frag = 0; udpmsg->atyp = S5ATIPV6; /* this part is unclear - do I have to use _my_ address or the original? */ udpmsg->_addr._ip6.addr = sender_ip6->sin6_addr; udpmsg->_addr._ip6.port = sender_ip6->sin6_port; memcpy(&outbuf[SOCKS_UDPMSG_V6_SIZE(udpmsg)], buf, recvlen); remote.sin6_addr = udp_ip6->sin6_addr; remote.sin6_port = udp_ip6->sin6_port; remote.sin6_family = AF_INET6; remote.sin6_len = sizeof(remote); addrlen = sizeof(remote); if (learn_client == 1) { msg_out(warn, "UDP: dropping server message - client is unknown!\n"); continue; } if (sendto(ss, outbuf, recvlen + SOCKS_UDPMSG_V6_SIZE(udpmsg), 0, (struct sockaddr*)&remote, addrlen) < 0) { msg_out(crit, "UDP: error sending IPv6 response to client\n"); break; } } else { struct sockaddr_in remote; struct sockaddr_in *udp_ip4 = NULL; struct sockaddr_in *sender_ip4 = NULL; bzero(&remote, sizeof(remote)); udp_ip4 = (struct sockaddr_in*)udp; sender_ip4 = (struct sockaddr_in*)&sender; udpmsg->rsv = 0; udpmsg->frag = 0; udpmsg->atyp = S5ATIPV4; /* this part is unclear - do I have to use _my_ address or the original? */ udpmsg->_addr._ip4.addr = sender_ip4->sin_addr.s_addr; udpmsg->_addr._ip4.addr = sender_ip4->sin_port; memcpy(&outbuf[SOCKS_UDPMSG_V4_SIZE(udpmsg)], buf, recvlen); remote.sin_addr.s_addr = udp_ip4->sin_addr.s_addr; remote.sin_port = udp_ip4->sin_port; remote.sin_family = AF_INET; remote.sin_len = sizeof(remote); addrlen = sizeof(remote); if (learn_client == 1) { msg_out(warn, "UDP: dropping server message - client is unknown!\n"); continue; } if (sendto(ss, outbuf, recvlen + SOCKS_UDPMSG_V4_SIZE(udpmsg), 0, (struct sockaddr*)&remote, addrlen) < 0) { msg_out(crit, "UDP: error sending IPv4 response to client\n"); break; } } } } close(ss); close(cs); #ifdef IPHONE_OS pthread_mutex_lock(&stat_lock); stat_connections--; pthread_mutex_unlock(&stat_lock); #endif }
WMAlphaBitmap::WMAlphaBitmap(IImage* img) { #if defined(_WIN32_WCE) IImagingFactory *pImgFactory = NULL; mWidth = 0; mHeight = 0; mImgBuf = NULL; HRESULT co_init_result = CoInitializeEx(NULL, 0/*COINIT_APARTMENTTHREADED*/); if ( (co_init_result == S_OK) || (co_init_result == S_FALSE) ) { msg_out("CoInitializeEx OK"); if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&pImgFactory))) { ImageInfo imgInfo; img->GetImageInfo(&imgInfo); mWidth = imgInfo.Width; mHeight = imgInfo.Height; IBitmapImage* pBitmap = 0; if ( SUCCEEDED(pImgFactory->CreateBitmapFromImage( img, mWidth, mHeight, PixelFormat32bppARGB, InterpolationHintDefault, &pBitmap) )) { msg_out("Create Bitmap OK"); RECT rc = { 0, 0, mWidth, mHeight}; BitmapData bitmap_data; if ( SUCCEEDED(pBitmap->LockBits( &rc, ImageLockModeRead, PixelFormatDontCare, &bitmap_data))) { // msg_out("Lock Bits OK"); void* src_buf = bitmap_data.Scan0; int stride = bitmap_data.Stride; int w = bitmap_data.Width; int h = bitmap_data.Height; mImgBuf = new unsigned int[w*h]; if (mImgBuf != 0) { msg_out("Img buffer allocated OK"); // start convert { unsigned int* dst = mImgBuf; unsigned int* src; int x; int y; for (y = 0 ; y < h; y++) { if (stride < 0) { src = (unsigned int*)(((unsigned char*)src_buf) + (h-1-y)*(-stride)); } else { src = (unsigned int*)(((unsigned char*)src_buf) + y*(stride)); } for (x = w; x > 0; x--) { *dst++ = *src++; } } } msg_out("Convert to img buffer finished OK"); // finish convert } else { err_out("Image Buffer not allocated !"); } pBitmap->UnlockBits(&bitmap_data); } else { err_out("Bitmap bits not locked !"); } pBitmap->Release(); } pImgFactory->Release(); } CoUninitialize(); } else { err_out("CoInitializeEx not initialized !"); } #endif //#if defined(_WIN32_WCE) }
void DrawingImageImpl::init(const char* path, void const *p, int size, WMBitmap* bitmap, bool useAlpha) { mID = ++ourDrawingImageID; RHO_MAP_TRACE1("DrawingImage create with ID = %d", mID); #if defined(_WIN32_WCE) IImagingFactory *pImgFactory = NULL; IImage *pImage = NULL; mWidth = 0; mHeight = 0; mBitmap = NULL; if (bitmap != NULL) { mBitmap = bitmap; mBitmap->addRef(); mWidth = bitmap->width(); mHeight = bitmap->height(); return; } HRESULT co_init_result = CoInitializeEx(NULL, 0/*COINIT_APARTMENTTHREADED*/); if ( (co_init_result == S_OK) || (co_init_result == S_FALSE) ) { msg_out("CoInitializeEx OK"); if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&pImgFactory))) { HRESULT res = 0; if (p != NULL) { // from buf res = pImgFactory->CreateImageFromBuffer( p, size, BufferDisposalFlagNone, &pImage); } else { // from file msg_out("Create Image Factory OK"); wchar_t wc_filename[2048]; mbstowcs(wc_filename, path, 2048); res = pImgFactory->CreateImageFromFile( wc_filename, &pImage); } if (SUCCEEDED(res)) { IImage* mimage = pImage; ImageInfo imgInfo; mimage->GetImageInfo(&imgInfo); mWidth = imgInfo.Width; mHeight = imgInfo.Height; RHO_MAP_TRACE2("Drawing Image was created with WIDTH = %d, HEIGHT = %d", mWidth, mHeight); mBitmap = new WMBitmap(mimage, useAlpha); mimage->Release(); } else { err_out("Image not created !"); } pImgFactory->Release(); } else { err_out("ImageFactory not created !"); } CoUninitialize(); } else { err_out("CoInitializeEx not initialized !"); } #endif //#if defined(_WIN32_WCE) }
int main(int ac, char **av) { int ch, i=0; pid_t pid; FILE *fp; uid_t uid; #ifdef USE_THREAD pthread_t tid; pthread_attr_t attr; struct rlimit rl; rlim_t max_fd = (rlim_t)MAX_FD; rlim_t save_fd = 0; #endif #ifdef USE_THREAD threading = 1; max_thread = MAX_THREAD; #endif max_child = MAX_CHILD; cur_child = 0; /* create service socket table (malloc) */ if (serv_init(NULL) < 0) { msg_out(crit, "cannot malloc: %m\n"); exit(-1); } proxy_tbl = NULL; proxy_tbl_ind = 0; method_num = 0; uid = getuid(); openlog(ident, LOG_PID | LOG_NDELAY, SYSLOGFAC); while((ch = getopt(ac, av, "a:c:i:J:m:o:p:u:frstbwgIqvh?")) != -1) switch (ch) { case 'a': if (optarg != NULL) { for (i=0; i<sizeof method_tab; optarg++) { if (*optarg == '\0') break; switch (*optarg) { case 'p': if ( uid != 0 ) { /* process does not started by root */ msg_out(warn, "uid == %d (!=0)," "user/pass auth will not work, ignored.\n", uid); break; } method_tab[i++] = S5AUSRPAS; method_num++; break; case 'n': method_tab[i++] = S5ANOAUTH; method_num++; break; default: break; } } } break; case 'b': bind_restrict = 0; break; case 'c': if (optarg != NULL) { config = strdup(optarg); } break; case 'u': if (optarg != NULL) { pwdfile = strdup(optarg); } break; case 'i': if (optarg != NULL) { if (serv_init(optarg) < 0) { msg_out(warn, "cannot init server socket(-i %s): %m\n", optarg); break; } } break; #ifdef SO_BINDTODEVICE case 'J': if (optarg != NULL) { bindtodevice = strdup(optarg); } break; #endif case 'o': if (optarg != NULL) { idle_timeout = atol(optarg); } break; case 'p': if (optarg != NULL) { pidfile = strdup(optarg); } break; case 'm': if (optarg != NULL) { #ifdef USE_THREAD max_thread = atoi(optarg); #endif max_child = atoi(optarg); } break; case 't': #ifdef USE_THREAD threading = 0; /* threading disabled. */ #endif break; case 'g': same_interface = 1; break; case 'f': fg = 1; break; case 'r': resolv_client = 1; break; case 's': forcesyslog = 1; break; case 'w': #ifdef HAVE_LIBWRAP use_tcpwrap = 1; #endif /* HAVE_LIBWRAP */ break; case 'I': inetd_mode = 1; break; case 'q': be_quiet = 1; break; case 'v': show_version(); exit(1); case 'h': case '?': default: usage(); } ac -= optind; av += optind; if ((fp = fopen(config, "r")) != NULL) { if (readconf(fp) != 0) { /* readconf error */ exit(1); } fclose(fp); } if (inetd_mode) { /* close all server socket if opened */ close_all_serv(); /* assuming that STDIN_FILENO handles bi-directional */ exit(inetd_service(STDIN_FILENO)); /* not reached */ } if (serv_sock_ind == 0) { /* no valid ifs yet */ if (serv_init(":") < 0) { /* use default */ /* fatal */ msg_out(crit, "cannot open server socket\n"); exit(1); } } #ifdef USE_THREAD if ( ! threading ) { #endif if (queue_init() != 0) { msg_out(crit, "cannot init signal queue\n"); exit(1); } #ifdef USE_THREAD } #endif /* try changing working directory */ if ( chdir(WORKDIR0) != 0 ) if ( chdir(WORKDIR1) != 0 ) msg_out(norm, "giving up chdir to workdir"); if (!fg) { /* force stdin/out/err allocate to /dev/null */ fclose(stdin); fp = fopen("/dev/null", "w+"); if (fileno(fp) != STDIN_FILENO) { msg_out(crit, "fopen: %m"); exit(1); } if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) { msg_out(crit, "dup2-1: %m"); exit(1); } if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { msg_out(crit, "dup2-2: %m"); exit(1); } switch(fork()) { case -1: msg_out(crit, "fork: %m"); exit(1); case 0: /* child */ pid = setsid(); if (pid == -1) { msg_out(crit, "setsid: %m"); exit(1); } break; default: /* parent */ exit(0); } } master_pid = getpid(); umask(S_IWGRP|S_IWOTH); if ((fp = fopen(pidfile, "w")) != NULL) { fprintf(fp, "%u\n", (unsigned)master_pid); fchown(fileno(fp), PROCUID, PROCGID); fclose(fp); } else { msg_out(warn, "cannot open pidfile %s", pidfile); } setsignal(SIGHUP, reload); setsignal(SIGINT, SIG_IGN); setsignal(SIGQUIT, SIG_IGN); setsignal(SIGILL, SIG_IGN); setsignal(SIGTRAP, SIG_IGN); setsignal(SIGABRT, SIG_IGN); #ifdef SIGEMT setsignal(SIGEMT, SIG_IGN); #endif setsignal(SIGFPE, SIG_IGN); setsignal(SIGBUS, SIG_IGN); setsignal(SIGSEGV, SIG_IGN); setsignal(SIGSYS, SIG_IGN); setsignal(SIGPIPE, SIG_IGN); setsignal(SIGALRM, SIG_IGN); setsignal(SIGTERM, cleanup); setsignal(SIGUSR1, SIG_IGN); setsignal(SIGUSR2, SIG_IGN); #ifdef SIGPOLL setsignal(SIGPOLL, SIG_IGN); #endif setsignal(SIGVTALRM, SIG_IGN); setsignal(SIGPROF, SIG_IGN); setsignal(SIGXCPU, SIG_IGN); setsignal(SIGXFSZ, SIG_IGN); #ifdef USE_THREAD if ( threading ) { if (max_thread <= 0 || max_thread > THREAD_LIMIT) { max_thread = THREAD_LIMIT; } /* resource limit is problem in threadig (e.g. Solaris:=64)*/ memset((caddr_t)&rl, 0, sizeof rl); if (getrlimit(RLIMIT_NOFILE, &rl) != 0) msg_out(warn, "getrlimit: %m"); else save_fd = rl.rlim_cur; if (rl.rlim_cur < (rlim_t)max_fd) rl.rlim_cur = max_fd; /* willing to fix to max_fd */ if ( rl.rlim_cur != save_fd ) /* if rlim_cur is changed */ if (setrlimit(RLIMIT_NOFILE, &rl) != 0) msg_out(warn, "cannot set rlimit(max_fd)"); setregid(0, PROCGID); setreuid(0, PROCUID); pthread_mutex_init(&mutex_select, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); msg_out(norm, "Starting: MAX_TH(%d)", max_thread); for (i=0; i<max_thread; i++) { if (pthread_create(&tid, &attr, (void *)&serv_loop, (void *)NULL) != 0) exit(1); } main_thread = pthread_self(); /* store main thread ID */ for (;;) { pause(); } } else { #endif setsignal(SIGCHLD, reapchild); setregid(0, PROCGID); setreuid(0, PROCUID); msg_out(norm, "Starting: MAX_CH(%d)", max_child); serv_loop(); #ifdef USE_THREAD } #endif return(0); }
int serv_loop() { SOCKS_STATE state; SOCK_INFO si; CL_INFO client; int cs; fd_set readable; int i, n, len; int error; pid_t pid; memset(&state, 0, sizeof(state)); memset(&si, 0, sizeof(si)); memset(&client, 0, sizeof(client)); state.si = &si; #ifdef USE_THREAD if (threading) { blocksignal(SIGHUP); blocksignal(SIGINT); blocksignal(SIGUSR1); } #endif for (;;) { readable = allsock; MUTEX_LOCK(mutex_select); n = select(maxsock+1, &readable, 0, 0, 0); if (n <= 0) { if (n < 0 && errno != EINTR) { msg_out(warn, "select: %m"); } MUTEX_UNLOCK(mutex_select); continue; } #ifdef USE_THREAD if ( ! threading ) { #endif /* handle any queued signal flags */ if (FD_ISSET(sig_queue[0], &readable)) { if (ioctl(sig_queue[0], FIONREAD, &i) != 0) { msg_out(crit, "ioctl: %m"); exit(-1); } while (--i >= 0) { char c; if (read(sig_queue[0], &c, 1) != 1) { msg_out(crit, "read: %m"); exit(-1); } switch(c) { case 'H': /* sighup */ reload(); break; case 'C': /* sigchld */ reapchild(); break; case 'T': /* sigterm */ cleanup(); break; default: break; } } } #ifdef USE_THREAD } #endif for ( i = 0; i < serv_sock_ind; i++ ) { if (FD_ISSET(serv_sock[i], &readable)) { n--; break; } } if ( n < 0 || i >= serv_sock_ind ) { MUTEX_UNLOCK(mutex_select); continue; } len = SS_LEN; cs = accept(serv_sock[i], &si.prc.addr.sa, (socklen_t *)&len); si.prc.len = len; if (cs < 0) { if (errno == EINTR #ifdef SOLARIS || errno == EPROTO #endif || errno == EWOULDBLOCK || errno == ECONNABORTED) { ; /* ignore */ } else { /* real accept error */ msg_out(warn, "accept: %m"); } MUTEX_UNLOCK(mutex_select); continue; } MUTEX_UNLOCK(mutex_select); #ifdef USE_THREAD if ( !threading ) { #endif if (max_child > 0 && cur_child >= max_child) { msg_out(warn, "child: cur %d; exeedeing max(%d)", cur_child, max_child); close(cs); continue; } #ifdef USE_THREAD } #endif /* get downstream-side socket name */ len = SS_LEN; getsockname(cs, &si.myc.addr.sa, (socklen_t *)&len); si.myc.len = len; error = getnameinfo(&si.prc.addr.sa, si.prc.len, client.addr, sizeof(client.addr), NULL, 0, NI_NUMERICHOST); if (resolv_client) { error = getnameinfo(&si.prc.addr.sa, si.prc.len, client.name, sizeof(client.name), NULL, 0, 0); msg_out(norm, "%s[%s] connected", client.name, client.addr); } else { msg_out(norm, "%s connected", client.addr); strncpy(client.name, client.addr, sizeof(client.name)); } i = validate_access(&client); if (i < 1) { /* access denied */ close(cs); continue; } set_blocking(cs); state.s = cs; #ifdef USE_THREAD if (!threading ) { #endif blocksignal(SIGHUP); blocksignal(SIGCHLD); pid = fork(); switch (pid) { case -1: /* fork child failed */ break; case 0: /* i am child */ for ( i = 0; i < serv_sock_ind; i++ ) { close(serv_sock[i]); } setsignal(SIGCHLD, SIG_DFL); setsignal(SIGHUP, SIG_DFL); releasesignal(SIGCHLD); releasesignal(SIGHUP); error = proto_socks(&state); if ( error == -1 ) { close(state.s); /* may already be closed */ exit(1); } relay(&state); exit(0); default: /* may be parent */ proclist_add(pid); break; } close(state.s); releasesignal(SIGHUP); releasesignal(SIGCHLD); #ifdef USE_THREAD } else { error = proto_socks(&state); if ( error == -1 ) { close(state.s); /* may already be closed */ /* udp may be dynamically allocated */ if (state.sr.udp != NULL) free(state.sr.udp); continue; } relay(&state); } #endif } }