Пример #1
0
static void
test_12()
{
	slist sl;
	slist *l = &sl;

	slist_init(l);
	slist_add(l, (void *)42);
	slist_add(l, (void *)15);
	slist_add(l, (void *)14);
	slist_add(l, (void *)13);
	slist_add(l, (void *)29);
	slist_add(l, (void *)15);
	slist_add(l, (void *)25);
	slist_add(l, (void *)55);
	slist_add(l, (void *)66);
	slist_add(l, (void *)23);
	slist_qsort(l, test_12_compar);
	ASSERT((int)slist_get(l, 0) == 13);
	ASSERT((int)slist_get(l, 1) == 14);
	ASSERT((int)slist_get(l, 2) == 15);
	ASSERT((int)slist_get(l, 3) == 15);
	ASSERT((int)slist_get(l, 4) == 23);
	ASSERT((int)slist_get(l, 5) == 25);
	ASSERT((int)slist_get(l, 6) == 29);
	ASSERT((int)slist_get(l, 7) == 42);
	ASSERT((int)slist_get(l, 8) == 55);
	ASSERT((int)slist_get(l, 9) == 66);
}
Пример #2
0
static void
test_01()
{
	int i;
	slist sl;
	slist *l = &sl;

	slist_init(&sl);


	for (i = 0; i < 255; i++) {
		slist_add(&sl, (void *)i);
	}
	for (i = 0; i < 128; i++) {
		slist_remove_first(&sl);
	}
	for (i = 0; i < 128; i++) {
		slist_add(&sl, (void *)(i + 255));
	}
	ASSERT((int)slist_get(&sl, 127) == 255);
	ASSERT((int)slist_get(&sl, 254) == 129 + 253);
	ASSERT((int)slist_length(&sl) == 255);

	/* dump(&sl); */
	/* printf("==\n"); */
	slist_add(&sl, (void *)(128 + 255));
	ASSERT((int)slist_get(&sl, 127) == 255);
	/* ASSERT((int)slist_get(&sl, 255) == 128 + 255); */
	ASSERT((int)slist_length(&sl) == 256);
	/* dump(&sl); */
}
Пример #3
0
/* Test code for removing of the first, last and middle item. */
static void
test_01a()
{
	int i, f;
	slist sl;
	slist *l = &sl;

	slist_init(&sl);
	slist_add(&sl, (void *)1);

	ASSERT(sl.list_size == 256);

#define	SETUP()						\
    {							\
	l->last_idx =  64;				\
	l->first_idx = 192;				\
	for (i = 0; i < slist_length(l); i++) {		\
		slist_set(l, i, (void *)i);		\
	}						\
    }

	/* Remove the first item. */
	SETUP();
	f = 0;
	while (slist_length(l) > 0) {
		slist_remove(l, 0);
		f++;
		for (i = 0; i < slist_length(l); i++) {
			ASSERT((int)slist_get(l, i) == i + f);
		}
	}

	/* Remove the last item. */
	SETUP();
	while (slist_length(l) > 0) {
		slist_remove(l, slist_length(l) - 1);
		for (i = 0; i < slist_length(l); i++) {
			ASSERT((int)slist_get(l, i) == i);
		}
	}
	/* Remove the second item from the end. */
	SETUP();
	while (slist_length(l) > 1) {
		slist_remove(l, slist_length(l) - 2);
		for (i = 0; i < slist_length(l) - 1; i++) {
			ASSERT((int)slist_get(l, i) == i);
		}
		if (slist_length(l) > 0) {
			ASSERT((int)slist_get(l, slist_length(l) - 1) == 127);
		}
	}
	slist_remove(l, slist_length(l) - 1);
	ASSERT(slist_length(l) == 0);
}
Пример #4
0
static void
test_itr_subr_01(slist *l)
{
	int i;

	for (i = 0; i < slist_length(l); i++)
		slist_set(l, i, (void *)(i + 1));

	slist_itr_first(l);
	ASSERT((int)slist_itr_next(l) == 1);	/* normal iterate */
	ASSERT((int)slist_itr_next(l) == 2);	/* normal iterate */
	slist_remove(l, 2);		      /* remove next. "3" is removed */
	ASSERT((int)slist_itr_next(l) == 4);	/* removed item is skipped */
	slist_remove(l, 1);		 /* remove past item. "2" is removed */
	ASSERT((int)slist_itr_next(l) == 5);	/* no influence */
	ASSERT((int)slist_get(l, 0) == 1);	/* checking for removing */
	ASSERT((int)slist_get(l, 1) == 4);	/* checking for removing */
	ASSERT((int)slist_get(l, 2) == 5);	/* checking for removing */

	/*
	 * Total number was 255. We removed 2 items and iterated 4 times.
	 * 1 removing was past item, so the remaining is 250.
	 */

	for (i = 0; i < 249; i++)
		ASSERT(slist_itr_next(l) != NULL);
	ASSERT(slist_itr_next(l) != NULL);
	ASSERT(slist_itr_next(l) == NULL);

	/*
	 * Same as above except removing before getting the last item.
	 */

	/* Reset (253 items) */
	for (i = 0; i < slist_length(l); i++)
		slist_set(l, i, (void *)(i + 1));
	slist_itr_first(l);

	ASSERT(slist_length(l) == 253);

	for (i = 0; i < 252; i++)
		ASSERT(slist_itr_next(l) != NULL);

	slist_remove(l, 252);
	ASSERT(slist_itr_next(l) == NULL);	/* The last item is NULL */

	slist_itr_first(l);
	while (slist_length(l) > 0)
		slist_remove_first(l);
	ASSERT(slist_length(l) == 0);
	ASSERT(slist_itr_next(l) == NULL);
}
Пример #5
0
static void
dump(slist *l)
{
	int i;

	fprintf(stderr,
	    "\tl->itr_curr = %d\n"
	    "\tl->itr_next = %d\n"
	    "\tl->first_idx = %d\n"
	    "\tl->last_idx = %d\n"
	    "\tl->list_size = %d\n"
	    , l->itr_curr, l->itr_next, l->first_idx, l->last_idx
	    , l->list_size);
	for (i = 0; i < slist_length(l); i++) {
		if ((i % 16) == 0)
			fprintf(stderr, "%08x ", i);
		fprintf(stderr, " %3d", (int)slist_get(l, i));
		if ((i % 16) == 7)
			fprintf(stderr, " -");
		if ((i % 16) == 15)
			fprintf(stderr, "\n");
	}
	if ((i % 16) != 0)
		fprintf(stderr, "\n");
}
Пример #6
0
/* disconnect all calls on the control context
 * @return return # of calls that is not waiting cleanup.
 */
