Esempio n. 1
0
/* receive CDN */
static int
l2tp_recv_CDN(l2tp_call *_this, u_char *pkt, int pktlen)
{
	int result, error, avpsz, len, sessid;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ], emes[256], pmes[256];

	/* initialize */
	result = 0;
	error = 0;
	sessid = 0;
	strlcpy(pmes, "(none)", sizeof(pmes));

	avp = (struct l2tp_avp *)buf;
	while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) {
		pkt += avpsz;
		pktlen -= avpsz;
		if (avp->vendor_id != 0) {
			L2TP_CALL_DBG((_this, LOG_DEBUG,
			    "Received a Vendor-specific AVP vendor-id=%d "
			    "type=%d", avp->vendor_id, avp->attr_type));
			continue;
		}
		if (avp->is_hidden != 0) {
			l2tp_call_log(_this, LOG_WARNING,
			    "Received AVP (%s/%d) is hidden.  But we don't "
			    "share secret.",
			    avp_attr_type_string(avp->attr_type),
			    avp->attr_type);
			if (avp->is_mandatory != 0) {
				l2tp_call_disconnect(_this,
				    L2TP_CDN_RCODE_ERROR_CODE,
				    L2TP_ECODE_UNKNOWN_MANDATORY_AVP, NULL,
				    NULL, 0);
				return 1;
			}
			continue;
		}
		switch (avp->attr_type) {
		case L2TP_AVP_TYPE_MESSAGE_TYPE:
			AVP_SIZE_CHECK(avp, ==, 8);
			continue;
		case L2TP_AVP_TYPE_RESULT_CODE:
			AVP_SIZE_CHECK(avp, >=, 8);
			result = avp->attr_value[0] << 8 | avp->attr_value[1];
			if (avp->length >= 10) {
				error = avp->attr_value[2] << 8 |
				    avp->attr_value[3];
				len = avp->length - 12;
				if (len > 0) {
					len = MIN(len, sizeof(pmes) - 1);
					memcpy(pmes, &avp->attr_value[4], len);
					pmes[len] = '\0';
				}
			}
			continue;
		case L2TP_AVP_TYPE_ASSIGNED_SESSION_ID:
			AVP_SIZE_CHECK(avp, >=, 8);
			sessid = avp_get_val16(avp);
			continue;
		default:
			if (avp->is_mandatory) {
				l2tp_call_log(_this, LOG_WARNING,
				    "AVP (%s/%d) is not supported, but it's "
				    "mandatory",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type);
				if (avp->is_mandatory != 0) {
					l2tp_call_disconnect(_this,
					    L2TP_CDN_RCODE_ERROR_CODE,
					    L2TP_ECODE_UNKNOWN_MANDATORY_AVP,
					    NULL, NULL, 0);
					return 1;
				}
#ifdef L2TP_CALL_DEBUG
			} else {
				L2TP_CALL_DBG((_this, LOG_DEBUG,
				    "AVP (%s/%d) is not handled",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type));
#endif
			}
		}
	}
	if (error == 0) {
		l2tp_call_log(_this, LOG_INFO,
		    "RecvCDN result=%s/%d", l2tp_cdn_rcode_string(result),
		    result);
	} else {
		l2tp_call_log(_this, LOG_INFO,
		    "RecvCDN result=%s/%d error=%s/%d message=%s",
		    l2tp_cdn_rcode_string(result), result,
		    l2tp_ecode_string(error), error, pmes);
	}

	return 0;

size_check_failed:
	/* continue to process even if the CDN message was broken */
	l2tp_call_log(_this, LOG_ERR, "Received bad CDN: %s", emes);

	return 0;
}
Esempio n. 2
0
/*
 * receive ICCN
 * @return	return 0 if the ICCN is acceptable.
 *		other value means fail to receive, and
 *		CDN was sent and status was updated.
 */
