Ejemplo n.º 1
0
void run(int argc, char **argv){
	ready_list_t ready_list;
	ready_list_t ready_list_2;
	ready_list_t::iterator it;
	const Fdevents::events_t *events;
	Server serv(ssdb);

	Fdevents select;
	select.set(serv_link->fd(), FDEVENT_IN, 0, serv_link);
	select.set(serv.reader->fd(), FDEVENT_IN, 0, serv.reader);
	select.set(serv.writer->fd(), FDEVENT_IN, 0, serv.writer);
	
	int link_count = 0;
	while(!quit){
		bool write_pending = false;
		ready_list.clear();
		ready_list_2.clear();
		
		if(write_pending || !ready_list.empty()){
			// give links that are not in ready_list a chance
			events = select.wait(0);
		}else{
			events = select.wait(50);
		}
		if(events == NULL){
			log_fatal("events.wait error: %s", strerror(errno));
			break;
		}
		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			if(fde->data.ptr == serv_link){
				Link *link = serv_link->accept();
				if(link == NULL){
					log_error("accept fail!");
					continue;
				}
				link_count ++;
				log_info("new link from %s:%d, fd: %d, link_count: %d",
					link->remote_ip, link->remote_port, link->fd(), link_count);
				
				link->nodelay();
				link->noblock();
				link->create_time = millitime();
				link->active_time = link->create_time;
				select.set(link->fd(), FDEVENT_IN, 1, link);
			}else if(fde->data.ptr == serv.reader || fde->data.ptr == serv.writer){
				WorkerPool<Server::ProcWorker, ProcJob> *worker = (WorkerPool<Server::ProcWorker, ProcJob> *)fde->data.ptr;
				ProcJob job;
				if(worker->pop(&job) == 0){
					log_fatal("reading result from workers error!");
					exit(0);
				}
				if(proc_result(job, select, ready_list_2) == PROC_ERROR){
					link_count --;
				}
			}else{
				Link *link = (Link *)fde->data.ptr;
				// 不能同时监听读和写事件, 只能监听其中一个
				if(fde->events & FDEVENT_ERR){
					log_info("fd: %d error, delete link", link->fd());
					link_count --;
					select.del(link->fd());
					delete link;
				}else if(fde->events & FDEVENT_IN){
					int len = link->read();
					//log_trace("fd: %d read: %d", link->fd(), len);
					if(len <= 0){
						log_info("fd: %d, read: %d, delete link", link->fd(), len);
						link_count --;
						select.del(link->fd());
						delete link;
					}else{
						ready_list.push_back(link);
					}
				}else if(fde->events & FDEVENT_OUT){
					int len = link->write();
					//log_trace("fd: %d write: %d", link->fd(), len);
					if(len <= 0){
						log_info("fd: %d, write: %d, delete link", link->fd(), len);
						link_count --;
						select.del(link->fd());
						delete link;
					}else if(link->output->empty()){
						//log_trace("delete %d from select.out", link->fd());
						select.clr(link->fd(), FDEVENT_OUT);
						if(!link->input->empty()){
							ready_list.push_back(link);
						}else{
							//log_trace("add %d to select.in", link->fd());
							select.set(link->fd(), FDEVENT_IN, 1, link);
						}
					}else{
						write_pending = true;
					}
				}
			}
		}

		for(it = ready_list.begin(); it != ready_list.end(); it ++){
			Link *link = *it;

			const Request *req = link->recv();
			if(req == NULL){
				log_warn("fd: %d, link parse error, delete link", link->fd());
				link_count --;
				select.del(link->fd());
				delete link;
				continue;
			}
			if(req->empty()){
				if(!select.isset(link->fd(), FDEVENT_IN)){
					//log_trace("add %d to select.in", link->fd());
					select.set(link->fd(), FDEVENT_IN, 1, link);
				}
				continue;
			}
			
			link->active_time = millitime();

			ProcJob job;
			job.link = link;
			serv.proc(&job);
			if(job.result == PROC_THREAD){
				select.del(link->fd());
				continue;
			}
			if(job.result == PROC_BACKEND){
				select.del(link->fd());
				link_count --;
				continue;
			}
			
			if(proc_result(job, select, ready_list_2) == PROC_ERROR){
				link_count --;
			}
		} // end foreach ready link
		ready_list.swap(ready_list_2);
	}
}
Ejemplo n.º 2
0
int TcpClient::ProcessHeader(bool eof)
{
    // search for the length/body separator, ':'
    char* body = 0;
    char* header = buffer_;
    char* end = buffer_ + bufferLength_;
    for (char* current = buffer_; current < end; current++)
    {
        if (*current == ':')
        {
            body = current + 1;
            break;
        }
    }

    // If we haven't gotten the entire header yet, return (keep reading)
    if (body == 0)
    {
        // EOF in the middle of a request is an error, otherwise its ok
        if (eof)
        {
            log_warn("EOF while reading header");
            return HEADER_FAULT;
        }
        return HEADER_INCOMPLETE;  // Keep reading
    }

    // check for comma separator
    if (commaExpected_)
    {
        if (*header != ',')
        {
            log_warn("Expected comma to separate messages");
            log_warn("bufferLength=" << bufferLength_ << ", buffer=" << buffer_);
            return HEADER_FAULT;
        }
        header++;
    }

    contentLength_ = atoi(header);
    if (contentLength_ <= 0)
    {
        log_warn("Invalid string length specified " << contentLength_);
        log_warn("bufferLength=" << bufferLength_ << ", buffer=" << buffer_);
        return HEADER_FAULT;
    }

    int bufferSpaceAvail = buffer_ + MaxBufferLength - body;
    contentAvail_ = end - body;

    if (contentLength_ > MaxContentLength)
    {
        log_warn("String length too large=" << contentLength_ << ", max allowed=" << MaxContentLength);
        return HEADER_FAULT;
    }
    if (contentLength_ > bufferSpaceAvail)
    {
        // try to malloc the buffer space needed
        response_ = static_cast<char*>(malloc(contentLength_+1));
        if (response_ == 0)
        {
            log_warn("Could not allocate space=" << contentLength_);
            return HEADER_FAULT;
        }
        // copy the content that was already read to the new space
        memcpy(response_,body,contentAvail_);
        responseAllocated_ = true;
    }
    else
    {
        responseAllocated_ = false;
        response_ = body;
    }
    response_[contentAvail_] = 0;
    log_info("specified content length is " << contentLength_);

    // a comma is expected to separate the next message
    commaExpected_ = true;

    return HEADER_COMPLETE;
}
Ejemplo n.º 3
0
/** Perform the final (client-side) step of a circuit-creation handshake of
 * type <b>type</b>, using our state in <b>handshake_state</b> and the
 * server's response in <b>reply</b>. On success, generate <b>keys_out_len</b>
 * bytes worth of key material in <b>keys_out_len</b>, set
 * <b>rend_authenticator_out</b> to the "KH" field that can be used to
 * establish introduction points at this hop, and return 0. On failure,
 * return -1, and set *msg_out to an error message if this is worth
 * complaining to the usre about. */