static int
l2tp_ctrl_disconnect_all_calls(l2tp_ctrl *_this, int drop)
{
	int i, len, ncalls;
	l2tp_call *call;

	L2TP_CTRL_ASSERT(_this != NULL);

	ncalls = 0;
	len = slist_length(&_this->call_list);
	for (i = 0; i < len; i++) {
		call = slist_get(&_this->call_list, i);
		if (call->state != L2TP_CALL_STATE_CLEANUP_WAIT) {
			ncalls++;
			if (l2tp_ctrl_txwin_is_full(_this)) {
				L2TP_CTRL_DBG((_this, LOG_INFO,
				    "Too many calls.  Sending window is not "
				    "enough to send CDN to all clients."));
				if (drop)
					l2tp_call_drop(call);
			} else
				l2tp_call_admin_disconnect(call);
		}
	}
	return ncalls;
}
Пример #7
0
void* slist_find(const struct simple_list* slist, const void* key, slist_cmp cmp) {
    for ( unsigned int i = 0; i < slist->size; i++ ) {
        if ( cmp(slist->key[i], key) == 0 ) {
            return slist_get(slist, i);
        }
    }
    return NULL;
}
Пример #8
0
static void
test_08()
{
	slist sl;
	slist *l = &sl;

	slist_init(l);
	slist_set_size(l, 4);
	slist_add(l, (void *)1);
	slist_add(l, (void *)2);
	slist_add(l, (void *)3);

	/* [1, 2, 3] */

	slist_itr_first(l);
	slist_itr_has_next(l);
	slist_itr_next(l);
	slist_itr_remove(l);
	/* [2, 3] */

	slist_add(l, (void *)4);
	/* [2, 3, 4] */
	ASSERT((int)slist_get(l, 0) == 2);
	ASSERT((int)slist_get(l, 1) == 3);
	ASSERT((int)slist_get(l, 2) == 4);
	slist_add(l, (void *)5);

	/* [2, 3, 4, 5] */
	ASSERT((int)slist_get(l, 0) == 2);
	ASSERT((int)slist_get(l, 1) == 3);
	ASSERT((int)slist_get(l, 2) == 4);
	ASSERT((int)slist_get(l, 3) == 5);
}
Пример #9
0
static void *slist_new(t_symbol *s)
{
    t_slist *x = (t_slist *)pd_new(slist_class);
    x->x_sym = s;
    x->x_c = slist_get(s);
    outlet_new(&x->x_obj, &s_float);
    x->x_symout=outlet_new(&x->x_obj, &s_symbol);
    x->x_lenout=outlet_new(&x->x_obj, &s_float);
    return (x);
}
Пример #10
0
static struct ConfigItem *
find_item(uint32_t hash) {
    SLIST_ITERATOR p = slist_head(configs, NULL);

    while(p != NULL) {
        struct ConfigItem *item = *(struct ConfigItem **)slist_get(p);

        if (item->hash == hash)
            return item;

        p = slist_next(p);
    }

    return NULL;
}
Пример #11
0
void* slist_put(struct simple_list* slist, void* key) {
    if ( slist->size == slist->capacity ) {
        slist_alloc(slist, /* growth = */ slist->capacity);
    }

    unsigned int index = slist->size;
    slist->key[index] = key;
    slist->size++;
    void* ptr = slist_get(slist, index);

#ifndef NVALGRIND
    VALGRIND_MEMPOOL_ALLOC(slist->value, ptr, slist->element_size);
#endif

    return ptr;
}
Пример #12
0
void
configs_cleanup(void) {
    if (!configs)
        return;

    SLIST_ITERATOR p = slist_head(configs, NULL);

    while(p != NULL) {
        struct ConfigItem *item = *(struct ConfigItem **)slist_get(p);

        free(item);

        p = slist_next(p);
    }

    slist_free(configs);
}
Пример #13
0
static void
test_02()
{
	int i;
	slist sl;
	slist *l = &sl;

	slist_init(&sl);


	/* Place 300 items for left side and 211 items for right side. */
	for (i = 0; i < 511; i++)
		slist_add(&sl, (void *)i);
	for (i = 0; i <= 300; i++)
		slist_remove_first(&sl);
	for (i = 0; i <= 300; i++)
		slist_add(&sl, (void *)i);


	/* Set values to make index number and value the same. */
	for (i = 0; i < slist_length(&sl); i++)
		slist_set(&sl, i, (void *)(i + 1));

	ASSERT(slist_length(&sl) == 511);      /* The logical length is 511. */
	ASSERT((int)sl.list[511] == 211);	/* The most right is 211th. */
	ASSERT((int)sl.list[0] == 212);		/* The most left is 212th. */
	ASSERT(sl.list_size == 512);		/* The physical size is 512. */

	slist_add(&sl, (void *)512);		/* Add 512th item. */

	ASSERT(sl.list_size == 768);	   /* The physical size is extended. */
	ASSERT(slist_length(&sl) == 512);      /* The logical length is 512. */
	ASSERT((int)sl.list[511] == 211);	/* boundary */
	ASSERT((int)sl.list[512] == 212);	/* boundary */
	ASSERT((int)sl.list[767] == 467);	/* The most right is 467th. */
	ASSERT((int)sl.list[0] == 468);		/* The most left is 468th. */

	/* Check all items */
	for (i = 0; i < slist_length(&sl); i++)
		ASSERT((int)slist_get(&sl, i) == i + 1);	/* check */
}
Пример #14
0
static void
test_06()
{
	int i, j;
	slist sl;
	slist *l = &sl;

	slist_init(l);
	for (i = 0; i < 255; i++)
		slist_add(l, (void *)i);

	i = 255;

	for (slist_itr_first(l); slist_itr_has_next(l); ) {
		ASSERT(slist_length(l) == i);
		slist_itr_next(l);
		ASSERT((int)slist_itr_remove(l) == 255 - i);
		ASSERT(slist_length(l) == i - 1);
		for (j = i; j < slist_length(l); j++)
			ASSERT((int)slist_get(l, j) == i + j);
		i--;
	}
}
Пример #15
0
void
pptpd_ctrl_finished_notify(pptpd *_this, pptp_ctrl *ctrl)
{
	pptp_ctrl *ctrl1;
	int i, nctrl;

	PPTPD_ASSERT(_this != NULL);
	PPTPD_ASSERT(ctrl != NULL);

	nctrl = 0;
	for (i = 0; i < slist_length(&_this->ctrl_list); i++) {
		ctrl1 = slist_get(&_this->ctrl_list, i);
		if (ctrl1 == ctrl) {
			slist_remove(&_this->ctrl_list, i);
			break;
		}
	}
	pptp_ctrl_destroy(ctrl);

	PPTPD_DBG((_this, LOG_DEBUG, "Remains %d ctrls", nctrl));
	if (pptpd_is_shutting_down(_this) && nctrl == 0)
		pptpd_stop_immediatly(_this);
}
Пример #16
0
/*
 * in         - Source file to be interpreted
 * file_name  - Name of the source file, for debugging purposes
 * sym_table  - Global (master) symbol table
 */
