예제 #1
0
/*
 * setup {@link ::_l2tp_ctrl L2TP LNS control connection} instance
 */
static void
l2tp_ctrl_reload(l2tp_ctrl *_this)
{
	_this->data_use_seq = L2TP_CTRL_CONF(_this)->data_use_seq;
	if (L2TP_CTRL_CONF(_this)->hello_interval != 0)
		_this->hello_interval =  L2TP_CTRL_CONF(_this)->hello_interval;
	if (L2TP_CTRL_CONF(_this)->hello_timeout != 0)
		_this->hello_timeout = L2TP_CTRL_CONF(_this)->hello_timeout;
}
예제 #2
0
/* send control packet */
int
l2tp_ctrl_send_packet(l2tp_ctrl *_this, int call_id, bytebuffer *bytebuf)
{
	struct l2tp_header *hdr;
	int rval;
	time_t curr_time;

	curr_time = get_monosec();

	bytebuffer_flip(bytebuf);
	hdr = (struct l2tp_header *)bytebuffer_pointer(bytebuf);
	memset(hdr, 0, sizeof(*hdr));

	hdr->t = 1;
	hdr->ver = L2TP_HEADER_VERSION_RFC2661;
	hdr->l = 1;
	hdr->length = htons(bytebuffer_remaining(bytebuf));
	hdr->tunnel_id = htons(_this->peer_tunnel_id);
	hdr->session_id = htons(call_id);

	hdr->s = 1;
	hdr->ns = htons(_this->snd_nxt);
	hdr->nr = htons(_this->rcv_nxt);

	if (bytebuffer_remaining(bytebuf) > sizeof(struct l2tp_header))
		/* Not ZLB */
		_this->snd_nxt++;

	L2TP_CTRL_DBG((_this, DEBUG_LEVEL_2,
	    "SEND C ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u ",
	    ntohs(hdr->ns), htons(hdr->nr),
	    _this->snd_nxt, _this->snd_una, _this->rcv_nxt));

	if (L2TP_CTRL_CONF(_this)->ctrl_out_pktdump  != 0) {
		l2tpd_log(_this->l2tpd, LOG_DEBUG,
		    "L2TP Control output packet dump");
		show_hd(debug_get_debugfp(), bytebuffer_pointer(bytebuf),
		    bytebuffer_remaining(bytebuf));
	}

	if ((rval = l2tp_ctrl_send(_this, bytebuffer_pointer(bytebuf),
	    bytebuffer_remaining(bytebuf))) < 0) {
		L2TP_CTRL_DBG((_this, LOG_DEBUG, "sendto() failed: %m"));
	}

	_this->last_snd_ctrl = curr_time;

	return (rval == bytebuffer_remaining(bytebuf))? 0 : 1;
}
예제 #3
0
/* send L2TP data message */
static int
l2tp_call_send_data_packet(l2tp_call *_this, bytebuffer *buffer)
{
	int rval;
	struct l2tp_header *hdr;

	bytebuffer_flip(buffer);
	hdr = (struct l2tp_header *)bytebuffer_pointer(buffer);
	memset(hdr, 0, sizeof(*hdr) - 4);	/* Nr, NS are option */

	hdr->t = 0;
	hdr->ver = L2TP_HEADER_VERSION_RFC2661;
	hdr->l = 1;
	hdr->length = htons(bytebuffer_remaining(buffer));
	hdr->tunnel_id = htons(_this->ctrl->peer_tunnel_id);
	hdr->session_id = htons(_this->peer_session_id);
	if (_this->use_seq) {
		hdr->s = 1;
		hdr->ns = htons(_this->snd_nxt++);
		hdr->nr = htons(_this->rcv_nxt);
	}

	if (L2TP_CTRL_CONF(_this->ctrl)->data_out_pktdump != 0) {
		l2tpd_log(_this->ctrl->l2tpd, LOG_DEBUG,
		    "ctrl=%u call=%u L2TP Data output packet dump",
		    _this->ctrl->id, _this->id);
		show_hd(debug_get_debugfp(), bytebuffer_pointer(buffer),
		    bytebuffer_remaining(buffer));
	}
	if ((rval = l2tp_ctrl_send(_this->ctrl, bytebuffer_pointer(buffer),
	    bytebuffer_remaining(buffer))) < 0) {
		L2TP_CALL_DBG((_this, LOG_DEBUG, "sendto() failed: %m"));
	}

	return (rval == bytebuffer_remaining(buffer))? 0 : 1;
}
예제 #4
0
/* bind ppp */
static int
l2tp_call_bind_ppp(l2tp_call *_this, dialin_proxy_info *dpi)
{
	int code, errcode;
	npppd_ppp *ppp;

	code = L2TP_CDN_RCODE_BUSY;
	errcode = 0;
	ppp = NULL;
	if ((ppp = ppp_create()) == NULL)
		goto fail;

	ASSERT(_this->ppp == NULL);

	if (_this->ppp != NULL)
		return -1;

	_this->ppp = ppp;

	ppp->tunnel_type = NPPPD_TUNNEL_L2TP;
	ppp->phy_context = _this;
	ppp->send_packet = l2tp_call_ppp_output;
	ppp->phy_close = l2tp_call_closed_by_ppp;

	strlcpy(ppp->phy_label, L2TP_CTRL_LISTENER_TUN_NAME(_this->ctrl),
	    sizeof(ppp->phy_label));
	L2TP_CALL_ASSERT(sizeof(ppp->phy_info) >= _this->ctrl->peer.ss_len);
	memcpy(&ppp->phy_info, &_this->ctrl->peer,
	    MIN(sizeof(ppp->phy_info), _this->ctrl->peer.ss_len));
	strlcpy(ppp->calling_number, _this->calling_number,
	    sizeof(ppp->calling_number));
	if (ppp_init(npppd_get_npppd(), ppp) != 0) {
		l2tp_call_log(_this, LOG_ERR, "failed binding ppp");
		goto fail;
	}

	l2tp_call_log(_this, LOG_NOTICE, "logtype=PPPBind ppp=%d", ppp->id);
	if (DIALIN_PROXY_IS_REQUESTED(dpi)) {
		if (!L2TP_CTRL_CONF(_this->ctrl)->accept_dialin) {
			l2tp_call_log(_this, LOG_ERR,
			    "'accept_dialin' is 'false' in the setting.");
			code = L2TP_CDN_RCODE_ERROR_CODE;
			errcode = L2TP_ECODE_INVALID_MESSAGE;
			goto fail;
		}

		if (ppp_dialin_proxy_prepare(ppp, dpi) != 0) {
			code = L2TP_CDN_RCODE_TEMP_NOT_AVALIABLE;
			goto fail;
		}
	}
	ppp_start(ppp);

	return 0;
fail:
	if (ppp != NULL)
		ppp_destroy(ppp);
	_this->ppp = NULL;

	l2tp_call_disconnect(_this, code, 0, NULL, NULL, 0);
	return 1;
}
예제 #5
0
/*
 * Terminate the control connection
 *
 * <p>
 * please specify an appropriate value to result( >0 ) for
 * StopCCN ResultCode AVP, when to sent Active Close (which
 * require StopCCN sent).</p>
 * <p>
 * When the return value of this function is zero, the _this
 * is already released. The lt2p_ctrl process that was bound to it
 * could not contine.
 * When the return value of this function is one, the timer
 * is reset.</p>
 *
 * @return	return 0 if terminate process was completed.
 */
