Exemplo n.º 1
0
/* Some route implementation which has "PPTP pass-through" function
 * will discard 1723/tcp packet between PAC and PNS, when it recognize
 * SLI from PAC. (for example, FLASHWAVE by Fujitsu).
 *
 * To avoid avobe situation, npppd send well-known SLI only.
 */
static int
pptp_call_send_SLI(pptp_call *_this)
{
	int lpkt;
	struct pptp_sli *sli;

	sli = bytebuffer_pointer(_this->ctrl->send_buf);
	lpkt = bytebuffer_remaining(_this->ctrl->send_buf);
	if (lpkt < sizeof(struct pptp_sli)) {
		pptp_call_log(_this, LOG_ERR,
		    "SendOCRP failed: No buffer space available");
		return -1;
	}
	memset(sli, 0, sizeof(struct pptp_sli));

	pptp_init_header(&sli->header, sizeof(struct pptp_sli),
	    PPTP_CTRL_MES_CODE_SLI);

	sli->peers_call_id = _this->id;
	sli->send_accm = 0xffffffff;
	sli->recv_accm = 0xffffffff;

	_this->last_io = get_monosec();
	pptp_call_log(_this, LOG_INFO, "SendSLI accm=%08x:%08x",
	    sli->send_accm, sli->recv_accm);
	sli->peers_call_id = htons(sli->peers_call_id);
	sli->send_accm = htonl(sli->send_accm);
	sli->recv_accm = htonl(sli->recv_accm);
	pptp_ctrl_output(_this->ctrl, NULL,  sizeof(struct pptp_sli));

	return 0;
}
Exemplo n.º 2
0
int
pptp_call_init(pptp_call *_this, pptp_ctrl *ctrl)
{
	memset(_this, 0, sizeof(pptp_call));
	_this->ctrl = ctrl;

	_this->maxwinsz = PPTP_CALL_DEFAULT_MAXWINSZ;
	_this->winsz = RUPDIV(_this->maxwinsz, 2);
	_this->last_io = get_monosec();
	_this->snd_nxt = 1;

	return 0;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/* Send Outgoing-Call-Reply */
static int
pptp_call_send_OCRP(pptp_call *_this, int result, int error, int cause)
{
	int lpkt;
	struct pptp_ocrp *ocrp;
	char logbuf[512];

	ocrp = bytebuffer_pointer(_this->ctrl->send_buf);
	lpkt = bytebuffer_remaining(_this->ctrl->send_buf);
	if (lpkt < sizeof(struct pptp_ocrp)) {
		pptp_call_log(_this, LOG_ERR,
		    "SendOCRP failed: No buffer space available");
		return -1;
	}
	memset(ocrp, 0, sizeof(struct pptp_ocrp));

	pptp_init_header(&ocrp->header, sizeof(struct pptp_ocrp),
	    PPTP_CTRL_MES_CODE_OCRP);

	ocrp->call_id = _this->id;
	ocrp->peers_call_id = _this->peers_call_id;
	ocrp->result_code = result;
	ocrp->error_code = error;
	ocrp->cause_code = cause;
	ocrp->connect_speed = PPTP_CALL_CONNECT_SPEED;
	ocrp->recv_winsz =  _this->maxwinsz;
	ocrp->packet_proccessing_delay = PPTP_CALL_INITIAL_PPD;
	ocrp->physical_channel_id = _this->id;

	pptp_call_OCRP_string(ocrp, logbuf, sizeof(logbuf));
	pptp_call_log(_this, LOG_INFO, "SendOCRP %s", logbuf);

	ocrp->call_id = htons(ocrp->call_id);
	ocrp->peers_call_id = htons(ocrp->peers_call_id);
	ocrp->cause_code = htons(ocrp->cause_code);
	ocrp->connect_speed = htons(ocrp->connect_speed);
	ocrp->recv_winsz = htons(ocrp->recv_winsz);
	ocrp->packet_proccessing_delay = htons(ocrp->packet_proccessing_delay);
	ocrp->physical_channel_id = htonl(ocrp->physical_channel_id);

	_this->last_io = get_monosec();
	pptp_ctrl_output(_this->ctrl, NULL,  sizeof(struct pptp_ocrp));

	return 0;
}
Exemplo n.º 5
0
/** This function is called when IPCP is opened */
void
ppp_ipcp_opened(npppd_ppp *_this)
{
	time_t curr_time;

	curr_time = get_monosec();

	npppd_set_ip_enabled(_this->pppd, _this, 1);
	if (_this->logged_acct_start == 0) {
		char label[512], ipstr[64];

		ppp_set_tunnel_label(_this, label, sizeof(label));

		strlcpy(ipstr, " ip=", sizeof(ipstr));
		strlcat(ipstr, inet_ntoa(_this->ppp_framed_ip_address),
		    sizeof(ipstr));
		if (_this->ppp_framed_ip_netmask.s_addr != 0xffffffffL) {
			strlcat(ipstr, ":", sizeof(ipstr));
			strlcat(ipstr, inet_ntoa(_this->ppp_framed_ip_netmask),
			    sizeof(ipstr));
		}

		ppp_log(_this, LOG_NOTICE,
		    "logtype=TUNNELSTART user=\"%s\" duration=%lusec layer2=%s "
 		    "layer2from=%s auth=%s %s iface=%s%s",
		    _this->username[0]? _this->username : "******",
		    (long)(curr_time - _this->start_monotime),
		    _this->phy_label, label,
		    _this->username[0]? ppp_peer_auth_string(_this) : "none",
 		    ipstr, npppd_ppp_get_iface_name(_this->pppd, _this),
		    (_this->lcp.dialin_proxy != 0)? " dialin_proxy=yes" : ""
		    );
#ifdef USE_NPPPD_RADIUS
		npppd_ppp_radius_acct_start(_this->pppd, _this);
#endif

		_this->logged_acct_start = 1;
		ppp_reset_idle_timeout(_this);
	}
#ifdef USE_NPPPD_PIPEX
	ppp_on_network_pipex(_this);
#endif
}
Exemplo n.º 6
0
/**
 * Start the npppd_ppp.
 * Set npppd_ppp#phy_context, npppd_ppp#send_packet, npppd_ppp#phy_close and
 * npppd_ppp#phy_info before call this function.
 */
void
ppp_start(npppd_ppp *_this)
{
	char label[512];

	PPP_ASSERT(_this != NULL);
	PPP_ASSERT(_this->recv_packet != NULL);
	PPP_ASSERT(_this->send_packet != NULL);
	PPP_ASSERT(_this->phy_close != NULL);

	_this->start_time = time(NULL);
	_this->start_monotime = get_monosec();
	/* log the lower layer information */
	ppp_set_tunnel_label(_this, label, sizeof(label));
	ppp_log(_this, LOG_INFO, "logtype=Started tunnel=%s(%s)",
	    _this->phy_label, label);

	lcp_lowerup(&_this->lcp);
}
Exemplo n.º 7
0
/* Send Call-Disconnect-Notify */
static void
pptp_call_send_CDN(pptp_call *_this, int result, int error, int cause,
    const char *statistics)
{
	int lpkt;
	struct pptp_cdn *cdn;

	cdn = bytebuffer_pointer(_this->ctrl->send_buf);
	lpkt = bytebuffer_remaining(_this->ctrl->send_buf);
	if (lpkt < sizeof(struct pptp_cdn)) {
		pptp_call_log(_this, LOG_ERR,
		    "SendCCR failed: No buffer space available");
		return;
	}
	memset(cdn, 0, sizeof(struct pptp_cdn));

	pptp_init_header(&cdn->header, sizeof(struct pptp_cdn),
	    PPTP_CTRL_MES_CODE_CDN);

	cdn->call_id = _this->id;
	cdn->result_code = result;
	cdn->error_code = error;
	cdn->cause_code = cause;
	if (statistics != NULL)
		strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics));

	pptp_call_log(_this, LOG_INFO, "SendCDN "
	    "call_id=%u result=%s(%d) error=%s(%d) cause=%d statistics=%s",
	    cdn->call_id,
	    pptp_CDN_result_string(cdn->result_code), cdn->result_code,
	    pptp_general_error_string(cdn->error_code), cdn->error_code,
	    cdn->cause_code,
		(statistics == NULL)? "(none)" : (char *)cdn->statistics);

	cdn->call_id = htons(cdn->call_id);
	cdn->cause_code = htons(cdn->cause_code);

	_this->last_io = get_monosec();
	pptp_ctrl_output(_this->ctrl, NULL, sizeof(struct pptp_cdn));
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
/* timeout processing */
static void
l2tp_ctrl_timeout(int fd, short evtype, void *ctx)
{
	int next_timeout, need_resend;
	time_t curr_time;
	l2tp_ctrl *_this;
	l2tp_call *call;

	/*
	 * the timer must be reset, when leave this function.
	 * MEMO: l2tp_ctrl_stop() will reset the timer in it.
	 * and please remember that the l2tp_ctrl_stop() may free _this.
	 */
	_this = ctx;
	L2TP_CTRL_ASSERT(_this != NULL);

	curr_time = get_monosec();

	next_timeout = 2;
	need_resend = 0;

	if (l2tp_ctrl_txwin_size(_this) > 0)  {
		if (_this->state == L2TP_CTRL_STATE_ESTABLISHED) {
			if (_this->hello_wait_ack != 0) {
				/* wait Hello reply */
				if (curr_time - _this->hello_io_time >=
				    _this->hello_timeout) {
					l2tp_ctrl_log(_this, LOG_NOTICE,
					    "timeout waiting ack for hello "
					    "packets.");
					l2tp_ctrl_stop(_this,
					    L2TP_STOP_CCN_RCODE_GENERAL);
					return;
				}
			}
		} else if (curr_time - _this->last_snd_ctrl >=
		    L2TP_CTRL_CTRL_PKT_TIMEOUT) {
			l2tp_ctrl_log(_this, LOG_NOTICE,
			    "timeout waiting ack for ctrl packets.");
			l2tp_ctrl_stop(_this,
			    L2TP_STOP_CCN_RCODE_GENERAL);
			return;
		}
		need_resend = 1;
	} else {
		for (slist_itr_first(&_this->call_list);
		    slist_itr_has_next(&_this->call_list);) {
			call = slist_itr_next(&_this->call_list);
			if (call->state == L2TP_CALL_STATE_CLEANUP_WAIT) {
				l2tp_call_destroy(call, 1);
				slist_itr_remove(&_this->call_list);
			}
		}
	}

	switch (_this->state) {
	case L2TP_CTRL_STATE_IDLE:
		/*
		 * idle:
		 * XXX: never happen in current implementation
		 */
		l2tp_ctrl_log(_this, LOG_ERR,
		    "Internal error, timeout on illegal state=idle");
		l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL);
		break;
	case L2TP_CTRL_STATE_WAIT_CTL_CONN:
		/*
		 * wait-ctrl-conn:
		 * 	if there is no ack for SCCRP, the peer will
		 * 	resend SCCRQ. however this implementation can
		 *	not recognize that the SCCRQ was resent or not.
		 *	Therefore, never resent from this side.
		 */
		need_resend = 0;
		break;
	case L2TP_CTRL_STATE_ESTABLISHED:
		if (slist_length(&_this->call_list) == 0 &&
		    curr_time - _this->last_snd_ctrl >=
			    L2TP_CTRL_WAIT_CALL_TIMEOUT) {
			if (_this->ncalls == 0)
				/* fail to receive first call */
				l2tp_ctrl_log(_this, LOG_WARNING,
				    "timeout waiting call");
			l2tp_ctrl_stop(_this,
			    L2TP_STOP_CCN_RCODE_GENERAL);
			return;
		}
		if (_this->hello_wait_ack == 0 && _this->hello_interval > 0) {
			/* send Hello */
			if (curr_time - _this->hello_interval >=
			    _this->hello_io_time) {
				if (l2tp_ctrl_send_HELLO(_this) == 0)
					/* success */
					_this->hello_wait_ack = 1;
				_this->hello_io_time = curr_time;
				need_resend = 0;
			}
		}
		break;
	case L2TP_CTRL_STATE_CLEANUP_WAIT:
		if (curr_time - _this->last_snd_ctrl >=
		    L2TP_CTRL_CLEANUP_WAIT_TIME) {
			l2tp_ctrl_log(_this, LOG_NOTICE,
			    "Cleanup timeout state=%d", _this->state);
			l2tp_ctrl_stop(_this, 0);
			return;
		}
		if (_this->active_closing != 0)
			l2tp_ctrl_send_disconnect_notify(_this);
		break;
	default:
		l2tp_ctrl_log(_this, LOG_ERR,
		    "Internal error, timeout on illegal state=%d",
			_this->state);
		l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL);
		return;
	}
	/* resend if required */
	if (need_resend)
		l2tp_ctrl_resend_una_packets(_this);
	l2tp_ctrl_reset_timeout(_this);
}
Exemplo n.º 10
0
/**
 * initialize and startup of {@link ::_l2tp_ctrl L2TP LNS control connection}
 * instance
 */