void liten(FILE * in, char * file_name, slist * sym_table, token ** ret) {
    
  // *ret = NULL;

  slist * block_stack = slist_init();

  slist * local_table = slist_init();
  slist_push(sym_table, local_table);

  file_desc * desc = malloc(sizeof(file_desc));
  desc->file = in;
  desc->name = file_name;
  desc->line = 1;

  int tok;
  char * temp = malloc(sizeof(char)*MAX_STR);
  strcpy(temp, "\0");
  int type = -1;
  slist * tok_queue = slist_init();

  while (1) {
    if (in == stdin) {
      printf(":> ");
    } else if (tok == EOF) {
      break;
    }
    tok = getc(in);
    while (1) {
      if (tok == '\n' || tok == EOF) {
        desc->line++;
        tokenize(desc, &temp, &type, tok_queue);
        type = -1;
        // slist_print(tok_queue, slist_print_token);
        // TODO: Check line for syntax errors
        if (tok_queue->len == 0) break;
        if (block_stack->len == 0) {
          rpn(desc, tok_queue, sym_table, block_stack, ret);
        } else {
          char * temp_str = ((token *) slist_get(tok_queue, 0)->obj)->obj;
          block * temp = (block *) slist_get(block_stack, -1)->obj;
          if (strcmp("end", temp_str) == 0) {
	          rpn(desc, tok_queue, sym_table, block_stack, ret);
          } else if (strcmp("if", temp_str) == 0 ||
	          strcmp("while", temp_str) == 0) {
	          if (temp->value == 1)
	            rpn(desc, tok_queue, sym_table, block_stack, ret);
	          else {
	            block * temp1 = malloc(sizeof(block));
	            temp1->value = 0;
	            if (strcmp("if", temp_str) == 0) {
		            temp1->type = IF_B;
	            } else if (strcmp("while", temp_str) == 0) {
		            temp1->type = WHILE_B;
	            }
	            slist_push(block_stack, temp1);
	          }
          } else if (strcmp("elif", temp_str) == 0) {
	          if (temp->type != IF_B) lite_error(desc, "'elif' exists in 'if' block");
	          if (temp->value == 1) temp->value = 0;
	          else
	            rpn(desc, tok_queue, sym_table, block_stack, ret);
          } else if (strcmp("else", temp_str) == 0) {			
	          if (temp->type != IF_B) lite_error(desc, "'else' exists in 'if' block");
	          if (temp->value == 1) temp->value = 0;
	          else temp->value = 1;
          } else {
	          if (temp->value == 1)
	            rpn(desc, tok_queue, sym_table, block_stack, ret);
          }
        }
        
        tok_queue = slist_init();
        
        } else {
          token_parse(desc, tok, &temp, &type, tok_queue);
        }
         
        if (in == stdin && tok == '\n') break;
        tok = getc(in);
      }
    }

    return;
}
Пример #17
0
/* call it when control packet is received */
int
l2tp_call_recv_packet(l2tp_ctrl *ctrl, l2tp_call *_this, int mestype,
    u_char *pkt, int pktlen)
{
	int i, len, session_id, send_cdn;
	l2tp_call *call;
	dialin_proxy_info dpi;

	/* when ICRQ, this will be NULL */
	L2TP_CALL_ASSERT(_this != NULL ||
	    mestype == L2TP_AVP_MESSAGE_TYPE_ICRQ);

	if (_this == NULL) {
		if (mestype != L2TP_AVP_MESSAGE_TYPE_ICRQ)
			return 1;
		if ((_this = l2tp_call_create()) == NULL) {
			l2tp_ctrl_log(ctrl, LOG_ERR,
			    "l2tp_call_create failed in %s(): %m", __func__);
			return 1;
		}
		l2tp_call_init(_this, ctrl);

		if (l2tp_call_recv_ICRQ(_this, pkt, pktlen) != 0)
			return 1;

		len = slist_length(&ctrl->call_list);
		session_id = _this->id;
	    again:
		/* assign a session ID */
		session_id &= 0xffff;
		if (session_id == 0)
			session_id = 1;
		for (i = 0; i < len; i++) {
			call = slist_get(&ctrl->call_list, i);
			if (call->session_id == session_id) {
				session_id++;
				goto again;
			}
		}
		_this->session_id = session_id;

		/* add the l2tp_call to call list */
		slist_add(&_this->ctrl->call_list, _this);

		if (l2tp_call_send_ICRP(_this) != 0)
			return 1;
		_this->state = L2TP_CALL_STATE_WAIT_CONN;
		return 0;
	}

	/* state machine */
	send_cdn = 0;
	switch (_this->state) {
	default:
		break;
	case L2TP_CALL_STATE_WAIT_CONN:
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_ICCN:
			memset(&dpi, 0, sizeof(dpi));
			if (l2tp_call_recv_ICCN(_this, pkt, pktlen, &dpi) != 0)
				return 1;
			l2tp_call_bind_ppp(_this, &dpi);
			l2tp_call_send_ZLB(_this);
			_this->state = L2TP_CALL_STATE_ESTABLISHED;
			_this->ctrl->ncalls++;
			return 0;
		case L2TP_AVP_MESSAGE_TYPE_ICRQ:
		case L2TP_AVP_MESSAGE_TYPE_ICRP:
			send_cdn = 1;
			/* FALLTHROUGH */
		default:
			l2tp_call_log(_this, LOG_ERR,
			    "Waiting ICCN.  But received %s",
			    avp_mes_type_string(mestype));
			if (send_cdn) {
				l2tp_call_disconnect(_this,
				    L2TP_CDN_RCODE_ERROR_CODE,
				    L2TP_ECODE_GENERIC_ERROR, "Illegal state.",
				    NULL, 0);
				return 0;
			}
		}
		break;
	case L2TP_CALL_STATE_ESTABLISHED:
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_CDN:
			/* disconnect from peer. log it */
			l2tp_recv_CDN(_this, pkt, pktlen);
			_this->state = L2TP_CALL_STATE_CLEANUP_WAIT;
			l2tp_call_notify_down(_this);
			l2tp_call_send_ZLB(_this);
			return 0;
		case L2TP_AVP_MESSAGE_TYPE_ICRQ:
		case L2TP_AVP_MESSAGE_TYPE_ICRP:
		case L2TP_AVP_MESSAGE_TYPE_ICCN:
			send_cdn = 1;
			break;
		default:
			break;
		}
		l2tp_call_log(_this, LOG_ERR,
		    "Call established.  But received %s",
		    avp_mes_type_string(mestype));
		if (send_cdn) {
			l2tp_call_disconnect(_this,
			    L2TP_CDN_RCODE_ERROR_CODE,
			    L2TP_ECODE_GENERIC_ERROR, "Illegal state.",
			    NULL, 0);
			return 0;
		}
		l2tp_call_disconnect(_this, 0, 0, NULL, NULL, 0);
		return 1;
	}
	l2tp_call_log(_this, LOG_INFO, "Received %s in unexpected state=%s",
	    avp_mes_type_string(mestype), l2tp_call_state_string(_this));
	l2tp_call_disconnect(_this, 0, 0, NULL, NULL, 0);
	return 1;
}
Пример #18
0
static void slist_setlist(t_slist *x,t_symbol *s)
{
    slist_release(x->x_c);
    x->x_c = slist_get(s);
}
Пример #19
0
/* Verify removing the last item on the physical location */
static void
test_05()
{
	int i;
	slist sl;
	slist *l = &sl;

	slist_init(&sl);
	/* Fill */
	for (i = 0; i < 255; i++) {
		slist_add(&sl, (void *)i);
	}
	/* Remove 254 items */
	for (i = 0; i < 254; i++) {
		slist_remove_first(&sl);
	}
	slist_set(l, 0, (void *)0);
	/* Add 7 items */
	for (i = 0; i < 8; i++) {
		slist_add(&sl, (void *)i + 1);
	}
	ASSERT(sl.first_idx == 254);
	ASSERT(sl.last_idx == 7);

	slist_remove(l, 0);
	ASSERT((int)slist_get(l, 0) == 1);
	ASSERT((int)slist_get(l, 1) == 2);
	ASSERT((int)slist_get(l, 2) == 3);
	ASSERT((int)slist_get(l, 3) == 4);
	ASSERT((int)slist_get(l, 4) == 5);
	ASSERT((int)slist_get(l, 5) == 6);
	ASSERT((int)slist_get(l, 6) == 7);
	ASSERT((int)slist_get(l, 7) == 8);
	ASSERT(l->first_idx == 255);

	slist_remove(l, 0);
	ASSERT((int)slist_get(l, 0) == 2);
	ASSERT((int)slist_get(l, 1) == 3);
	ASSERT((int)slist_get(l, 2) == 4);
	ASSERT((int)slist_get(l, 3) == 5);
	ASSERT((int)slist_get(l, 4) == 6);
	ASSERT((int)slist_get(l, 5) == 7);
	ASSERT((int)slist_get(l, 6) == 8);
	ASSERT(l->first_idx == 0);
}
Пример #20
0
/* Receive packet */
void
l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer,
    struct sockaddr *sock, void *nat_t_ctx, u_char *pkt, int pktlen)
{
	int i, len, offsiz, reqlen, is_ctrl;
	uint16_t mestype;
	struct l2tp_avp *avp, *avp0;
	l2tp_ctrl *ctrl;
	l2tp_call *call;
	char buf[L2TP_AVP_MAXSIZ], errmsg[256];
	time_t curr_time;
	u_char *pkt0;
	struct l2tp_header hdr;
	char hbuf[NI_MAXHOST + NI_MAXSERV + 16];