int
onion_skin_client_handshake(int type,
                      const onion_handshake_state_t *handshake_state,
                      const uint8_t *reply, size_t reply_len,
                      uint8_t *keys_out, size_t keys_out_len,
                      uint8_t *rend_authenticator_out,
                      const char **msg_out)
{
  if (handshake_state->tag != type)
    return -1;

  switch (type) {
  case ONION_HANDSHAKE_TYPE_TAP:
    if (reply_len != TAP_ONIONSKIN_REPLY_LEN) {
      if (msg_out)
        *msg_out = "TAP reply was not of the correct length.";
      return -1;
    }
    if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
                                        (const char*)reply,
                                        (char *)keys_out, keys_out_len,
                                        msg_out) < 0)
      return -1;

    memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN);

    return 0;
  case ONION_HANDSHAKE_TYPE_FAST:
    if (reply_len != CREATED_FAST_LEN) {
      if (msg_out)
        *msg_out = "TAP reply was not of the correct length.";
      return -1;
    }
    if (fast_client_handshake(handshake_state->u.fast, reply,
                              keys_out, keys_out_len, msg_out) < 0)
      return -1;

    memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN);
    return 0;
  case ONION_HANDSHAKE_TYPE_NTOR:
    if (reply_len < NTOR_REPLY_LEN) {
      if (msg_out)
        *msg_out = "ntor reply was not of the correct length.";
      return -1;
    }
    {
      size_t keys_tmp_len = keys_out_len + DIGEST_LEN;
      uint8_t *keys_tmp = tor_malloc(keys_tmp_len);
      if (onion_skin_ntor_client_handshake(handshake_state->u.ntor,
                                        reply,
                                        keys_tmp, keys_tmp_len, msg_out) < 0) {
        tor_free(keys_tmp);
        return -1;
      }
      memcpy(keys_out, keys_tmp, keys_out_len);
      memcpy(rend_authenticator_out, keys_tmp + keys_out_len, DIGEST_LEN);
      memwipe(keys_tmp, 0, keys_tmp_len);
      tor_free(keys_tmp);
    }
    return 0;
  default:
    log_warn(LD_BUG, "called with unknown handshake state type %d", type);
    tor_fragile_assert();
    return -1;
  }
}
Ejemplo n.º 4
0
void NetworkServer::serve(){
	writer = new ProcWorkerPool("writer");
	writer->start(WRITER_THREADS);
	reader = new ProcWorkerPool("reader");
	reader->start(READER_THREADS);

	ready_list_t ready_list;
	ready_list_t ready_list_2;
	ready_list_t::iterator it;
	const Fdevents::events_t *events;

	fdes->set(serv_link->fd(), FDEVENT_IN, 0, serv_link);
	fdes->set(this->reader->fd(), FDEVENT_IN, 0, this->reader);
	fdes->set(this->writer->fd(), FDEVENT_IN, 0, this->writer);
	
	uint32_t last_ticks = g_ticks;
	
	while(!quit){
		// status report
		if((uint32_t)(g_ticks - last_ticks) >= STATUS_REPORT_TICKS){
			last_ticks = g_ticks;
			log_info("server running, links: %d", this->link_count);
		}
		
		ready_list.swap(ready_list_2);
		ready_list_2.clear();
		
		if(!ready_list.empty()){
			// ready_list not empty, so we should return immediately
			events = fdes->wait(0);
		}else{
			events = fdes->wait(50);
		}
		if(events == NULL){
			log_fatal("events.wait error: %s", strerror(errno));
			break;
		}
		
		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			if(fde->data.ptr == serv_link){
				Link *link = accept_link();
				if(link){
					this->link_count ++;				
					log_debug("new link from %s:%d, fd: %d, links: %d",
						link->remote_ip, link->remote_port, link->fd(), this->link_count);
					fdes->set(link->fd(), FDEVENT_IN, 1, link);
				}
			}else if(fde->data.ptr == this->reader || fde->data.ptr == this->writer){
				ProcWorkerPool *worker = (ProcWorkerPool *)fde->data.ptr;
				ProcJob job;
				if(worker->pop(&job) == 0){
					log_fatal("reading result from workers error!");
					exit(0);
				}
				if(proc_result(&job, &ready_list) == PROC_ERROR){
					//
                }
			}else{
				proc_client_event(fde, &ready_list);
			}
		}

		for(it = ready_list.begin(); it != ready_list.end(); it ++){
			Link *link = *it;
			if(link->error()){
                destroy_link(link);
				continue;
			}

			const Request *req = link->recv();
			if(req == NULL){
				log_warn("fd: %d, link parse error, delete link", link->fd());
                destroy_link(link);
				continue;
			}
			if(req->empty()){
				link->unRef();
				fdes->set(link->fd(), FDEVENT_IN, 1, link);
				log_debug("serve parse incomplete request, remote_ip: %s ref: %d", link->remote_ip, link->ref_count);
				continue;
			}
			
			link->active_time = millitime();
            //FIXME
			char remote_ip_port[32];
		    snprintf(remote_ip_port, 32, "%s:%d", link->remote_ip, link->remote_port);
			this->active_links.add(remote_ip_port,(int64_t)link->active_time);

			ProcJob job;
			job.link = link;
			this->proc(&job);
			if(job.result == PROC_THREAD){
				fdes->del(link->fd());
				continue;
			}
			if(job.result == PROC_BACKEND){
				fdes->del(link->fd());
				this->link_count --;
                char remote_ip_port[32];
                snprintf(remote_ip_port, 32, "%s:%d", link->remote_ip, link->remote_port);
                this->link_map.erase(remote_ip_port);
                this->active_links.del(remote_ip_port);
                // don't delete link
				continue;
			}
			
			if(proc_result(&job, &ready_list_2) == PROC_ERROR){
				//
            }
		} // end foreach ready link

        //every event loop
        destroy_idle_link();
	}
}
Ejemplo n.º 5
0
/** daemonize, drop user priviliges and chroot if needed */
static void
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
	const char** cfgfile)
{
#ifdef HAVE_GETPWNAM
	struct passwd *pwd = NULL;
	uid_t uid;
	gid_t gid;
	/* initialize, but not to 0 (root) */
	memset(&uid, 112, sizeof(uid));
	memset(&gid, 112, sizeof(gid));
	log_assert(cfg);

	if(cfg->username && cfg->username[0]) {
		if((pwd = getpwnam(cfg->username)) == NULL)
			fatal_exit("user '%s' does not exist.", cfg->username);
		uid = pwd->pw_uid;
		gid = pwd->pw_gid;
		/* endpwent below, in case we need pwd for setusercontext */
	}
#endif

	/* init syslog (as root) if needed, before daemonize, otherwise
	 * a fork error could not be printed since daemonize closed stderr.*/
	if(cfg->use_syslog) {
		log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
	}
	/* if using a logfile, we cannot open it because the logfile would
	 * be created with the wrong permissions, we cannot chown it because
	 * we cannot chown system logfiles, so we do not open at all.
	 * So, using a logfile, the user does not see errors unless -d is
	 * given to unbound on the commandline. */

	/* read ssl keys while superuser and outside chroot */
#ifdef HAVE_SSL
	if(!(daemon->rc = daemon_remote_create(cfg)))
		fatal_exit("could not set up remote-control");
	if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
		if(!(daemon->listen_sslctx = listen_sslctx_create(
			cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
			fatal_exit("could not set up listen SSL_CTX");
	}
	if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
		fatal_exit("could not set up connect SSL_CTX");
#endif

#ifdef HAVE_KILL
	/* check old pid file before forking */
	if(cfg->pidfile && cfg->pidfile[0]) {
		/* calculate position of pidfile */
		if(cfg->pidfile[0] == '/')
			daemon->pidfile = strdup(cfg->pidfile);
		else	daemon->pidfile = fname_after_chroot(cfg->pidfile, 
				cfg, 1);
		if(!daemon->pidfile)
			fatal_exit("pidfile alloc: out of memory");
		checkoldpid(daemon->pidfile,
			/* true if pidfile is inside chrootdir, or nochroot */
			!(cfg->chrootdir && cfg->chrootdir[0]) ||
			(cfg->chrootdir && cfg->chrootdir[0] &&
			strncmp(daemon->pidfile, cfg->chrootdir,
				strlen(cfg->chrootdir))==0));
	}
#endif

	/* daemonize because pid is needed by the writepid func */
	if(!debug_mode && cfg->do_daemonize) {
		detach();
	}

	/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
	if(cfg->pidfile && cfg->pidfile[0]) {
		writepid(daemon->pidfile, getpid());
		if(!(cfg->chrootdir && cfg->chrootdir[0]) || 
			(cfg->chrootdir && cfg->chrootdir[0] && 
			strncmp(daemon->pidfile, cfg->chrootdir, 
			strlen(cfg->chrootdir))==0)) {
			/* delete of pidfile could potentially work,
			 * chown to get permissions */
			if(cfg->username && cfg->username[0]) {
			  if(chown(daemon->pidfile, uid, gid) == -1) {
				log_err("cannot chown %u.%u %s: %s",
					(unsigned)uid, (unsigned)gid,
					daemon->pidfile, strerror(errno));
			  }
			}
		}
	}
#else
	(void)daemon;
#endif

	/* Set user context */
#ifdef HAVE_GETPWNAM
	if(cfg->username && cfg->username[0]) {
#ifdef HAVE_SETUSERCONTEXT
		/* setusercontext does initgroups, setuid, setgid, and
		 * also resource limits from login config, but we
		 * still call setresuid, setresgid to be sure to set all uid*/
		if(setusercontext(NULL, pwd, uid, (unsigned)
			LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
			log_warn("unable to setusercontext %s: %s",
				cfg->username, strerror(errno));
#endif /* HAVE_SETUSERCONTEXT */
	}
#endif /* HAVE_GETPWNAM */

	/* box into the chroot */
#ifdef HAVE_CHROOT
	if(cfg->chrootdir && cfg->chrootdir[0]) {
		if(chdir(cfg->chrootdir)) {
			fatal_exit("unable to chdir to chroot %s: %s",
				cfg->chrootdir, strerror(errno));
		}
		verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir);
		if(chroot(cfg->chrootdir))
			fatal_exit("unable to chroot to %s: %s", 
				cfg->chrootdir, strerror(errno));
		if(chdir("/"))
			fatal_exit("unable to chdir to / in chroot %s: %s",
				cfg->chrootdir, strerror(errno));
		verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir);
		if(strncmp(*cfgfile, cfg->chrootdir, 
			strlen(cfg->chrootdir)) == 0) 
			(*cfgfile) += strlen(cfg->chrootdir);

		/* adjust stored pidfile for chroot */
		if(daemon->pidfile && daemon->pidfile[0] && 
			strncmp(daemon->pidfile, cfg->chrootdir,
			strlen(cfg->chrootdir))==0) {
			char* old = daemon->pidfile;
			daemon->pidfile = strdup(old+strlen(cfg->chrootdir));
			free(old);
			if(!daemon->pidfile)
				log_err("out of memory in pidfile adjust");
		}
		daemon->chroot = strdup(cfg->chrootdir);
		if(!daemon->chroot)
			log_err("out of memory in daemon chroot dir storage");
	}
#else
	(void)cfgfile;
#endif
	/* change to working directory inside chroot */
	if(cfg->directory && cfg->directory[0]) {
		char* dir = cfg->directory;
		if(cfg->chrootdir && cfg->chrootdir[0] &&
			strncmp(dir, cfg->chrootdir, 
			strlen(cfg->chrootdir)) == 0)
			dir += strlen(cfg->chrootdir);
		if(dir[0]) {
			if(chdir(dir)) {
				fatal_exit("Could not chdir to %s: %s",
					dir, strerror(errno));
			}
			verbose(VERB_QUERY, "chdir to %s", dir);
		}
	}

	/* drop permissions after chroot, getpwnam, pidfile, syslog done*/
#ifdef HAVE_GETPWNAM
	if(cfg->username && cfg->username[0]) {
#  ifdef HAVE_INITGROUPS
		if(initgroups(cfg->username, gid) != 0)
			log_warn("unable to initgroups %s: %s",
				cfg->username, strerror(errno));
#  endif /* HAVE_INITGROUPS */
		endpwent();

#ifdef HAVE_SETRESGID
		if(setresgid(gid,gid,gid) != 0)
#elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
		if(setregid(gid,gid) != 0)
#else /* use setgid */
		if(setgid(gid) != 0)
#endif /* HAVE_SETRESGID */
			fatal_exit("unable to set group id of %s: %s", 
				cfg->username, strerror(errno));
#ifdef HAVE_SETRESUID
		if(setresuid(uid,uid,uid) != 0)
#elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
		if(setreuid(uid,uid) != 0)
#else /* use setuid */
		if(setuid(uid) != 0)
#endif /* HAVE_SETRESUID */
			fatal_exit("unable to set user id of %s: %s", 
				cfg->username, strerror(errno));
		verbose(VERB_QUERY, "drop user privileges, run as %s", 
			cfg->username);
	}
#endif /* HAVE_GETPWNAM */
	/* file logging inited after chroot,chdir,setuid is done so that 
	 * it would succeed on SIGHUP as well */
	if(!cfg->use_syslog)
		log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
}
Ejemplo n.º 6
0
void
tw_master_cycle(struct env_master* env)
{   
    int         sigio;
    sigset_t           set;
    struct itimerval   itv;
    unsigned int       live;

	// msec: 1/1000 sec
    unsigned int       delay;
	int i, r;
	struct timeval tv;
   

	nc_process_role = NC_PROCESS_MASTER;
	nc_setproctitle("master");

    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);
    //reconfigure
    sigaddset(&set, SIGHUP);  
    // noaccept
    sigaddset(&set, SIGWINCH);
	
    sigaddset(&set, SIGTERM);
    sigaddset(&set, SIGQUIT);
	
    //sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
    //sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));


    // block above singalling
    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
        log_error("sigprocmask() failed %s", strerror(errno));
    }
    sigemptyset(&set);

    nc_start_worker_processes(env);

    // master
    //delay = 1000;
	delay = 1; // 1ms
    sigio = 0;
    live = 1;
	nc_reload_start = 0;

    for ( ;; ) {
        // no singal, alarm event
        if (nc_sigalarm) {	 
        	sigio = 0;
		   	// like slow start
            // delay *= 2;			
            nc_sigalarm= 0;
			
			rebuild_fdset();
			tv.tv_sec = 0;
			tv.tv_usec = 0;
			//log_error("tyson, %d", fds_width);
			r = select(fds_width, &rdfs, NULL, NULL, &tv);
			if (r) {
				for (i = 0; i < fds_width; i++) {
					if (FD_ISSET(i, &rdfs)){
						nc_read_channel(i, &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
					}	
				}
			}
			
			/*
			for (i = 0; i < nc_last_process; i++) {
				if (nc_processes[i].pid == -1 || nc_processes[i].pid == 0){
					continue;
				}

				
				//log_debug(LOG_ERR, "tyson here");
				nc_read_channel(nc_processes[0].channel_back[0], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
				//nc_read_channel(nc_processes[i].channel[1], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
			}*/

			
			if (nc_reload_start && !nc_cnt_reload) {
				nc_reload_start = 0;
				nc_cnt_reload = NC_CNT_RELOAD_MAGIC;
			}
         }

        log_debug("termination cycle: %d", delay);

        itv.it_interval.tv_sec = 0;
        itv.it_interval.tv_usec = 0;
        itv.it_value.tv_sec = delay / 1000;
        itv.it_value.tv_usec = (delay % 1000 ) * 1000;
	    // produce SIGALARM
        if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
        	log_debug("setitimer() failed %s", strerror(errno));
        }
	
        //log_debug("sigsuspend");
        sigsuspend(&set);
		// wake up this place
        log_debug("wake up, sigio %d", sigio);
    	 
        if (nc_reap) {
            nc_reap = 0;
            log_warn("reap children");
			
            live = nc_reap_children();
        }
	 
		// best effort, send signal via channel before death
        // if (!live && (nc_terminate || nc_quit)) {
		if (nc_terminate) {
			nc_term_children();
			sleep(1);
            nc_master_post_run(env);
	     	exit(1);
        }
		
        if (nc_terminate) {
            if (delay == 0) {
                delay = 50;
            }

            if (sigio) {
                sigio--;
                continue;
            }

            sigio = env->worker_processes;
	        // kill -9
            if (delay > 2000) {		
                nc_signal_worker_processes(SIGKILL);
            } else {
                nc_signal_worker_processes(SIGTERM);
            }

            continue;
        }

		// graceful shutdown
        if (nc_quit) {
            nc_signal_worker_processes(SIGQUIT);                 
			/*
            ls = cycle->listening.elts;
            for (n = 0; n < cycle->listening.nelts; n++) {
                if (ngx_close_socket(ls[n].fd) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
                                  ngx_close_socket_n " %V failed",
                                  &ls[n].addr_text);
                }
            }
            cycle->listening.nelts = 0;
            */

            continue;
        }

		// todo
		/*
        if (nc_restart) {
            nc_restart = 0;
            nc_start_worker_processes(env);
            live = 1;
        }
		*/
#ifdef GRACEFUL
		if (nc_reload && !nc_reload_start) {
			nc_reload = 0;  
			nc_reload_start = 1;
			nc_cnt_reload = NC_CNT_RELOAD_MAGIC;
			//reset after all worker processes reload done
			nc_signal_worker_processes(SIGHUP);
			continue;
		} else if (nc_reload) {
			log_debug(LOG_ERR, "deny reload request due to reason: still in reconfiguation status %d", nc_reload_start);
		}
#endif

    }
}
Ejemplo n.º 7
0
int MRtmpHandshake::handshake_with_client(MTcpSocket & skt)
{
    int ret = ERROR_SUCCESS;

    int c0c1Size = C0_SIZE + C1_SIZE;
    char* c0c1 = new char[c0c1Size];
    mAutoFreeArray(char, c0c1);

    if ((ret = skt.readFully(c0c1, c0c1Size)) <= 0) {
        log_warn("read c0c1 failed. ret=%d", ret);
        return ret;
    }
    log_verbose("read c0c1 success.");

    bool encrypted = false;
    bool FP9HandShake = false;
    int type = c0c1[0];
    if (type == 3) {
        encrypted = false;
    } else if (type == 6 || type == 8){
        encrypted = true;
        FP9HandShake = true;
        /* use FP10 if client is capable */
        if (c0c1[5] == 128) {
            type = 8;
        }
    } else {
        ret = ERROR_RTMP_PLAIN_REQUIRED;
        log_warn("only support rtmp plain text. ret=%d", ret);
        return ret;
    }

    //if c1[4] is not 0,use complex handshake
    if (!FP9HandShake && c0c1[5]) {
        FP9HandShake = true;
    }

    log_verbose("check c0 success, required plain text.");
    if (FP9HandShake) {
        // use complex handshake
        ret = use_complex_response(skt, c0c1 + 1, encrypted);
        if (ret == ERROR_SUCCESS) {
            log_trace("complex handshake success.");
            return ret;
        }
        log_trace("--------------> ret = %d", ret);
        if (ret != ERROR_RTMP_TRY_SIMPLE_HS) {
            log_error("complex handshake failed. ret=%d", ret);
            return ret;
        }
    } else {
        //use simple handshake
        if ((ret = use_simple_response(skt,c0c1)) != ERROR_SUCCESS) {
            log_warn("simple handshake read c2 failed. ret=%d", ret);
            return ret;
        }

        log_trace("simple handshake success.");
    }
    if (ret == ERROR_RTMP_TRY_SIMPLE_HS)
        ret = use_simple_response(skt,c0c1);

    return ret;
}
Ejemplo n.º 8
0
Archivo: send.c Proyecto: saghevli/zmap
// global sender initialize (not thread specific)
iterator_t* send_init(void)
{
	// compute number of targets
	uint64_t allowed = blacklist_count_allowed();
	assert(allowed <= (1LL << 32));
	if (allowed == (1LL << 32)) {
		zsend.targets = 0xFFFFFFFF;
	} else {
		zsend.targets = allowed;
	}
	if (zsend.targets > zconf.max_targets) {
		zsend.targets = zconf.max_targets;
	}

	// generate a new primitive root and starting position
	iterator_t *it;
	it = iterator_init(zconf.senders, zconf.shard_num, zconf.total_shards);

	// process the dotted-notation addresses passed to ZMAP and determine
	// the source addresses from which we'll send packets;
	srcip_first = inet_addr(zconf.source_ip_first);
	if (srcip_first == INADDR_NONE) {
		log_fatal("send", "invalid begin source ip address: `%s'",
				zconf.source_ip_first);
	}
	srcip_last = inet_addr(zconf.source_ip_last);
	if (srcip_last == INADDR_NONE) {
		log_fatal("send", "invalid end source ip address: `%s'",
				zconf.source_ip_last);
	}
	log_debug("send", "srcip_first: %u", srcip_first);
	log_debug("send", "srcip_last: %u", srcip_last);
	if (srcip_first == srcip_last) {
		srcip_offset = 0;
		num_src_addrs = 1;
	} else {
		uint32_t ip_first = ntohl(srcip_first);
		uint32_t ip_last = ntohl(srcip_last);
		assert(ip_first && ip_last);
		assert(ip_last > ip_first);
		uint32_t offset = (uint32_t) (aesrand_getword() & 0xFFFFFFFF);
		srcip_offset = offset % (srcip_last - srcip_first);
		num_src_addrs = ip_last - ip_first + 1;
	}

	// process the source port range that ZMap is allowed to use
	num_src_ports = zconf.source_port_last - zconf.source_port_first + 1;
	log_debug("send", "will send from %i address%s on %u source ports",
		  num_src_addrs, ((num_src_addrs ==1 ) ? "":"es"),
		  num_src_ports);

	// global initialization for send module
	assert(zconf.probe_module);
	if (zconf.probe_module->global_initialize) {
		zconf.probe_module->global_initialize(&zconf);
	}

	// concert specified bandwidth to packet rate
	if (zconf.bandwidth > 0) {
		int pkt_len = zconf.probe_module->packet_length;
		pkt_len *= 8;	
		pkt_len += 8*24;	// 7 byte MAC preamble, 1 byte Start frame, 
		                        // 4 byte CRC, 12 byte inter-frame gap
		if (pkt_len < 84*8) {
			pkt_len = 84*8;
		}
		if (zconf.bandwidth / pkt_len > 0xFFFFFFFF) {
			zconf.rate = 0;
		} else {
			zconf.rate = zconf.bandwidth / pkt_len;
			if (zconf.rate == 0) {
				log_warn("send", "bandwidth %lu bit/s is slower than 1 pkt/s, "
								"setting rate to 1 pkt/s", zconf.bandwidth);
				zconf.rate = 1;
			}
		}
		log_debug("send", "using bandwidth %lu bits/s, rate set to %d pkt/s",
						zconf.bandwidth, zconf.rate);
	}

	// Get the source hardware address, and give it to the probe
	// module
	if (get_iface_hw_addr(zconf.iface, zconf.hw_mac)) {
		log_fatal("send", "could not retrieve hardware address for "
			  "interface: %s", zconf.iface);
		return NULL;
	}

	if (zconf.dryrun) {
		log_info("send", "dryrun mode -- won't actually send packets");
	}

	// initialize random validation key
	validate_init();

	zsend.start = now();	
	return it;
}
Ejemplo n.º 9
0
/** Given an encrypted DH public key as generated by onion_skin_create,
 * and the private key for this onion router, generate the reply (128-byte
 * DH plus the first 20 bytes of shared key material), and store the
 * next key_out_len bytes of key material in key_out.
 */