static int
l2tp_ctrl_init(l2tp_ctrl *_this, l2tpd *_l2tpd, struct sockaddr *peer,
    struct sockaddr *sock, void *nat_t_ctx)
{
	int tunid, i;
	bytebuffer *bytebuf;
	time_t curr_time;

	memset(_this, 0, sizeof(l2tp_ctrl));

	curr_time = get_monosec();
	_this->l2tpd = _l2tpd;
	_this->state = L2TP_CTRL_STATE_IDLE;
	_this->last_snd_ctrl = curr_time;

	slist_init(&_this->call_list);

	/* seek a free tunnel ID */
	i = 0;
	_this->id = ++l2tp_ctrl_id_seq;
	for (i = 0, tunid = _this->id; ; i++, tunid++) {
		tunid &= 0xffff;
		_this->tunnel_id = l2tp_ctrl_id_seq & 0xffff;
		if (tunid == 0)
			continue;
		if (l2tpd_get_ctrl(_l2tpd, tunid) == NULL)
			break;
		if (i > 80000) {
			/* this must be happen, just log it. */
			l2tpd_log(_l2tpd, LOG_ERR, "Too many l2tp controls");
			return -1;
		}
	}

	_this->tunnel_id = tunid;

	L2TP_CTRL_ASSERT(peer != NULL);
	L2TP_CTRL_ASSERT(sock != NULL);
	memcpy(&_this->peer, peer, peer->sa_len);
	memcpy(&_this->sock, sock, sock->sa_len);

