Exemplo n.º 1
0
/* send CDN */
static int
l2tp_call_send_CDN(l2tp_call *_this, int result_code, int error_code, const
    char *errmes, struct l2tp_avp *addavp[], int naddavp)
{
	uint32_t val32;
	int i, avplen, len;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ];
	bytebuffer *bytebuf;

	L2TP_CALL_ASSERT(_this != NULL);
	bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1);
	if (bytebuf == NULL) {
		l2tp_call_log(_this, LOG_ERR, "sending CDN failed: no buffer");
		return 1;
	}
	avp = (struct l2tp_avp *)buf;

	/* Message Type = CDN */
	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_CDN);
	bytebuf_add_avp(bytebuf, avp, 2);

	/* Result Code */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_RESULT_CODE;
#if 0
/*
 * Windows 2000 work around:
 * Windows 2000 will return "2 - Length is wrong" in StopCCN,
 * when it received "length = 8 and no error code AVP".
 * Avoid the error, use AVP length = 10.
 */
	if (error_code > 0) {
		val32 = (result_code << 16) | (error_code & 0xffff);
		avplen = 4;
		avp_set_val32(avp, val32);
	} else {
		avplen = 2;
		avp_set_val16(avp, result_code);
	}
#else
	val32 = (result_code << 16) | (error_code & 0xffff);
	avplen = 4;
	avp_set_val32(avp, val32);
#endif

	if (errmes != NULL) {
		len = MIN(strlen(errmes), L2TP_AVP_MAXSIZ - 128);
		memcpy(&avp->attr_value[avplen], errmes, len);
		avplen += len;
	}
	bytebuf_add_avp(bytebuf, avp, avplen);

	/* Assigned Session Id */
	memset(avp, 0, sizeof(*avp));
	avp->is_mandatory = 1;
	avp->attr_type = L2TP_AVP_TYPE_ASSIGNED_SESSION_ID;
	if (_this != NULL && _this->session_id != 0)
		avp_set_val16(avp, _this->session_id);
	else
		avp_set_val16(avp, 0);
	bytebuf_add_avp(bytebuf, avp, 2);

	for (i = 0; i < naddavp; i++)
		bytebuf_add_avp(bytebuf, addavp[i], addavp[i]->length - 6);

	if (l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id,
	    bytebuf) != 0) {
		l2tp_call_log(_this, LOG_ERR, "Error sending CDN: %m");
		return 1;
	}

	if (error_code > 0) {
		l2tp_call_log(_this, LOG_INFO,
		    "SendCDN result=%s/%d error=%s/%d messsage=%s",
		    l2tp_cdn_rcode_string(result_code), result_code,
		    l2tp_ecode_string(error_code), error_code,
		    (errmes == NULL)? "none" : errmes);
	} else {
		l2tp_call_log(_this, LOG_INFO, "SendCDN result=%s/%d",
		    l2tp_cdn_rcode_string(result_code), result_code);
	}

	return 0;
}
Exemplo n.º 2
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");
}