void hashmap_enter(hashmap *hm, void *key, void *value)
{
	assert (key != NULL && value != NULL);
	int pos = hm->hash_fun(key, hm->num_buckets) + 1;
	assert (pos > 0 && pos <= hm->num_buckets);
	vector* target = (struct vector*) (hm->pairs + pos);

	pair* p;
	if ((p = malloc(sizeof(pair))) == NULL) {
		printf("memory allocation error in pair creation.\n");
		exit(0);
	}
	p->key = key;
	p->value = value;

	if (target->len == 0) {
		vector_append(target, p);
		vector_append(hm->used_buckets, &pos);
	} else {
		int exists = vector_search(target, key, hm->compare_fun, 0, false);
		if (exists == -1) {
			vector_append(target, p);
		} else {
			printf("The key %d already exists.\n", *(int*) p->key);
		}
	}
	if (hm->free_fun != NULL)
		hm->free_fun(p);
	free(p);
	p = NULL;
}
예제 #2
0
void ip_knocked_handle( struct vector *ip_knock_stats, const char *ip ) {

	assert( ip_knock_stats != NULL && ip != NULL );

	struct ip_knocked_info to_find;
	to_find.ip = ip_to_uint( ip );

	int index = vector_search( ip_knock_stats, &to_find, ip_knocked_info_cmp );

	if( index != -1 ) {

		// IP already knocked, check if it should be banned.
		struct ip_knocked_info *knock_info = vector_get( ip_knock_stats, index );
		if( knock_info->knock_count > pss_configuration.max_knock_count ) {
			ban_ip( ip );
			vector_delete_el( ip_knock_stats, index, free );
		} else {
			++knock_info->knock_count;
		}

	} else {

		// IP knocked for the first time, add to vector.
		vector_add( ip_knock_stats, ip_knocked_info_create( ip ) );

	}

}
예제 #3
0
int main() {
  
  srand(time(NULL));

  int size = 15;
  int generations = 15;
  int print_gen = 1;
  Vector *V = vector_make(size);

  int i;
  int j = 1;
  for(;j <= generations; j++) {
    if(j % print_gen == 0) { printf("on gen %d\n", j); }
    i = 0;
    for(;i<size;i++) {
      int *tmp = malloc(sizeof(int));
      *tmp = rand() % 20;
      vector_ref(V, i, tmp); 
    }
    int *tmp = malloc(sizeof(int));
    *tmp = 5;
    if(vector_search(V, tmp, comparator) != -1) { printf("found\n"); }
    vector_walk(V, print);
    printf("\n");
  }
  vector_free(V, 1);
  return 0;
}
예제 #4
0
파일: nsdispatch.c 프로젝트: 2asoft/freebsd
/*
 * Finally, the actual implementation.
 */
static nss_method
nss_method_lookup(const char *source, const char *database,
    const char *method, const ns_dtab disp_tab[], void **mdata)
{
	ns_mod	*mod;
	ns_mtab	*match, key;
	int	 i;

	if (disp_tab != NULL)
		for (i = 0; disp_tab[i].src != NULL; i++)
			if (strcasecmp(source, disp_tab[i].src) == 0) {
				*mdata = disp_tab[i].mdata;
				return (disp_tab[i].method);
			}
	mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
	    string_compare);
	if (mod != NULL && mod->handle != NULL) {
		key.database = database;
		key.name = method;
		match = bsearch(&key, mod->mtab, mod->mtabsize,
		    sizeof(mod->mtab[0]), mtab_compare);
		if (match != NULL) {
			*mdata = match->mdata;
			return (match->method);
		}
	}

	*mdata = NULL;
	return (NULL);
}
예제 #5
0
END_TEST

START_TEST (search_should_fail_if_element_not_found)
{

  int num1 = 12, num2 = 22, num3 = 42;

  vector *v = vector_new(sizeof(int *), NULL, 5);
  vector_append(v, &num1);
  vector_append(v, &num2);

  fail_unless(vector_search(v, &num3, compare_ints, 0, false) == VECT_SEARCH_NOT_FOUND);
  fail_unless(vector_search(v, &num3, compare_ints, 0, true) == VECT_SEARCH_NOT_FOUND);

  vector_free(v);
}
int checkDocForOtherKeys(BTreeKey** keys, int nKeys, char* url)
{
  int i;
  for (i = 0; i < nKeys; i++)
    if (!vector_search(keys[i]->mInfo, url))
      return 0;

  return 1;
}
예제 #7
0
END_TEST

START_TEST (search_should_fail_if_invalid_start_parameter)
{

  int num1 = 12, num2 = 22, num3 = 23;

  vector *v = vector_new(sizeof(int *), NULL, 5);
  vector_append(v, &num1);
  vector_append(v, &num2);
  vector_append(v, &num3);

  fail_unless(vector_search(v, &num1, compare_ints, -2, false) == VECT_SEARCH_INVALID_START);
  fail_unless(vector_search(v, &num2, compare_ints, 3, false) == VECT_SEARCH_INVALID_START);
  fail_unless(vector_search(v, &num1, compare_ints, -2, true) == VECT_SEARCH_INVALID_START);
  fail_unless(vector_search(v, &num2, compare_ints, 3, true) == VECT_SEARCH_INVALID_START);

  vector_free(v);
}
void* hashmap_get_value(const hashmap* hm, const void* key)
{
	int pos = hm->hash_fun(key, hm->num_buckets) + 1;
	vector* target = (struct vector*) (hm->pairs + pos);

	int pos_in_vector = vector_search(target, key, hm->compare_fun, 0, false);
	pair* temp = vector_get(target, pos_in_vector);

	return temp->value;
}
예제 #9
0
END_TEST

START_TEST (search_should_fail_if_invalid_key)
{


  vector *v = vector_new(sizeof(int *), NULL, 5);
  fail_unless(vector_search(v, NULL, compare_ints, 0, false) == VECT_SEARCH_INVALID_KEY);

  vector_free(v);
}
예제 #10
0
파일: nsdispatch.c 프로젝트: 2asoft/freebsd
/*
 * NSS nsmap management.
 */
void
_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
{
	const ns_mod	*modp;

	dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
	    sizeof(*src));
	modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
	    string_compare);
	if (modp == NULL)
		nss_load_module(src->name, NULL);
}
void addPositionVector(Vector* vec, char* url, int pos)
{
  VectorNode* node = vector_search(vec, url);

  if (!node)
  {
    node = vector_newVectorNode(url);
    vector_push(vec, node);
  }

  addPositionVectorNode(node, pos);
}
예제 #12
0
void ip_knocked( const char *ip, int port, struct vector *knock_stats, int prot_type ) {

	assert( ip != NULL && knock_stats != NULL );

	static int knock_no = 0;

	/* When IP is banned, it is deleted from vector. To not waste to much memory,
	shrink them to minimum size, everytime the counter knock_no hits specified number. */
	if( knock_no % SHRINK_VECTORS_EVERY_N_KNOCKS == 0 ) {
		vector_shrink_to_fit( knock_stats );
	}

	++knock_no;

	if( vector_search( pss_configuration.ip_whitelist, (void *)ip, ip_bitmask_cmp ) != -1 ) {
		return; // Ip whitelisted, ignore.
	}

	// Check if port is specified in config, if yes - take care of the IP.
	if( prot_type == P_TCP ) {

		if( vector_search( pss_configuration.tcp_trap_ports, &port, port_in_range ) != -1 ) {
			ip_knocked_handle( knock_stats, ip );
		}

	} else if( prot_type == P_UDP ) {

		if( vector_search( pss_configuration.udp_trap_ports, &port, port_in_range ) != -1 ) {
			ip_knocked_handle( knock_stats, ip );
		}

	} else {
		pss_log( "Wrong parameter passed to ip_knocked() function.\n" );
	}

}
예제 #13
0
END_TEST