int
l2tp_ctrl_stop(l2tp_ctrl *_this, int result)
{
	int i;
	l2tpd *_l2tpd;

	L2TP_CTRL_ASSERT(_this != NULL);

	switch (_this->state) {
	case L2TP_CTRL_STATE_ESTABLISHED:
		_this->state = L2TP_CTRL_STATE_CLEANUP_WAIT;
		if (result > 0) {
			_this->active_closing = result;
			l2tp_ctrl_send_disconnect_notify(_this);
			break;
		}
		goto cleanup;
	default:
		l2tp_ctrl_log(_this, LOG_DEBUG, "%s() unexpected state=%s",
		    __func__, l2tp_ctrl_state_string(_this));
		/* FALLTHROUGH */
	case L2TP_CTRL_STATE_WAIT_CTL_CONN:
		/* FALLTHROUGH */
	case L2TP_CTRL_STATE_CLEANUP_WAIT:
cleanup:
		if (slist_length(&_this->call_list) != 0) {
			if (l2tp_ctrl_disconnect_all_calls(_this, 1) > 0)
				break;
		}
#if 0
		if (L2TP_CTRL_CONF(_this)e_ipsec_sa != 0)
			l2tp_ctrl_purge_ipsec_sa(_this);
#endif

		l2tp_ctrl_log(_this, LOG_NOTICE, "logtype=Finished");

		evtimer_del(&_this->ev_timeout);

		/* free send buffer */
		if (_this->snd_buffers != NULL) {
			for (i = 0; i < _this->winsz; i++)
				bytebuffer_destroy(_this->snd_buffers[i]);
			free(_this->snd_buffers);
			_this->snd_buffers = NULL;
		}
		if (_this->zlb_buffer != NULL) {
			bytebuffer_destroy(_this->zlb_buffer);
			_this->zlb_buffer = NULL;
		}

		/* free l2tp_call */
		l2tp_ctrl_destroy_all_calls(_this);
		slist_fini(&_this->call_list);

		l2tpd_remove_ctrl(_this->l2tpd, _this->tunnel_id);

		_l2tpd = _this->l2tpd;
		l2tp_ctrl_destroy(_this);

		l2tpd_ctrl_finished_notify(_l2tpd);
		return 0;	/* stopped */
	}
	l2tp_ctrl_reset_timeout(_this);

	return 1;
}
예제 #6
0
/*
 * send SCCRP
 */