static int
l2tp_call_recv_ICCN(l2tp_call *_this, u_char *pkt, int pktlen,
    dialin_proxy_info *dpi)
{
	int avpsz, tx_conn_speed;
	uint32_t framing_type = 0;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ], emes[256];

	tx_conn_speed = 0;
	avp = (struct l2tp_avp *)buf;
	while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) {
		pkt += avpsz;
		pktlen -= avpsz;
		if (avp->vendor_id != 0) {
			L2TP_CALL_DBG((_this, LOG_DEBUG,
			    "Received a Vendor-specific AVP vendor-id=%d "
			    "type=%d", avp->vendor_id, avp->attr_type));
			continue;
		}
		if (avp->is_hidden != 0) {
			l2tp_call_log(_this, LOG_WARNING,
			    "Received AVP (%s/%d) is hidden.  But we don't "
			    "share secret.",
			    avp_attr_type_string(avp->attr_type),
			    avp->attr_type);
			if (avp->is_mandatory != 0) {
				l2tp_call_disconnect(_this,
				    L2TP_CDN_RCODE_ERROR_CODE,
				    L2TP_ECODE_UNKNOWN_MANDATORY_AVP, NULL,
				    NULL, 0);
				return 1;
			}
			continue;
		}
		switch (avp->attr_type) {
		case L2TP_AVP_TYPE_MESSAGE_TYPE:
			AVP_SIZE_CHECK(avp, ==, 8);
			continue;
		case L2TP_AVP_TYPE_RX_CONNECT_SPEED:
			/*
			 * As RFC 2661 this AVP is not mandatory.  But `xl2tpd'
			 * sends this as a mandatory AVP.  Handle this to
			 * ignore the xl2tpd' bug.
			 */
			AVP_SIZE_CHECK(avp, ==, 10);
			continue;
		case L2TP_AVP_TYPE_TX_CONNECT_SPEED:
			AVP_SIZE_CHECK(avp, ==, 10);
			tx_conn_speed = avp_get_val32(avp);
			continue;
		case L2TP_AVP_TYPE_FRAMING_TYPE:
			AVP_SIZE_CHECK(avp, ==, 10);
			framing_type = avp_get_val32(avp);
			continue;
		case L2TP_AVP_TYPE_SEQUENCING_REQUIRED:
			_this->seq_required = 1;
			_this->use_seq = 1;
			continue;
#ifndef	L2TPD_TEST
	    /*
	     * AVP's for Proxy-LCP and Proxy-Authen
	     */
		case L2TP_AVP_TYPE_LAST_SENT_LCP_CONFREQ:
			memcpy(dpi->last_sent_lcp.data, avp->attr_value,
			    avp_attr_length(avp));
			dpi->last_sent_lcp.ldata = avp_attr_length(avp);
			break;
		case L2TP_AVP_TYPE_LAST_RECV_LCP_CONFREQ:
			memcpy(dpi->last_recv_lcp.data, avp->attr_value,
			    avp_attr_length(avp));
			dpi->last_recv_lcp.ldata = avp_attr_length(avp);
			break;
		case L2TP_AVP_TYPE_PROXY_AUTHEN_CHALLENGE:
			memcpy(dpi->auth_chall, avp->attr_value,
			    MIN(avp_attr_length(avp), sizeof(dpi->auth_chall)));
			dpi->lauth_chall = avp_attr_length(avp);
			break;
		case L2TP_AVP_TYPE_PROXY_AUTHEN_ID:
			dpi->auth_id = avp_get_val16(avp);
			break;
		case L2TP_AVP_TYPE_PROXY_AUTHEN_NAME:
			memcpy(dpi->username, avp->attr_value,
			    MIN(sizeof(dpi->username) - 1,
			    avp_attr_length(avp)));
			break;
		case L2TP_AVP_TYPE_PROXY_AUTHEN_RESPONSE:
			memcpy(dpi->auth_resp, avp->attr_value,
			    MIN(avp_attr_length(avp), sizeof(dpi->auth_resp)));
			dpi->lauth_resp = avp_attr_length(avp);
			break;
		case L2TP_AVP_TYPE_PROXY_AUTHEN_TYPE:
			switch (avp_get_val16(avp)) {
			default:
				l2tp_call_log(_this, LOG_WARNING,
				    "RecvICCN Unknown proxy-authen-type=%d",
				    avp_get_val16(avp));
				/* FALLTHROUGH */
			case L2TP_AUTH_TYPE_NO_AUTH:
				dpi->auth_type = 0;
				break;
			case L2TP_AUTH_TYPE_PPP_CHAP:
				dpi->auth_type = PPP_AUTH_CHAP_MD5;
				break;
			case L2TP_AUTH_TYPE_PPP_PAP:
				dpi->auth_type = PPP_AUTH_PAP;
				break;
			case L2TP_AUTH_TYPE_MS_CHAP_V1:
				dpi->auth_type = PPP_AUTH_CHAP_MS;
				break;
			}
			break;
#endif
		default:
			if (avp->is_mandatory != 0) {
				l2tp_call_log(_this, LOG_WARNING,
				    "AVP (%s/%d) is not supported, but it's "
				    "mandatory",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type);
				l2tp_call_disconnect(_this,
				    L2TP_CDN_RCODE_ERROR_CODE,
				    L2TP_ECODE_UNKNOWN_MANDATORY_AVP, NULL,
				    NULL, 0);
				return 1;
#ifdef L2TP_CALL_DEBUG
			} else {
				L2TP_CALL_DBG((_this, LOG_DEBUG,
				    "AVP (%s/%d) is not handled",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type));
#endif
			}
		}
	}
	l2tp_call_log(_this, LOG_INFO, "RecvICCN "
	    "session_id=%u calling_number=%s tx_conn_speed=%u framing=%s",
	    _this->peer_session_id, _this->calling_number, tx_conn_speed,
	    ((framing_type & L2TP_FRAMING_CAP_FLAGS_ASYNC) != 0)? "async" :
	    ((framing_type & L2TP_FRAMING_CAP_FLAGS_SYNC) != 0)? "sync" :
	    "unknown");

	return 0;