int
onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
                            crypto_pk_t *private_key,
                            crypto_pk_t *prev_private_key,
                            char *handshake_reply_out, /*ONIONSKIN_REPLY_LEN*/
                            char *key_out,
                            size_t key_out_len)
{
  char challenge[ONIONSKIN_CHALLENGE_LEN];
  crypto_dh_t *dh = NULL;
  ssize_t len;
  char *key_material=NULL;
  size_t key_material_len=0;
  int i;
  crypto_pk_t *k;

  len = -1;
  for (i=0;i<2;++i) {
    k = i==0?private_key:prev_private_key;
    if (!k)
      break;
    note_crypto_pk_op(DEC_ONIONSKIN);
    len = crypto_pk_private_hybrid_decrypt(k, challenge,
                                           ONIONSKIN_CHALLENGE_LEN,
                                           onion_skin, ONIONSKIN_CHALLENGE_LEN,
                                           PK_PKCS1_OAEP_PADDING,0);
    if (len>0)
      break;
  }
  if (len<0) {
    log_info(LD_PROTOCOL,
             "Couldn't decrypt onionskin: client may be using old onion key");
    goto err;
  } else if (len != DH_KEY_LEN) {
    log_warn(LD_PROTOCOL, "Unexpected onionskin length after decryption: %ld",
             (long)len);
    goto err;
  }

  dh = crypto_dh_new(DH_TYPE_CIRCUIT);
  if (!dh) {
    log_warn(LD_BUG, "Couldn't allocate DH key");
    goto err;
  }
  if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) {
    log_info(LD_GENERAL, "crypto_dh_get_public failed.");
    goto err;
  }

  key_material_len = DIGEST_LEN+key_out_len;
  key_material = tor_malloc(key_material_len);
  len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
                                 DH_KEY_LEN, key_material,
                                 key_material_len);
  if (len < 0) {
    log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
    goto err;
  }

  /* send back H(K|0) as proof that we learned K. */
  memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN);

  /* use the rest of the key material for our shared keys, digests, etc */
  memcpy(key_out, key_material+DIGEST_LEN, key_out_len);

  memset(challenge, 0, sizeof(challenge));
  memset(key_material, 0, key_material_len);
  tor_free(key_material);
  crypto_dh_free(dh);
  return 0;
 err:
  memset(challenge, 0, sizeof(challenge));
  if (key_material) {
    memset(key_material, 0, key_material_len);
    tor_free(key_material);
  }
  if (dh) crypto_dh_free(dh);

  return -1;
}
Ejemplo n.º 10
0
static int udp_global_initialize(struct state_conf *conf) {
	char *args, *c;
	int i;
	unsigned int n;

	FILE *inp;

	num_ports = conf->source_port_last - conf->source_port_first + 1;

	udp_send_msg = strdup(udp_send_msg_default);
	udp_send_msg_len = strlen(udp_send_msg);

	if (!(conf->probe_args && strlen(conf->probe_args) > 0))
		return(0);

	args = strdup(conf->probe_args);
	if (! args) exit(1);

	c = strchr(args, ':');
	if (! c) {
		free(args);
		free(udp_send_msg);
		log_fatal("udp", udp_usage_error);
		exit(1);
	}

	*c++ = 0;

	if (strcmp(args, "text") == 0) {
		free(udp_send_msg);
		udp_send_msg = strdup(c);
		udp_send_msg_len = strlen(udp_send_msg);

	} else if (strcmp(args, "file") == 0 || strcmp(args, "template") == 0) {
		inp = fopen(c, "rb");
		if (!inp) {
			free(args);
			free(udp_send_msg);
			log_fatal("udp", "could not open UDP data file '%s'\n", c);
			exit(1);
		}
		free(udp_send_msg);
		udp_send_msg = xmalloc(MAX_UDP_PAYLOAD_LEN);
		udp_send_msg_len = fread(udp_send_msg, 1, MAX_UDP_PAYLOAD_LEN, inp);
		fclose(inp);

		if (strcmp(args, "template") == 0) {
			udp_send_substitutions = 1;
			udp_template = udp_template_load(udp_send_msg, udp_send_msg_len);
		}

	} else if (strcmp(args, "hex") == 0) {
		udp_send_msg_len = strlen(c) / 2;
		free(udp_send_msg);
		udp_send_msg = xmalloc(udp_send_msg_len);

		for (i=0; i < udp_send_msg_len; i++) {
			if (sscanf(c + (i*2), "%2x", &n) != 1) {
				free(args);
				free(udp_send_msg);
				log_fatal("udp", "non-hex character: '%c'", c[i*2]);
				exit(1);
			}
			udp_send_msg[i] = (n & 0xff);
		}
	} else {
		log_fatal("udp", udp_usage_error);
		free(udp_send_msg);
		free(args);
		exit(1);
	}

	if (udp_send_msg_len > MAX_UDP_PAYLOAD_LEN) {
		log_warn("udp", "warning: reducing UDP payload to %d "
				"bytes (from %d) to fit on the wire\n",
				MAX_UDP_PAYLOAD_LEN, udp_send_msg_len);
		udp_send_msg_len = MAX_UDP_PAYLOAD_LEN;
	}
	free(args);
	return EXIT_SUCCESS;
}
Ejemplo n.º 11
0
/** Executes the given process as a child process of Tor.  This function is
 * responsible for setting up the child process and run it. This includes
 * setting up pipes for interprocess communication, initialize the waitpid
 * callbacks, and finally run fork() followed by execve(). Returns
 * <b>PROCESS_STATUS_RUNNING</b> upon success. */
process_status_t
process_unix_exec(process_t *process)
{
  static int max_fd = -1;

  process_unix_t *unix_process;
  pid_t pid;
  int stdin_pipe[2];
  int stdout_pipe[2];
  int stderr_pipe[2];
  int retval, fd;

  unix_process = process_get_unix_process(process);

  /* Create standard in pipe. */
  retval = pipe(stdin_pipe);

  if (-1 == retval) {
    log_warn(LD_PROCESS,
             "Unable to create pipe for stdin "
             "communication with process: %s",
             strerror(errno));

    return PROCESS_STATUS_ERROR;
  }

  /* Create standard out pipe. */
  retval = pipe(stdout_pipe);

  if (-1 == retval) {
    log_warn(LD_PROCESS,
             "Unable to create pipe for stdout "
             "communication with process: %s",
             strerror(errno));

    /** Cleanup standard in pipe. */
    close(stdin_pipe[0]);
    close(stdin_pipe[1]);

    return PROCESS_STATUS_ERROR;
  }

  /* Create standard error pipe. */
  retval = pipe(stderr_pipe);

  if (-1 == retval) {
    log_warn(LD_PROCESS,
             "Unable to create pipe for stderr "
             "communication with process: %s",
             strerror(errno));

    /** Cleanup standard in pipe. */
    close(stdin_pipe[0]);
    close(stdin_pipe[1]);

    /** Cleanup standard out pipe. */
    close(stdout_pipe[0]);
    close(stdout_pipe[1]);

    return PROCESS_STATUS_ERROR;
  }

#ifdef _SC_OPEN_MAX
  if (-1 == max_fd) {
    max_fd = (int)sysconf(_SC_OPEN_MAX);

    if (max_fd == -1) {
      max_fd = DEFAULT_MAX_FD;
      log_warn(LD_PROCESS,
               "Cannot find maximum file descriptor, assuming: %d", max_fd);
    }
  }
#else /* !(defined(_SC_OPEN_MAX)) */
  max_fd = DEFAULT_MAX_FD;
#endif /* defined(_SC_OPEN_MAX) */

  pid = fork();

  if (0 == pid) {
    /* This code is running in the child process context. */

#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
    /* Attempt to have the kernel issue a SIGTERM if the parent
     * goes away. Certain attributes of the binary being execve()ed
     * will clear this during the execve() call, but it's better
     * than nothing.
     */
    prctl(PR_SET_PDEATHSIG, SIGTERM);
#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) */

    /* Link process stdout to the write end of the pipe. */
    retval = dup2(stdout_pipe[1], STDOUT_FILENO);
    if (-1 == retval)
      goto error;

    /* Link process stderr to the write end of the pipe. */
    retval = dup2(stderr_pipe[1], STDERR_FILENO);
    if (-1 == retval)
      goto error;

    /* Link process stdin to the read end of the pipe */
    retval = dup2(stdin_pipe[0], STDIN_FILENO);
    if (-1 == retval)
      goto error;

    /* Close our pipes now after they have been dup2()'ed. */
    close(stderr_pipe[0]);
    close(stderr_pipe[1]);
    close(stdout_pipe[0]);
    close(stdout_pipe[1]);
    close(stdin_pipe[0]);
    close(stdin_pipe[1]);

    /* Close all other fds, including the read end of the pipe.  XXX: We should
     * now be doing enough FD_CLOEXEC setting to make this needless.
     */
    for (fd = STDERR_FILENO + 1; fd < max_fd; fd++)
      close(fd);

    /* Create the argv value for our new process. */
    char **argv = process_get_argv(process);

    /* Create the env value for our new process. */
    process_environment_t *env = process_get_environment(process);

    /* Call the requested program. */
    retval = execve(argv[0], argv, env->unixoid_environment_block);

    /* If we made it here it is because execve failed :-( */
    if (-1 == retval)
      fprintf(stderr, "Call to execve() failed: %s", strerror(errno));

    tor_free(argv);
    process_environment_free(env);

    tor_assert_unreached();

 error:
    /* LCOV_EXCL_START */
    fprintf(stderr, "Error from child process: %s", strerror(errno));
    _exit(1);
    /* LCOV_EXCL_STOP */
  }

  /* We are in the parent process. */
  if (-1 == pid) {
    log_warn(LD_PROCESS,
             "Failed to create child process: %s", strerror(errno));

    /** Cleanup standard in pipe. */
    close(stdin_pipe[0]);
    close(stdin_pipe[1]);

    /** Cleanup standard out pipe. */
    close(stdout_pipe[0]);
    close(stdout_pipe[1]);

    /** Cleanup standard error pipe. */
    close(stderr_pipe[0]);
    close(stderr_pipe[1]);

    return PROCESS_STATUS_ERROR;
  }

  /* Register our PID. */
  unix_process->pid = pid;

  /* Setup waitpid callbacks. */
  unix_process->waitpid = set_waitpid_callback(pid,
                                               process_unix_waitpid_callback,
                                               process);

  /* Handle standard out. */
  unix_process->stdout_handle.fd = stdout_pipe[0];
  retval = close(stdout_pipe[1]);

  if (-1 == retval) {
    log_warn(LD_PROCESS, "Failed to close write end of standard out pipe: %s",
             strerror(errno));
  }

  /* Handle standard error. */
  unix_process->stderr_handle.fd = stderr_pipe[0];
  retval = close(stderr_pipe[1]);

  if (-1 == retval) {
    log_warn(LD_PROCESS,
             "Failed to close write end of standard error pipe: %s",
             strerror(errno));
  }

  /* Handle standard in. */
  unix_process->stdin_handle.fd = stdin_pipe[1];
  retval = close(stdin_pipe[0]);

  if (-1 == retval) {
    log_warn(LD_PROCESS, "Failed to close read end of standard in pipe: %s",
             strerror(errno));
  }

  /* Setup our handles. */
  process_unix_setup_handle(process,
                            &unix_process->stdout_handle,
                            EV_READ|EV_PERSIST,
                            stdout_read_callback);

  process_unix_setup_handle(process,
                            &unix_process->stderr_handle,
                            EV_READ|EV_PERSIST,
                            stderr_read_callback);

  process_unix_setup_handle(process,
                            &unix_process->stdin_handle,
                            EV_WRITE|EV_PERSIST,
                            stdin_write_callback);

  /* Start reading from standard out and standard error. */
  process_unix_start_reading(&unix_process->stdout_handle);
  process_unix_start_reading(&unix_process->stderr_handle);

  return PROCESS_STATUS_RUNNING;
}
Ejemplo n.º 12
0
Archivo: torgzip.c Proyecto: adoll/tor
/** Given zero or more zlib-compressed or gzip-compressed strings of
 * total length
 * <b>in_len</b> bytes at <b>in</b>, uncompress them into a newly allocated
 * buffer, using the method described in <b>method</b>.  Store the uncompressed
 * string in *<b>out</b>, and its length in *<b>out_len</b>.  Return 0 on
 * success, -1 on failure.
 *
 * If <b>complete_only</b> is true, we consider a truncated input as a
 * failure; otherwise we decompress as much as we can.  Warn about truncated
 * or corrupt inputs at <b>protocol_warn_level</b>.
 */