	ctrl = NULL;
	curr_time = get_monosec();
	pkt0 = pkt;

	L2TP_CTRL_ASSERT(peer->sa_family == sock->sa_family);
	L2TP_CTRL_ASSERT(peer->sa_family == AF_INET ||
	    peer->sa_family == AF_INET6)
    /*
     * Parse L2TP Header
     */
	memset(&hdr, 0, sizeof(hdr));
	if (pktlen < 2) {
		snprintf(errmsg, sizeof(errmsg), "a short packet.  "
		    "length=%d", pktlen);
		goto bad_packet;
	}
	memcpy(&hdr, pkt, 2);
	pkt += 2;
	if (hdr.ver != L2TP_HEADER_VERSION_RFC2661) {
		/* XXX: only RFC2661 is supported */
		snprintf(errmsg, sizeof(errmsg),
		    "Unsupported version at header = %d", hdr.ver);
		goto bad_packet;
	}
	is_ctrl = (hdr.t != 0)? 1 : 0;

	/* calc required length */
	reqlen = 6;		/* for Flags, Tunnel-Id, Session-Id field */
	if (hdr.l) reqlen += 2;	/* for Length field (opt) */
	if (hdr.s) reqlen += 4;	/* for Ns, Nr field (opt) */
	if (hdr.o) reqlen += 2;	/* for Offset Size field (opt) */
	if (reqlen > pktlen) {
		snprintf(errmsg, sizeof(errmsg),
		    "a short packet. length=%d", pktlen);
		goto bad_packet;
	}