size_check_failed:
	l2tp_call_log(_this, LOG_ERR, "Received bad ICCN: %s", emes);
	l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE,
	    L2TP_ECODE_WRONG_LENGTH, NULL, NULL, 0);
	return 1;
}
Esempio n. 3
0
/*
 * Receiver StopCCN
 */
static int
l2tp_ctrl_recv_StopCCN(l2tp_ctrl *_this, u_char *pkt, int pktlen)
{
	int result, error, avpsz, len;
	uint16_t tunid;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ + 16], emes[256], pmes[256];

	result = 0;
	error = 0;
	tunid = 0;
	pmes[0] = '\0';
	avp = (struct l2tp_avp *)buf;
	while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) {
		pkt += avpsz;
		pktlen -= avpsz;
		if (avp->vendor_id != 0) {
			L2TP_CTRL_DBG((_this, LOG_DEBUG,
			    "Received a Vendor-specific AVP vendor-id=%d "
			    "type=%d", avp->vendor_id, avp->attr_type));
			continue;
		}
		if (avp->is_hidden != 0) {
			l2tp_ctrl_log(_this, LOG_WARNING,
			    "Received AVP (%s/%d) is hidden.  But we don't "
			    "share secret.",
			    avp_attr_type_string(avp->attr_type),
			    avp->attr_type);
			if (avp->is_mandatory != 0) {
				l2tp_ctrl_stop(_this,
				    L2TP_STOP_CCN_RCODE_GENERAL_ERROR |
				    L2TP_ECODE_UNKNOWN_MANDATORY_AVP);
				return 1;
			}
			continue;
		}
		switch (avp->attr_type) {
		case L2TP_AVP_TYPE_MESSAGE_TYPE:
			AVP_SIZE_CHECK(avp, ==, 8);
			continue;
		case L2TP_AVP_TYPE_RESULT_CODE:
			AVP_SIZE_CHECK(avp, >=, 8);
			result = avp->attr_value[0] << 8 | avp->attr_value[1];
			if (avp->length >= 10) {
				error = avp->attr_value[2] << 8 |
				    avp->attr_value[3];
				len = avp->length - 12;
				if (len > 0) {
					len = MINIMUM(len, sizeof(pmes) - 1);
					memcpy(pmes, &avp->attr_value[4], len);
					pmes[len] = '\0';
				}
			}
			continue;
		case L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID:
			AVP_SIZE_CHECK(avp, ==, 8);
			tunid = avp_get_val16(avp);
			continue;
		default:
			if (avp->is_mandatory != 0) {
				l2tp_ctrl_log(_this, LOG_WARNING,
				    "Received AVP (%s/%d) is not supported, "
				    "but it's mandatory",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type);
#ifdef L2TP_CTRL_DEBUG
			} else {
				L2TP_CTRL_DBG((_this, LOG_DEBUG,
				    "AVP (%s/%d) is not handled",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type));
#endif
			}
		}
	}

	if (result == L2TP_CDN_RCODE_ERROR_CODE &&
	    error == L2TP_ECODE_NO_RESOURCE) {
		/*
		 * Memo:
		 * This state may be happen in following state.
		 * - lots of connect/disconect by long-running
		 *   windows2000, sometimes it fall to this state.
		 *   Once it fall to here, connection will fail till
		 *   the windows rebooted
		 */
		l2tp_ctrl_log(_this, LOG_WARNING,
		    "Peer indicates \"No Resource\" error.");
	}

	l2tp_ctrl_log(_this, LOG_INFO, "RecvStopCCN result=%s/%u "
	    "error=%s/%u tunnel_id=%u message=\"%s\"",
	    l2tp_stopccn_rcode_string(result), result,
	    l2tp_ecode_string(error), error, tunid, pmes);

	return 0;