int
tor_gzip_uncompress(char **out, size_t *out_len,
                    const char *in, size_t in_len,
                    compress_method_t method,
                    int complete_only,
                    int protocol_warn_level)
{
  struct z_stream_s *stream = NULL;
  size_t out_size, old_size;
  off_t offset;
  int r;

  tor_assert(out);
  tor_assert(out_len);
  tor_assert(in);
  tor_assert(in_len < UINT_MAX);

  if (method == GZIP_METHOD && !is_gzip_supported()) {
    /* Old zlib version don't support gzip in inflateInit2 */
    log_warn(LD_BUG, "Gzip not supported with zlib %s", ZLIB_VERSION);
    return -1;
  }

  *out = NULL;

  stream = tor_malloc_zero(sizeof(struct z_stream_s));
  stream->zalloc = Z_NULL;
  stream->zfree = Z_NULL;
  stream->opaque = NULL;
  stream->next_in = (unsigned char*) in;
  stream->avail_in = (unsigned int)in_len;

  if (inflateInit2(stream,
                   method_bits(method)) != Z_OK) {
    log_warn(LD_GENERAL, "Error from inflateInit2: %s",
             stream->msg?stream->msg:"<no message>");
    goto err;
  }

  out_size = in_len * 2;  /* guess 50% compression. */
  if (out_size < 1024) out_size = 1024;
  if (out_size >= SIZE_T_CEILING || out_size > UINT_MAX)
    goto err;

  *out = tor_malloc(out_size);
  stream->next_out = (unsigned char*)*out;
  stream->avail_out = (unsigned int)out_size;

  while (1) {
    switch (inflate(stream, complete_only ? Z_FINISH : Z_SYNC_FLUSH))
      {
      case Z_STREAM_END:
        if (stream->avail_in == 0)
          goto done;
        /* There may be more compressed data here. */
        if ((r = inflateEnd(stream)) != Z_OK) {
          log_warn(LD_BUG, "Error freeing gzip structures");
          goto err;
        }
        if (inflateInit2(stream, method_bits(method)) != Z_OK) {
          log_warn(LD_GENERAL, "Error from second inflateInit2: %s",
                   stream->msg?stream->msg:"<no message>");
          goto err;
        }
        break;
      case Z_OK:
        if (!complete_only && stream->avail_in == 0)
          goto done;
        /* In case zlib doesn't work as I think.... */
        if (stream->avail_out >= stream->avail_in+16)
          break;
      case Z_BUF_ERROR:
        if (stream->avail_out > 0) {
          log_fn(protocol_warn_level, LD_PROTOCOL,
                 "possible truncated or corrupt zlib data");
          goto err;
        }
        offset = stream->next_out - (unsigned char*)*out;
        old_size = out_size;
        out_size *= 2;
        if (out_size < old_size) {
          log_warn(LD_GENERAL, "Size overflow in uncompression.");
          goto err;
        }
        if (is_compression_bomb(in_len, out_size)) {
          log_warn(LD_GENERAL, "Input looks like a possible zlib bomb; "
                   "not proceeding.");
          goto err;
        }
        if (out_size >= SIZE_T_CEILING) {
          log_warn(LD_BUG, "Hit SIZE_T_CEILING limit while uncompressing.");
          goto err;
        }
        *out = tor_realloc(*out, out_size);
        stream->next_out = (unsigned char*)(*out + offset);
        if (out_size - offset > UINT_MAX) {
          log_warn(LD_BUG,  "Ran over unsigned int limit of zlib while "
                   "uncompressing.");
          goto err;
        }
        stream->avail_out = (unsigned int)(out_size - offset);
        break;
      default:
        log_warn(LD_GENERAL, "Gzip decompression returned an error: %s",
                 stream->msg ? stream->msg : "<no message>");
        goto err;
      }
  }
 done:
  *out_len = stream->next_out - (unsigned char*)*out;
  r = inflateEnd(stream);
  tor_free(stream);
  if (r != Z_OK) {
    log_warn(LD_BUG, "Error freeing gzip structures");
    goto err;
  }

  /* NUL-terminate output. */
  if (out_size == *out_len)
    *out = tor_realloc(*out, out_size + 1);
  (*out)[*out_len] = '\0';

  return 0;
 err:
  if (stream) {
    inflateEnd(stream);
    tor_free(stream);
  }
  if (*out) {
    tor_free(*out);
  }
  return -1;
}
Ejemplo n.º 13
0
Archivo: torgzip.c Proyecto: adoll/tor
/** Given <b>in_len</b> bytes at <b>in</b>, compress them into a newly
 * allocated buffer, using the method described in <b>method</b>.  Store the
 * compressed string in *<b>out</b>, and its length in *<b>out_len</b>.
 * Return 0 on success, -1 on failure.
 */
int
tor_gzip_compress(char **out, size_t *out_len,
                  const char *in, size_t in_len,
                  compress_method_t method)
{
  struct z_stream_s *stream = NULL;
  size_t out_size, old_size;
  off_t offset;

  tor_assert(out);
  tor_assert(out_len);
  tor_assert(in);
  tor_assert(in_len < UINT_MAX);

  *out = NULL;

  if (method == GZIP_METHOD && !is_gzip_supported()) {
    /* Old zlib version don't support gzip in deflateInit2 */
    log_warn(LD_BUG, "Gzip not supported with zlib %s", ZLIB_VERSION);
    goto err;
  }

  stream = tor_malloc_zero(sizeof(struct z_stream_s));
  stream->zalloc = Z_NULL;
  stream->zfree = Z_NULL;
  stream->opaque = NULL;
  stream->next_in = (unsigned char*) in;
  stream->avail_in = (unsigned int)in_len;

  if (deflateInit2(stream, Z_BEST_COMPRESSION, Z_DEFLATED,
                   method_bits(method),
                   8, Z_DEFAULT_STRATEGY) != Z_OK) {
    log_warn(LD_GENERAL, "Error from deflateInit2: %s",
             stream->msg?stream->msg:"<no message>");
    goto err;
  }

  /* Guess 50% compression. */
  out_size = in_len / 2;
  if (out_size < 1024) out_size = 1024;
  *out = tor_malloc(out_size);
  stream->next_out = (unsigned char*)*out;
  stream->avail_out = (unsigned int)out_size;

  while (1) {
    switch (deflate(stream, Z_FINISH))
      {
      case Z_STREAM_END:
        goto done;
      case Z_OK:
        /* In case zlib doesn't work as I think .... */
        if (stream->avail_out >= stream->avail_in+16)
          break;
      case Z_BUF_ERROR:
        offset = stream->next_out - ((unsigned char*)*out);
        old_size = out_size;
        out_size *= 2;
        if (out_size < old_size) {
          log_warn(LD_GENERAL, "Size overflow in compression.");
          goto err;
        }
        *out = tor_realloc(*out, out_size);
        stream->next_out = (unsigned char*)(*out + offset);
        if (out_size - offset > UINT_MAX) {
          log_warn(LD_BUG,  "Ran over unsigned int limit of zlib while "
                   "uncompressing.");
          goto err;
        }
        stream->avail_out = (unsigned int)(out_size - offset);
        break;
      default:
        log_warn(LD_GENERAL, "Gzip compression didn't finish: %s",
                 stream->msg ? stream->msg : "<no message>");
        goto err;
      }
  }
 done:
  *out_len = stream->total_out;
#ifdef OPENBSD
  /* "Hey Rocky!  Watch me change an unsigned field to a signed field in a
   *    third-party API!"
   * "Oh, that trick will just make people do unsafe casts to the unsigned
   *    type in their cross-platform code!"
   * "Don't be foolish.  I'm _sure_ they'll have the good sense to make sure
   *    the newly unsigned field isn't negative." */
  tor_assert(stream->total_out >= 0);
#endif
  if (((size_t)stream->total_out) > out_size + 4097) {
    /* If we're wasting more than 4k, don't. */
    *out = tor_realloc(*out, stream->total_out + 1);
  }
  if (deflateEnd(stream)!=Z_OK) {
    log_warn(LD_BUG, "Error freeing gzip structures");
    goto err;
  }
  tor_free(stream);

  if (is_compression_bomb(*out_len, in_len)) {
    log_warn(LD_BUG, "We compressed something and got an insanely high "
          "compression factor; other Tors would think this was a zlib bomb.");
    goto err;
  }

  return 0;
 err:
  if (stream) {
    deflateEnd(stream);
    tor_free(stream);
  }
  tor_free(*out);
  return -1;
}
Ejemplo n.º 14
0
static void monitor_update(iterator_t *it, pthread_mutex_t *recv_ready_mutex)
{
	uint32_t total_sent = iterator_get_sent(it);
	if (last_now > 0.0) {
		double age = now() - zsend.start;
		double delta = now() - last_now;
		double remaining_secs = compute_remaining_time(age, total_sent);
		double percent_complete = 100.*age/(age + remaining_secs);


		// ask pcap for fresh values
		pthread_mutex_lock(recv_ready_mutex);
		recv_update_pcap_stats();
		pthread_mutex_unlock(recv_ready_mutex);

		// format times for display
		char time_left[20];
		if (age < 5) {
			time_left[0] = '\0';
		} else {
			char buf[20];
			time_string((int)remaining_secs, 1, buf, sizeof(buf));
			snprintf(time_left, sizeof(time_left), " (%s left)", buf);
		}
		char time_past[20];
		time_string((int)age, 0, time_past, sizeof(time_past));

		char send_rate[20], send_avg[20],
			 recv_rate[20], recv_avg[20],
			 pcap_drop[20], pcap_drop_avg[20];
		// recv stats
		number_string((zrecv.success_unique - last_rcvd)/delta,
						recv_rate, sizeof(recv_rate));
		number_string((zrecv.success_unique/age), recv_avg, sizeof(recv_avg));
		// dropped stats
		number_string((zrecv.pcap_drop + zrecv.pcap_ifdrop - last_drop)/delta,
						pcap_drop, sizeof(pcap_drop));
		number_string(((zrecv.pcap_drop + zrecv.pcap_ifdrop)/age),
						pcap_drop_avg, sizeof(pcap_drop_avg));

		// Warn if we drop > 5% of our average receive rate
		uint32_t drop_rate = (uint32_t)((zrecv.pcap_drop + zrecv.pcap_ifdrop - last_drop) / delta);
		if (drop_rate > (uint32_t)((zrecv.success_unique - last_rcvd) / delta) / 20) {
			log_warn("monitor", "Dropped %d packets in the last second, (%d total dropped (pcap: %d + iface: %d))",
					 drop_rate, zrecv.pcap_drop + zrecv.pcap_ifdrop, zrecv.pcap_drop, zrecv.pcap_ifdrop);
		}	

		// Warn if we fail to send > 1% of our average send rate
		uint32_t fail_rate = (uint32_t)((zsend.sendto_failures - last_failures) / delta); // failures/sec
		if (fail_rate > ((total_sent / age) / 100)) {
			log_warn("monitor", "Failed to send %d packets/sec (%d total failures)",
					 fail_rate, zsend.sendto_failures);
		}
		float hits;
		if (!total_sent) {
			hits = 0;
		} else {
			hits = zrecv.success_unique*100./total_sent;
		}
		if (!zsend.complete) {
			// main display (during sending)
			number_string((total_sent - last_sent)/delta,
							send_rate, sizeof(send_rate));
			number_string((total_sent/age), send_avg, sizeof(send_avg));
			fprintf(stderr,
					"%5s %0.0f%%%s; send: %u %sp/s (%sp/s avg); "
					"recv: %u %sp/s (%sp/s avg); "
					"drops: %sp/s (%sp/s avg); "
					"hits: %0.2f%%\n", 
					time_past,
					percent_complete,
					time_left,
					total_sent,
					send_rate,
					send_avg,
					zrecv.success_unique,
					recv_rate,
					recv_avg,
					pcap_drop,
					pcap_drop_avg,
					hits);
		} else {
		  	// alternate display (during cooldown)
			number_string((total_sent/(zsend.finish - zsend.start)), send_avg, sizeof(send_avg));
			fprintf(stderr, 
					"%5s %0.0f%%%s; send: %u done (%sp/s avg); "
					"recv: %u %sp/s (%sp/s avg); "
					"drops: %sp/s (%sp/s avg); "
					"hits: %0.2f%%\n", 
					time_past,
					percent_complete,
					time_left,
					total_sent,
					send_avg,
					zrecv.success_unique,
					recv_rate,
					recv_avg,
					pcap_drop,
					pcap_drop_avg,
					hits);
		}
	}
	last_now  = now();
	last_sent = total_sent;
	last_rcvd = zrecv.success_unique;
	last_drop = zrecv.pcap_drop + zrecv.pcap_ifdrop;
	last_failures = zsend.sendto_failures;
}
Ejemplo n.º 15
0
/** Parse the content of a client_key file in <b>ckstr</b> and add
 * rend_authorized_client_t's for each parsed client to
 * <b>parsed_clients</b>. Return the number of parsed clients as result
 * or -1 for failure. */