	if (hdr.l != 0) {
		GETSHORT(hdr.length, pkt);
		if (hdr.length > pktlen) {
			snprintf(errmsg, sizeof(errmsg),
			    "Actual packet size is smaller than the length "
			    "field %d < %d", pktlen, hdr.length);
			goto bad_packet;
		}
		pktlen = hdr.length;	/* remove trailing trash */
	}
	GETSHORT(hdr.tunnel_id, pkt);
	GETSHORT(hdr.session_id, pkt);
	if (hdr.s != 0) {
		GETSHORT(hdr.ns, pkt);
		GETSHORT(hdr.nr, pkt);
	}
	if (hdr.o != 0) {
		GETSHORT(offsiz, pkt);
		if (pktlen < offsiz) {
			snprintf(errmsg, sizeof(errmsg),
			    "offset field is bigger than remaining packet "
			    "length %d > %d", offsiz, pktlen);
			goto bad_packet;
		}
		pkt += offsiz;
	}
	L2TP_CTRL_ASSERT(pkt - pkt0 == reqlen);
	pktlen -= (pkt - pkt0);	/* cut down the length of header */

	ctrl = NULL;
	memset(buf, 0, sizeof(buf));
	mestype = 0;
	avp = NULL;

	if (is_ctrl) {
		avp0 = (struct l2tp_avp *)buf;
		avp = avp_find_message_type_avp(avp0, pkt, pktlen);
		if (avp != NULL)
			mestype = avp->attr_value[0] << 8 | avp->attr_value[1];
	}
	ctrl = l2tpd_get_ctrl(_this, hdr.tunnel_id);