static void
l2tp_ctrl_send_SCCRP(l2tp_ctrl *_this)
{
	int len;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ], hbuf[HOST_NAME_MAX+1];
	const char *val;
	bytebuffer *bytebuf;

	if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) {
		l2tp_ctrl_log(_this, LOG_ERR,
		    "sending SCCRP failed: no buffer.");
		return;
	}
	avp = (struct l2tp_avp *)buf;

	/* Message Type = SCCRP */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE;
	avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_SCCRP);
	bytebuf_add_avp(bytebuf, avp, 2);

	/* Protocol Version = 1.0 */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_PROTOCOL_VERSION;
	avp->attr_value[0] = L2TP_RFC2661_VERSION;
	avp->attr_value[1] = L2TP_RFC2661_REVISION;
	bytebuf_add_avp(bytebuf, avp, 2);

	/* Framing Capability = Async */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_FRAMING_CAPABILITIES;
	avp_set_val32(avp, L2TP_FRAMING_CAP_FLAGS_SYNC);
	bytebuf_add_avp(bytebuf, avp, 4);

	/* Host Name */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_HOST_NAME;
	if ((val = L2TP_CTRL_CONF(_this)->hostname) == NULL) {
		gethostname(hbuf, sizeof(hbuf));
		val = hbuf;
	}
	len = strlen(val);
	memcpy(avp->attr_value, val, len);
	bytebuf_add_avp(bytebuf, avp, len);

	/* Assigned Tunnel Id */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID;
	avp_set_val16(avp, _this->tunnel_id);
	bytebuf_add_avp(bytebuf, avp, 2);

	/* Bearer Capability
	 * This implementation never act as LAC.
	 *
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_BEARER_CAPABILITIES;
	avp_set_val32(avp, 0);
	bytebuf_add_avp(bytebuf, avp, 4);
	 */

	/* Firmware Revision */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 0;
	avp->attr_type = L2TP_AVP_TYPE_FIRMWARE_REVISION;
	avp->attr_value[0] = MAJOR_VERSION;
	avp->attr_value[1] = MINOR_VERSION;
	bytebuf_add_avp(bytebuf, avp, 2);

	/* Vendor Name */
	if ((val = L2TP_CTRL_CONF(_this)->vendor_name) != NULL) {
		memset(avp, 0, sizeof(*avp));
		avp->is_mandatory = 0;
		avp->attr_type = L2TP_AVP_TYPE_VENDOR_NAME;

		len = strlen(val);
		memcpy(avp->attr_value, val, len);
		bytebuf_add_avp(bytebuf, avp, len);
	}

	/* Window Size */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_RECV_WINDOW_SIZE;
	avp_set_val16(avp, _this->winsz);
	bytebuf_add_avp(bytebuf, avp, 2);

	if ((l2tp_ctrl_send_packet(_this, 0, bytebuf)) != 0) {
		l2tp_ctrl_log(_this, LOG_ERR, "sending SCCRP failed");
		l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL);
		return;
	}
	l2tp_ctrl_log(_this, LOG_INFO, "SendSCCRP");
}