START_TEST (search_should_return_element_position)
{

  int num1 = 12, num2 = 22, num3 = 23;

  vector *v = vector_new(sizeof(int *), NULL, 5);
  vector_append(v, &num1);
  vector_append(v, &num2);
  vector_append(v, &num3);

  fail_unless(vector_search(v, &num1, compare_ints, 0, false) == 0);
  fail_unless(vector_search(v, &num2, compare_ints, 0, false) == 1);
  fail_unless(vector_search(v, &num3, compare_ints, 0, false) == 2);

  fail_unless(vector_search(v, &num1, compare_ints, 0, true) == 0);
  fail_unless(vector_search(v, &num2, compare_ints, 0, true) == 1);
  fail_unless(vector_search(v, &num3, compare_ints, 0, true) == 2);

  vector_free(v);
}
예제 #14
0
END_TEST

START_TEST (search_should_ignore_everything_before_start_parameter)
{

  int num1 = 12, num2 = 22, num3 = 23, num4 = 30, num5 = 34;

  vector *v = vector_new(sizeof(int *), NULL, 5);
  vector_append(v, &num1);
  vector_append(v, &num2);
  vector_append(v, &num3);
  vector_append(v, &num4);
  vector_append(v, &num5);

  fail_unless(vector_search(v, &num1, compare_ints, 1, false) == VECT_SEARCH_NOT_FOUND);
  fail_unless(vector_search(v, &num2, compare_ints, 2, false) == VECT_SEARCH_NOT_FOUND);
  fail_unless(vector_search(v, &num5, compare_ints, 2, false) == 4);

  fail_unless(vector_search(v, &num1, compare_ints, 1, true) == VECT_SEARCH_NOT_FOUND);
  fail_unless(vector_search(v, &num2, compare_ints, 2, true) == VECT_SEARCH_NOT_FOUND);
  fail_unless(vector_search(v, &num5, compare_ints, 2, true) == 4);

  vector_free(v);
}
예제 #15
0
파일: nsdispatch.c 프로젝트: 2asoft/freebsd
int
_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
	    const char *method_name, const ns_src defaults[], ...)
{
	va_list		 ap;
	const ns_dbt	*dbt;
	const ns_src	*srclist;
	nss_method	 method, fb_method;
	void		*mdata;
	int		 isthreaded, serrno, i, result, srclistsize;
	struct fb_state	*st;
	int		 saved_depth;

#ifdef NS_CACHING
	nss_cache_data	 cache_data;
	nss_cache_data	*cache_data_p;
	int		 cache_flag;
#endif
	
	dbt = NULL;
	fb_method = NULL;

	isthreaded = __isthreaded;
	serrno = errno;
	if (isthreaded) {
		result = _pthread_rwlock_rdlock(&nss_lock);
		if (result != 0) {
			result = NS_UNAVAIL;
			goto fin;
		}
	}

	result = fb_getstate(&st);
	if (result != 0) {
		result = NS_UNAVAIL;
		goto fin;
	}

	result = nss_configure();
	if (result != 0) {
		result = NS_UNAVAIL;
		goto fin;
	}
	++st->dispatch_depth;
	if (st->dispatch_depth > st->fallback_depth) {
		dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
		    string_compare);
		fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
		    method_name, disp_tab, &mdata);
	}

	if (dbt != NULL) {
		srclist = dbt->srclist;
		srclistsize = dbt->srclistsize;
	} else {
		srclist = defaults;
		srclistsize = 0;
		while (srclist[srclistsize].name != NULL)
			srclistsize++;
	}

#ifdef NS_CACHING
	cache_data_p = NULL;
	cache_flag = 0;
#endif
	for (i = 0; i < srclistsize; i++) {
		result = NS_NOTFOUND;
		method = nss_method_lookup(srclist[i].name, database,
		    method_name, disp_tab, &mdata);

		if (method != NULL) {
#ifdef NS_CACHING
			if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 &&
			    nss_cache_cycle_prevention_func == NULL) {
#ifdef NS_STRICT_LIBC_EID_CHECKING
				if (issetugid() != 0)
					continue;
#endif
				cache_flag = 1;

				memset(&cache_data, 0, sizeof(nss_cache_data));
				cache_data.info = (nss_cache_info const *)mdata;
				cache_data_p = &cache_data;

				va_start(ap, defaults);
				if (cache_data.info->id_func != NULL)
					result = __nss_common_cache_read(retval,
					    cache_data_p, ap);
				else if (cache_data.info->marshal_func != NULL)
					result = __nss_mp_cache_read(retval,
					    cache_data_p, ap);
				else
					result = __nss_mp_cache_end(retval,
					    cache_data_p, ap);
				va_end(ap);
			} else {
				cache_flag = 0;
				errno = 0;
				va_start(ap, defaults);
				result = method(retval, mdata, ap);
				va_end(ap);
			}
#else /* NS_CACHING */
			errno = 0;
			va_start(ap, defaults);
			result = method(retval, mdata, ap);
			va_end(ap);
#endif /* NS_CACHING */

			if (result & (srclist[i].flags))
				break;
		} else {
			if (fb_method != NULL) {
				saved_depth = st->fallback_depth;
				st->fallback_depth = st->dispatch_depth + 1;
				va_start(ap, defaults);
				result = fb_method(retval,
				    (void *)srclist[i].name, ap);
				va_end(ap);
				st->fallback_depth = saved_depth;
			} else
				nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
				    "and no fallback provided",
				    srclist[i].name, database, method_name);
		}
	}

