Exemple #1
0
/** The callback function on network is available for pipex */
static void
ppp_on_network_pipex(npppd_ppp *_this)
{
	if (_this->use_pipex == 0)
		return;
	if (_this->tunnel_type != PPP_TUNNEL_PPTP &&
	    _this->tunnel_type != PPP_TUNNEL_PPPOE &&
	    _this->tunnel_type != PPP_TUNNEL_L2TP)
		return;

	if (_this->pipex_started != 0)
		return;	/* already started */

	if (_this->assigned_ip4_enabled != 0 &&
	    (!MPPE_MUST_NEGO(_this) || _this->ccp.fsm.state == OPENED ||
		    _this->ccp.fsm.state == STOPPED)) {
		/* IPCP is opened and MPPE is not required or MPPE is opened */
		if (npppd_ppp_pipex_enable(_this->pppd, _this) != 0)
			ppp_log(_this, LOG_WARNING, "failed enable pipex: %m");
		ppp_log(_this, LOG_NOTICE, "Using pipex=%s",
		    (_this->pipex_enabled != 0)? "yes" : "no");
		_this->pipex_started = 1;
	}
	/* else wait CCP or IPCP */
}
Exemple #2
0
/** This function is called on authentication succeed */
void
ppp_auth_ok(npppd_ppp *_this)
{
	if (npppd_ppp_bind_iface(_this->pppd, _this) != 0) {
		ppp_log(_this, LOG_WARNING, "No interface binding.");
		ppp_stop(_this, NULL);

		return;
	}
	if (_this->realm != NULL) {
		npppd_ppp_get_username_for_auth(_this->pppd, _this,
		    _this->username, _this->username);
		if (!npppd_check_calling_number(_this->pppd, _this)) {
			ppp_log(_this, LOG_ALERT,
			    "logtype=TUNNELDENY user=\"%s\" "
			    "reason=\"Calling number check is failed\"",
			    _this->username);
			    /* XXX */
			ppp_stop(_this, NULL);
			return;
		}
	}
	if (_this->peer_auth != 0) {
		/* Limit the number of connections per the user */
		if (!npppd_check_user_max_session(_this->pppd, _this)) {
			ppp_log(_this, LOG_WARNING,
			    "user %s exceeds user-max-session limit",
			    _this->username);
			ppp_stop(_this, NULL);

			return;
		}
		PPP_ASSERT(_this->realm != NULL);
	}

	if (!npppd_ppp_iface_is_ready(_this->pppd, _this)) {
		ppp_log(_this, LOG_WARNING,
		    "interface '%s' is not ready.",
		    npppd_ppp_get_iface_name(_this->pppd, _this));
		ppp_stop(_this, NULL);

		return;
	}
	if (_this->proxy_authen_resp != NULL) {
		free(_this->proxy_authen_resp);
		_this->proxy_authen_resp = NULL;
	}

	fsm_lowerup(&_this->ipcp.fsm);
	fsm_open(&_this->ipcp.fsm);
#ifdef	USE_NPPPD_MPPE
	if (MPPE_MUST_NEGO(_this)) {
		fsm_lowerup(&_this->ccp.fsm);
		fsm_open(&_this->ccp.fsm);
	}
#endif

	return;
}
Exemple #3
0
/*
 * reading some authentication settings and storing ppp_order in
 * order of settings.
 */