	/* prepare send buffer */
	_this->winsz = L2TPD_DEFAULT_SEND_WINSZ;
	if ((_this->snd_buffers = calloc(_this->winsz, sizeof(bytebuffer *)))
	    == NULL) {
		l2tpd_log(_l2tpd, LOG_ERR,
		    "calloc() failed in %s(): %m", __func__);
		goto fail;
	}
	for (i = 0; i < _this->winsz; i++) {
		if ((bytebuf = bytebuffer_create(L2TPD_SND_BUFSIZ)) == NULL) {
			l2tpd_log(_l2tpd, LOG_ERR,
			    "bytebuffer_create() failed in %s(): %m", __func__);
			goto fail;
		}
		_this->snd_buffers[i] = bytebuf;
	}
	if ((_this->zlb_buffer = bytebuffer_create(sizeof(struct l2tp_header)
	    + 128)) == NULL) {
		l2tpd_log(_l2tpd, LOG_ERR,
		    "bytebuffer_create() failed in %s(): %m", __func__);
		goto fail;
	}
#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE)
	if (nat_t_ctx != NULL) {
		if ((_this->sa_cookie = malloc(
		    sizeof(struct in_ipsec_sa_cookie))) != NULL) {
			*(struct in_ipsec_sa_cookie *)_this->sa_cookie =
			    *(struct in_ipsec_sa_cookie *)nat_t_ctx;
		} else {
			l2tpd_log(_l2tpd, LOG_ERR,
			    "creating sa_cookie failed: %m");
			goto fail;
		}
	}
#endif
	_this->hello_interval = L2TP_CTRL_DEFAULT_HELLO_INTERVAL;
	_this->hello_timeout = L2TP_CTRL_DEFAULT_HELLO_TIMEOUT;
	_this->hello_io_time = curr_time;