#ifdef NS_CACHING
	if (cache_data_p != NULL &&
	    (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) {
		va_start(ap, defaults);
		if (result == NS_SUCCESS) {
			if (cache_data.info->id_func != NULL)
				__nss_common_cache_write(retval, cache_data_p,
				    ap);
			else if (cache_data.info->marshal_func != NULL)
				__nss_mp_cache_write(retval, cache_data_p, ap);
		} else if (result == NS_NOTFOUND) {
			if (cache_data.info->id_func == NULL) {
				if (cache_data.info->marshal_func != NULL)
					__nss_mp_cache_write_submit(retval,
					    cache_data_p, ap);
			} else
				__nss_common_cache_write_negative(cache_data_p);
		}
		va_end(ap);
	}
#endif /* NS_CACHING */

	if (isthreaded)
		(void)_pthread_rwlock_unlock(&nss_lock);
	--st->dispatch_depth;
fin:
	errno = serrno;
	return (result);
}
예제 #16
0
/* the volatile qualifiers should be removed as well.                  */ 
int callmgr_main(int argc, char **argv, char **envp) {
  struct in_addr inetaddr;
  int inet_sock, unix_sock;
  fd_set call_set;
  PPTP_CONN * conn;
  VECTOR * call_list;
  int max_fd=0;
  volatile int first=1;
  int retval;
  int i;
  char * volatile phonenr;

  /* Step 0: Check arguments */
  if (argc < 2) 
    fatal("Usage: %s ip.add.ress.here [--phone <phone number>]", argv[0]);
  phonenr = argc==3 ? argv[2] : NULL;
  if (inet_aton(argv[1], &inetaddr)==0)
    fatal("Invalid IP address: %s", argv[1]);

  /* Step 1: Open sockets. */
  if ((inet_sock = open_inetsock(inetaddr)) < 0)
    fatal("Could not open control connection to %s", argv[1]);
  if ((unix_sock = open_unixsock(inetaddr)) < 0)
    fatal("Could not open unix socket for %s", argv[1]);

  /* Step 1b: FORK and return status to calling process. */
  switch (fork()) {
  case 0: /* child. stick around. */
    break;
  case -1: /* failure.  Fatal. */
    fatal("Could not fork.");
  default: /* Parent. Return status to caller. */
    exit(0);
  }

  /* re-open stderr as /dev/null to release it */
  file2fd("/dev/null", "wb", STDERR_FILENO);

  /* Step 1c: Clean up unix socket on TERM */
  if (sigsetjmp(callmgr_env, 1)!=0)
    goto cleanup;

  signal(SIGINT, callmgr_sighandler);
  signal(SIGTERM, callmgr_sighandler);

  signal(SIGPIPE, callmgr_do_nothing);
  signal(SIGUSR1, callmgr_do_nothing); /* signal state change; wake up accept */

  /* Step 2: Open control connection and register callback */
  if ((conn = pptp_conn_open(inet_sock, 1, NULL/* callback */)) == NULL) {
    close(unix_sock); close(inet_sock); fatal("Could not open connection.");
  }

  FD_ZERO(&call_set);
  max_fd = unix_sock;
  call_list = vector_create();
  { 
    struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
    if (conninfo==NULL) {
      close(unix_sock); close(inet_sock); fatal("No memory.");
    }
    conninfo->call_list = call_list;
    conninfo->call_set  = &call_set;
    pptp_conn_closure_put(conn, conninfo);
  }

  if (sigsetjmp(callmgr_env, 1)!=0) goto shutdown;

  /* Step 3: Get FD_SETs */
  do {
    int rc;
    fd_set read_set = call_set, write_set;
    FD_ZERO (&write_set);
    FD_SET (unix_sock, &read_set);
    pptp_fd_set(conn, &read_set, &write_set, &max_fd);

    for (; max_fd > 0 ; max_fd--) {
      if (FD_ISSET (max_fd, &read_set) ||
          FD_ISSET (max_fd, &write_set))
        break;
    }

    /* Step 4: Wait on INET or UNIX event */

    if ((rc = select(max_fd+1, &read_set, &write_set, NULL, NULL)) <0)
      /* a signal or somesuch. */
      continue;

    /* Step 5a: Handle INET events */
    pptp_dispatch(conn, &read_set, &write_set);

    /* Step 5b: Handle new connection to UNIX socket */
    if (FD_ISSET(unix_sock, &read_set)) {
      /* New call! */
      struct sockaddr_un from;
      int len = sizeof(from);
      PPTP_CALL * call;
      struct local_callinfo *lci;
      int s;

      /* Accept the socket */
      FD_CLR (unix_sock, &read_set);
      if ((s = accept(unix_sock, (struct sockaddr *) &from, &len))<0) {
	warn("Socket not accepted: %s", strerror(errno));
	goto skip_accept;
      }
      /* Allocate memory for local call information structure. */
      if ((lci = malloc(sizeof(*lci))) == NULL) {
	warn("Out of memory."); close(s); goto skip_accept;
      }
      lci->unix_sock = s;

      /* Give the initiator time to write the PIDs while we open the call */
      call = pptp_call_open(conn, call_callback, phonenr);
      /* Read and store the associated pids */
      read(s, &lci->pid[0], sizeof(lci->pid[0]));
      read(s, &lci->pid[1], sizeof(lci->pid[1]));
      /* associate the local information with the call */
      pptp_call_closure_put(conn, call, (void *) lci);
      /* The rest is done on callback. */
      
      /* Keep alive; wait for close */
      retval = vector_insert(call_list, s, call); assert(retval);
      if (s > max_fd) max_fd = s;
      FD_SET(s, &call_set);
      first = 0;
    }
  skip_accept:
    /* Step 5c: Handle socket close */
    for (i=0; i<max_fd+1; i++)
      if (FD_ISSET(i, &read_set)) {
	/* close it */
	PPTP_CALL * call;
	retval = vector_search(call_list, i, &call);
	if (retval) {
	  struct local_callinfo *lci = pptp_call_closure_get(conn, call);
          log("Closing connection");
	  if(lci->pid[0]) kill(lci->pid[0], SIGTERM);
	  if(lci->pid[1]) kill(lci->pid[1], SIGTERM);
	  free(lci);
	  /* soft shutdown.  Callback will do hard shutdown later */
	  pptp_call_close(conn, call);
	  vector_remove(call_list, i);
	}
	FD_CLR(i, &call_set);
	close(i);
      }
  } while (vector_size(call_list)>0 || first);

shutdown:
  {
    fd_set read_set, write_set;

    /* warn("Shutdown"); */
    /* kill all open calls */
    for (i=0; i<vector_size(call_list); i++) {
      PPTP_CALL *call = vector_get_Nth(call_list, i);
      struct local_callinfo *lci = pptp_call_closure_get(conn, call);
      log("Closing connection");
      pptp_call_close(conn, call);
      if(lci->pid[0]) kill(lci->pid[0], SIGTERM);
      if(lci->pid[1]) kill(lci->pid[1], SIGTERM);
    }
    /* attempt to dispatch these messages */
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    pptp_fd_set(conn, &read_set, &write_set, &max_fd);
    FD_ZERO(&read_set);
    pptp_dispatch(conn, &read_set, &write_set);
    if (i>0) sleep(2);
    /* no more open calls.  Close the connection. */
    pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN);
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    pptp_fd_set(conn, &read_set, &write_set, &max_fd);
    FD_ZERO(&read_set);
    pptp_dispatch(conn, &read_set, &write_set);
    sleep(2);
    /* with extreme prejudice */
    pptp_conn_destroy(conn);
    vector_destroy(call_list);
  }