	if (ctrl == NULL) {
		/* new control */
		if (!is_ctrl) {
			snprintf(errmsg, sizeof(errmsg),
			    "bad data message: tunnelId=%d is not "
			    "found.", hdr.tunnel_id);
			goto bad_packet;
		}
		if (mestype != L2TP_AVP_MESSAGE_TYPE_SCCRQ) {
			snprintf(errmsg, sizeof(errmsg),
			    "bad control message: tunnelId=%d is not "
			    "found.  mestype=%s", hdr.tunnel_id,
			    avp_mes_type_string(mestype));
			goto bad_packet;
		}

		if ((ctrl = l2tp_ctrl_create()) == NULL) {
			l2tp_ctrl_log(ctrl, LOG_ERR,
			    "l2tp_ctrl_create() failed: %m");
			goto fail;
		}

		if (l2tp_ctrl_init(ctrl, _this, peer, sock, nat_t_ctx) != 0) {
			l2tp_ctrl_log(ctrl, LOG_ERR,
			    "l2tp_ctrl_start() failed: %m");
			goto fail;
		}

		ctrl->listener_index = listener_index;
		l2tp_ctrl_reload(ctrl);
	} else {
		/*
		 * treat as an error if src address and port is not
		 * match. (because it is potentially DoS attach)
		 */
		int notmatch = 0;

		if (ctrl->peer.ss_family != peer->sa_family)
			notmatch = 1;
		else if (peer->sa_family == AF_INET) {
			if (SIN(peer)->sin_addr.s_addr != 
			    SIN(&ctrl->peer)->sin_addr.s_addr ||
			    SIN(peer)->sin_port != SIN(&ctrl->peer)->sin_port)
				notmatch = 1;
		} else if (peer->sa_family == AF_INET6) {
			if (!IN6_ARE_ADDR_EQUAL(&(SIN6(peer)->sin6_addr),
				    &(SIN6(&ctrl->peer)->sin6_addr)) ||
			    SIN6(peer)->sin6_port !=
				    SIN6(&ctrl->peer)->sin6_port)
				notmatch = 1;
 		}
		if (notmatch) {
			snprintf(errmsg, sizeof(errmsg),
			    "tunnelId=%u is already assigned for %s",
			    hdr.tunnel_id, addrport_tostring(
				(struct sockaddr *)&ctrl->peer,
				ctrl->peer.ss_len, hbuf, sizeof(hbuf)));
			goto bad_packet;
		}
	}
	ctrl->last_rcv = curr_time;
	call = NULL;
	if (hdr.session_id != 0) {
		/* search l2tp_call by Session ID */
		/* linear search is enough for this purpose */
		len = slist_length(&ctrl->call_list);
		for (i = 0; i < len; i++) {
			call = slist_get(&ctrl->call_list, i);
			if (call->session_id == hdr.session_id)
				break;
			call = NULL;
		}
	}
	if (!is_ctrl) {
		int delayed = 0;

		/* L2TP data */
		if (ctrl->state != L2TP_CTRL_STATE_ESTABLISHED) {
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received Data packet in '%s'",
			    l2tp_ctrl_state_string(ctrl));
			goto fail;
		}
		if (call == NULL) {
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received a data packet but it has no call.  "
			    "session_id=%u",  hdr.session_id);
			goto fail;
		}
		L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2,
		    "call=%u RECV   ns=%u nr=%u snd_nxt=%u rcv_nxt=%u len=%d",
		    call->id, hdr.ns, hdr.nr, call->snd_nxt, call->rcv_nxt,
		    pktlen));
		if (call->state != L2TP_CALL_STATE_ESTABLISHED){
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received a data packet but call is not "
			    "established");
			goto fail;
		}

		if (hdr.s != 0) {
			if (SEQ_LT(hdr.ns, call->rcv_nxt)) {
				if (SEQ_LT(hdr.ns,
				    call->rcv_nxt - L2TP_CALL_DELAY_LIMIT)) {
					/* sequence number seems to be delayed */
					/* XXX: need to log? */
					L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
					    "receive a out of sequence "
					    "data packet: %u < %u.",
					    hdr.ns, call->rcv_nxt));
					return;
				}
				delayed = 1;
			} else {
				call->rcv_nxt = hdr.ns + 1;
			}
		}

		l2tp_call_ppp_input(call, pkt, pktlen, delayed);

		return;
	}
	if (hdr.s != 0) {
		L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2,
		    "RECV %s ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u "
		    "len=%d", (is_ctrl)? "C" : "", hdr.ns, hdr.nr,
		    ctrl->snd_nxt, ctrl->snd_una, ctrl->rcv_nxt, pktlen));

		if (pktlen <= 0)
			l2tp_ctrl_log(ctrl, LOG_INFO, "RecvZLB");

		if (SEQ_GT(hdr.nr, ctrl->snd_una)) {
			if (hdr.nr == ctrl->snd_nxt ||
			    SEQ_LT(hdr.nr, ctrl->snd_nxt))
				ctrl->snd_una = hdr.nr;
			else {
				l2tp_ctrl_log(ctrl, LOG_INFO,
				    "Received message has bad Nr field: "
				    "%u < %u.", hdr.ns, ctrl->snd_nxt);
				/* XXX Drop with ZLB? */
				goto fail;
			}
		}
		if (l2tp_ctrl_txwin_size(ctrl) <= 0) {
			/* no waiting ack */
			if (ctrl->hello_wait_ack != 0) {
				/*
				 * Reset Hello state, as an ack for the Hello
				 * is recived.
				 */
				ctrl->hello_wait_ack = 0;
				ctrl->hello_io_time = curr_time;
			}
			switch (ctrl->state) {
			case L2TP_CTRL_STATE_CLEANUP_WAIT:
				l2tp_ctrl_stop(ctrl, 0);
				return;
			}
		}
		if (hdr.ns != ctrl->rcv_nxt) {
			/* there are remaining packet */
			if (l2tp_ctrl_resend_una_packets(ctrl) <= 0) {
				/* resend or sent ZLB */
				l2tp_ctrl_send_ZLB(ctrl);
			}
#ifdef	L2TP_CTRL_DEBUG
			if (pktlen != 0) {	/* not ZLB */
				L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
				    "receive out of sequence %u must be %u.  "
				    "mestype=%s", hdr.ns, ctrl->rcv_nxt,
				    avp_mes_type_string(mestype)));
			}
