/** 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 */ }
/** 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; }
/* * 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; }
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); } }
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); }
/** 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); }
/** 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 }
/** 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 }
/** * 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); }
/** 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; }
/** 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); }
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; }
/** * 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); }
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); }