size_check_failed:
	l2tp_ctrl_log(_this, LOG_ERR, "Received bad StopCCN: %s", emes);

	return -1;
}
Esempio n. 4
0
/*
 * receieve ICRQ
 * @return	return 0 if the ICRQ is acceptable.
 *		other values means fail to receive, and
 *		CDN was sent and status was updated.
 */
static int
l2tp_call_recv_ICRQ(l2tp_call *_this, u_char *pkt, int pktlen)
{
	int avpsz, slen;
	struct l2tp_avp *avp;
	char buf[L2TP_AVP_MAXSIZ], emes[256];

	avp = (struct l2tp_avp *)buf;
	while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) {
		pkt += avpsz;
		pktlen -= avpsz;
		if (avp->vendor_id != 0) {
			L2TP_CALL_DBG((_this, LOG_DEBUG,
			    "Received a Vendor-specific AVP vendor-id=%d "
			    "type=%d", avp->vendor_id, avp->attr_type));
			continue;
		}
		if (avp->is_hidden != 0) {
			l2tp_call_log(_this, LOG_WARNING,
			    "Received AVP (%s/%d) is hidden.  But we don't "
			    "share secret.",
			    avp_attr_type_string(avp->attr_type),
			    avp->attr_type);
			if (avp->is_mandatory != 0) {
				l2tp_call_disconnect(_this,
				    L2TP_CDN_RCODE_ERROR_CODE,
				    L2TP_ECODE_UNKNOWN_MANDATORY_AVP, NULL,
				    NULL, 0);
				return 1;
			}
			continue;
		}
		switch (avp->attr_type) {
		case L2TP_AVP_TYPE_MESSAGE_TYPE:
			AVP_SIZE_CHECK(avp, ==, 8);
			continue;
		case L2TP_AVP_TYPE_ASSIGNED_SESSION_ID:
			AVP_SIZE_CHECK(avp, ==, 8);
			_this->peer_session_id = avp_get_val16(avp);
			continue;
		case L2TP_AVP_TYPE_CALL_SERIAL_NUMBER:
		case L2TP_AVP_TYPE_BEARER_TYPE:
		case L2TP_AVP_TYPE_PHYSICAL_CHANNEL_ID:
			/*
			 * Memo:
			 * Microsoft "L2TP/IPsec VPN Client" for
			 * Windows 98/Me/NT asserts mandatory bit in
			 * Physical Channel Id
			 */
			break;
		case L2TP_AVP_TYPE_CALLING_NUMBER:
			slen = MIN(sizeof(_this->calling_number) - 1,
			    avp_attr_length(avp));
			memcpy(_this->calling_number, avp->attr_value, slen);
			_this->calling_number[slen] = '\0';
			break;
		case L2TP_AVP_TYPE_CALLED_NUMBER:
		case L2TP_AVP_TYPE_SUB_ADDRESS:
			continue;
		default:
			if (avp->is_mandatory) {
				l2tp_call_log(_this, LOG_WARNING,
				    "AVP (%s/%d) is not supported, but it's "
				    "mandatory",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type);
				if (avp->is_mandatory != 0) {
					l2tp_call_disconnect(_this,
					    L2TP_CDN_RCODE_ERROR_CODE,
					    L2TP_ECODE_UNKNOWN_MANDATORY_AVP,
					    NULL, NULL, 0);
					return 1;
				}
#ifdef L2TP_CALL_DEBUG
			} else {
				L2TP_CALL_DBG((_this, LOG_DEBUG,
				    "AVP (%s/%d) is not handled",
				    avp_attr_type_string(avp->attr_type),
				    avp->attr_type));
#endif
			}
		}
	}
	if (_this->peer_session_id == 0) {
		l2tp_call_log(_this, LOG_ERR,
		    "Received a bad ICRP: SessionId = 0");
		l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE,
		    L2TP_ECODE_INVALID_MESSAGE, "Session Id must not be 0",
		    NULL, 0);
		return 1;
	}
	l2tp_call_log(_this, LOG_INFO, "RecvICRQ session_id=%u",
	    _this->peer_session_id);

	return 0;