static void
lcp_load_authconfig(fsm *f)
{
	int i, f_none;
	const char *val;
	lcp *_this;

	_this = &f->ppp->lcp;
	i = 0;
	f_none = 0;
	if ((val = ppp_config_str(f->ppp, "auth.method")) != NULL) {
		char *authp0, *authp, authbuf[512];

		strlcpy(authbuf, val, sizeof(authbuf));
		authp0 = authbuf;
		while ((authp = strsep(&authp0, SPACE)) != NULL &&
		    i < countof(_this->auth_order) - 1) {
			if (strcasecmp("none", authp) == 0) {
				f_none = 1;
			} else if (strcasecmp("PAP", authp) == 0) {
				_this->auth_order[i++] = PPP_AUTH_PAP;
				psm_opt_set_enabled(_this, pap, 1);
			} else if (strcasecmp("CHAP", authp) == 0 ||
			    strcasecmp("MD5CHAP", authp) == 0) {
				_this->auth_order[i++] =
				    PPP_AUTH_CHAP_MD5;
				psm_opt_set_enabled(_this, chap, 1);
			} else if (strcasecmp("CHAPMS", authp) == 0 ||
			    strcasecmp("MSCHAP", authp) == 0) {
#if 0 /* MS-CHAP is not supported. */
				_this->auth_order[i++] =
				    PPP_AUTH_CHAP_MS;
				psm_opt_set_enabled(_this, chapms, 1);
#endif
			} else if (strcasecmp("CHAPMSV2", authp) == 0 ||
			    strcasecmp("MSCHAPV2", authp) == 0 ||
			    strcasecmp("CHAPMS_V2", authp) == 0 ||
			    strcasecmp("MSCHAP_V2", authp) == 0) {
				_this->auth_order[i++] = PPP_AUTH_CHAP_MS_V2;
				psm_opt_set_enabled(_this,chapms_v2, 1);
#ifdef USE_NPPPD_EAP_RADIUS
			} else if (strcasecmp("EAP-RADIUS", authp) == 0) {
				_this->auth_order[i++] = PPP_AUTH_EAP;
				psm_opt_set_enabled(_this, eap, 1);
#endif
			} else
				ppp_log(f->ppp, LOG_WARNING,
				    "unknown auth protocol: %s", authp);
		}
	}
	if (f_none && i != 0) {
		ppp_log(f->ppp, LOG_WARNING, "auth protocol 'none' "
		    "must be specified individually");
		f_none = 0;
	}
	_this->auth_order[i] = -1;
}
Exemple #4
0
static void
ppp_set_tunnel_label(npppd_ppp *_this, char *buf, int lbuf)
{
	int flag, af;
	char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

	hbuf[0] = 0;
	sbuf[0] = 0;
	af = ((struct sockaddr *)&_this->phy_info)->sa_family;
	if (af < AF_MAX) {
		flag = NI_NUMERICHOST;
		if (af == AF_INET || af == AF_INET6)
			flag |= NI_NUMERICSERV;
		if (getnameinfo((struct sockaddr *)&_this->phy_info,
		    ((struct sockaddr *)&_this->phy_info)->sa_len, hbuf,
		    sizeof(hbuf), sbuf, sizeof(sbuf), flag) != 0) {
			ppp_log(_this, LOG_ERR, "getnameinfo() failed at %s",
			    __func__);
			strlcpy(hbuf, "0.0.0.0", sizeof(hbuf));
			strlcpy(sbuf, "0", sizeof(sbuf));
		}
		if (af == AF_INET || af == AF_INET6)
			snprintf(buf, lbuf, "%s:%s", hbuf, sbuf);
		else
			snprintf(buf, lbuf, "%s", hbuf);
	} else if (af == NPPPD_AF_PHONE_NUMBER) {
		strlcpy(buf,
		    ((npppd_phone_number *)&_this->phy_info)->pn_number, lbuf);
	}
}
Exemple #5
0
static void
npppd_iface_network_input_ipv4(npppd_iface *_this, u_char *pktp, int lpktp)
{
	struct ip *iphdr;
	npppd *_npppd;
	npppd_ppp *ppp;
	struct npppd_iface_network_input_arg input_arg;

	NPPPD_IFACE_ASSERT(_this != NULL);
	NPPPD_IFACE_ASSERT(pktp != NULL);

	iphdr = (struct ip *)pktp;
	_npppd = _this->npppd;

	if (lpktp < sizeof(iphdr)) {
		npppd_iface_log(_this, LOG_ERR, "Received short packet.");
		return;
	}
	if (IN_MULTICAST(ntohl(iphdr->ip_dst.s_addr))) {
		NPPPD_IFACE_ASSERT(((npppd *)(_this->npppd))->rd != NULL);
		input_arg._this = _this;
		input_arg.pktp = pktp;
		input_arg.lpktp = lpktp;
		/* delegate */
		rd_walktree(((npppd *)(_this->npppd))->rd,
		    npppd_iface_network_input_delegate, &input_arg);
		return;
	}
	ppp = npppd_get_ppp_by_ip(_npppd, iphdr->ip_dst);
	if (ppp == NULL) {
#ifdef NPPPD_DEBUG
		log_printf(LOG_INFO, "%s received a packet to unknown "
		    "%s.", _this->ifname, inet_ntoa(iphdr->ip_dst));
#endif
		return;
	}
#ifndef NO_ADJUST_MSS
	if (ppp->adjust_mss) {
		adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru));
	}