#endif
			return;
		}
		if (pktlen <= 0)
			return;		/* ZLB */

		if (l2tp_ctrl_txwin_is_full(ctrl)) {
			L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
			    "Received message cannot be handled. "
			    "Transmission window is full."));
			l2tp_ctrl_send_ZLB(ctrl);
			return;
		}

		ctrl->rcv_nxt++;
		if (avp == NULL) {
			l2tpd_log(_this, LOG_WARNING,
			    "bad control message: no message-type AVP.");
			goto fail;
		}
	}

    /*
     * state machine (RFC2661 pp. 56-57)
     */
	switch (ctrl->state) {
	case L2TP_CTRL_STATE_IDLE:
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
			if (l2tp_ctrl_recv_SCCRQ(ctrl, pkt, pktlen, _this,
			    peer) == 0) {
				/* acceptable */
				l2tp_ctrl_send_SCCRP(ctrl);
				ctrl->state = L2TP_CTRL_STATE_WAIT_CTL_CONN;
				return;
			}
			/*
			 * in case un-acceptable, it was already processed
			 * at l2tcp_ctrl_recv_SCCRQ
			 */
			return;
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
			/*
			 * RFC specifies that sent of StopCCN in the state,
			 * However as this implementation only support Passive
			 * open, this packet will not received.
			 */
			/* FALLTHROUGH */
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
		default:
			break;
		}
		goto fsm_fail;

	case L2TP_CTRL_STATE_WAIT_CTL_CONN:
	    /* Wait-Ctl-Conn */
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
			l2tp_ctrl_log(ctrl, LOG_INFO, "RecvSCCN");
			if (l2tp_ctrl_send_ZLB(ctrl) == 0) {
				ctrl->state = L2TP_CTRL_STATE_ESTABLISHED;
			}
			return;
		case L2TP_AVP_MESSAGE_TYPE_StopCCN:
			goto receive_stop_ccn;
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
		default:
			break;
		}
		break;	/* fsm_fail */
	case L2TP_CTRL_STATE_ESTABLISHED:
	    /* Established */
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
			break;