int
rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
{
  int result = -1;
  smartlist_t *tokens;
  directory_token_t *tok;
  const char *current_entry = NULL;
  memarea_t *area = NULL;
  char *err_msg = NULL;
  if (!ckstr || strlen(ckstr) == 0)
    return -1;
  tokens = smartlist_new();
  /* Begin parsing with first entry, skipping comments or whitespace at the
   * beginning. */
  area = memarea_new();
  current_entry = eat_whitespace(ckstr);
  while (!strcmpstart(current_entry, "client-name ")) {
    rend_authorized_client_t *parsed_entry;
    /* Determine end of string. */
    const char *eos = strstr(current_entry, "\nclient-name ");
    if (!eos)
      eos = current_entry + strlen(current_entry);
    else
      eos = eos + 1;
    /* Free tokens and clear token list. */
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_clear(tokens);
    memarea_clear(area);
    /* Tokenize string. */
    if (tokenize_string(area, current_entry, eos, tokens,
                        client_keys_token_table, 0)) {
      log_warn(LD_REND, "Error tokenizing client keys file.");
      goto err;
    }
    /* Advance to next entry, if available. */
    current_entry = eos;
    /* Check minimum allowed length of token list. */
    if (smartlist_len(tokens) < 2) {
      log_warn(LD_REND, "Impossibly short client key entry.");
      goto err;
    }
    /* Parse client name. */
    tok = find_by_keyword(tokens, C_CLIENT_NAME);
    tor_assert(tok == smartlist_get(tokens, 0));
    tor_assert(tok->n_args == 1);

    if (!rend_valid_client_name(tok->args[0])) {
      log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
               "between 1 and %d, and valid characters are "
               "[A-Za-z0-9+-_].)", tok->args[0], REND_CLIENTNAME_MAX_LEN);
      goto err;
    }
    /* Check if client name is duplicate. */
    if (strmap_get(parsed_clients, tok->args[0])) {
      log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
               "duplicate client name: '%s'. Ignoring.", tok->args[0]);
      goto err;
    }
    parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
    parsed_entry->client_name = tor_strdup(tok->args[0]);
    strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
    /* Parse client key. */
    tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
    if (tok) {
      parsed_entry->client_key = tok->key;
      tok->key = NULL; /* Prevent free */
    }

    /* Parse descriptor cookie. */
    tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
    tor_assert(tok->n_args == 1);
    if (rend_auth_decode_cookie(tok->args[0], parsed_entry->descriptor_cookie,
                                NULL, &err_msg) < 0) {
      tor_assert(err_msg);
      log_warn(LD_REND, "%s", err_msg);
      tor_free(err_msg);
      goto err;
    }
  }
  result = strmap_size(parsed_clients);
  goto done;
 err:
  result = -1;
 done:
  /* Free tokens and clear token list. */
  SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
  smartlist_free(tokens);
  if (area)
    memarea_drop_all(area);
  return result;
}
Ejemplo n.º 16
0
int request_dispatch(session_t *ses, struct evbuffer *in, struct evbuffer *out){
    spie_header_t *pro;

    assert((ses != NULL) && (in != NULL) && (out != NULL));

    while(header_unpack(in, &pro) == 0){
        switch(pro->cmdcode){
        case SPIE_CMD_TEMPLOGIN:
            svr_request_templogin(ses, in, out, pro);
            break;

        case SPIE_CMD_TEMPADD:
            svr_request_tempadd(ses, in, out, pro);
            break;

        case SPIE_CMD_LOGIN:
            svr_request_login(ses, in, out, pro);
            break;

        case SPIE_CMD_ADDUSER:
            svr_request_adduser(ses, in, out, pro);
            break;

        case SPIE_CMD_DELUSER:
            svr_request_deluser(ses, in, out, pro);
            break;

        case SPIE_CMD_LISTUSER:
            svr_request_listuser(ses, in, out, pro);
            break;

        case SPIE_CMD_UPDATEUSER:
            svr_request_updateuser(ses, in, out, pro);
            break;

        case SPIE_CMD_SYSINFO:
            svr_request_sysinfo(ses, in, out, pro);
            break;

        case SPIE_CMD_FOPEN:
            svr_request_fopen(ses, in, out, pro);
            break;

        case SPIE_CMD_FCLOSE:
            svr_request_fclose(ses, in, out, pro);
            break;

        case SPIE_CMD_FWRITE:
            svr_request_fwrite(ses, in, out, pro);
            break;

        case SPIE_CMD_FREAD:
            svr_request_fread(ses, in, out, pro);
            break;
    
        case SPIE_CMD_FSTAT:
            svr_request_fstat(ses, in, out, pro);
            break;

        case SPIE_CMD_FTRUNCATE:
            svr_request_ftruncate(ses, in, out, pro);
            break;

        case SPIE_CMD_FMOVETO:
            svr_request_fmoveto(ses, in, out, pro);
            break;

         case SPIE_CMD_FCREATE:
            svr_request_fcreate(ses, in, out, pro);
            break;

        case SPIE_CMD_FDELETE:
            svr_request_fdelete(ses, in, out, pro);
            break;

       case SPIE_CMD_FREADSNAP:
            svr_request_freadsnap(ses, in, out, pro);
            break;

        case SPIE_CMD_FWRITESNAP:
            svr_request_fwritesnap(ses, in, out, pro);
            break;

        case SPIE_CMD_LOOKUP_CREATE:
            svr_request_lookup_create(ses, in, out, pro);
            break;

        case SPIE_CMD_LOOKUP_DESTROY:
            svr_request_lookup_destroy(ses, in, out, pro);
            break;

        case SPIE_CMD_LOOKUP_NEXT:
            svr_request_lookup_next(ses, in, out, pro);
            break;

        default:
            log_warn("received command is unkown:%d\n", pro->cmdcode);
            trans_ack_fail(out, pro, SPIE_ECODE_INVAL);
            break;
        }

        pro = NULL;
    }

    return 0;
}
Ejemplo n.º 17
0
/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
 * encrypted introduction points to the newly allocated
 * *<b>intro_points_encrypted_out</b>, their encrypted size to
 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
 * and -1 for failure.
 *
 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
 * be strict about time formats.
 */
int
rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
                                 char *desc_id_out,
                                 char **intro_points_encrypted_out,
                                 size_t *intro_points_encrypted_size_out,
                                 size_t *encoded_size_out,
                                 const char **next_out, const char *desc,
                                 int as_hsdir)
{
  rend_service_descriptor_t *result =
                            tor_malloc_zero(sizeof(rend_service_descriptor_t));
  char desc_hash[DIGEST_LEN];
  const char *eos;
  smartlist_t *tokens = smartlist_new();
  directory_token_t *tok;
  char secret_id_part[DIGEST_LEN];
  int i, version, num_ok=1;
  smartlist_t *versions;
  char public_key_hash[DIGEST_LEN];
  char test_desc_id[DIGEST_LEN];
  memarea_t *area = NULL;
  const int strict_time_fmt = as_hsdir;

  tor_assert(desc);
  /* Check if desc starts correctly. */
  if (strcmpstart(desc, "rendezvous-service-descriptor ")) {
    log_info(LD_REND, "Descriptor does not start correctly.");
    goto err;
  }
  /* Compute descriptor hash for later validation. */
  if (router_get_hash_impl(desc, strlen(desc), desc_hash,
                           "rendezvous-service-descriptor ",
                           "\nsignature", '\n', DIGEST_SHA1) < 0) {
    log_warn(LD_REND, "Couldn't compute descriptor hash.");
    goto err;
  }
  /* Determine end of string. */
  eos = strstr(desc, "\nrendezvous-service-descriptor ");
  if (!eos)
    eos = desc + strlen(desc);
  else
    eos = eos + 1;
  /* Check length. */
  if (eos-desc > REND_DESC_MAX_SIZE) {
    /* XXXX+ If we are parsing this descriptor as a server, this
     * should be a protocol warning. */
    log_warn(LD_REND, "Descriptor length is %d which exceeds "
             "maximum rendezvous descriptor size of %d bytes.",
             (int)(eos-desc), REND_DESC_MAX_SIZE);
    goto err;
  }
  /* Tokenize descriptor. */
  area = memarea_new();
  if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
    log_warn(LD_REND, "Error tokenizing descriptor.");
    goto err;
  }
  /* Set next to next descriptor, if available. */
  *next_out = eos;
  /* Set length of encoded descriptor. */
  *encoded_size_out = eos - desc;
  /* Check min allowed length of token list. */
  if (smartlist_len(tokens) < 7) {
    log_warn(LD_REND, "Impossibly short descriptor.");
    goto err;
  }
  /* Parse base32-encoded descriptor ID. */
  tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
  tor_assert(tok == smartlist_get(tokens, 0));
  tor_assert(tok->n_args == 1);
  if (!rend_valid_descriptor_id(tok->args[0])) {
    log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(desc_id_out, DIGEST_LEN,
                    tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
    log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse descriptor version. */
  tok = find_by_keyword(tokens, R_VERSION);
  tor_assert(tok->n_args == 1);
  result->version =
    (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
  if (result->version != 2 || !num_ok) {
    /* If it's <2, it shouldn't be under this format.  If the number
     * is greater than 2, we bumped it because we broke backward
     * compatibility.  See how version numbers in our other formats
     * work. */
    log_warn(LD_REND, "Unrecognized descriptor version: %s",
             escaped(tok->args[0]));
    goto err;
  }
  /* Parse public key. */
  tok = find_by_keyword(tokens, R_PERMANENT_KEY);
  result->pk = tok->key;
  tok->key = NULL; /* Prevent free */
  /* Parse secret ID part. */
  tok = find_by_keyword(tokens, R_SECRET_ID_PART);
  tor_assert(tok->n_args == 1);
  if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
      strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
    log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
    log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse publication time -- up-to-date check is done when storing the
   * descriptor. */
  tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
  tor_assert(tok->n_args == 1);
  if (parse_iso_time_(tok->args[0], &result->timestamp,
                      strict_time_fmt, 0) < 0) {
    log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
    goto err;
  }
  /* Parse protocol versions. */
  tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
  tor_assert(tok->n_args == 1);
  versions = smartlist_new();
  smartlist_split_string(versions, tok->args[0], ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  for (i = 0; i < smartlist_len(versions); i++) {
    version = (int) tor_parse_long(smartlist_get(versions, i),
                                   10, 0, INT_MAX, &num_ok, NULL);
    if (!num_ok) /* It's a string; let's ignore it. */
      continue;
    if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
      /* Avoid undefined left-shift behaviour. */
      continue;
    result->protocols |= 1 << version;
  }
  SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
  smartlist_free(versions);
  /* Parse encrypted introduction points. Don't verify. */
  tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
  if (tok) {
    if (strcmp(tok->object_type, "MESSAGE")) {
      log_warn(LD_DIR, "Bad object type: introduction points should be of "
               "type MESSAGE");
      goto err;
    }
    *intro_points_encrypted_out = tor_memdup(tok->object_body,
                                             tok->object_size);
    *intro_points_encrypted_size_out = tok->object_size;
  } else {
    *intro_points_encrypted_out = NULL;
    *intro_points_encrypted_size_out = 0;
  }
  /* Parse and verify signature. */
  tok = find_by_keyword(tokens, R_SIGNATURE);
  if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
                            "v2 rendezvous service descriptor") < 0)
    goto err;
  /* Verify that descriptor ID belongs to public key and secret ID part. */
  if (crypto_pk_get_digest(result->pk, public_key_hash) < 0) {
    log_warn(LD_REND, "Unable to compute rend descriptor public key digest");
    goto err;
  }
  rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
                               secret_id_part);
  if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
    log_warn(LD_REND, "Parsed descriptor ID does not match "
             "computed descriptor ID.");
    goto err;
  }
  goto done;
 err:
  rend_service_descriptor_free(result);
  result = NULL;
 done:
  if (tokens) {
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_free(tokens);
  }
  if (area)
    memarea_drop_all(area);
  *parsed_out = result;
  if (result)
    return 0;
  return -1;
}
Ejemplo n.º 18
0
int main(int argc, char* argv[])
{
  try
  {
    cxxtools::Arg<bool> fatal;
    fatal.set(argc, argv, 'f');
    fatal.set(argc, argv, "--fatal");

    cxxtools::Arg<bool> error;
    error.set(argc, argv, 'e');
    error.set(argc, argv, "--error");

    cxxtools::Arg<bool> warn;
    warn.set(argc, argv, 'w');
    warn.set(argc, argv, "--warn");

    cxxtools::Arg<bool> info;
    info.set(argc, argv, 'i');
    info.set(argc, argv, "--info");

    cxxtools::Arg<bool> debug;
    debug.set(argc, argv, 'd');
    debug.set(argc, argv, "--debug");

    cxxtools::Arg<std::string> properties("log4j.properties");
    properties.set(argc, argv, 'p');
    properties.set(argc, argv, "--properties");

    if (argc <= 2)
    {
      std::cerr << "usage: " << argv[0] << " [options] category message\n"
                   "\toptions:  -f|--fatal\n"
                   "\t          -e|--error\n"
                   "\t          -w|--warn\n"
                   "\t          -i|--info\n"
                   "\t          -d|--debug\n"
                   "\t          -p|--properties filename" << std::endl;
      return -1;
    }

    log_init(properties.getValue());

    category = argv[1];

    for (int a = 2; a < argc; ++a)
    {
      if (fatal)
        log_fatal(argv[a]);
      else if (error)
        log_error(argv[a]);
      else if (warn)
        log_warn(argv[a]);
      else if (info)
        log_info(argv[a]);
      else if (debug)
        log_debug(argv[a]);
    }
  }
  catch (const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
    return -1;
  }
}
Ejemplo n.º 19
0
static int _pv_resize_single(struct cmd_context *cmd,
			     struct volume_group *vg,
			     struct physical_volume *pv,
			     const uint64_t new_size)
{
	struct pv_list *pvl;
	uint64_t size = 0;
	uint32_t new_pe_count = 0;
	int r = 0;
	struct dm_list mdas;
	const char *pv_name = pv_dev_name(pv);
	const char *vg_name = pv_vg_name(pv);
	struct lvmcache_info *info;
	int mda_count = 0;
	struct volume_group *old_vg = vg;

	dm_list_init(&mdas);

	if (is_orphan_vg(vg_name)) {
		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
			log_error("Can't get lock for orphans");
			return 0;
		}

		if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
			unlock_vg(cmd, vg_name);
			log_error("Unable to read PV \"%s\"", pv_name);
			return 0;
		}

		mda_count = dm_list_size(&mdas);
	} else {
		vg = vg_read_for_update(cmd, vg_name, NULL, 0);

		if (vg_read_error(vg)) {
			vg_release(vg);
			log_error("Unable to read volume group \"%s\".",
				  vg_name);
			return 0;
		}

		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
			log_error("Unable to find \"%s\" in volume group \"%s\"",
				  pv_name, vg->name);
			goto out;
		}

		pv = pvl->pv;

		if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
			log_error("Can't get info for PV %s in volume group %s",
				  pv_name, vg->name);
			goto out;
		}

		mda_count = dm_list_size(&info->mdas);

		if (!archive(vg))
			goto out;
	}

	/* FIXME Create function to test compatibility properly */
	if (mda_count > 1) {
		log_error("%s: too many metadata areas for pvresize", pv_name);
		goto out;
	}

	if (!(pv->fmt->features & FMT_RESIZE_PV)) {
		log_error("Physical volume %s format does not support resizing.",
			  pv_name);
		goto out;
	}

	/* Get new size */
	if (!dev_get_size(pv_dev(pv), &size)) {
		log_error("%s: Couldn't get size.", pv_name);
		goto out;
	}

	if (new_size) {
		if (new_size > size)
			log_warn("WARNING: %s: Overriding real size. "
				  "You could lose data.", pv_name);
		log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
			    " sectors.", pv_name, new_size, pv_size(pv));
		size = new_size;
	}

	if (size < PV_MIN_SIZE) {
		log_error("%s: Size must exceed minimum of %ld sectors.",
			  pv_name, PV_MIN_SIZE);
		goto out;
	}

	if (size < pv_pe_start(pv)) {
		log_error("%s: Size must exceed physical extent start of "
			  "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv));
		goto out;
	}

	pv->size = size;

	if (vg) {
		pv->size -= pv_pe_start(pv);
		new_pe_count = pv_size(pv) / vg->extent_size;

 		if (!new_pe_count) {
			log_error("%s: Size must leave space for at "
				  "least one physical extent of "
				  "%" PRIu32 " sectors.", pv_name,
				  pv_pe_size(pv));
			goto out;
		}

		if (!pv_resize(pv, vg, new_pe_count))
			goto_out;
	}

	log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
		    pv_name, pv_size(pv));

	log_verbose("Updating physical volume \"%s\"", pv_name);
	if (!is_orphan_vg(vg_name)) {
		if (!vg_write(vg) || !vg_commit(vg)) {
			log_error("Failed to store physical volume \"%s\" in "
				  "volume group \"%s\"", pv_name, vg->name);
			goto out;
		}
		backup(vg);
	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
		log_error("Failed to store physical volume \"%s\"",
			  pv_name);
		goto out;
	}

	log_print("Physical volume \"%s\" changed", pv_name);
	r = 1;