size_check_failed:
	l2tp_call_log(_this, LOG_ERR, "Received bad ICRQ: %s", emes);
	l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE,
	    L2TP_ECODE_WRONG_LENGTH, NULL, NULL, 0);

	return 1;
}
Esempio n. 5
0
/*
 * receiver SCCRQ
 */
static int
l2tp_ctrl_recv_SCCRQ(l2tp_ctrl *_this, u_char *pkt, int pktlen, l2tpd *_l2tpd,
    struct sockaddr *peer)
{
	int avpsz, len, protover, protorev, firmrev, result;
	struct l2tp_avp *avp;
	char host[NI_MAXHOST], serv[NI_MAXSERV];
	char buf[L2TP_AVP_MAXSIZ], emes[256], hostname[256], vendorname[256];

	result = L2TP_STOP_CCN_RCODE_GENERAL_ERROR;
	strlcpy(hostname, "(no hostname)", sizeof(hostname));
	strlcpy(vendorname, "(no vendorname)", sizeof(vendorname));

	firmrev = 0;
	protover = 0;
	protorev = 0;
	avp = (struct l2tp_avp *)buf;
	while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) {
		pkt += avpsz;
		pktlen -= avpsz;
		if (avp->vendor_id != 0) {
			L2TP_CTRL_DBG((_this, LOG_DEBUG,
			    "Received a Vendor-specific AVP vendor-id=%d "
			    "type=%d", avp->vendor_id, avp->attr_type));
			continue;
		}
		switch (avp->attr_type) {
		case L2TP_AVP_TYPE_MESSAGE_TYPE:
			AVP_SIZE_CHECK(avp, ==, 8);
			continue;
		case L2TP_AVP_TYPE_PROTOCOL_VERSION:
			AVP_SIZE_CHECK(avp, ==, 8);
			protover = avp->attr_value[0];
			protorev = avp->attr_value[1];

			if (protover != L2TP_RFC2661_VERSION ||
			    protorev != L2TP_RFC2661_REVISION) {
				result = L2TP_STOP_CCN_RCODE_GENERAL_ERROR;
				snprintf(emes, sizeof(emes),
				    "Peer's protocol version is not supported:"
				    " %d.%d", protover, protorev);
				goto not_acceptable;
			}
			continue;
		case L2TP_AVP_TYPE_FRAMING_CAPABILITIES:
			AVP_SIZE_CHECK(avp, ==, 10);
			if ((avp_get_val32(avp) & L2TP_FRAMING_CAP_FLAGS_SYNC)
			    == 0) {
				L2TP_CTRL_DBG((_this, LOG_DEBUG, "Peer doesn't "
				    "support synchronous framing"));
			}
			continue;
		case L2TP_AVP_TYPE_BEARER_CAPABILITIES:
			AVP_SIZE_CHECK(avp, ==, 10);
			continue;
		case L2TP_AVP_TYPE_TIE_BREAKER:
			AVP_SIZE_CHECK(avp, ==, 14);
			/*
			 * As the implementation never send SCCRQ,
			 * the peer is always winner
			 */
			continue;
		case L2TP_AVP_TYPE_FIRMWARE_REVISION:
			AVP_SIZE_CHECK(avp, >=, 6);
			firmrev = avp_get_val16(avp);
			continue;
		case L2TP_AVP_TYPE_HOST_NAME:
			AVP_SIZE_CHECK(avp, >, 4);
			len = MINIMUM(sizeof(hostname) - 1, avp->length - 6);
			memcpy(hostname, avp->attr_value, len);
			hostname[len] = '\0';
			continue;
		case L2TP_AVP_TYPE_VENDOR_NAME:
			AVP_SIZE_CHECK(avp, >, 4);
			len = MINIMUM(sizeof(vendorname) - 1, avp->length - 6);
			memcpy(vendorname, avp->attr_value, len);
			vendorname[len] = '\0';
			continue;
		case L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID:
			AVP_SIZE_CHECK(avp, ==, 8);
			_this->peer_tunnel_id = avp_get_val16(avp);
			continue;
		case L2TP_AVP_TYPE_RECV_WINDOW_SIZE:
			AVP_SIZE_CHECK(avp, ==, 8);
			_this->peer_winsz = avp_get_val16(avp);
			continue;
		}
		if (avp->is_mandatory) {
			l2tp_ctrl_log(_this, LOG_WARNING,
			    "Received AVP (%s/%d) is not supported, but it's "
			    "mandatory", avp_attr_type_string(avp->attr_type),
			    avp->attr_type);
#ifdef L2TP_CTRL_DEBUG
		} else {
			L2TP_CTRL_DBG((_this, LOG_DEBUG,
			    "AVP (%s/%d) is not handled",
			    avp_attr_type_string(avp->attr_type),
			    avp->attr_type));
#endif
		}
	}
	if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len,
	    host, sizeof(host), serv, sizeof(serv),
	    NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM) != 0) {
		l2tp_ctrl_log(_this, LOG_ERR,
		    "getnameinfo() failed at %s(): %m", __func__);
		strlcpy(host, "error", sizeof(host));
		strlcpy(serv, "error", sizeof(serv));
	}
	l2tp_ctrl_log(_this, LOG_NOTICE, "logtype=Started RecvSCCRQ "
	    "from=%s:%s/udp tunnel_id=%u/%u protocol=%d.%d winsize=%d "
	    "hostname=%s vendor=%s firm=%04X", host, serv, _this->tunnel_id,
	    _this->peer_tunnel_id, protover, protorev, _this->peer_winsz,
	    hostname, vendorname, firmrev);

	return 0;
not_acceptable:
size_check_failed:
	l2tp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: %s", emes);
	l2tp_ctrl_stop(_this, result);

	return 1;
}