cleanup:
  close_inetsock(inet_sock, inetaddr);
  close_unixsock(unix_sock, inetaddr);
  return 0;
}
예제 #17
0
int main(int argc, char **argv)
{
    vector *v;
    string *s;
    string **tmp;
    string *sup;
    int i;

    v = vector_init(stcmp);
    sup = string_init_cstring("6");

    while(--argc)
    {
        s = string_init_cstring(argv[argc]);
        vector_append(v, s);
    }

    printf("size: %d\n", v->len);

    printf("---\n");

    /* Print. */
    for(i = 0; i < v->len; ++i)
        string_println(vector_get(v, i));

    printf("---\n");

    /* Sort and print again. */
    vector_sort(v);
    for(i = 0; i < v->len; ++i)
        string_println(vector_get(v, i));

    printf("---\n");

    /* Search for sup. */
    if(vector_index(v, sup) != -1)
        string_print(sup), printf(" found.\n");
    else
        string_print(sup), printf(" not found.\n");

    printf("---\n");

    /* Using bsearch. */
    tmp = vector_search(v, sup);

    if(tmp)
    {
        string_print(*tmp);
        printf(" found using bsearch.\n");
    }
    else
    {
        string_print(sup);
        printf(" bsearch failed.\n");
    }

    printf("---\n");

    /* Shuffle and print again. */
    vector_shuffle(v);

    for(i = 0; i < v->len; ++i)
        string_println(vector_get(v, i));

    printf("---\n");

    for(i = 0; i < v->len; ++i)
        string_free(vector_get(v, i));

    string_free(sup);
    vector_free(v);

    return 0;
}
예제 #18
0
파일: pptp_callmgr.c 프로젝트: OPSF/uClinux
/* Call Manager */
int main(int argc, char **argv, char **envp) {
  struct in_addr inetaddr;
  int inet_sock, unix_sock;
  fd_set call_set;
  PPTP_CONN * conn;
  VECTOR * call_list;
  int max_fd=0;
  int first=1;
  int retval;
  int i;

  openlog("pptp_callmgr", LOG_PID, 0);

  /* Step 0: Check arguments */
  if (argc!=2){
    logmsg("Usage: %s ip.add.ress.here", argv[0]);
	exit(0);
  }
  if (inet_aton(argv[1], &inetaddr)==0){
    logmsg("Invalid IP address: %s", argv[1]);
	exit(0);
  }

  /*
  We need to connect to the unxisocket first becasue of the way this program
  is launched.  We need to check if we can bind to the Unix socket to see if we 
  have already started.
  */
  if ((unix_sock = open_unixsock(inetaddr)) < 0){
    logmsg("Could not open unix socket for %s", argv[1]);
	exit(0); /*Exit because there is nothing yet to be done in here*/
  }

  if ((inet_sock = open_inetsock(inetaddr)) < 0){  /* Step 1: Open sockets. */
    logmsg("Could not open control connection to %s", argv[1]);
	close_unixsock(unix_sock, inetaddr);
	sleep(2); /* so we don't respawn too quickly and annoy init */
	exit(0);
  }

#if 0 /* we are already an execing program if 2 exec model chosen */
  /* Step 1b: FORK and return status to calling process. */
  switch (fork()) {
  case 0: /* child. stick around. */
    break;
  default: /* Parent. Return status to caller. */
    exit(0);
  }
#endif

  /* Step 1c: Clean up unix socket on TERM */
  signal(SIGINT, sighandler);
  signal(SIGTERM, sighandler);
  signal(SIGKILL, sighandler);
  if (sigsetjmp(env, 1)!=0) goto cleanup;
  signal(SIGPIPE, do_nothing);
  signal(SIGUSR1, do_nothing); /* signal state change; wake up accept */

  /* Step 2: Open control connection and register callback */
  if ((conn = pptp_conn_open(inet_sock, 1, NULL/* callback */)) == NULL) {
    logmsg("Could not open connection.");
	sleep(2); /* so we don't respawn too quickly and annoy init */
	goto cleanup;
  }

  pptp_debug("Call Mgr Started for %s", argv[1]);

  FD_ZERO(&call_set);
  max_fd = inet_sock > unix_sock ? inet_sock : unix_sock;
  call_list = vector_create();
  { 
    struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
    if (conninfo==NULL) {
      logmsg("No memory.");
	  goto cleanup;
    }
    conninfo->call_list = call_list;
    conninfo->call_set  = &call_set;
    pptp_conn_closure_put(conn, conninfo);
  }

  if (sigsetjmp(env, 1)!=0) { pptp_debug("signalled!"); goto shutdown; }

  setpgrp(); /* stop our dad from killing us */

  /* Step 3: Get FD_SETs */
  do {
    fd_set read_set, write_set, excpt_set = call_set;
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
	read_set = call_set; /* need to remember the calls */
	if (pptp_conn_established(conn) && unix_sock != -1)
      FD_SET(unix_sock, &read_set);
    pptp_fd_set(conn, &read_set, &write_set);

    /* Step 4: Wait on INET or UNIX event */
    if (select(max_fd+1, &read_set, &write_set, &excpt_set, NULL)<0) {
	  if (errno != EINTR) {
		logmsg("select: %s", strerror(errno));
	  }
	  sleep(1); /* hope the error goes away,  but be nice to the host also */
      /* a signal or somesuch. */
      continue;
	}

    /* Step 5a: Handle INET events */
    pptp_dispatch(conn, &read_set, &write_set);

    /* Step 5b: Handle new connection to UNIX socket */
    if (unix_sock >= 0 && FD_ISSET(unix_sock, &read_set)) {
      /* New call! */
      struct sockaddr_un from;
      int len = sizeof(from);
      PPTP_CALL * call;
      struct local_callinfo *lci;
      int s;

      /* Accept the socket */
      if ((s = accept(unix_sock, (struct sockaddr *) &from, &len))<0) {
		logmsg("Socket not accepted: %s", strerror(errno));
		goto skip_accept;
      }
	  pptp_debug("accepting unixsock %d", s);
      /* Allocate memory for local call information structure. */
      if ((lci = malloc(sizeof(*lci))) == NULL) {
		logmsg("Out of memory.");
		close(s);
		goto skip_accept;
      }
      lci->unix_sock = s;

      /* Give the initiator time to write the PIDs while we open the call */
      call = pptp_call_open(conn, call_callback);
	  if (call == NULL){
	    logmsg("Couldn't allocate new call");
	    close(s);
	    goto skip_accept;
	  }
      /* Read and store the associated pids */
	  pptp_debug("Waiting to read the pids");
      read(s, &lci->pid[0], sizeof(lci->pid[0]));
	  pptp_debug("pids read!!");
      /* associate the local information with the call */
      pptp_call_closure_put(conn, call, (void *) lci);
      /* The rest is done on callback. */
      
      /* Keep alive; wait for close */
      retval = vector_insert(call_list, s, call); assert(retval);
      if (s > max_fd) max_fd = s;
        FD_SET(s, &call_set);
      first = 0;
    }
  skip_accept:
  	if (pptp_conn_down(conn)) {
      logmsg("conn down!");
	  goto shutdown;
	}
    /* Step 5c: Handle socket close */
    for (i=0; i<=max_fd; i++) {
      if (FD_ISSET(i, &call_set) &&
	  		(FD_ISSET(i, &excpt_set) || FD_ISSET(i, &read_set))) {
	/* close it */
	PPTP_CALL * call;

	pptp_debug("exception/data on fd %d", i);
	retval = vector_search(call_list, i, &call);
	if (retval) {
#if 1
	  struct local_callinfo *lci = pptp_call_closure_get(conn, call);
	  if (lci) {
	  kill(lci->pid[0], SIGTERM);
      memset(lci, 0, sizeof(*lci));
	  free(lci);
	  }
	  pptp_call_closure_put(conn, call, NULL);
	  vector_remove(call_list, i);
#endif
	  /* soft shutdown.  Callback will do hard shutdown later */
	  pptp_call_close(conn, call);
	}
	FD_CLR(i, &call_set);
	pptp_debug("closing unixsock %d", i);
	close(i);
      }
	}
  } while (!pptp_conn_down(conn) && (vector_size(call_list)>0 || first));

  logmsg("Callmanager has no more calls ! exiting");
shutdown:
  pptp_debug("Shutdown");
  /* make sure we clean up properly if interrupted during shutdown */
  signal(SIGINT, sighandler);
  signal(SIGTERM, sighandler);
  signal(SIGKILL, sighandler);
  if (sigsetjmp(env, 1)!=0) goto cleanup;

  if (!pptp_conn_down(conn)) {
    fd_set read_set, write_set;

    pptp_debug("Shutdown cleanly");
    /* kill all open calls */
    for (i=0; i<vector_size(call_list); i++) {
      PPTP_CALL *call = vector_get_Nth(call_list, i);
      struct local_callinfo *lci = pptp_call_closure_get(conn, call);
	  if (lci) {
      kill(lci->pid[0], SIGTERM);
	  }
      pptp_call_close(conn, call);
    }
    /* attempt to dispatch these messages */
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    pptp_fd_set(conn, &read_set, &write_set);
    FD_ZERO(&read_set);
    pptp_dispatch(conn, &read_set, &write_set);
    if (i>0) sleep(2);
    /* no more open calls.  Close the connection. */
    pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN);
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    pptp_fd_set(conn, &read_set, &write_set);
    FD_ZERO(&read_set);
    pptp_dispatch(conn, &read_set, &write_set);
    sleep(2);
    /* with extreme prejudice */
    pptp_conn_destroy(conn, 1);
    vector_destroy(call_list);
  }