out:
	unlock_vg(cmd, vg_name);
	if (!old_vg)
		vg_release(vg);
	return r;
}
Ejemplo n.º 20
0
  int dup_sync_sender_manager::duplicate_batch_data(int bucket_number, const mput_record_vec* record_vec,
                                                    const std::vector<uint64_t>& des_server_ids, base_packet *request,
                                                    int version)
  {
    unsigned _copy_count=des_server_ids.size();
    uint32_t max_packet_id = atomic_add_return(_copy_count,&packet_id_creater);

    if(0==max_packet_id)
      max_packet_id = atomic_add_return(_copy_count,&packet_id_creater);

    int ret=packets_mgr.addWaitNode(0,NULL,NULL,bucket_number,des_server_ids,request,max_packet_id,version);
    if(ret != TAIR_RETURN_SUCCESS)
    {
      return ret;
    }

    for(unsigned int  i=0;i < _copy_count; i++)
    {
      request_mput* tmp_packet = new request_mput();
      // just reuse original request's data, if necessray
      if (_copy_count < 2) {
        tmp_packet->swap(*(dynamic_cast<request_mput*>(request)));
      } else {
        tmp_packet->clone(*(dynamic_cast<request_mput*>(request)), true);
      }
      tmp_packet->server_flag = TAIR_SERVERFLAG_DUPLICATE;
      tmp_packet->packet_id = max_packet_id;
      // reset the compressed data as server_flag changed
      if (tmp_packet->compressed != 0) {
        tmp_packet->compressed = 0;
        if (tmp_packet->packet_data != NULL) {
          delete tmp_packet->packet_data;
        }
        tmp_packet->compress();
      }
      //and send it to slave
      log_debug("duplicate packet %d sent: %s",tmp_packet->packet_id,tbsys::CNetUtil::addrToString(des_server_ids[i]).c_str());
      if(conn_mgr->sendPacket(des_server_ids[i], tmp_packet, NULL, NULL, true) == false)
      {
        //duplicate sendpacket error.
        log_error("duplicate packet %d faile send: %s",tmp_packet->packet_id,tbsys::CNetUtil::addrToString(des_server_ids[i]).c_str());
        delete tmp_packet;
        ret = TAIR_RETURN_DUPLICATE_BUSY;
        break;
      }
    }

    if (TAIR_RETURN_SUCCESS != ret)
    {
      //clear waitnode.
      packets_mgr.clear_waitnode(max_packet_id);
      //return failed,the caller will delete the packet.
      return ret;
    }

    //all data is send,wait response or timeout it.
    CPacket_Timeout_hint  *phint=new CPacket_Timeout_hint(max_packet_id);
    if(!packets_mgr.put_timeout_hint(max_packet_id%MAX_DUP_COUNT,phint))
    {
      //put to queue error,should remove the map node.
      delete phint;
      packets_mgr.clear_waitnode(max_packet_id);
	    log_warn("timeout wait packet full ,ignore packet=%d",max_packet_id);
      return TAIR_RETURN_DUPLICATE_BUSY;
    }
    return TAIR_DUP_WAIT_RSP;
  }
Ejemplo n.º 21
0
int MRtmpHandshake::handshake_with_server_use_complex(MTcpSocket & skt,bool rtmpe,bool swf)
{
    int ret = ERROR_SUCCESS;

    char* c0c1 = new char[1537];
    bool FP9HandShake = false;
    mAutoFreeArray(char, c0c1);
    if (rtmpe) {
        c0c1[0] = 0x06;
        FP9HandShake = true;
    } else {
        c0c1[0] = 0x03;
    }

    //create c0c1
    c1s1 c1;
    if ((ret = c1.c1_create(srs_schema1)) != ERROR_SUCCESS) {
        return ret;
    }

    c1.dump(&c0c1[1]);

    if ((ret = skt.write(c0c1, 1537)) < 0) {
        log_warn("complex handshake send c0c1 failed. ret=%d", ret);
        return ret;
    }

    //recv s0s1;
    char s0s1[1537];

    if ((ret = skt.readFully(s0s1, 1537)) <= 0) {
        log_warn("complex handshake recv s0s1 failed. ret=%d", ret);
        return ret;
    }

    log_trace("version of rtmp is %d, version of flash player is %d.%d.%d.%d",s0s1[0],s0s1[5],s0s1[6],s0s1[7],s0s1[8]);

    c1s1 s1;
    // try schema0.
    if ((ret = s1.c1_parse(&s0s1[1], srs_schema0)) != ERROR_SUCCESS) {
        log_error("parse s1 schema%d error. ret=%d", srs_schema0, ret);
        return ret;
    }

    // try schema1
    bool is_valid = false;
    if ((ret = s1.s1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
        if ((ret = s1.c1_parse(&s0s1[1], srs_schema1)) != ERROR_SUCCESS) {
            log_error("parse s1 schema%d error. ret=%d", srs_schema1, ret);
            return ret;
        }

        if ((ret = s1.s1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
            ret = ERROR_RTMP_TRY_SIMPLE_HS;
            log_info("all schema valid failed, try simple handshake. ret=%d", ret);
            return ret;
        }
    }

    log_verbose("decode s1 success.");

    c2s2 c2;
    if ((ret = c2.c2_create(&s1)) != ERROR_SUCCESS) {
        log_error("create s2 from c1 failed. ret=%d", ret);
        return ret;
    }
    log_verbose("create s2 from c1 success.");

    // sendout c2
    char* c2_temp = new char[1536];
    c2.dump(c2_temp);
    if ((ret = skt.write(c2_temp, 1536)) < 0) {
        log_warn("complex handshake send c2 failed. ret=%d", ret);
        return ret;
    }

    log_verbose("complex handshake send c2 success.");

    // recv s2
    char* s2 = new char[1536];
    mAutoFreeArray(char, s2);
    if ((ret = skt.readFully(s2, 1536)) <= 0) {
        log_warn("complex handshake read s2 failed. ret=%d", ret);
        return ret;
    }

    if (s2[4] == 0 && s2[5] == 0 && s2[6] == 0 && s2[7] == 0) {
        log_trace("sever refuse connenct");
        return -1;
    }

    log_trace("complex handshake with server success");

    return ret;
}
Ejemplo n.º 22
0
  tbnet::IPacketHandler::HPRetCode dup_sync_sender_manager::handlePacket(tbnet::Packet *packet, void *args)
  {
	  int packet_id = reinterpret_cast<long>(args);
    if (!packet->isRegularPacket()) {
      tbnet::ControlPacket *cp = (tbnet::ControlPacket*)packet;
			log_error("cmd:%d,packetid:%d,timeout.", cp->getCommand(),packet_id);
		  handleTimeOutPacket(packet_id);
      return tbnet::IPacketHandler::FREE_CHANNEL;
    }
    int pcode = packet->getPCode();
    log_debug("================= get duplicate response, pcode: %d", pcode);
    if (TAIR_RESP_DUPLICATE_PACKET == pcode) {
      response_duplicate* resp = (response_duplicate*)packet;
      log_debug("response packet %d ,bucket =%d, server=%s",resp->packet_id,resp->bucket_id, \
          tbsys::CNetUtil::addrToString(resp->server_id).c_str());
      int ret = do_duplicate_response(resp->bucket_id, resp->server_id, resp->packet_id);
      if (0 != ret && TAIR_RETURN_DUPLICATE_ACK_WAIT != ret)
      {
        log_error("response packet %d failed,bucket =%d, server=%s, code=%d", resp->packet_id, resp->bucket_id, \
            tbsys::CNetUtil::addrToString(resp->server_id).c_str(), ret);
      }

      resp->free();
    } else if ( pcode == TAIR_RESP_MRETURN_DUP_PACKET) {
      response_mreturn_dup *resp_dup = dynamic_cast<response_mreturn_dup*>(packet);
      if (resp_dup == NULL) {
        log_error("bad packet %d", pcode);
      } else {
        log_debug("duplicate response packet %u, bucket = %d, server = %s", resp_dup->packet_id, resp_dup->bucket_id, tbsys::CNetUtil::addrToString(resp_dup->server_id).c_str());
        CPacket_wait_Nodes *pnode = NULL;
        int ret = packets_mgr.doResponse(resp_dup->bucket_id, resp_dup->server_id, resp_dup->packet_id, &pnode);
        response_mreturn *resp = new response_mreturn();
        resp->swap(*resp_dup);
        if (ret == TAIR_RETURN_SUCCESS && pnode != NULL) {
          resp->setChannelId(pnode->chid);
          resp->config_version = pnode->conf_version;
          if (pnode->conn->postPacket(resp) == false) {
            delete resp;
            ret = TAIR_RETURN_DUPLICATE_SEND_ERROR;
          }
        } else {
          delete resp;
        }
      }
    } else if (pcode == TAIR_RESP_PREFIX_INCDEC_PACKET) {
      response_prefix_incdec *resp = dynamic_cast<response_prefix_incdec*>(packet);
      if (resp == NULL) {
        log_error("bad packet %d", pcode);
      } else {
        log_debug("duplicate response packet %u, bucket = %d, server = %s",
            resp->packet_id, resp->bucket_id, tbsys::CNetUtil::addrToString(resp->server_id).c_str());
        CPacket_wait_Nodes *pnode = NULL;
        int ret = packets_mgr.doResponse(resp->bucket_id, resp->server_id, resp->packet_id, &pnode);
        if (ret == TAIR_RETURN_SUCCESS && pnode != NULL) {
          resp->server_flag = TAIR_SERVERFLAG_CLIENT;
          resp->setChannelId(pnode->chid);
          resp->config_version = pnode->conf_version;
          if (!pnode->conn->postPacket(resp)) {
            delete resp;
            ret = TAIR_RETURN_DUPLICATE_SEND_ERROR;
          }
        }
      }
    } else {
      log_warn("unknow packet! pcode: %d", pcode);
      packet->free();
    }

    return tbnet::IPacketHandler::KEEP_CHANNEL;
  }
Ejemplo n.º 23
0
/** check file descriptor count */
static void
checkrlimits(struct config_file* cfg)
{
#ifndef S_SPLINT_S
#ifdef HAVE_GETRLIMIT
	/* list has number of ports to listen to, ifs number addresses */
	int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 + 
			(int)cfg->incoming_num_tcp:0));
	size_t listen_ifs = (size_t)(cfg->num_ifs==0?
		((cfg->do_ip4 && !cfg->if_automatic?1:0) + 
		 (cfg->do_ip6?1:0)):cfg->num_ifs);
	size_t listen_num = list*listen_ifs;
	size_t outudpnum = (size_t)cfg->outgoing_num_ports;
	size_t outtcpnum = cfg->outgoing_num_tcp;
	size_t misc = 4; /* logfile, pidfile, stdout... */
	size_t perthread_noudp = listen_num + outtcpnum + 
		2/*cmdpipe*/ + 2/*libevent*/ + misc; 
	size_t perthread = perthread_noudp + outudpnum;

#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
	int numthread = 1; /* it forks */
#else
	int numthread = (cfg->num_threads?cfg->num_threads:1);
#endif
	size_t total = numthread * perthread + misc;
	size_t avail;
	struct rlimit rlim;

	if(total > 1024 && 
		strncmp(event_get_version(), "mini-event", 10) == 0) {
		log_warn("too many file descriptors requested. The builtin"
			"mini-event cannot handle more than 1024. Config "
			"for less fds or compile with libevent");
		if(numthread*perthread_noudp+15 > 1024)
			fatal_exit("too much tcp. not enough fds.");
		cfg->outgoing_num_ports = (int)((1024 
			- numthread*perthread_noudp 
			- 10 /* safety margin */) /numthread);
		log_warn("continuing with less udp ports: %u",
			cfg->outgoing_num_ports);
		total = 1024;
	}
	if(perthread > 64 && 
		strncmp(event_get_version(), "winsock-event", 13) == 0) {
		log_err("too many file descriptors requested. The winsock"
			" event handler cannot handle more than 64 per "
			" thread. Config for less fds");
		if(perthread_noudp+2 > 64)
			fatal_exit("too much tcp. not enough fds.");
		cfg->outgoing_num_ports = (int)((64 
			- perthread_noudp 
			- 2/* safety margin */));
		log_warn("continuing with less udp ports: %u",
			cfg->outgoing_num_ports);
		total = numthread*(perthread_noudp+
			(size_t)cfg->outgoing_num_ports)+misc;
	}
	if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
		log_warn("getrlimit: %s", strerror(errno));
		return;
	}
	if(rlim.rlim_cur == (rlim_t)RLIM_INFINITY)
		return;
	if((size_t)rlim.rlim_cur < total) {
		avail = (size_t)rlim.rlim_cur;
		rlim.rlim_cur = (rlim_t)(total + 10);
		rlim.rlim_max = (rlim_t)(total + 10);
#ifdef HAVE_SETRLIMIT
		if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
			log_warn("setrlimit: %s", strerror(errno));
#else
		if(1) {
#endif
			log_warn("cannot increase max open fds from %u to %u",
				(unsigned)avail, (unsigned)total+10);
			/* check that calculation below does not underflow,
			 * with 15 as margin */
			if(numthread*perthread_noudp+15 > avail)
				fatal_exit("too much tcp. not enough fds.");
			cfg->outgoing_num_ports = (int)((avail 
				- numthread*perthread_noudp 
				- 10 /* safety margin */) /numthread);
			log_warn("continuing with less udp ports: %u",
				cfg->outgoing_num_ports);
			log_warn("increase ulimit or decrease threads, "
				"ports in config to remove this warning");
			return;
		}
		log_warn("increased limit(open files) from %u to %u",
			(unsigned)avail, (unsigned)total+10);
	}