#endif
	if (ppp->timeout_sec > 0 && !ip_is_idle_packet(iphdr, lpktp))
		ppp_reset_idle_timeout(ppp);

#ifdef	USE_NPPPD_MPPE
	if (MPPE_SEND_READY(ppp)) {
		/* output via MPPE if MPPE started */
		mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, pktp, lpktp);
		return;
	} else if (MPPE_IS_REQUIRED(ppp)) {
		/* in case MPPE not started but MPPE is mandatory */
		ppp_log(ppp, LOG_WARNING, "A packet received from network, "
		    "but MPPE is not started.");
		return;
	}
#endif
	ppp_output(ppp, PPP_PROTO_IP, 0, 0, pktp, lpktp);
}
Exemple #6
0
/** timer event handler for idle timer */
static void
ppp_idle_timeout(int fd, short evtype, void *context)
{
	npppd_ppp *_this;

	_this = context;

	ppp_log(_this, LOG_NOTICE, "Idle timeout(%d sec)", _this->timeout_sec);
#ifdef USE_NPPPD_RADIUS
	ppp_set_radius_terminate_cause(_this,
	    RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
#endif
	ppp_stop(_this, NULL);
}
Exemple #7
0
/** This function is called when CCP is opened */
void
ppp_ccp_opened(npppd_ppp *_this)
{
#ifdef USE_NPPPD_MPPE
	if (_this->ccp.mppe_rej == 0) {
		if (_this->mppe_started == 0) {
			mppe_start(&_this->mppe);
		}
	} else {
		ppp_log(_this, LOG_INFO, "mppe is rejected by peer");
		if (_this->mppe.required)
			ppp_stop(_this, "MPPE is requred");
	}
#endif
#ifdef USE_NPPPD_PIPEX
	ppp_on_network_pipex(_this);
#endif
}
Exemple #8
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
}
Exemple #9
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);
}
Exemple #10
0
/** Prepare "dialin proxy".  Return 0 if "dialin proxy" is not available.  */
int
ppp_dialin_proxy_prepare(npppd_ppp *_this, dialin_proxy_info *dpi)
{
	int renego_force, renego;

	renego = (ppp_config_str_equal(_this,
	    "l2tp.dialin.lcp_renegotiation", "disable", 0))? 0 : 1;
	renego_force = ppp_config_str_equal(_this,
	    "l2tp.dialin.lcp_renegotiation", "force", 0);
	if (renego_force)
		renego = 1;

	if (lcp_dialin_proxy(&_this->lcp, dpi, renego, renego_force) != 0) {
		ppp_log(_this, LOG_ERR,
		    "Failed to dialin-proxy, proxied lcp is broken.");
		return 1;
	}

	return 0;
}
Exemple #11
0
/** called when the lcp is up */
void
ppp_lcp_up(npppd_ppp *_this)
{
#ifdef USE_NPPPD_MPPE
	if (MPPE_REQUIRED(_this) && !MPPE_MUST_NEGO(_this)) {
		ppp_log(_this, LOG_ERR, "MPPE is required, auth protocol must "
		    "be MS-CHAP-V2 or EAP");
		ppp_stop(_this, "Encryption required");
		return;
	}
#endif
	/*
	 * Use our MRU value even if the peer insists on larger value.
	 * We set the peer_mtu here, the value will be used as the MTU of the
	 * routing entry.  So we will not receive packets larger than the MTU.
	 */
	if (_this->peer_mru > _this->mru)
		_this->peer_mru = _this->mru;

	if (_this->peer_auth != 0 && _this->auth_runonce == 0) {
		if (AUTH_IS_PAP(_this)) {
			pap_start(&_this->pap);
			_this->auth_runonce = 1;
			return;
		}
		if (AUTH_IS_CHAP(_this)) {
			chap_start(&_this->chap);
			_this->auth_runonce = 1;
			return;
		}
#ifdef USE_NPPPD_EAP_RADIUS
                if (AUTH_IS_EAP(_this)) {
                        eap_init(&_this->eap, _this);
                        eap_start(&_this->eap);
                        return;
                }
#endif
	}
	if (_this->peer_auth == 0)
		ppp_auth_ok(_this);
}
Exemple #12
0
static int
radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop)
{
	RADIUS_PACKET *radpkt;
	RADIUS_REQUEST_CTX radctx;
	radius_req_setting *rad_setting;
	char buf[128];

	if (ppp->username[0] == '\0')
		return 0;

	radpkt = NULL;
	radctx = NULL;
	rad_setting = npppd_auth_radius_get_radius_acct_setting(ppp->realm);
	if (!radius_req_setting_has_server(rad_setting))
		return 0;
	if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST))
	    == NULL)
		goto fail;

	if (radius_prepare(rad_setting, (void *)(uintptr_t)ppp->id, &radctx,
	    npppd_ppp_radius_acct_reqcb, 0) != 0)
		goto fail;

    /* NAS Information */
	/*
	 * RFC 2865 "5.4.  NAS-IP-Address" or RFC 3162 "2.1. NAS-IPv6-Address"
	 */
	if (radius_prepare_nas_address(rad_setting, radpkt) != 0)
		goto fail;

	/* RFC 2865 "5.41. NAS-Port-Type" */
	ATTR_INT32(RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL);

	/* RFC 2865 "5.5. NAS-Port" */
	ATTR_INT32(RADIUS_TYPE_NAS_PORT, ppp->id);
	    /* npppd has no physical / virtual ports in design. */

	/* RFC 2865 5.31. Calling-Station-Id */
	if (ppp->calling_number[0] != '\0')
		ATTR_STR(RADIUS_TYPE_CALLING_STATION_ID, ppp->calling_number);

    /* Tunnel Protocol Information */
	switch (ppp->tunnel_type) {
	case PPP_TUNNEL_L2TP:
		/* RFC 2868 3.1. Tunnel-Type */
		ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_L2TP);
		if (l2tp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
			goto fail;
		break;
	case PPP_TUNNEL_PPTP:
		/* RFC 2868 3.1. Tunnel-Type */
		ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_PPTP);
		if (pptp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
			goto fail;
		break;
	}

    /* Framed Protocol (PPP) Information */
	/* RFC 2865 5.1 User-Name */
	ATTR_STR(RADIUS_TYPE_USER_NAME, ppp->username);

	/* RFC 2865 "5.7. Service-Type" */
	ATTR_INT32(RADIUS_TYPE_SERVICE_TYPE, RADIUS_SERVICE_TYPE_FRAMED);

	/* RFC 2865 "5.8. Framed-Protocol" */
	ATTR_INT32(RADIUS_TYPE_FRAMED_PROTOCOL, RADIUS_FRAMED_PROTOCOL_PPP);

	/* RFC 2865 "5.8. Framed-IP-Address" */
	if (ppp_ip_assigned(ppp) && !stop)
		ppp->realm_framed_ip_address = ppp->ppp_framed_ip_address;
	if (ppp->realm_framed_ip_address.s_addr != INADDR_ANY) {
		ATTR_INT32(RADIUS_TYPE_FRAMED_IP_ADDRESS,
		    ntohl(ppp->realm_framed_ip_address.s_addr));
	}

    /* Accounting */
	/* RFC 2866  5.1. Acct-Status-Type */
	ATTR_INT32(RADIUS_TYPE_ACCT_STATUS_TYPE, (stop)
	    ? RADIUS_ACCT_STATUS_TYPE_STOP : RADIUS_ACCT_STATUS_TYPE_START);

	/* RFC 2866  5.2.  Acct-Delay-Time */
	ATTR_INT32(RADIUS_TYPE_ACCT_DELAY_TIME, 0);

	if (stop) {
		/* RFC 2866  5.3 Acct-Input-Octets */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_OCTETS,
		    (uint32_t)(ppp->ibytes & 0xFFFFFFFFU));	/* LSB 32bit */

		/* RFC 2866  5.4 Acct-Output-Octets */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_OCTETS,
		    (uint32_t)(ppp->obytes & 0xFFFFFFFFU));	/* LSB 32bit */
	}

	/* RFC 2866  5.5 Acct-Session-Id */
	snprintf(buf, sizeof(buf), "%08X%08X", pppd->boot_id, ppp->id);
	ATTR_STR(RADIUS_TYPE_ACCT_SESSION_ID, buf);

	/* RFC 2866 5.6.  Acct-Authentic */
	ATTR_INT32(RADIUS_TYPE_ACCT_AUTHENTIC, RADIUS_ACCT_AUTHENTIC_RADIUS);

	if (stop) {
		/* RFC 2866 5.7. Acct-Session-Time */
		ATTR_INT32(RADIUS_TYPE_ACCT_SESSION_TIME,
		    ppp->end_monotime - ppp->start_monotime);

		/* RFC 2866  5.8 Acct-Input-Packets */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_PACKETS, ppp->ipackets);

		/* RFC 2866  5.9 Acct-Output-Packets */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_PACKETS, ppp->opackets);

		/* RFC 2866  5.10. Acct-Terminate-Cause */
		if (ppp->terminate_cause != 0)
			ATTR_INT32(RADIUS_TYPE_ACCT_TERMINATE_CAUSE,
			    ppp->terminate_cause);

		/* RFC 2869  5.1 Acct-Input-Gigawords */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, ppp->ibytes >> 32);

		/* RFC 2869  5.2 Acct-Output-Gigawords */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS,
		    ppp->obytes >> 32);
	}

	radius_set_request_authenticator(radpkt,
	    radius_get_server_secret(radctx));

	/* Send the request */
	radius_request(radctx, radpkt);

	return 0;