cleanup:
  close_inetsock(inet_sock, inetaddr);
  inet_sock = -1;
  close_unixsock(unix_sock, inetaddr);
  unix_sock = -1;
  pptp_debug("Gone");
  return 0;
}
예제 #19
0
static void
kerext_debug_process(void *args) {
	PROCESS							*prp;
	THREAD							*thp, *act = actives[KERNCPU];
	DEBUG							*dep;
	struct kerargs_debug_process	*kap = args;
	int								status;
	int								stopped;
	int								tid;

	if(!(prp = lookup_pid(kap->pid))) {
		kererr(act, ESRCH);
		return;
	}

	dep = prp->debugger;

	if(kap->request == NTO_DEBUG_PROCESS_INFO || (prp->flags & _NTO_PF_TERMING)) {
		tid = 0;
	} else if(dep && kap->tid == 0) {
		tid = dep->tid + 1;
	} else {
		tid = kap->tid;
	}

	thp = 0;
	if(tid > 0 && !(thp = vector_search(&prp->threads, tid - 1,
			(kap->request == NTO_DEBUG_THREAD_INFO ||
			kap->request == NTO_DEBUG_STOP) ? (unsigned *)&tid : 0))) {
		kererr(act, ESRCH);
		return;
	}

	stopped = 0;
	if(thp && ((thp->flags & _NTO_TF_TO_BE_STOPPED) ||
			(thp->state != STATE_RUNNING && thp->state != STATE_READY))) {
		stopped = 1;
	}

	status = EINVAL;
	switch(kap->request) {
	case NTO_DEBUG_PROCESS_INFO:		// pid:na:debug_process_t
		status =  debug_process(prp, &kap->data->process);
		break;

	case NTO_DEBUG_THREAD_INFO:			// pid:tid:debug_thread_t
		status = debug_thread(prp, thp, &kap->data->thread);
		break;

	case NTO_DEBUG_GET_GREG:			// pid:tid:debug_greg_t
		if(thp) {
			memcpy(&kap->data->greg, &thp->reg, sizeof thp->reg);
			status = EOK;
		}
		break;

	case NTO_DEBUG_SET_GREG:			// pid:tid:debug_greg_t
		if(stopped) {
			lock_kernel();
			cpu_greg_load(thp, (CPU_REGISTERS *)&kap->data->greg);
			status = EOK;
		}
		break;

	case NTO_DEBUG_GET_FPREG:			// pid:tid:debug_fpreg_t
		if(thp) {
			FPU_REGISTERS	*fpudata = FPUDATA_PTR(thp->fpudata);
			int				cpu = FPUDATA_CPU(thp->fpudata);

			status = ENXIO;
			if(fpudata) {
				if(FPUDATA_INUSE(thp->fpudata) && cpu != KERNCPU) {
					// In use on another CPU; send ipi, restart kernel call
					SENDIPI(cpu, IPI_CONTEXT_SAVE);
					KERCALL_RESTART(act);
					return;
				}
				if(actives_fpu[thp->runcpu] == thp) {
					if(KERNCPU == thp->runcpu) {
						cpu_force_fpu_save(thp);
						actives_fpu[KERNCPU] = NULL;
					} else {
						// We should not get here
						crash();
					}
				}
				memcpy(&kap->data->fpreg, fpudata, sizeof *fpudata);
				status = EOK;
			} else if(thp->un.lcl.tls && thp->un.lcl.tls->__fpuemu_data) {
// @@@ NEED TO FIND PROPER SIZE OF EMULATOR DATA
				memcpy(&kap->data->fpreg, thp->un.lcl.tls->__fpuemu_data, sizeof(*fpudata) + 256);
				status = EOK;
			}
		}
		break;
			
	case NTO_DEBUG_SET_FPREG:			// pid:tid:debug_fpreg_t
		if(thp && stopped) {
			FPU_REGISTERS	*fpudata = FPUDATA_PTR(thp->fpudata);
			int				cpu = FPUDATA_CPU(thp->fpudata);

			status = ENXIO;
			if(thp->fpudata) {
				if(FPUDATA_INUSE(thp->fpudata) && cpu != KERNCPU) {
					// In use on another CPU; send ipi, restart kernel call
					SENDIPI(cpu, IPI_CONTEXT_SAVE);
					KERCALL_RESTART(act);
					return;
				}
				if(actives_fpu[thp->runcpu] == thp) {
					if(KERNCPU == thp->runcpu) {
						cpu_force_fpu_save(thp);
						actives_fpu[KERNCPU] = NULL;
					} else {
						// We should not get here
						crash();
					}
				}
				memcpy(fpudata, &kap->data->fpreg, sizeof *fpudata);
				status = EOK;
			} else if(thp->un.lcl.tls && thp->un.lcl.tls->__fpuemu_data) {
// @@@ NEED TO FIND PROPER SIZE OF EMULATOR DATA
				memcpy(thp->un.lcl.tls->__fpuemu_data, &kap->data->fpreg, sizeof(*fpudata) + 256);
				status = EOK;
			}
		}
		break;

	case NTO_DEBUG_STOP:				// pid:na:na
		if(dep) {
			status =  debug_stop(prp);
		}
		break;

	case NTO_DEBUG_RUN:					// pid:tid:debug_run_t
		if(dep && stopped) {
			status = debug_run(prp, &kap->data->run);
		}
		break;

	case NTO_DEBUG_CURTHREAD:			// pid:tid:NULL
		if(dep) {
			lock_kernel();
			SETKSTATUS(act, dep->tid + 1);
			if(thp) {
				dep->tid = thp->tid;
			}
			return;
		}
		break;

	case NTO_DEBUG_FREEZE:				// pid:tid:NULL
		if(thp == NULL){
			status = EINVAL;
			break;
		}
		if(stopped) {
			lock_kernel();
			thp->flags |= _NTO_TF_FROZEN;
		}
		break;

	case NTO_DEBUG_THAW:				// pid:tid:NULL
		if(thp == NULL){
			status = EINVAL;
			break;
		}
		if(stopped) {
			lock_kernel();
			thp->flags &= ~_NTO_TF_FROZEN;
		}
		break;

	case NTO_DEBUG_BREAK:				// pid:na:debug_break_t
		if(dep && stopped) {
			status = debug_break(prp, &kap->data->brk);
		}
		break;

	case NTO_DEBUG_GET_BREAKLIST:		// pid:na:debug_breaklist_t
		status = debug_break_list(prp, &kap->data->brklist);
		break;

	case NTO_DEBUG_SET_FLAG:			// pid:na:uint32_t
		if(dep && !(kap->data->flags & ~_DEBUG_FLAG_MASK)) {
			lock_kernel();
			dep->flags |= kap->data->flags;
		}
		break;

	case NTO_DEBUG_CLEAR_FLAG:			// pid:na:uint32_t
		if(dep && !(kap->data->flags & ~_DEBUG_FLAG_MASK)) {
			lock_kernel();
			dep->flags &= ~kap->data->flags;
		}
		break;

	case NTO_DEBUG_GET_ALTREG:			// pid:tid:debug_altreg_t
		if(thp) {
			status = cpu_debug_get_altregs(thp, &kap->data->altreg);
		}
		break;

	case NTO_DEBUG_SET_ALTREG:			// pid:tid:debug_altreg_t
		if(thp) {
			status = cpu_debug_set_altregs(thp, &kap->data->altreg);
		}
		break;

	case NTO_DEBUG_GET_PERFREG:
		if ( thp ) {
			status = cpu_debug_get_perfregs(thp, &kap->data->perfreg);
		}
		break;

	case NTO_DEBUG_SET_PERFREG:
		if ( thp && !stopped )
			status = EINVAL;
		else {
			if ( (kap->data->flags & ~PERFREGS_ENABLED_FLAG) == cpu_perfreg_id() ) {
				status = cpu_debug_set_perfregs(thp, &kap->data->perfreg);
			}
			else
				status = ENODEV;
		}
		break;
	}

	if(status != EOK) {
		kererr(act, status);
	} else {
		lock_kernel();
		SETKSTATUS(act, 0);
	}
}
예제 #20
0
파일: nano_query.c 프로젝트: vocho/openqnx
void *
nano_query(int type, unsigned index1, int subtype, unsigned index2,
							unsigned *next, void *objbuf, int objsize) {
	VECTOR	*vecp;
	void	*obj;
	PROCESS	*prp;

	if((vecp = vector_search(&query_vector, type, 0))) {
		switch(type) {
		case _QUERY_PROCESS:
			if(subtype == _QUERY_PROCESS_VECTOR) {
				while((obj = prp = vector_search(vecp, PINDEX(index1), next))) {
					if(next) {
						if(PINDEX(prp->pid) == *next) {
							break;						
						}
						index1 = *next + 1;
					} else {
						if(prp->pid != index1) {
							obj = 0;
						}
						break;
					}
				}
			} else if((obj = prp = vector_search(vecp, PINDEX(index1), 0)) && (prp->pid == index1) && (index1 != 0)) {
				obj = vector_search((VECTOR *)((uintptr_t)prp + vec_offset[subtype - _QUERY_PROCESS_CHANCONS]), index2, next);
			} else {
				obj = NULL;
			}
			break;
		case _QUERY_INTERRUPT:
			obj = vector_search(vecp, index1, next);
			if(obj && objbuf) {
				struct interrupt_entry			*iep = obj;
				struct interrupt_query_entry	*iqep = objbuf;
				struct interrupt_level			*ilp;

				// We have to fill in some extra stuff since proc
				// can't follow the thread pointer after we've returned
				// and it doesn't know about interrupt levels.
				if(iep->handler == NULL) {
					iqep->event = *(struct sigevent *)iep->area;
				}
				iqep->tid = iep->thread->tid + 1;
				iqep->pid = iep->thread->process->pid;
				ilp = &interrupt_level[iep->level];
				iqep->vector = ilp->info->vector_base + iep->level - ilp->level_base;

				// Restrict the copy to just the interrupt_entry portion.
				objsize = sizeof(*iep);
			}
			break;
		default:
			obj = vector_search(vecp, index1, next);
			break;
		}

		if(obj && objbuf) {
			memcpy(objbuf, obj, objsize);
		}

		return(obj);
	}

	return(NULL);
}
예제 #21
0
void main(void) {
  int i, j, retval;

  VECTOR *v = vector_create();
  assert(v != NULL);
  assert(vector_size(v)==0);
  for (i=0; i<=MAX; i++) {
    assert(!vector_contains(v, i));
    assert(!vector_remove(v, i));
    assert(!vector_search(v, i, (PPTP_CALL **)&j));
    retval = vector_scan(v, i, MAX*2, &j);
    assert(retval);
    assert(j==i);
  }

  for (i=1; i<=MAX; i++) {
    retval = vector_insert(v, i, (PPTP_CALL *)i);
    assert(retval);
    assert(vector_size(v)==i);
  }
  for (i=1; i<MAX; i++) {
    retval = vector_search(v, i, (PPTP_CALL **)&j);
    assert(retval);
    assert(j==i);
    retval = vector_contains(v, i);
    assert(retval);
  }
  assert(vector_size(v)==MAX);
  retval = vector_contains(v, MAX+1);
  assert(!retval);
  retval = vector_search(v, MAX+1, (PPTP_CALL **)&j);
  assert(!retval);

  retval = vector_scan(v, 0, MAX, &j);
  assert(retval);
  assert(j==0);
  retval = vector_scan(v, 1, MAX, &j);
  assert(!retval);
  retval = vector_scan(v, 1, MAX+1, &j);
  assert(retval);
  assert(j==MAX+1);
  retval = vector_scan(v, 1, MAX+MAX, &j);
  assert(retval);
  assert(j==MAX+1);

  for (i=0; i<(MAX*10); i++) {
    int k = (random() % MAX) + 1;
    assert(vector_contains(v, k));
    assert(!vector_scan(v, 1, k, &j));
    assert(!vector_scan(v, k, MAX, &j));
    retval = vector_remove(v, k);
    assert(retval);
    assert(vector_size(v)==MAX-1);
    assert(!vector_contains(v, k));
    assert(!vector_search(v, k, (PPTP_CALL **) &j));
    retval = vector_scan(v, 1, MAX, &j);
    assert(retval);
    assert(j==k);
    retval = vector_insert(v, k, (PPTP_CALL *) k);
    assert(retval);
    assert(vector_size(v)==MAX);
    assert(vector_contains(v, k));
    assert(!vector_scan(v, 1, MAX, &j));
    retval = vector_search(v, k, (PPTP_CALL **) &j);
    assert(retval);
    assert(j==k);
  }

  for (i=1; i<=MAX; i++) {
    assert(vector_size(v)==MAX-(i-1));
    vector_remove(v, i);
    assert(vector_size(v)==MAX-i);
    assert(!vector_contains(v, i));
    retval = vector_search(v, i, (PPTP_CALL **) &j);
    assert(!retval);
    retval = vector_scan(v, 1, MAX, &j);
    assert(retval);
    assert(j==1);
  }
  assert(vector_size(v)==0);
  vector_destroy(v);
}
void searchMultipleWord(FILE* file, BTree* tree, wchar_t* entryWord)
{
  preprocessador(entryWord);
  char* word = calloc(STRING_SIZE, sizeof(char));
  wcstombs(word, entryWord, STRING_SIZE);

  int nOtherWords = 0;
  char** otherWords;
  wchar_t* otherWcharWords = calloc(STRING_SIZE, sizeof(wchar_t));
  int stop = 0;
  do
  {
    fwscanf(file, L"%ls", otherWcharWords);
    stop = checkLastWchar(otherWcharWords, L'\"');
    nOtherWords++;
    if (nOtherWords == 1)
    {
      otherWords = malloc(sizeof(char*));
    } else {
      otherWords = realloc(otherWords, nOtherWords * sizeof(char*));
    }
    otherWords[nOtherWords - 1] = calloc(STRING_SIZE, sizeof(char));
    preprocessador(otherWcharWords);
    wcstombs(otherWords[nOtherWords - 1], otherWcharWords, STRING_SIZE);
  } while (!stop);
  free(otherWcharWords);

  BTreeKey** keys = calloc(nOtherWords + 1, sizeof(BTreeKey*));
  keys[0] = btree_search(tree->root, word);
  int i;
  for (i = 1; i <= nOtherWords; i++)
  {
    keys[i] = btree_search(tree->root, otherWords[i - 1]);
    if (!keys[i])
      return;
  }
  
  VectorNode* ptr = keys[0]->mInfo->head;
  int firstSequence = 1;
  while(ptr)
  {
    if (checkDocForOtherKeys(keys, nOtherWords + 1, ptr->mDocument))
    {
      VectorNode** ptrs_to_analize = calloc(nOtherWords + 1, sizeof(VectorNode*));
      ptrs_to_analize[0] = ptr;

      for (i = 1; i <= nOtherWords; i++)
        ptrs_to_analize[i] = vector_search(keys[i]->mInfo, ptr->mDocument);

      if (findSequenceWord(ptrs_to_analize, nOtherWords + 1))
      {
        if (firstSequence)
        {
          printf("\"%s", word);
          for (i = 1; i <= nOtherWords; i++)
            printf(" %s", keys[i]->mWord);
          printf("\"\n%s\n", ptr->mDocument);
          firstSequence = 0;
        } else {
          printf("%s\n", ptr->mDocument);
        }
      }
      ptr = ptr->next;
      free (ptrs_to_analize);
    } else {
      ptr = NULL;
    }
  }
  free(keys);
  free(word);
  for (i = 0; i < nOtherWords; i++)
    free(otherWords[i]);
  free(otherWords);

}
예제 #23
0
/*** pptp_dispatch_ctrl_packet ************************************************/
int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size)
{
    struct pptp_header *header = (struct pptp_header *)buffer;
    u_int8_t close_reason = PPTP_STOP_NONE;
    assert(conn && conn->call); assert(buffer);
    assert(ntoh32(header->magic) == PPTP_MAGIC);
    assert(ntoh16(header->length) == size);
    assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL);
    if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) {
        log("Invalid packet received [type: %d; length: %d].",
                (int) ntoh16(header->ctrl_type), (int) size);
        return 0;
    }
    switch (ntoh16(header->ctrl_type)) {
        /* ----------- STANDARD Start-Session MESSAGES ------------ */
        case PPTP_START_CTRL_CONN_RQST:
        {
            struct pptp_start_ctrl_conn *packet = 
                (struct pptp_start_ctrl_conn *) buffer;
            struct pptp_start_ctrl_conn reply = {
                PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),
                hton16(PPTP_VERSION), 0, 0,
                hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),
                hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),
                PPTP_HOSTNAME, PPTP_VENDOR };
            int idx, rc;
            log("Received Start Control Connection Request");
            /* fix this packet, if necessary */
            idx = get_quirk_index();
            if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {
                if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply)))
                    warn("calling the start_ctrl_conn hook failed (%d)", rc);
            }
            if (conn->conn_state == CONN_IDLE) {
                if (ntoh16(packet->version) < PPTP_VERSION) {
                    /* Can't support this (earlier) PPTP_VERSION */
                    reply.version = packet->version;
                    /* protocol version not supported */
                    reply.result_code = hton8(5);
                    pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
                    pptp_reset_timer(); /* give sender a chance for a retry */
                } else { /* same or greater version */
                    if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
                        conn->conn_state = CONN_ESTABLISHED;
                        log("server connection ESTABLISHED.");
                        pptp_reset_timer();
                    }
                }
            }
            break;
        }
        case PPTP_START_CTRL_CONN_RPLY:
        {
            struct pptp_start_ctrl_conn *packet = 
                (struct pptp_start_ctrl_conn *) buffer;
            log("Received Start Control Connection Reply");
            if (conn->conn_state == CONN_WAIT_CTL_REPLY) {
                /* XXX handle collision XXX [see rfc] */
                if (ntoh16(packet->version) != PPTP_VERSION) {
                    if (conn->callback != NULL)
                        conn->callback(conn, CONN_OPEN_FAIL);
                    close_reason = PPTP_STOP_PROTOCOL;
                    goto pptp_conn_close;
                }
                if (ntoh8(packet->result_code) != 1 &&
                    /* J'ai change le if () afin que la connection ne se ferme
                     * pas pour un "rien" :p [email protected] -
                     * 
                     * Don't close the connection if the result code is zero
                     * (feature found in certain ADSL modems)
                     */
                        ntoh8(packet->result_code) != 0) { 
                    log("Negative reply received to our Start Control "
                            "Connection Request");
                    ctrlp_error(packet->result_code, packet->error_code,
                            -1, pptp_start_ctrl_conn_rply,
                            MAX_START_CTRL_CONN_REPLY);
                    if (conn->callback != NULL)
                        conn->callback(conn, CONN_OPEN_FAIL);
                    close_reason = PPTP_STOP_PROTOCOL;
                    goto pptp_conn_close;
                }
                conn->conn_state = CONN_ESTABLISHED;
                /* log session properties */
                conn->version      = ntoh16(packet->version);
                conn->firmware_rev = ntoh16(packet->firmware_rev);
                memcpy(conn->hostname, packet->hostname, sizeof(conn->hostname));
                memcpy(conn->vendor, packet->vendor, sizeof(conn->vendor));
                pptp_reset_timer(); /* 60 seconds until keep-alive */
                log("Client connection established.");
                if (conn->callback != NULL)
                    conn->callback(conn, CONN_OPEN_DONE);
            } /* else goto pptp_conn_close; */
            break;
        }
            /* ----------- STANDARD Stop-Session MESSAGES ------------ */
        case PPTP_STOP_CTRL_CONN_RQST:
        {
            /* conn_state should be CONN_ESTABLISHED, but it could be 
             * something else */
            struct pptp_stop_ctrl_conn reply = {
                PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY), 
                hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
            };
            log("Received Stop Control Connection Request.");
            if (conn->conn_state == CONN_IDLE) break;
            if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
                if (conn->callback != NULL)
                    conn->callback(conn, CONN_CLOSE_RQST);
                conn->conn_state = CONN_IDLE;
		return -1;
            }
            break;
        }
        case PPTP_STOP_CTRL_CONN_RPLY:
        {
            log("Received Stop Control Connection Reply.");
            /* conn_state should be CONN_WAIT_STOP_REPLY, but it 
             * could be something else */
            if (conn->conn_state == CONN_IDLE) break;
            conn->conn_state = CONN_IDLE;
	    return -1;
        }
            /* ----------- STANDARD Echo/Keepalive MESSAGES ------------ */
        case PPTP_ECHO_RPLY:
        {
            struct pptp_echo_rply *packet = 
                (struct pptp_echo_rply *) buffer;
            logecho( PPTP_ECHO_RPLY);
            if ((conn->ka_state == KA_OUTSTANDING) && 
                    (ntoh32(packet->identifier) == conn->ka_id)) {
                conn->ka_id++;
                conn->ka_state = KA_NONE;
                pptp_reset_timer();
            }
            break;
        }
        case PPTP_ECHO_RQST:
        {
            struct pptp_echo_rqst *packet = 
                (struct pptp_echo_rqst *) buffer;
            struct pptp_echo_rply reply = {
                PPTP_HEADER_CTRL(PPTP_ECHO_RPLY), 
                packet->identifier, /* skip hton32(ntoh32(id)) */
                hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
            };
            logecho( PPTP_ECHO_RQST);
            pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
            pptp_reset_timer();
            break;
        }
            /* ----------- OUTGOING CALL MESSAGES ------------ */
        case PPTP_OUT_CALL_RQST:
        {
            struct pptp_out_call_rqst *packet =
                (struct pptp_out_call_rqst *)buffer;
            struct pptp_out_call_rply reply = {
                PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY),
                0 /* callid */, packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0,
                hton32(PPTP_CONNECT_SPEED), 
                hton16(PPTP_WINDOW), hton16(PPTP_DELAY), 0 
            };
            log("Received Outgoing Call Request.");
            /* XXX PAC: eventually this should make an outgoing call. XXX */
            reply.result_code = hton8(7); /* outgoing calls verboten */
            pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
            break;
        }
        case PPTP_OUT_CALL_RPLY:
        {
            struct pptp_out_call_rply *packet =
                (struct pptp_out_call_rply *)buffer;
            PPTP_CALL * call;
            u_int16_t callid = ntoh16(packet->call_id_peer);
            log("Received Outgoing Call Reply.");
            if (!vector_search(conn->call, (int) callid, &call)) {
                log("PPTP_OUT_CALL_RPLY received for non-existant call: "
                        "peer call ID (us)  %d call ID (them) %d.",
                        callid, ntoh16(packet->call_id));
                break;
            }
            if (call->call_type != PPTP_CALL_PNS) {
                log("Ack!  How did this call_type get here?"); /* XXX? */
                break; 
            }
            if (call->state.pns != PNS_WAIT_REPLY) {
                warn("Unexpected(?) Outgoing Call Reply will be ignored.");
                break;
            }
            /* check for errors */
            if (packet->result_code != 1) {
                /* An error.  Log it verbosely. */
                log("Our outgoing call request [callid %d] has not been "
                        "accepted.", (int) callid);
                ctrlp_error(packet->result_code, packet->error_code,
                        packet->cause_code, pptp_out_call_reply_result,
                        MAX_OUT_CALL_REPLY_RESULT);
                call->state.pns = PNS_IDLE;
                if (call->callback != NULL)
                    call->callback(conn, call, CALL_OPEN_FAIL);
                pptp_call_destroy(conn, call);
            } else {
                /* connection established */
                call->state.pns = PNS_ESTABLISHED;
                call->peer_call_id = ntoh16(packet->call_id);
                call->speed        = ntoh32(packet->speed);
                pptp_reset_timer();
                /* call pptp_set_link. unless the user specified a quirk
                   and this quirk has a set_link hook, this is a noop */
                pptp_set_link(conn, call->peer_call_id);
                if (call->callback != NULL)
                    call->callback(conn, call, CALL_OPEN_DONE);
                log("Outgoing call established (call ID %u, peer's "
                        "call ID %u).\n", call->call_id, call->peer_call_id);
            }
            break;
        }
            /* ----------- INCOMING CALL MESSAGES ------------ */
            /* XXX write me XXX */
            /* ----------- CALL CONTROL MESSAGES ------------ */
        case PPTP_CALL_CLEAR_RQST:
        {
            struct pptp_call_clear_rqst *packet =
                (struct pptp_call_clear_rqst *)buffer;
            struct pptp_call_clear_ntfy reply = {
                PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_NTFY), packet->call_id,
                1, PPTP_GENERAL_ERROR_NONE, 0, 0, {0}
            };
            log("Received Call Clear Request.");
            if (vector_contains(conn->call, ntoh16(packet->call_id))) {
                PPTP_CALL * call;
                vector_search(conn->call, ntoh16(packet->call_id), &call);
                if (call->callback != NULL)
                    call->callback(conn, call, CALL_CLOSE_RQST);
                pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
                pptp_call_destroy(conn, call);
                log("Call closed (RQST) (call id %d)", (int) call->call_id);
            }
            break;
        }
        case PPTP_CALL_CLEAR_NTFY:
        {
            struct pptp_call_clear_ntfy *packet =
                (struct pptp_call_clear_ntfy *)buffer;
            log("Call disconnect notification received (call id %d)",
                    ntoh16(packet->call_id));
            if (vector_contains(conn->call, ntoh16(packet->call_id))) {
                PPTP_CALL * call;
                ctrlp_error(packet->result_code, packet->error_code,
                        packet->cause_code, pptp_call_disc_ntfy,
                        MAX_CALL_DISC_NTFY);
                vector_search(conn->call, ntoh16(packet->call_id), &call);
                pptp_call_destroy(conn, call);
            }
            /* XXX we could log call stats here XXX */
            /* XXX not all servers send this XXX */
            break;
        }
        case PPTP_SET_LINK_INFO:
        {
            /* I HAVE NO CLUE WHAT TO DO IF send_accm IS NOT 0! */
            /* this is really dealt with in the HDLC deencapsulation, anyway. */
            struct pptp_set_link_info *packet =
                (struct pptp_set_link_info *)buffer;
            /* log it. */
            log("PPTP_SET_LINK_INFO received from peer_callid %u",
                    (unsigned int) ntoh16(packet->call_id_peer));
            log("  send_accm is %08lX, recv_accm is %08lX",
                    (unsigned long) ntoh32(packet->send_accm),
                    (unsigned long) ntoh32(packet->recv_accm));
            if (!(ntoh32(packet->send_accm) == 0 &&
                    ntoh32(packet->recv_accm) == 0))
                warn("Non-zero Async Control Character Maps are not supported!");
            break;
        }
        default:
            log("Unrecognized Packet %d received.", 
                    (int) ntoh16(((struct pptp_header *)buffer)->ctrl_type));
            /* goto pptp_conn_close; */
            break;
    }
    return 0;
pptp_conn_close:
    warn("pptp_conn_close(%d)", (int) close_reason);
    pptp_conn_close(conn, close_reason);
    return 0;
}