	/* initialize timeout timer */
	l2tp_ctrl_reset_timeout(_this);

	/* register l2tp context */
	l2tpd_add_ctrl(_l2tpd, _this);
	return 0;
fail:
	l2tp_ctrl_stop(_this, 0);
	return -1;
}
Exemplo n.º 11
0
void
pptp_call_input(pptp_call *_this, int mes_type, u_char *pkt, int lpkt)
{

	PPTP_CALL_ASSERT(_this != NULL);
	PPTP_CALL_ASSERT(pkt != NULL);
	PPTP_CALL_ASSERT(lpkt >= 4);

	_this->last_io = get_monosec();
	switch (mes_type) {
	case PPTP_CTRL_MES_CODE_OCRQ:
		if (_this->state != PPTP_CALL_STATE_IDLE) {
			pptp_call_send_OCRP(_this,
			    PPTP_OCRP_RESULT_GENERIC_ERROR,
			    PPTP_ERROR_BAD_CALL, 0);
			goto bad_state;
		}
		if (pptp_call_recv_OCRQ(_this, pkt, lpkt) != 0) {
			pptp_call_send_OCRP(_this,
			    PPTP_OCRP_RESULT_GENERIC_ERROR,
			    PPTP_ERROR_BAD_CALL, 0);
			return;
		}
		if (pptpd_assign_call(_this->ctrl->pptpd, _this) != 0) {
			pptp_call_send_OCRP(_this, PPTP_OCRP_RESULT_BUSY,
			    PPTP_ERROR_NONE, 0);
			return;
		}
		if (pptp_call_send_OCRP(_this, PPTP_OCRP_RESULT_CONNECTED,
		    PPTP_ERROR_NONE, 0) != 0) {
			pptp_call_disconnect(_this,
			    PPTP_CDN_RESULT_GENRIC_ERROR,
			    PPTP_ERROR_PAC_ERROR, NULL);
			return;
		}
		if (pptp_call_start(_this) != 0) {
			pptp_call_disconnect(_this,
			    PPTP_CDN_RESULT_GENRIC_ERROR,
			    PPTP_ERROR_PAC_ERROR, NULL);
			return;
		}
		_this->state = PPTP_CALL_STATE_ESTABLISHED;
		break;
	case PPTP_CTRL_MES_CODE_SLI:
		if (pptp_call_recv_SLI(_this, pkt, lpkt) != 0) {
			return;
		}
		return;
	case PPTP_CTRL_MES_CODE_CCR:
		pptp_call_recv_CCR(_this, pkt, lpkt);
		if (_this->state == PPTP_CALL_STATE_ESTABLISHED) {
			pptp_call_disconnect(_this, PPTP_CDN_RESULT_REQUEST,
			    PPTP_ERROR_NONE, NULL);
		} else {
			pptp_call_disconnect(_this, 0, 0, NULL);
			if (_this->state != PPTP_CALL_STATE_CLEANUP_WAIT)
				goto bad_state;
		}
		return;
	default:
	    pptp_call_log(_this, LOG_WARNING,
		"Unhandled control message type=%s(%d)",
		    pptp_ctrl_mes_type_string(mes_type), mes_type);
	}
	return;
bad_state:
	pptp_call_log(_this, LOG_WARNING,
	    "Received control message %s(%d) in bad state=%s",
		pptp_ctrl_mes_type_string(mes_type), mes_type,
		pptp_call_state_string(_this->state));
}
Exemplo n.º 12
0
static void
ppp_stop0(npppd_ppp *_this)
{
	char mppe_str[BUFSIZ];
	char label[512];

#ifdef USE_NPPPD_RADIUS
	ppp_set_radius_terminate_cause(_this, RADIUS_TERMNATE_CAUSE_NAS_ERROR);
#endif
	ppp_set_disconnect_cause(_this, PPP_DISCON_NORMAL, 0, 1 /* by local */,
	    NULL);

	_this->end_monotime = get_monosec();

	if (_this->phy_close != NULL)
		_this->phy_close(_this);
	_this->phy_close = NULL;

	/*
	 * NAT/Blackhole detection for PPTP(GRE)
	 */
	if (_this->lcp.dialin_proxy != 0 &&
	    _this->lcp.dialin_proxy_lcp_renegotiation == 0) {
		/* No LCP packets on dialin proxy without LCP renegotiation */
	} else if (_this->lcp.recv_ress == 0) {	/* No responses */
		if (_this->lcp.recv_reqs == 0)	/* No requests */
			ppp_log(_this, LOG_WARNING, "no PPP frames from the "
			    "peer.  router/NAT issue? (may have filtered out)");
		else
			ppp_log(_this, LOG_WARNING, "my PPP frames may not "
			    "have arrived at the peer.  router/NAT issue? (may "
			    "be the only-first-person problem)");
	}
#ifdef USE_NPPPD_PIPEX
	if (npppd_ppp_pipex_disable(_this->pppd, _this) != 0)
		ppp_log(_this, LOG_ERR,
		    "npppd_ppp_pipex_disable() failed: %m");
#endif

	ppp_set_tunnel_label(_this, label, sizeof(label));
#ifdef	USE_NPPPD_MPPE
	if (_this->mppe_started) {
		snprintf(mppe_str, sizeof(mppe_str),
		    "mppe=yes mppe_in=%dbits,%s mppe_out=%dbits,%s",
		    _this->mppe.recv.keybits,
		    (_this->mppe.recv.stateless)? "stateless" : "stateful",
		    _this->mppe.send.keybits,
		    (_this->mppe.send.stateless)? "stateless" : "stateful");
	} else
#endif
		snprintf(mppe_str, sizeof(mppe_str), "mppe=no");
	ppp_log(_this, LOG_NOTICE,
		"logtype=TUNNELUSAGE user=\"%s\" duration=%ldsec layer2=%s "
		"layer2from=%s auth=%s data_in=%llubytes,%upackets "
		"data_out=%llubytes,%upackets error_in=%u error_out=%u %s "
		"iface=%s",
		_this->username[0]? _this->username : "******",
		(long)(_this->end_monotime - _this->start_monotime),
		_this->phy_label,  label,
		_this->username[0]? ppp_peer_auth_string(_this) : "none",
		(unsigned long long)_this->ibytes, _this->ipackets,
		(unsigned long long)_this->obytes, _this->opackets,
		_this->ierrors, _this->oerrors, mppe_str,
		npppd_ppp_get_iface_name(_this->pppd, _this));

#ifdef USE_NPPPD_RADIUS
	npppd_ppp_radius_acct_stop(_this->pppd, _this);
#endif
	npppd_ppp_unbind_iface(_this->pppd, _this);
#ifdef	USE_NPPPD_MPPE
	mppe_fini(&_this->mppe);
#endif
	evtimer_del(&_this->idle_event);

	npppd_release_ip(_this->pppd, _this);
	ppp_destroy(_this);
}