#else	
	(void)cfg;
#endif /* HAVE_GETRLIMIT */
#endif /* S_SPLINT_S */
}

/** set verbosity, check rlimits, cache settings */
static void
apply_settings(struct daemon* daemon, struct config_file* cfg, 
	int cmdline_verbose)
{
	/* apply if they have changed */
	verbosity = cmdline_verbose + cfg->verbosity;
	daemon_apply_cfg(daemon, cfg);
	checkrlimits(cfg);
}
Ejemplo n.º 24
0
void NetworkServer::serve(){
	writer = new ProcWorkerPool("writer");
	writer->start(num_writers);
	reader = new ProcWorkerPool("reader");
	reader->start(num_readers);

	pthread_t tid;
	int err = pthread_create(&tid, NULL, &NetworkServer::_ops_timer_thread, this);
	if (err != 0) {
		log_error("can't start ops timer thread: %s", strerror(err));
		exit(-1);
	}

	link_dict_t ready_dict;
	link_dict_t tmp_dict;
	link_dict_t blocked_dict;
	link_dict_t::iterator it;
	const Fdevents::events_t *events;

	fdes->set(serv_link->fd(), FDEVENT_IN, 0, serv_link);
	fdes->set(this->reader->fd(), FDEVENT_IN, 0, this->reader);
	fdes->set(this->writer->fd(), FDEVENT_IN, 0, this->writer);

	uint32_t last_ticks = g_ticks;

	while(!quit){
		// status report
		if((uint32_t)(g_ticks - last_ticks) >= STATUS_REPORT_TICKS){
			last_ticks = g_ticks;
			log_debug("server running, links: %d", this->link_count);
		}

		ready_dict.swap(tmp_dict);
		tmp_dict.clear();

		if(!ready_dict.empty()){
			/* ready_dict not empty, so we should return immediately */
			events = fdes->wait(0);
		}else{
			events = fdes->wait(50);
		}
		if(events == NULL){
			log_fatal("events.wait error: %s", strerror(errno));
			break;
		}

		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			if(fde->data.ptr == serv_link){
				Link *link = accept_link();
				if(link){
					this->link_count ++;
					log_debug("new link from %s:%d, fd: %d, links: %d",
						link->remote_ip, link->remote_port, link->fd(), this->link_count);
					fdes->set(link->fd(), FDEVENT_IN, 1, link);
				}
			}else if(fde->data.ptr == this->reader || fde->data.ptr == this->writer){
				ProcWorkerPool *worker = (ProcWorkerPool *)fde->data.ptr;
				ProcJob job;
				if(worker->pop(&job) == 0){
					log_fatal("reading result from workers error!");
					exit(0);
				}
				if(proc_result(&job, &ready_dict) == PROC_ERROR){
					//
				}
			}else{
				proc_client_event(fde, &ready_dict);
			}
		}

		/* if clients paused, add specified link into blocked_list and disable parsing request */
		if(NetworkServer::clients_paused) {
			if(NetworkServer::clients_pause_end_time < time_ms()) {
				NetworkServer::clients_paused = 0;
				NetworkServer::clients_pause_end_time = 0;
				ready_dict.insert(blocked_dict.begin(), blocked_dict.end());
				blocked_dict.clear();
			} else {
				blocked_dict.insert(ready_dict.begin(), ready_dict.end());
				ready_dict.clear();
				continue;
			}
		}

		for(it = ready_dict.begin(); it != ready_dict.end(); it ++){
			Link *link = it->second;
			if(link->error()){
				this->link_count --;
				fdes->del(link->fd());
				delete link;
				continue;
			}

			const Request *req = link->recv();
			if(req == NULL){
				log_warn("fd: %d, link parse error, delete link", link->fd());
				this->link_count --;
				fdes->del(link->fd());
				delete link;
				continue;
			}
			if(req->empty()){
				fdes->set(link->fd(), FDEVENT_IN, 1, link);
				continue;
			}

			link->active_time = millitime();

			ProcJob job;
			job.link = link;
			this->proc(&job);
			if(job.result == PROC_THREAD){
				fdes->del(link->fd());
				continue;
			}
			if(job.result == PROC_BACKEND){
				fdes->del(link->fd());
				this->link_count --;
				continue;
			}

			if(proc_result(&job, &tmp_dict) == PROC_ERROR){
				//
			}
		} // end foreach ready link
	}
}
Ejemplo n.º 25
0
/**
 * @brief Interpreter
 * @param in Context structure
 * @return void
 *
 * An interpreter for configuration files. The context structure
 * contains the data to be passed to the interpreter.
 */
void
Interpreter(const struct Interpreter_in *in)
{
#define interpreter_message(string) \
    log_warn(0, "%s:%ld: Parse Error: %s", in->path, in->line_num, string)
    const char	*ccp = &in->line[0];
    char	*id  = NULL;
    char	*arg = NULL;

    if (!isalnum(*ccp) && *ccp != '_') {
	interpreter_message("Unexpected leading character");
	goto die;
    }

    id = copy_identifier(ccp);
    while (isalnum(*ccp) || *ccp == '_') {
	ccp++;
    }

    adv_while_isspace(&ccp);
    if (*ccp++ != '=') {
	interpreter_message("Expected expression after identifier");
	goto die;
    }

    adv_while_isspace(&ccp);
    if (*ccp++ != '\"') {
	interpreter_message("Expected statement after expression");
	goto die;
    } else if ((arg = copy_argument(ccp)) == NULL) {
	interpreter_message("Lacks ending quote for the argument");
	goto die;
    } else {
	;
    }

    while (*ccp++ != '\"') {
	;
    }

    adv_while_isspace(&ccp);
    if (*ccp++ != ';') {
	interpreter_message("No line terminator");
	goto die;
    }

    adv_while_isspace(&ccp);
    if (*ccp && *ccp != '#') {
	interpreter_message("Implicit data after line terminator");
	goto die;
    } else if ( !(in->validator_func(id)) ) { /* Unrecognized identifier. */
#if IGNORE_UNRECOGNIZED_IDENTIFIERS
	;
#else
	interpreter_message("No such identifier");
	goto die;
#endif
    } else if ((errno = in->install_func(id, arg)) != 0) {
	log_warn(errno, "%s:%ld: install_func returned %d", in->path, in->line_num, errno);
	goto die;
    } else {
	;
    }

    free_not_null(id);
    free_not_null(arg);
    return;

  die:
    free_not_null(id);
    free_not_null(arg);
    abort();
}
Ejemplo n.º 26
0
/** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
 * write the result to a newly allocated string that is pointed to by
 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
 * Return 0 if decryption was successful and -1 otherwise. */
int
rend_decrypt_introduction_points(char **ipos_decrypted,
                                 size_t *ipos_decrypted_size,
                                 const char *descriptor_cookie,
                                 const char *ipos_encrypted,
                                 size_t ipos_encrypted_size)
{
  tor_assert(ipos_encrypted);
  tor_assert(descriptor_cookie);
  if (ipos_encrypted_size < 2) {
    log_warn(LD_REND, "Size of encrypted introduction points is too "
                      "small.");
    return -1;
  }
  if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
    char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
         session_key[CIPHER_KEY_LEN], *dec;
    int declen, client_blocks;
    size_t pos = 0, len, client_entries_len;
    crypto_digest_t *digest;
    crypto_cipher_t *cipher;
    client_blocks = (int) ipos_encrypted[1];
    client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
                         REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
    if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
      log_warn(LD_REND, "Size of encrypted introduction points is too "
                        "small.");
      return -1;
    }
    memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
    digest = crypto_digest_new();
    crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
    crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
    crypto_digest_get_digest(digest, client_id,
                             REND_BASIC_AUTH_CLIENT_ID_LEN);
    crypto_digest_free(digest);
    for (pos = 2; pos < 2 + client_entries_len;
         pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
      if (tor_memeq(ipos_encrypted + pos, client_id,
                  REND_BASIC_AUTH_CLIENT_ID_LEN)) {
        /* Attempt to decrypt introduction points. */
        cipher = crypto_cipher_new(descriptor_cookie);
        if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
                                  + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
                                  CIPHER_KEY_LEN) < 0) {
          log_warn(LD_REND, "Could not decrypt session key for client.");
          crypto_cipher_free(cipher);
          return -1;
        }
        crypto_cipher_free(cipher);

        len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
        dec = tor_malloc_zero(len + 1);
        declen = crypto_cipher_decrypt_with_iv(session_key, dec, len,
            ipos_encrypted + 2 + client_entries_len,
            ipos_encrypted_size - 2 - client_entries_len);

        if (declen < 0) {
          log_warn(LD_REND, "Could not decrypt introduction point string.");
          tor_free(dec);
          return -1;
        }
        if (fast_memcmpstart(dec, declen, "introduction-point ")) {
          log_warn(LD_REND, "Decrypted introduction points don't "
                            "look like we could parse them.");
          tor_free(dec);
          continue;
        }
        *ipos_decrypted = dec;
        *ipos_decrypted_size = declen;
        return 0;
      }
    }
    log_warn(LD_REND, "Could not decrypt introduction points. Please "
             "check your authorization for this service!");
    return -1;
  } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
    char *dec;
    int declen;
    if (ipos_encrypted_size < CIPHER_IV_LEN + 2) {
      log_warn(LD_REND, "Size of encrypted introduction points is too "
                        "small.");
      return -1;
    }
    dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1 + 1);

    declen = crypto_cipher_decrypt_with_iv(descriptor_cookie, dec,
                                           ipos_encrypted_size -
                                               CIPHER_IV_LEN - 1,
                                           ipos_encrypted + 1,
                                           ipos_encrypted_size - 1);

    if (declen < 0) {
      log_warn(LD_REND, "Decrypting introduction points failed!");
      tor_free(dec);
      return -1;
    }
    *ipos_decrypted = dec;
    *ipos_decrypted_size = declen;
    return 0;
  } else {
    log_warn(LD_REND, "Unknown authorization type number: %d",
             ipos_encrypted[0]);
    return -1;
  }
}
Ejemplo n.º 27
0
static struct config *
config_load(const char *path)
{
	struct config	*conf;
	FILE		*fp;
	size_t		 flen;
	char		*key, *value, *buf, *lbuf;
	const char	*e;
	long long	 ll;

	lbuf = NULL;

	conf = calloc(1, sizeof(*conf));
	if (conf == NULL) {
		log_warn("warn: table-mysql: calloc");
		return (NULL);
	}

	dict_init(&conf->conf);
	dict_init(&conf->sources);

	conf->source_refresh = DEFAULT_REFRESH;
	conf->source_expire = DEFAULT_EXPIRE;

	fp = fopen(path, "r");
	if (fp == NULL) {
		log_warn("warn: table-mysql: fopen");
		goto end;
	}

	while ((buf = fgetln(fp, &flen))) {
		if (buf[flen - 1] == '\n')
			buf[flen - 1] = '\0';
		else {
			lbuf = malloc(flen + 1);
			if (lbuf == NULL) {
				log_warn("warn: table-mysql: malloc");
				goto end;
			}
			memcpy(lbuf, buf, flen);
			lbuf[flen] = '\0';
			buf = lbuf;
		}

		key = buf;
		while (isspace((unsigned char)*key))
			++key;
		if (*key == '\0' || *key == '#')
			continue;
		value = key;
		strsep(&value, " \t:");
		if (value) {
			while (*value) {
				if (!isspace((unsigned char)*value) &&
				    !(*value == ':' && isspace((unsigned char)*(value + 1))))
					break;
				++value;
			}
			if (*value == '\0')
				value = NULL;
		}

		if (value == NULL) {
			log_warnx("warn: table-mysql: missing value for key %s", key);
			goto end;
		}

		if (dict_check(&conf->conf, key)) {
			log_warnx("warn: table-mysql: duplicate key %s", key);
			goto end;
		}
		
		value = strdup(value);
		if (value == NULL) {
			log_warn("warn: table-mysql: malloc");
			goto end;
		}

		dict_set(&conf->conf, key, value);
	}

	if ((value = dict_get(&conf->conf, "fetch_source_expire"))) {
		e = NULL;
		ll = strtonum(value, 0, INT_MAX, &e);
		if (e) {
			log_warnx("warn: table-mysql: bad value for fetch_source_expire: %s", e);
			goto end;
		}
		conf->source_expire = ll;
	}
	if ((value = dict_get(&conf->conf, "fetch_source_refresh"))) {
		e = NULL;
		ll = strtonum(value, 0, INT_MAX, &e);
		if (e) {
			log_warnx("warn: table-mysql: bad value for fetch_source_refresh: %s", e);
			goto end;
		}
		conf->source_refresh = ll;
	}

	free(lbuf);
	fclose(fp);
	return (conf);

    end:
	free(lbuf);
	if (fp)
		fclose(fp);
	config_free(conf);
	return (NULL);
}
Ejemplo n.º 28
0
/** Parse the encoded introduction points in <b>intro_points_encoded</b> of
 * length <b>intro_points_encoded_size</b> and write the result to the
 * descriptor in <b>parsed</b>; return the number of successfully parsed
 * introduction points or -1 in case of a failure. */