receive_stop_ccn:
		case L2TP_AVP_MESSAGE_TYPE_StopCCN:
			if (l2tp_ctrl_recv_StopCCN(ctrl, pkt, pktlen) == 0) {
				if (l2tp_ctrl_resend_una_packets(ctrl) <= 0)
					l2tp_ctrl_send_ZLB(ctrl);
				l2tp_ctrl_stop(ctrl, 0);
				return;
			}
			l2tp_ctrl_log(ctrl, LOG_ERR, "Received bad StopCCN");
			l2tp_ctrl_send_ZLB(ctrl);
			l2tp_ctrl_stop(ctrl, 0);
			return;

		case L2TP_AVP_MESSAGE_TYPE_HELLO:
			if (l2tp_ctrl_resend_una_packets(ctrl) <= 0)
				l2tp_ctrl_send_ZLB(ctrl);
			return;
		case L2TP_AVP_MESSAGE_TYPE_CDN:
		case L2TP_AVP_MESSAGE_TYPE_ICRP:
		case L2TP_AVP_MESSAGE_TYPE_ICCN:
			if (call == NULL) {
				l2tp_ctrl_log(ctrl, LOG_INFO,
				    "Unknown call message: %s",
				    avp_mes_type_string(mestype));
				goto fail;
			}
			/* FALLTHROUGH */
		case L2TP_AVP_MESSAGE_TYPE_ICRQ:
			l2tp_call_recv_packet(ctrl, call, mestype, pkt,
			    pktlen);
			return;
		default:
			break;
		}
		break;	/* fsm_fail */
	case L2TP_CTRL_STATE_CLEANUP_WAIT:
		if (mestype == L2TP_AVP_MESSAGE_TYPE_StopCCN) {
			/*
			 * We left ESTABLISHED state, but the peer sent StopCCN.
			 */
			goto receive_stop_ccn;
		}
		break;	/* fsm_fail */
	}

fsm_fail:
	/* state machine error */
	l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state",
	    avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl));
	l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_FSM_ERROR);

	return;
fail:
	if (ctrl != NULL && mestype != 0) {
		l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state",
		    avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl));
		l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_GENERAL_ERROR);
	}
	return;

bad_packet:
	l2tpd_log(_this, LOG_INFO, "Received from=%s: %s",
	    addrport_tostring(peer, peer->sa_len, hbuf, sizeof(hbuf)), errmsg);

	return;
}