fail:
	ppp_log(ppp, LOG_WARNING, "radius accounting request failed: %m");

	if (radctx != NULL)
		radius_cancel_request(radctx);
	if (radpkt != NULL)
		radius_delete_packet(radpkt);

	return -1;
}
Exemple #13
0
/**
 * Receive the PPP packet.
 * @param	flags	Indicate information of received packet by bit flags.
 *			{@link ::PPP_IO_FLAGS_MPPE_ENCRYPTED} and
 *			{@link ::PPP_IO_FLAGS_DELAYED} may be used.
 * @return	return 0 on success.  return 1 on failure.
 */
static int
ppp_recv_packet(npppd_ppp *_this, unsigned char *pkt, int lpkt, int flags)
{
	u_char *inp, *inp_proto;
	uint16_t proto;

	PPP_ASSERT(_this != NULL);

	inp = pkt;

	if (lpkt < 4) {
		ppp_log(_this, LOG_DEBUG, "%s(): Rcvd short header.", __func__);
		return 0;
	}


	if (_this->has_acf == 0) {
		/* nothing to do */
	} else if (inp[0] == PPP_ALLSTATIONS && inp[1] == PPP_UI) {
		inp += 2;
	} else {
		/*
		 * Address and Control Field Compression
		 */
		if (!psm_opt_is_accepted(&_this->lcp, acfc) &&
		    _this->logged_no_address == 0) {
			/*
			 * On packet loss condition, we may receive ACFC'ed
			 * packets before our LCP is opened because the peer's
			 * LCP is opened already.
			 */
			ppp_log(_this, LOG_INFO,
			    "%s: Rcvd broken frame.  ACFC is not accepted, "
			    "but received ppp frame that has no address.",
			    __func__);
			/*
			 * Log this once because it may be noisy.
			 * For example, Yahama RTX-1000 refuses to use ACFC
			 * but it send PPP frames without the address field.
			 */
			_this->logged_no_address = 1;
		}
	}
	inp_proto = inp;
	if ((inp[0] & 0x01) != 0) {
		/*
		 * Protocol Field Compression
		 */
		if (!psm_opt_is_accepted(&_this->lcp, pfc)) {
			ppp_log(_this, LOG_INFO,
			    "%s: Rcvd broken frame.  No protocol field: "
			    "%02x %02x", __func__, inp[0], inp[1]);
			return 1;
		}
		GETCHAR(proto, inp);
	} else {
		GETSHORT(proto, inp);
	}

	/*
	 * if the PPP frame is reordered, drop it
	 * unless proto is reorder-tolerant
	 */
	if (flags & PPP_IO_FLAGS_DELAYED && proto != PPP_PROTO_IP)
		return 1;

	if (_this->log_dump_in != 0 && debug_get_debugfp() != NULL) {
		char buf[256];

		snprintf(buf, sizeof(buf), "log.%s.in.pktdump",
		    proto_name(proto));
		if (ppp_config_str_equal(_this, buf, "true", 0) != 0)  {
			ppp_log(_this, LOG_DEBUG,
			    "PPP input dump proto=%s(%d/%04x)",
			    proto_name(proto), proto, proto);
			show_hd(debug_get_debugfp(), pkt, lpkt);
		}
	}
#ifdef USE_NPPPD_PIPEX
	if (_this->pipex_enabled != 0 &&
	    _this->tunnel_type == PPP_TUNNEL_PPPOE) {
		switch (proto) {
		case PPP_PROTO_IP:
			return 2;		/* handled by PIPEX */
		case PPP_PROTO_NCP | NCP_CCP:
			if (lpkt - (inp - pkt) < 4)
				break;		/* error but do it on fsm.c */
			if (*inp == 0x0e ||	/* Reset-Request */
			    *inp == 0x0f	/* Reset-Ack */) {
				return 2;	/* handled by PIPEX */
			}
			/* FALLTHROUGH */
		default:
			break;
		}
	}
#endif /* USE_NPPPD_PIPEX */

	switch (proto) {
#ifdef	USE_NPPPD_MPPE
	case PPP_PROTO_IP:
		/* Checks for MPPE */
		if ((flags & PPP_IO_FLAGS_MPPE_ENCRYPTED) == 0) {
			if (MPPE_REQUIRED(_this)) {
				/* MPPE is required but naked ip */

				if (_this->logged_naked_ip == 0) {
					ppp_log(_this, LOG_INFO,
					    "mppe is required but received "
					    "naked IP.");
					/* log this once */
					_this->logged_naked_ip = 1;
				}
				/*
				 * Windows sends naked IP packets in condition
				 * such that MPPE is not opened and IPCP is not
				 * opened(*1).  This occurs at a high
				 * probability when the CCP establishment is
				 * delayed because of packet loss etc.  If we
				 * call ppp_stop() here, Windows on the packet
				 * loss condition etc cannot not connect us.
				 * So we don't call ppp_stop() here.
				 * (*1) At least Microsof Windows 2000
				 * Professional SP4 does.
				 */
				 /*ppp_stop(_this, "Encryption is required.");*/

				return 1;
			}
			if (MPPE_READY(_this)) {
				/* MPPE is opened but naked ip packet */
				ppp_log(_this, LOG_WARNING,
				    "mppe is available but received naked IP.");
			}
		}
		/* else input from MPPE */
		break;
	case PPP_PROTO_MPPE:
#ifdef USE_NPPPD_MPPE
		if (_this->mppe_started == 0)  {
#else
		{
#endif
			ppp_log(_this, LOG_ERR,
			    "mppe packet is received but mppe is stopped.");
			return 1;
		}
		break;
#endif
	}

	switch (proto) {
	case PPP_PROTO_IP:
		npppd_network_output(_this->pppd, _this, AF_INET, inp,
		    lpkt - (inp - pkt));
		goto handled;
	case PPP_PROTO_LCP:
		fsm_input(&_this->lcp.fsm, inp, lpkt - (inp - pkt));
		goto handled;
	case PPP_PROTO_PAP:
		pap_input(&_this->pap, inp, lpkt - (inp - pkt));
		goto handled;
	case PPP_PROTO_CHAP:
		chap_input(&_this->chap, inp, lpkt - (inp - pkt));
		goto handled;
#ifdef USE_NPPPD_EAP_RADIUS
	case PPP_PROTO_EAP:
		eap_input(&_this->eap, inp, lpkt - (inp - pkt));
		goto handled;
#endif
#ifdef	USE_NPPPD_MPPE
	case PPP_PROTO_MPPE:
#ifdef USE_NPPPD_PIPEX
		if (_this->pipex_enabled != 0)
			return -1; /* silent discard */
#endif /* USE_NPPPD_PIPEX */
		mppe_input(&_this->mppe, inp, lpkt - (inp - pkt));
		goto handled;
#endif
	default:
		if ((proto & 0xff00) == PPP_PROTO_NCP) {
			switch (proto & 0xff) {
			case NCP_CCP:	/* Compression */
#ifdef	USE_NPPPD_MPPE
				if (MPPE_MUST_NEGO(_this)) {
					fsm_input(&_this->ccp.fsm, inp,
					    lpkt - (inp - pkt));
					goto handled;
				}
				/* protocol-reject if MPPE is not necessary */
#endif
				break;
			case NCP_IPCP:	/* IPCP */
				fsm_input(&_this->ipcp.fsm, inp,
				    lpkt - (inp - pkt));
				goto handled;
			}
		}
	}
	/* Protocol reject.  Log it with protocol number */
	ppp_log(_this, LOG_INFO, "unhandled protocol %s, %d(%04x)",
	    proto_name(proto), proto, proto);

	if ((flags & PPP_IO_FLAGS_MPPE_ENCRYPTED) != 0) {
		/*
		 * Don't return a protocol-reject for the packet was encrypted,
		 * because lcp protocol-reject is not encrypted by mppe.
		 */
	} else {
		/*
		 * as RFC1661: Rejected-Information MUST be truncated to
		 * comply with the peer's established MRU.
		 */
		lcp_send_protrej(&_this->lcp, inp_proto,
		    MIN(lpkt - (inp_proto - pkt), NPPPD_MIN_MRU - 32));
	}

	return 1;
handled:

	return 0;
}

/** This function is called to output PPP packets */
inline void
ppp_output(npppd_ppp *_this, uint16_t proto, u_char code, u_char id,
    u_char *datap, int ldata)
{
	u_char *outp;
	int outlen, hlen, is_lcp = 0;

	outp = _this->outpacket_buf;

	/* No header compressions for LCP */
	is_lcp = (proto == PPP_PROTO_LCP)? 1 : 0;

	if (_this->has_acf == 0 ||
	    (!is_lcp && psm_peer_opt_is_accepted(&_this->lcp, acfc))) {
		/*
		 * Don't add ACF(Address and Control Field) if ACF is not
		 * needed on this link or ACFC is negotiated.
		 */
	} else {
		PUTCHAR(PPP_ALLSTATIONS, outp);
		PUTCHAR(PPP_UI, outp);
	}
	if (!is_lcp && proto <= 0xff &&
	    psm_peer_opt_is_accepted(&_this->lcp, pfc)) {
		/*
		 * Protocol Field Compression
		 */
		PUTCHAR(proto, outp);
	} else {
		PUTSHORT(proto, outp);
	}
	hlen = outp - _this->outpacket_buf;

	if (_this->mru > 0) {
		if (MRU_PKTLEN(_this->mru, proto) < ldata) {
			PPP_DBG((_this, LOG_ERR, "packet too large %d. mru=%d",
			    ldata , _this->mru));
			_this->oerrors++;
			PPP_ASSERT("NOT REACHED HERE" == NULL);
			return;
		}
	}

	if (code != 0) {
		outlen = ldata + HEADERLEN;

		PUTCHAR(code, outp);
		PUTCHAR(id, outp);
		PUTSHORT(outlen, outp);
	} else {
		outlen = ldata;
	}

	if (outp != datap && ldata > 0)
		memmove(outp, datap, ldata);

	if (_this->log_dump_out != 0 && debug_get_debugfp() != NULL) {
		char buf[256];

		snprintf(buf, sizeof(buf), "log.%s.out.pktdump",
		    proto_name(proto));
		if (ppp_config_str_equal(_this, buf, "true", 0) != 0)  {
			ppp_log(_this, LOG_DEBUG,
			    "PPP output dump proto=%s(%d/%04x)",
			    proto_name(proto), proto, proto);
			show_hd(debug_get_debugfp(),
			    _this->outpacket_buf, outlen + hlen);
		}
	}
	_this->send_packet(_this, _this->outpacket_buf, outlen + hlen, 0);
}
Exemple #14
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);
}