int
rend_parse_introduction_points(rend_service_descriptor_t *parsed,
                               const char *intro_points_encoded,
                               size_t intro_points_encoded_size)
{
  const char *current_ipo, *end_of_intro_points;
  smartlist_t *tokens = NULL;
  directory_token_t *tok;
  rend_intro_point_t *intro;
  extend_info_t *info;
  int result, num_ok=1;
  memarea_t *area = NULL;
  tor_assert(parsed);
  /** Function may only be invoked once. */
  tor_assert(!parsed->intro_nodes);
  if (!intro_points_encoded || intro_points_encoded_size == 0) {
    log_warn(LD_REND, "Empty or zero size introduction point list");
    goto err;
  }
  /* Consider one intro point after the other. */
  current_ipo = intro_points_encoded;
  end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
  tokens = smartlist_new();
  parsed->intro_nodes = smartlist_new();
  area = memarea_new();

  while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
                      "introduction-point ")) {
    /* Determine end of string. */
    const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
                                 "\nintroduction-point ");
    if (!eos)
      eos = end_of_intro_points;
    else
      eos = eos+1;
    tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
    /* Free tokens and clear token list. */
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_clear(tokens);
    memarea_clear(area);
    /* Tokenize string. */
    if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
      log_warn(LD_REND, "Error tokenizing introduction point");
      goto err;
    }
    /* Advance to next introduction point, if available. */
    current_ipo = eos;
    /* Check minimum allowed length of introduction point. */
    if (smartlist_len(tokens) < 5) {
      log_warn(LD_REND, "Impossibly short introduction point.");
      goto err;
    }
    /* Allocate new intro point and extend info. */
    intro = tor_malloc_zero(sizeof(rend_intro_point_t));
    info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
    /* Parse identifier. */
    tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
    if (base32_decode(info->identity_digest, DIGEST_LEN,
                      tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
      log_warn(LD_REND, "Identity digest contains illegal characters: %s",
               tok->args[0]);
      rend_intro_point_free(intro);
      goto err;
    }
    /* Write identifier to nickname. */
    info->nickname[0] = '$';
    base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
                  info->identity_digest, DIGEST_LEN);
    /* Parse IP address. */
    tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
    if (tor_addr_parse(&info->addr, tok->args[0])<0) {
      log_warn(LD_REND, "Could not parse introduction point address.");
      rend_intro_point_free(intro);
      goto err;
    }
    if (tor_addr_family(&info->addr) != AF_INET) {
      log_warn(LD_REND, "Introduction point address was not ipv4.");
      rend_intro_point_free(intro);
      goto err;
    }

    /* Parse onion port. */
    tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
    info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
                                           &num_ok,NULL);
    if (!info->port || !num_ok) {
      log_warn(LD_REND, "Introduction point onion port %s is invalid",
               escaped(tok->args[0]));
      rend_intro_point_free(intro);
      goto err;
    }
    /* Parse onion key. */
    tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
    if (!crypto_pk_public_exponent_ok(tok->key)) {
      log_warn(LD_REND,
               "Introduction point's onion key had invalid exponent.");
      rend_intro_point_free(intro);
      goto err;
    }
    info->onion_key = tok->key;
    tok->key = NULL; /* Prevent free */
    /* Parse service key. */
    tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
    if (!crypto_pk_public_exponent_ok(tok->key)) {
      log_warn(LD_REND,
               "Introduction point key had invalid exponent.");
      rend_intro_point_free(intro);
      goto err;
    }
    intro->intro_key = tok->key;
    tok->key = NULL; /* Prevent free */
    /* Add extend info to list of introduction points. */
    smartlist_add(parsed->intro_nodes, intro);
  }
  result = smartlist_len(parsed->intro_nodes);
  goto done;

 err:
  result = -1;

 done:
  /* Free tokens and clear token list. */
  if (tokens) {
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_free(tokens);
  }
  if (area)
    memarea_drop_all(area);

  return result;
}
Ejemplo n.º 29
0
static rstatus_t
conf_validate_pool(struct conf *cf, struct conf_pool *cp)
{
    rstatus_t status;

    ASSERT(!cp->valid);
    ASSERT(!string_empty(&cp->name));

    if (!cp->listen.valid) {
        log_error("conf: directive \"listen:\" is missing");
        return NC_ERROR;
    }

    /* set default values for unset directives */

    if (cp->distribution == CONF_UNSET_DIST) {
        cp->distribution = CONF_DEFAULT_DIST;
    }

    if (cp->hash == CONF_UNSET_HASH) {
        cp->hash = CONF_DEFAULT_HASH;
    }

    if (cp->timeout == CONF_UNSET_NUM) {
        cp->timeout = CONF_DEFAULT_TIMEOUT;
    }

    if (cp->backlog == CONF_UNSET_NUM) {
        cp->backlog = CONF_DEFAULT_LISTEN_BACKLOG;
    }

    cp->client_connections = CONF_DEFAULT_CLIENT_CONNECTIONS;

    if (cp->redis != CONF_UNSET_NUM) {
        log_warn("conf: directive \"redis:\" is deprecated, "
                 "use \"protocol:\" instead");

        if (cp->proto != CONF_UNSET_PROTO &&
            (cp->redis || cp->proto != PROTO_MEMCACHED) &&
            (!cp->redis || cp->proto != PROTO_REDIS)) {

            log_error("conf: directive \"redis: %s\" is incompatible with "
                      "directive \"protocol: %s\"",
                      cp->redis ? "true" : "false",
                      proto_type_string(cp->proto));
            return NC_ERROR;
        }

        cp->proto = cp->redis ? PROTO_REDIS : PROTO_MEMCACHED;
    }

    if (cp->proto == CONF_UNSET_PROTO) {
        cp->proto = CONF_DEFAULT_PROTO;
    }

    if (cp->tcpkeepalive == CONF_UNSET_NUM) {
        cp->tcpkeepalive = CONF_DEFAULT_TCPKEEPALIVE;
    }

    if (cp->redis_db == CONF_UNSET_NUM) {
        cp->redis_db = CONF_DEFAULT_REDIS_DB;
    }

    if (cp->preconnect == CONF_UNSET_NUM) {
        cp->preconnect = CONF_DEFAULT_PRECONNECT;
    }

    if (cp->auto_eject_hosts == CONF_UNSET_NUM) {
        cp->auto_eject_hosts = CONF_DEFAULT_AUTO_EJECT_HOSTS;
    }

    if (cp->server_connections == CONF_UNSET_NUM) {
        cp->server_connections = CONF_DEFAULT_SERVER_CONNECTIONS;
    } else if (cp->server_connections == 0) {
        log_error("conf: directive \"server_connections:\" cannot be 0");
        return NC_ERROR;
    }

    if (cp->server_retry_timeout == CONF_UNSET_NUM) {
        cp->server_retry_timeout = CONF_DEFAULT_SERVER_RETRY_TIMEOUT;
    }

    if (cp->server_failure_limit == CONF_UNSET_NUM) {
        cp->server_failure_limit = CONF_DEFAULT_SERVER_FAILURE_LIMIT;
    }

    if (!cp->redis && cp->redis_auth.len > 0) {
        log_error("conf: directive \"redis_auth:\" is only valid for a redis pool");
        return NC_ERROR;
    }

    status = conf_validate_server(cf, cp);
    if (status != NC_OK) {
        return status;
    }

    cp->valid = 1;

    return NC_OK;
}
Ejemplo n.º 30
0
static void dps_statistics_process(void)
{
	PyObject *strret, *strargs;
	PyGILState_STATE gstate;
	char *domain_list_ret = NULL, *domain_list = NULL;
	char *str, *saveptr, *token;
	int domain;
	json_t *js_stats = NULL;  /* json statistics array of each domain */
	dps_object_load_balancing_t load_balancing;

	do
	{
		saveptr = NULL;
		/* No need to send the statistics */
		if(dps_statistics_send == 0){
			log_debug(PythonDataHandlerLogLevel, "Statistics has been set to NOT SENDING!");
			break;
		}
		// Ensure the PYTHON Global Interpreter Lock
		gstate = PyGILState_Ensure();
		// Domain_List_Get(self):
		strargs = Py_BuildValue("()");
		if (strargs == NULL)
		{
			// Release the PYTHON Global Interpreter Lock
			PyGILState_Release(gstate);
			log_warn(PythonDataHandlerLogLevel, "Py_BuildValue returns NULL");
			break;
		}
		// Invoke the Domain_List_Get call
		strret = PyEval_CallObject(Statistics_Interface.Domain_List_Get, strargs);
		Py_DECREF(strargs);

		if (strret == NULL)
		{
			// Release the PYTHON Global Interpreter Lock
			PyGILState_Release(gstate);
			log_warn(PythonDataHandlerLogLevel,
			         "PyEval_CallObject Domain_List_Get returns NULL");
			break;
		}
		//@return: The string of all Domain IDs
		//@rtype: String
		PyArg_Parse(strret, "z", &domain_list_ret);
		domain_list = strdup(domain_list_ret);
		// Lose the reference on all parameters and return arguments since they
		// are no longer needed.
		Py_DECREF(strret);
		// Release the PYTHON Global Interpreter Lock
		PyGILState_Release(gstate);

		if (!statistics_need_send_to_leader)
		{
			log_info(RESTHandlerLogLevel, "Not sending stats to leader");
			break;
		}

		js_stats = json_array();
		if(js_stats == NULL)
		{
			log_warn(RESTHandlerLogLevel, "Cannot allocate json_array");
			break;
		}
		//Parse domain list and collect statistics for every domain
		for (str = domain_list; ; str = NULL)
		{
			if ((token = strtok_r(str, ",", &saveptr)) == NULL)
			{
				break;
			}
			domain = atoi(token);
			dps_statistics_update_per_domain(domain);
			//TODO: Get statistics and push it to requestor
			//Currently the pushing action is OK, but now it is turned off,
			//it should be turned on when the system is actually deployed
			memset(&load_balancing, 0, sizeof(load_balancing));
			load_balancing.domain_id = domain;
			dps_statistics_domain_load_balancing_get(&load_balancing);
			if(dps_statistics_array_append(js_stats, &load_balancing) != DOVE_STATUS_OK)
			{
				log_error(RESTHandlerLogLevel,
				          "Cannot append statistics for domain %d",
				          domain);
				json_decref(js_stats);
				js_stats = NULL;
				break;
			}
		}
		if (js_stats == NULL)
		{
			break;
		}

		log_info(RESTHandlerLogLevel, "Send statistics to LEADER!");
		dps_statistics_report_to_cluster_leader(js_stats);

	}while(0);

	if (domain_list != NULL)
	{
		free(domain_list);
	}

	return;
}