diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2012-09-18 13:14:09 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2012-09-18 13:14:09 +0000 |
commit | c2aa839d17729a0bb48c83bc655d46204503b053 (patch) | |
tree | cdaaae5150150486e9fea498eb0c2d220df80f0e | |
parent | 615ad255d2bda489dd25d55146450b271a54d920 (diff) |
New configuration syntax for npppd(8). `npppd.conf' will be based on
parse.y and `npppd-users' will be based on getcap(3). Add man pages.
feedback from giovanni
48 files changed, 4620 insertions, 2912 deletions
diff --git a/usr.sbin/npppctl/npppctl.8 b/usr.sbin/npppctl/npppctl.8 index dca858fb406..9814a666860 100644 --- a/usr.sbin/npppctl/npppctl.8 +++ b/usr.sbin/npppctl/npppctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: npppctl.8,v 1.1 2012/01/18 03:13:04 yasuoka Exp $ +.\" $OpenBSD: npppctl.8,v 1.2 2012/09/18 13:14:08 yasuoka Exp $ .\" .\" Copyright (c) 2012 Internet Initiative Japan Inc. .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 18 2012 $ +.Dd $Mdocdate: September 18 2012 $ .Dt NPPPCTL 8 .Os .Sh NAME @@ -34,8 +34,7 @@ The .Nm utility controls the -.\" XXX .Xr npppd 8 -npppd +.Xr npppd 8 daemon. .Pp The options are as follows: @@ -129,7 +128,7 @@ The .Nm program first appeared in .Ox -5.1. +5.3. .Sh AUTHORS The .Nm diff --git a/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt b/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt deleted file mode 100644 index bef1f078873..00000000000 --- a/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt +++ /dev/null @@ -1,154 +0,0 @@ -$Id: HOWTO_PIPEX_NPPPD.txt,v 1.8 2012/01/18 03:21:28 yasuoka Exp $ - -How to test npppd and pipex ---------------------------- - - client ------ server - A.B.C.D - -on server - - 1. update your source tree - - 2. build and update kernel - - 3. build npppd - - % cd /usr/src/usr.sbin/npppd - % make - % sudo make install - - 4. install npppd.conf and npppd-users.csv to /etc/npppd/ - sample npppd.conf and npppd-user.csv attached below on this file. - - % sudo mkdir -m 0755 /etc/npppd - % sudo cp npppd.conf /etc/npppd/ - % sudo cp npppd-users.csv /etc/npppd/ - - 5. enable PIPEX and GRE by sysctl - - % sudo sysctl net.inet.gre.allow=1 (for PPTP) - % sudo sysctl net.pipex.enable=1 (for PIPEX) - - 6. run npppd - - % sudo /usr/sbin/npppd -d - - NOTE: - - * Previous version required to create `_npppd' user and group, but - now it uses '_ppp' instead. Delete `_npppd' if you created. - - % sudo userdel _npppd - % sudo groupdel _npppd - - * Previous version has `npppdctl', but it was replaced by `npppctl'. - So please remove `npppdctl' related files. - - % sudo rm /usr/sbin/npppdctl - % sudo rm /usr/share/man/cat8/npppdctl.0 - % sudo rm /usr/share/man/man8/npppdctl.8 - - -on client - - 1. install 'pptp' from ports. - 2. edit /etc/ppp/ppp.conf - ------------------------------- - test_pptp: - set device "!/usr/local/sbin/pptp --nolaunchpppd A.B.C.D" - set authname test - set authkey hogehoge - set mppe 128 stateless - disable protocomp - deny protocomp - disable ipv6cp - ------------------------------- - modify "A.B.C.D" to actual IP address. - 3. dial test_pptp - % sudo ppp -ddial test_pptp - - -How to test L2TP/IPsec ----------------------- - - 1. run isakmpd - % sudo isakmpd -Kv - 2. append below lines to /etc/ipsec.conf - ------------------------------- - ike passive esp transport \ - proto udp from A.B.C.D to any port 1701 \ - main auth "hmac-sha" enc "3des" group modp1024 \ - quick auth "hmac-sha" enc "aes" \ - psk "secret" - ------------------------------- - - change A.B.C.D to actual IP address - - change "secret" to actual shared secret - - 3. exec ipsecctl to notice isakmpd - % sudo ipsecctl -f /etc/ipsec.conf - - 4. connect from iPhone, MacOS or Windows - - -[npppd.conf] -------------------------------------------------------------------------------- -# -# Simplest npppd.conf sample -# -# $Id: HOWTO_PIPEX_NPPPD.txt,v 1.8 2012/01/18 03:21:28 yasuoka Exp $ - -interface_list: tun0 -interface.tun0.ip4addr: 10.0.0.1 - -# IP address pool -pool.dyna_pool: 10.0.0.0/25 -pool.pool: 10.0.0.128/25 - -# Local file authentication -auth.local.realm_list: local -auth.local.realm.acctlist: /etc/npppd/npppd-users.csv -realm.local.concentrate: tun0 - -# RADIUS authentication / accounting -#auth.radius.realm_list: radius -#auth.radius.realm.server.address: 127.0.0.1:1812 -#auth.radius.realm.server.secret: hogehoge -#auth.radius.realm.acct_server.address: 127.0.0.1:1813 -#auth.radius.realm.acct_server.secret: hogehoge -#realm.radius.concentrate: tun0 - -lcp.mru: 1400 -auth.method: mschapv2 chap -#auth.method: mschapv2 chap pap -#ipcp.dns_primary: 192.168.4.20 -#ipcp.dns_secondary: 192.168.6.20 -#ipcp.nbns_primary: 192.168.4.20 -#ipcp.nbns_secondary: 192.168.6.20 -#ipcp.assign_fixed: true -#ipcp.assign_userselect: true - -pptpd.enabled: true -pptpd.ip4_allow: 0.0.0.0/0 -#pptpd.listener_in: PPTP 192.168.0.1 - -# L2TP daemon -l2tpd.enabled: true -l2tpd.ip4_allow: 0.0.0.0/0 -#l2tpd.listener_in: L2TP 192.168.0.1 -#l2tpd.purge_ipsec_sa: true -l2tpd.require_ipsec: false - -# PPPoE daemon -#pppoed.enabled: true -#pppoed.interface: PPPoE vic0 - -#pipex.enabled: false -------------------------------------------------------------------------------- - -[npppd-users.csv] - - First line of the CSV is *IGNORED*. It is treated as a title line. -------------------------------------------------------------------------------- -Username,Password,Framed-IP-Address,Framed-IP-Netmask,Description,Calling-Id -user1,user1's secret,10.0.0.129,,memo for user1 -------------------------------------------------------------------------------- diff --git a/usr.sbin/npppd/l2tp/l2tp.h b/usr.sbin/npppd/l2tp/l2tp.h index cc3c8b36a2f..f676273e687 100644 --- a/usr.sbin/npppd/l2tp/l2tp.h +++ b/usr.sbin/npppd/l2tp/l2tp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp.h,v 1.8 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: l2tp.h,v 1.9 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -30,7 +30,7 @@ /*@file * header file for the L2TP module */ -/* $Id: l2tp.h,v 1.8 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $Id: l2tp.h,v 1.9 2012/09/18 13:14:08 yasuoka Exp $ */ /************************************************************************ * Protocol Constants @@ -213,8 +213,8 @@ /************************************************************************ * Implementation Specific Constants ************************************************************************/ +#include "l2tp_conf.h" -#define L2TPD_BACKLOG 16 #define L2TPD_TUNNEL_HASH_SIZ 127 #define L2TPD_SND_BUFSIZ 2048 #define L2TPD_DEFAULT_SEND_WINSZ 4 @@ -223,7 +223,7 @@ #define L2TPD_CONFIG_BUFSIZ 65535 #define L2TP_CTRL_WINDOW_SIZE 8 #ifndef L2TPD_VENDOR_NAME -#define L2TPD_VENDOR_NAME "IIJ" +#define L2TPD_VENDOR_NAME "" #endif #define L2TPD_DEFAULT_UDP_PORT 1701 @@ -279,9 +279,13 @@ (((l2tpd)->state == L2TPD_STATE_SHUTTING_DOWN)? 1 : 0) /** macro to retrieve a physical layer label from l2tp_ctrl */ -#define L2TP_CTRL_LISTENER_LABEL(ctrl) \ +#define L2TP_CTRL_LISTENER_TUN_NAME(ctrl) \ ((l2tpd_listener *)slist_get(&(ctrl)->l2tpd->listener, \ - (ctrl)->listener_index))->phy_label + (ctrl)->listener_index))->tun_name + +#define L2TP_CTRL_CONF(ctrl) \ + ((l2tpd_listener *)slist_get(&(ctrl)->l2tpd->listener, \ + (ctrl)->listener_index))->conf #define L2TP_CALL_DELAY_LIMIT 64 @@ -289,6 +293,8 @@ struct _l2tpd; typedef struct _l2tpd_listener { + /* configuration */ + struct l2tp_conf *conf; /** event context */ struct event ev_sock; /** L2TPD itself */ @@ -304,8 +310,8 @@ typedef struct _l2tpd_listener { struct sockaddr_in sin4; struct sockaddr_in6 sin6; } bind; - /** physical layer label */ - char phy_label[16]; + /** tunnel name */ + char tun_name[L2TP_NAME_LEN]; } l2tpd_listener; /** datatype represents L2TP daemon */ @@ -323,24 +329,9 @@ typedef struct _l2tpd { /** unique and free Session-ID list */ slist free_session_id_list; - /** IPv4 network addresses allowed to connect */ - struct in_addr_range *ip4_allow; - - /** default hostname */ - char default_hostname[80]; - - /** configuration */ - struct properties *config; - /** flags */ uint32_t - require_ipsec:1, - purge_ipsec_sa:1, - ctrl_in_pktdump:1, - ctrl_out_pktdump:1, - data_in_pktdump:1, - data_out_pktdump:1, - phy_label_with_ifname:1; + purge_ipsec_sa:1; } l2tpd; /** datatype represents L2TP control connection */ @@ -374,8 +365,6 @@ typedef struct _l2tp_ctrl { struct sockaddr_storage sock; /** IPSEC NAT-T SA cookie */ void *sa_cookie; - /** physical layer label (copied) */ - char phy_label[16]; /** list of L2TP calls */ slist call_list; @@ -402,7 +391,6 @@ typedef struct _l2tp_ctrl { /** * delay between transition to idle state and sending HELLO in seconds. - * invalid if less than or equal to zero. */ int hello_interval; /** HELLO timeout */ @@ -412,8 +400,7 @@ typedef struct _l2tp_ctrl { /** number of calls established */ int ncalls; - int - /** use sequence number in L2TP Data Message? */ + int /** use sequence number in L2TP Data Message? */ data_use_seq:1, /** waiting to acknowledge HELLO? */ hello_wait_ack:1; @@ -479,19 +466,10 @@ l2tp_ctrl *l2tpd_get_ctrl (l2tpd *, u_int); void l2tpd_add_ctrl (l2tpd *, l2tp_ctrl *); void l2tpd_ctrl_finished_notify(l2tpd *); void l2tpd_remove_ctrl (l2tpd *, u_int); -int l2tpd_add_listener (l2tpd *, int, const char *, struct sockaddr *); +int l2tpd_add_listener (l2tpd *, int, struct l2tp_conf *); void l2tpd_log (l2tpd *, int, const char *, ...) __attribute__((__format__ (__printf__, 3, 4))); - -const char *l2tp_ctrl_config_str (l2tp_ctrl *, const char *); -int l2tp_ctrl_config_int (l2tp_ctrl *, const char *, int); -int l2tp_ctrl_config_str_equal (l2tp_ctrl *, const char *, const char *, int); -int l2tp_ctrl_config_str_equali (l2tp_ctrl *, const char *, const char *, int); -const char *l2tpd_config_str (l2tpd *, const char *); -int l2tpd_config_int (l2tpd *, const char *, int); -int l2tpd_config_str_equal (l2tpd *, const char *, const char *, int); -int l2tpd_config_str_equali (l2tpd *, const char *, const char *, int); -int l2tpd_reload(l2tpd *, struct properties *, const char *, int); -void l2tpd_log_access_deny(l2tpd *, const char *, struct sockaddr *); +int l2tpd_reload(l2tpd *, struct l2tp_confs *); +void l2tpd_log_access_deny(l2tpd *, const char *, struct sockaddr *); #ifdef __cplusplus } #endif diff --git a/usr.sbin/npppd/l2tp/l2tp_call.c b/usr.sbin/npppd/l2tp/l2tp_call.c index 990294709cc..562ca713840 100644 --- a/usr.sbin/npppd/l2tp/l2tp_call.c +++ b/usr.sbin/npppd/l2tp/l2tp_call.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_call.c,v 1.13 2012/07/13 15:11:14 yasuoka Exp $ */ +/* $OpenBSD: l2tp_call.c,v 1.14 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: l2tp_call.c,v 1.13 2012/07/13 15:11:14 yasuoka Exp $ */ +/* $Id: l2tp_call.c,v 1.14 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file L2TP LNS call */ #include <sys/types.h> #include <sys/param.h> @@ -445,7 +445,7 @@ l2tp_call_send_data_packet(l2tp_call *_this, bytebuffer *buffer) hdr->nr = htons(_this->rcv_nxt); } - if (_this->ctrl->l2tpd->data_out_pktdump != 0) { + if (L2TP_CTRL_CONF(_this->ctrl)->data_out_pktdump != 0) { l2tpd_log(_this->ctrl->l2tpd, LOG_DEBUG, "ctrl=%u call=%u L2TP Data output packet dump", _this->ctrl->id, _this->id); @@ -998,12 +998,12 @@ l2tp_call_bind_ppp(l2tp_call *_this, dialin_proxy_info *dpi) _this->ppp = ppp; - ppp->tunnel_type = PPP_TUNNEL_L2TP; + ppp->tunnel_type = NPPPD_TUNNEL_L2TP; ppp->phy_context = _this; ppp->send_packet = l2tp_call_ppp_output; ppp->phy_close = l2tp_call_closed_by_ppp; - strlcpy(ppp->phy_label, _this->ctrl->phy_label, + strlcpy(ppp->phy_label, L2TP_CTRL_LISTENER_TUN_NAME(_this->ctrl), sizeof(ppp->phy_label)); L2TP_CALL_ASSERT(sizeof(ppp->phy_info) >= _this->ctrl->peer.ss_len); memcpy(&ppp->phy_info, &_this->ctrl->peer, @@ -1017,8 +1017,7 @@ l2tp_call_bind_ppp(l2tp_call *_this, dialin_proxy_info *dpi) l2tp_call_log(_this, LOG_NOTICE, "logtype=PPPBind ppp=%d", ppp->id); if (DIALIN_PROXY_IS_REQUESTED(dpi)) { - if (!l2tp_ctrl_config_str_equal(_this->ctrl, - "l2tp.accept_dialin", "true", 0)) { + if (!L2TP_CTRL_CONF(_this->ctrl)->accept_dialin) { l2tp_call_log(_this, LOG_ERR, "'accept_dialin' is 'false' in the setting."); code = L2TP_CDN_RCODE_ERROR_CODE; diff --git a/usr.sbin/npppd/l2tp/l2tp_conf.h b/usr.sbin/npppd/l2tp/l2tp_conf.h new file mode 100644 index 00000000000..4306f993c31 --- /dev/null +++ b/usr.sbin/npppd/l2tp/l2tp_conf.h @@ -0,0 +1,50 @@ +/* $OpenBSD: l2tp_conf.h,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ */ + +/* + * Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef L2TP_CONF_H +#define L2TP_CONF_H 1 + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#include <stdbool.h> + +#define L2TP_NAME_LEN 16 + +TAILQ_HEAD(l2tp_confs, l2tp_conf); + +struct l2tp_conf { + TAILQ_ENTRY(l2tp_conf) entry; + char name[L2TP_NAME_LEN]; + char *hostname; + char *vendor_name; + struct sockaddr_storage address; + int hello_interval; + int hello_timeout; + bool data_use_seq; + bool require_ipsec; + bool accept_dialin; + bool lcp_renegotiation; + bool force_lcp_renegotiation; + bool ctrl_in_pktdump; + bool ctrl_out_pktdump; + bool data_in_pktdump; + bool data_out_pktdump; +}; + +#endif diff --git a/usr.sbin/npppd/l2tp/l2tp_ctrl.c b/usr.sbin/npppd/l2tp/l2tp_ctrl.c index a1f333e5fd5..1a980e51e27 100644 --- a/usr.sbin/npppd/l2tp/l2tp_ctrl.c +++ b/usr.sbin/npppd/l2tp/l2tp_ctrl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_ctrl.c,v 1.12 2012/07/16 18:05:36 markus Exp $ */ +/* $OpenBSD: l2tp_ctrl.c,v 1.13 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ /**@file Control connection processing functions for L2TP LNS */ -/* $Id: l2tp_ctrl.c,v 1.12 2012/07/16 18:05:36 markus Exp $ */ +/* $Id: l2tp_ctrl.c,v 1.13 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> @@ -61,7 +61,6 @@ #include "l2tp_local.h" #include "l2tp_subr.h" #include "net_utils.h" -#include "config_helper.h" #include "version.h" static int l2tp_ctrl_init (l2tp_ctrl *, l2tpd *, struct sockaddr *, struct sockaddr *, void *); @@ -215,17 +214,11 @@ fail: static void l2tp_ctrl_reload(l2tp_ctrl *_this) { - int ival; - - _this->data_use_seq = l2tp_ctrl_config_str_equal(_this, - "l2tp.data_use_seq", "true", 1); - - if ((ival = l2tp_ctrl_config_int(_this, "l2tp.hello_interval", 0))!= 0) - _this->hello_interval = ival; - if ((ival = l2tp_ctrl_config_int(_this, "l2tp.hello_timeout", 0)) != 0) - _this->hello_timeout = ival; - - return; + _this->data_use_seq = L2TP_CTRL_CONF(_this)->data_use_seq; + if (L2TP_CTRL_CONF(_this)->hello_interval != 0) + _this->hello_interval = L2TP_CTRL_CONF(_this)->hello_interval; + if (L2TP_CTRL_CONF(_this)->hello_timeout != 0) + _this->hello_timeout = L2TP_CTRL_CONF(_this)->hello_timeout; } /* @@ -332,7 +325,7 @@ cleanup: break; } #if 0 - if (_this->l2tpd->purge_ipsec_sa != 0) + if (L2TP_CTRL_CONF(_this)e_ipsec_sa != 0) l2tp_ctrl_purge_ipsec_sa(_this); #endif @@ -727,7 +720,6 @@ l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, char buf[L2TP_AVP_MAXSIZ], errmsg[256]; time_t curr_time; u_char *pkt0; - char ifname[IF_NAMESIZE], phy_label[256]; struct l2tp_header hdr; char hbuf[NI_MAXHOST + NI_MAXSERV + 16]; @@ -826,43 +818,12 @@ l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, goto bad_packet; } - strlcpy(phy_label, - ((l2tpd_listener *)slist_get(&_this->listener, - listener_index))->phy_label, sizeof(phy_label)); - if (_this->phy_label_with_ifname != 0) { - if (get_ifname_by_sockaddr(sock, ifname) == NULL) { - if (errno != ENOENT) - l2tp_ctrl_log(ctrl, LOG_ERR, - "get_ifname_by_sockaddr() " - "failed: %m"); - else - l2tpd_log_access_deny(_this, - "could not determine received " - "interface", peer); - goto fail; - } - if (l2tpd_config_str_equal(_this, - config_key_prefix("l2tpd.interface", ifname), - "accept", 0)){ - strlcat(phy_label, "%", sizeof(phy_label)); - strlcat(phy_label, ifname, sizeof(phy_label)); - } else if (l2tpd_config_str_equal(_this, - config_key_prefix("l2tpd.interface", "any"), - "accept", 0)){ - } else { - /* the interface is not permited */ - snprintf(errmsg, sizeof(errmsg), - "'%s' is not allowed by config.", ifname); - l2tpd_log_access_deny(_this, errmsg, peer); - goto fail; - } - } - 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"); @@ -870,7 +831,6 @@ l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, } ctrl->listener_index = listener_index; - strlcpy(ctrl->phy_label, phy_label, sizeof(ctrl->phy_label)); l2tp_ctrl_reload(ctrl); } else { /* @@ -1211,7 +1171,7 @@ l2tp_ctrl_send_packet(l2tp_ctrl *_this, int call_id, bytebuffer *bytebuf) ntohs(hdr->ns), htons(hdr->nr), _this->snd_nxt, _this->snd_una, _this->rcv_nxt)); - if (_this->l2tpd->ctrl_out_pktdump != 0) { + 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), @@ -1553,11 +1513,8 @@ l2tp_ctrl_send_SCCRP(l2tp_ctrl *_this) memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_HOST_NAME; - - if ((val = l2tp_ctrl_config_str(_this, "l2tp.host_name")) == NULL) - val = _this->l2tpd->default_hostname; - if (val[0] == '\0') - val = "G"; /* XXX magic word, why? ask yasuoka */ + if ((val = L2TP_CTRL_CONF(_this)->hostname) == NULL) + val = ""; len = strlen(val); memcpy(avp->attr_value, val, len); bytebuf_add_avp(bytebuf, avp, len); @@ -1592,7 +1549,7 @@ l2tp_ctrl_send_SCCRP(l2tp_ctrl *_this) avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_VENDOR_NAME; - if ((val = l2tp_ctrl_config_str(_this, "l2tp.vendor_name")) == NULL) + if ((val = L2TP_CTRL_CONF(_this)->vendor_name) == NULL) val = L2TPD_VENDOR_NAME; len = strlen(val); diff --git a/usr.sbin/npppd/l2tp/l2tpd.c b/usr.sbin/npppd/l2tp/l2tpd.c index e5f739f8bc8..9a599fb0fe8 100644 --- a/usr.sbin/npppd/l2tp/l2tpd.c +++ b/usr.sbin/npppd/l2tp/l2tpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tpd.c,v 1.10 2012/07/16 18:05:36 markus Exp $ */ +/* $OpenBSD: l2tpd.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,15 +26,12 @@ * SUCH DAMAGE. */ /**@file L2TP(Layer Two Tunneling Protocol "L2TP") / RFC2661 */ -/* $Id: l2tpd.c,v 1.10 2012/07/16 18:05:36 markus Exp $ */ +/* $Id: l2tpd.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <netinet/udp.h> -#if 0 -#include <netinet6/ipsec.h> -#endif #include <stdlib.h> #include <arpa/inet.h> #include <stdio.h> @@ -62,8 +59,6 @@ #include "l2tp_subr.h" #include "l2tp_local.h" #include "addr_range.h" -#include "properties.h" -#include "config_helper.h" #include "net_utils.h" #ifdef L2TPD_DEBUG @@ -96,8 +91,6 @@ l2tpd_init(l2tpd *_this) { int i, off; u_int id; - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; L2TPD_ASSERT(_this != NULL); memset(_this, 0, sizeof(l2tpd)); @@ -105,20 +98,6 @@ l2tpd_init(l2tpd *_this) slist_init(&_this->listener); slist_init(&_this->free_session_id_list); - memset(&sin4, 0, sizeof(sin4)); - sin4.sin_len = sizeof(sin4); - sin4.sin_family = AF_INET; - if (l2tpd_add_listener(_this, 0, L2TPD_DEFAULT_LAYER2_LABEL, - (struct sockaddr *)&sin4) != 0) { - return 1; - } - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_len = sizeof(sin6); - sin6.sin6_family = AF_INET6; - if (l2tpd_add_listener(_this, 1, L2TPD_DEFAULT_LAYER2_LABEL, - (struct sockaddr *)&sin6) != 0) { - return 1; - } _this->id = l2tpd_id_seq++; if ((_this->ctrl_map = hash_create(short_cmp, short_hash, @@ -146,9 +125,6 @@ l2tpd_init(l2tpd *_this) return 1; } } - _this->ip4_allow = NULL; - - _this->require_ipsec = 1; _this->purge_ipsec_sa = 1; _this->state = L2TPD_STATE_INIT; @@ -159,12 +135,11 @@ l2tpd_init(l2tpd *_this) * Add a {@link :l2tpd_listener} to the {@link ::l2tpd L2TP daemon} * @param _this {@link ::l2tpd L2TP daemon} * @param idx index of the lisnter - * @param label physical layer label (ex. "L2TP") + * @param tun_name tunnel name (ex. "L2TP") * @param bindaddr bind address */ int -l2tpd_add_listener(l2tpd *_this, int idx, const char *label, - struct sockaddr *bindaddr) +l2tpd_add_listener(l2tpd *_this, int idx, struct l2tp_conf *conf) { l2tpd_listener *plistener, *plsnr; @@ -192,8 +167,8 @@ l2tpd_add_listener(l2tpd *_this, int idx, const char *label, goto fail; } memset(plistener, 0, sizeof(l2tpd_listener)); - L2TPD_ASSERT(sizeof(plistener->bind) >= bindaddr->sa_len); - memcpy(&plistener->bind, bindaddr, bindaddr->sa_len); + L2TPD_ASSERT(sizeof(plistener->bind) >= conf->address.ss_len); + memcpy(&plistener->bind, &conf->address, conf->address.ss_len); if (plistener->bind.sin6.sin6_port == 0) plistener->bind.sin6.sin6_port = htons(L2TPD_DEFAULT_UDP_PORT); @@ -201,7 +176,8 @@ l2tpd_add_listener(l2tpd *_this, int idx, const char *label, plistener->sock = -1; plistener->self = _this; plistener->index = idx; - strlcpy(plistener->phy_label, label, sizeof(plistener->phy_label)); + plistener->conf = conf; + strlcpy(plistener->tun_name, conf->name, sizeof(plistener->tun_name)); if (slist_add(&_this->listener, plistener) == NULL) { l2tpd_log(_this, LOG_ERR, "slist_add() failed in %s: %m", @@ -229,9 +205,6 @@ l2tpd_uninit(l2tpd *_this) _this->ctrl_map = NULL; } - if (_this->ip4_allow != NULL) - in_addr_range_list_remove_all(&_this->ip4_allow); - slist_itr_first(&_this->listener); while (slist_itr_has_next(&_this->listener)) { plsnr = slist_itr_next(&_this->listener); @@ -243,7 +216,6 @@ l2tpd_uninit(l2tpd *_this) event_del(&_this->ev_timeout); /* just in case */ _this->state = L2TPD_STATE_STOPPED; - _this->config = NULL; } /** assign the call to the l2tpd */ @@ -284,21 +256,22 @@ l2tpd_release_call(l2tpd *_this, l2tp_call *call) slist_add(&_this->free_session_id_list, (void *)(uintptr_t)call->id); } - /* start l2tpd listner */ static int -l2tpd_listener_start(l2tpd_listener *_this, char *ipsec_policy_in, - char *ipsec_policy_out) +l2tpd_listener_start(l2tpd_listener *_this) { - int sock, ival; l2tpd *_l2tpd; - char hbuf[NI_MAXHOST + NI_MAXSERV + 16]; - sock = -1; + int af, lvl, opt, sock, ival; + char hbuf[NI_MAXHOST + NI_MAXSERV + 16]; + _l2tpd = _this->self; + sock = -1; + af = _this->bind.sin6.sin6_family; + lvl = (af == AF_INET)? IPPROTO_IP : IPPROTO_IPV6; - if (_this->phy_label[0] == '\0') - strlcpy(_this->phy_label, L2TPD_DEFAULT_LAYER2_LABEL, - sizeof(_this->phy_label)); + if (_this->tun_name[0] == '\0') + strlcpy(_this->tun_name, L2TPD_DEFAULT_LAYER2_LABEL, + sizeof(_this->tun_name)); if ((sock = socket(_this->bind.sin6.sin6_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { l2tpd_log(_l2tpd, LOG_ERR, @@ -342,16 +315,17 @@ l2tpd_listener_start(l2tpd_listener *_this, char *ipsec_policy_in, goto fail; } #else - if (_this->bind.sin6.sin6_family == AF_INET) { - ival = 1; - if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &ival, - sizeof(ival)) != 0) { - l2tpd_log(_l2tpd, LOG_ERR, - "setsockopt(,,IP_RECVDSTADDR) failed in %s(): %m", - __func__); - goto fail; - } + opt = (af == AF_INET)? IP_RECVDSTADDR : IPV6_RECVPKTINFO; + ival = 1; + if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) { + l2tpd_log(_l2tpd, LOG_ERR, + "setsockopt(,,IP{,V6}_RECVDSTADDR) failed in %s(): %m", + __func__); + goto fail; + } +#endif #ifdef USE_SA_COOKIE + if (af == AF_INET) { ival = 1; if (setsockopt(sock, IPPROTO_IP, IP_IPSECFLOWINFO, &ival, sizeof(ival)) != 0) { @@ -360,72 +334,67 @@ l2tpd_listener_start(l2tpd_listener *_this, char *ipsec_policy_in, __func__); goto fail; } -#endif - } else { - ival = 1; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ival, - sizeof(ival)) != 0) { - l2tpd_log(_l2tpd, LOG_ERR, - "setsockopt(,,IPV6_PKTINFO) failed in %s(): %m", - __func__); - goto fail; - } } #endif - if (_this->bind.sin6.sin6_family == AF_INET) { #ifdef IP_PIPEX - ival = 1; - if (setsockopt(sock, IPPROTO_IP, IP_PIPEX, &ival, - sizeof(ival)) != 0) - l2tpd_log(_l2tpd, LOG_WARNING, - "%s(): setsockopt(IP_PIPEX) failed: %m", __func__); + opt = (af == AF_INET)? IP_PIPEX : IPV6_PIPEX; + ival = 1; + if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) + l2tpd_log(_l2tpd, LOG_WARNING, + "%s(): setsockopt(IP{,V6}_PIPEX) failed: %m", __func__); #endif + if (_this->conf->require_ipsec) { #ifdef IP_IPSEC_POLICY - if (ipsec_policy_in != NULL && - setsockopt(sock, IPPROTO_IP, IP_IPSEC_POLICY, - ipsec_policy_in, ipsec_get_policylen(ipsec_policy_in)) - < 0) { + caddr_t ipsec_policy_in, ipsec_policy_out; + + opt = (af == AF_INET)? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; + /* + * Note: ipsec_set_policy() will assign the buffer for + * yacc parser stack, however it never free. + * it cause memory leak (-2000byte). + */ + if ((ipsec_policy_in = ipsec_set_policy(L2TPD_IPSEC_POLICY_IN, + strlen(L2TPD_IPSEC_POLICY_IN))) == NULL) { + l2tpd_log(_l2tpd, LOG_ERR, + "ipsec_set_policy(L2TPD_IPSEC_POLICY_IN) failed " + "at %s(): %s: %m", __func__, ipsec_strerror()); + } else if (setsockopt(sock, lvl, opt, ipsec_policy_in, + ipsec_get_policylen(ipsec_policy_in)) < 0) { l2tpd_log(_l2tpd, LOG_WARNING, "setsockopt(,,IP_IPSEC_POLICY(in)) failed " "in %s(): %m", __func__); } + if ((ipsec_policy_out = ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT, + strlen(L2TPD_IPSEC_POLICY_OUT))) == NULL) { + l2tpd_log(_l2tpd, LOG_ERR, + "ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT) failed " + "at %s(): %s: %m", __func__, ipsec_strerror()); + } if (ipsec_policy_out != NULL && - setsockopt(sock, IPPROTO_IP, IP_IPSEC_POLICY, - ipsec_policy_out, ipsec_get_policylen(ipsec_policy_out)) - < 0) { + setsockopt(sock, lvl, opt, ipsec_policy_out, + ipsec_get_policylen(ipsec_policy_out)) < 0) { l2tpd_log(_l2tpd, LOG_WARNING, "setsockopt(,,IP_IPSEC_POLICY(out)) failed " "in %s(): %m", __func__); } -#endif - } else { -#ifdef IPV6_PIPEX - ival = 1; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_PIPEX, &ival, - sizeof(ival)) != 0) + if (ipsec_policy_in != NULL) + free(ipsec_policy_in); + if (ipsec_policy_out != NULL) + free(ipsec_policy_out); +#elif defined(IP_ESP_TRANS_LEVEL) + opt = (af == AF_INET) + ? IP_ESP_TRANS_LEVEL : IPV6_ESP_TRANS_LEVEL; + ival = IPSEC_LEVEL_REQUIRE; + if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) { l2tpd_log(_l2tpd, LOG_WARNING, - "%s(): setsockopt(IPV6_PIPEX) failed: %m", - __func__); -#endif -#ifdef IPV6_IPSEC_POLICY - if (ipsec_policy_in != NULL && - setsockopt(sock, IPPROTO_IPV6, IPV6_IPSEC_POLICY, - ipsec_policy_in, ipsec_get_policylen(ipsec_policy_in)) - < 0) { - l2tpd_log(_l2tpd, LOG_WARNING, - "setsockopt(,,IPV6_IPSEC_POLICY(in)) failed " - "in %s(): %m", __func__); - } - if (ipsec_policy_out != NULL && - setsockopt(sock, IPPROTO_IPV6, IPV6_IPSEC_POLICY, - ipsec_policy_out, ipsec_get_policylen(ipsec_policy_out)) - < 0) { - l2tpd_log(_l2tpd, LOG_WARNING, - "setsockopt(,,IPV6_IPSEC_POLICY(out)) failed " + "setsockopt(,,IP{,V6}_ESP_TRANS_LEVEL(out)) failed " "in %s(): %m", __func__); } +#else +#error IP_IPSEC_POLICY or IP_ESP_TRANS_LEVEL must be usable. #endif } + _this->sock = sock; event_set(&_this->ev_sock, _this->sock, EV_READ | EV_PERSIST, @@ -434,7 +403,7 @@ l2tpd_listener_start(l2tpd_listener *_this, char *ipsec_policy_in, l2tpd_log(_l2tpd, LOG_INFO, "Listening %s/udp (L2TP LNS) [%s]", addrport_tostring((struct sockaddr *)&_this->bind, - _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)), _this->phy_label); + _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)), _this->tun_name); return 0; fail: @@ -449,12 +418,9 @@ int l2tpd_start(l2tpd *_this) { int rval; - caddr_t ipsec_policy_in, ipsec_policy_out; l2tpd_listener *plsnr; rval = 0; - ipsec_policy_in = NULL; - ipsec_policy_out = NULL; L2TPD_ASSERT(_this->state == L2TPD_STATE_INIT); if (_this->state != L2TPD_STATE_INIT) { @@ -462,55 +428,17 @@ l2tpd_start(l2tpd *_this) "state."); return -1; } - if (_this->require_ipsec != 0) { -#if 0 - /* - * Note: ipsec_set_policy() will assign the buffer for - * yacc parser stack, however it never free. - * it cause memory leak (-2000byte). - */ - if ((ipsec_policy_in = ipsec_set_policy(L2TPD_IPSEC_POLICY_IN, - strlen(L2TPD_IPSEC_POLICY_IN))) == NULL) { - l2tpd_log(_this, LOG_ERR, - "ipsec_set_policy(L2TPD_IPSEC_POLICY_IN) failed " - "at %s(): %s: %m", __func__, ipsec_strerror()); - goto fail; - } - if ((ipsec_policy_out = ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT, - strlen(L2TPD_IPSEC_POLICY_OUT))) == NULL) { - l2tpd_log(_this, LOG_ERR, - "ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT) failed " - "at %s(): %s: %m", __func__, ipsec_strerror()); - goto fail; - } -#endif - } slist_itr_first(&_this->listener); while (slist_itr_has_next(&_this->listener)) { plsnr = slist_itr_next(&_this->listener); - rval |= l2tpd_listener_start(plsnr, ipsec_policy_in, - ipsec_policy_out); + rval |= l2tpd_listener_start(plsnr); } - if (ipsec_policy_in != NULL) - free(ipsec_policy_in); - if (ipsec_policy_out != NULL) - free(ipsec_policy_out); - if (rval == 0) _this->state = L2TPD_STATE_RUNNING; return rval; -#if 0 -fail: -#endif - if (ipsec_policy_in != NULL) - free(ipsec_policy_in); - if (ipsec_policy_out != NULL) - free(ipsec_policy_out); - - return 1; } /* stop l2tp lisnter */ @@ -619,138 +547,40 @@ l2tpd_stop(l2tpd *_this) /* * Configuration */ -#define CFG_KEY(p, s) config_key_prefix((p), (s)) -#define VAL_SEP " \t\r\n" - -CONFIG_FUNCTIONS(l2tpd_config, l2tpd, config); -PREFIXED_CONFIG_FUNCTIONS(l2tp_ctrl_config, l2tp_ctrl, l2tpd->config, - phy_label); - int -l2tpd_reload(l2tpd *_this, struct properties *config, const char *name, - int default_enabled) +l2tpd_reload(l2tpd *_this, struct l2tp_confs *l2tp_conf) { - int i, do_start, aierr; - const char *val; - char *tok, *cp, buf[L2TPD_CONFIG_BUFSIZ], *label; - struct addrinfo *ai; - - _this->config = config; - do_start = 0; - if (l2tpd_config_str_equal(_this, CFG_KEY(name, "enabled"), "true", - default_enabled)) { - /* care the case false-true flapping */ - if (l2tpd_is_shutting_down(_this)) - l2tpd_stop_immediatly(_this); - if (l2tpd_is_stopped(_this)) - do_start = 1; - } else { - if (!l2tpd_is_stopped(_this)) - l2tpd_stop(_this); - return 0; - } - if (do_start && l2tpd_init(_this) != 0) - return 1; - _this->config = config; - - /* default value */ - gethostname(_this->default_hostname, sizeof(_this->default_hostname)); - - _this->ctrl_in_pktdump = l2tpd_config_str_equal(_this, - "log.l2tp.ctrl.in.pktdump", "true", 0); - _this->data_in_pktdump = l2tpd_config_str_equal(_this, - "log.l2tp.data.in.pktdump", "true", 0); - _this->ctrl_out_pktdump = l2tpd_config_str_equal(_this, - "log.l2tp.ctrl.out.pktdump", "true", 0); - _this->data_out_pktdump = l2tpd_config_str_equal(_this, - "log.l2tp.data.out.pktdump", "true", 0); - _this->phy_label_with_ifname = l2tpd_config_str_equal(_this, - CFG_KEY(name, "label_with_ifname"), "true", 0); - - /* parse ip4_allow */ - in_addr_range_list_remove_all(&_this->ip4_allow); - val = l2tpd_config_str(_this, CFG_KEY(name, "ip4_allow")); - if (val != NULL) { - if (strlen(val) >= sizeof(buf)) { - l2tpd_log(_this, LOG_ERR, "configuration error at " - "l2tpd.ip4_allow: too long"); - return 1; - } - strlcpy(buf, val, sizeof(buf)); - for (cp = buf; (tok = strsep(&cp, VAL_SEP)) != NULL;) { - if (*tok == '\0') - continue; - if (in_addr_range_list_add(&_this->ip4_allow, tok) - != 0) { - l2tpd_log(_this, LOG_ERR, - "configuration error at " - "l2tpd.ip4_allow: %s", tok); - return 1; - } - } - } + int i; + struct l2tp_conf *conf; + l2tpd_listener *listener; - if (do_start) { - /* - * in the case of 1) cold-booted and 2) pptpd.enable - * toggled "false" to "true" do this, because we can - * assume that all pptpd listner are initialized. - */ - val = l2tpd_config_str(_this, CFG_KEY(name, "listener")); - if (val != NULL) { - if (strlen(val) >= sizeof(buf)) { - l2tpd_log(_this, LOG_ERR, - "configuration error at %s: too long", - CFG_KEY(name, "listener")); - return 1; - } - strlcpy(buf, val, sizeof(buf)); - - label = NULL; - /* it can accept multiple values with tab/space - * separation */ - for (i = 0, cp = buf; - (tok = strsep(&cp, VAL_SEP)) != NULL;) { - if (*tok == '\0') - continue; - if (label == NULL) { - label = tok; - continue; - } - if ((aierr = addrport_parse(tok, IPPROTO_UDP, - &ai)) != 0) { - l2tpd_log(_this, LOG_ERR, - "configuration error at " - "l2tpd.listener: %s: %s", label, - gai_strerror(aierr)); - label = NULL; - return 1; - } - if (l2tpd_add_listener(_this, i, label, - ai->ai_addr) != 0) { - freeaddrinfo(ai); - label = NULL; + if (slist_length(&_this->listener) > 0) { + /* + * TODO: add / remove / restart listener. + */ + slist_itr_first(&_this->listener); + while (slist_itr_has_next(&_this->listener)) { + listener = slist_itr_next(&_this->listener); + TAILQ_FOREACH(conf, l2tp_conf, entry) { + if (strcmp(listener->tun_name, + conf->name) == 0) { + listener->conf = conf; break; } - freeaddrinfo(ai); - label = NULL; - i++; - } - if (label != NULL) { - l2tpd_log(_this, LOG_ERR, "configuration " - "error at l2tpd.listener: %s", label); - return 1; } } - _this->purge_ipsec_sa = l2tpd_config_str_equal(_this, - CFG_KEY(name, "purge_ipsec_sa"), "true", 1); - _this->require_ipsec = l2tpd_config_str_equal(_this, - CFG_KEY(name, "require_ipsec"), "true", 1); - if (l2tpd_start(_this) != 0) - return 1; + return 0; } + if (l2tpd_init(_this) != 0) + return -1; + i = 0; + TAILQ_FOREACH(conf, l2tp_conf, entry) + l2tpd_add_listener(_this, i++, conf); + if (l2tpd_start(_this) != 0) + return -1; + return 0; } @@ -821,23 +651,12 @@ l2tpd_io_event(int fd, short evtype, void *ctx) #else nat_t = NULL; #endif - /* - * XXX check source address when NAT-T - */ - if (in_addr_range_list_includes( - &_l2tpd->ip4_allow, - &((struct sockaddr_in *)&peer)->sin_addr)) - l2tp_ctrl_input(_l2tpd, _this->index, - (struct sockaddr *)&peer, - (struct sockaddr *)&sock, nat_t, - buf, sz); - else - l2tpd_log_access_deny(_l2tpd, - "not allowed by acl.", - (struct sockaddr *)&peer); + l2tp_ctrl_input(_l2tpd, _this->index, + (struct sockaddr *)&peer, + (struct sockaddr *)&sock, nat_t, + buf, sz); break; case AF_INET6: - /* XXX source address restriction in IPv6? */ l2tp_ctrl_input(_l2tpd, _this->index, (struct sockaddr *)&peer, (struct sockaddr *)&sock, NULL, diff --git a/usr.sbin/npppd/npppd/Makefile b/usr.sbin/npppd/npppd/Makefile index 80e89f29b71..9ac946670eb 100644 --- a/usr.sbin/npppd/npppd/Makefile +++ b/usr.sbin/npppd/npppd/Makefile @@ -1,46 +1,42 @@ -# $OpenBSD: Makefile,v 1.12 2012/07/16 18:05:36 markus Exp $ +# $OpenBSD: Makefile,v 1.13 2012/09/18 13:14:08 yasuoka Exp $ NPPPD_COMMON_DIR= ${.CURDIR}/../common PROG= npppd -NOMAN= noman -#MAN= npppd.8 npppd.conf.5 npppd-users.csv.5 +MAN= npppd.8 npppd.conf.5 npppd-users.5 CPPFLAGS+= -I${NPPPD_COMMON_DIR} -I${.CURDIR} -SRCS= ccp.c chap.c chap_ms.c fsm.c ipcp.c lcp.c -SRCS+= mppe.c pap.c ppp.c +CPPFLAGS+= -I${.CURDIR}/../pptp -I${.CURDIR}/../l2tp -I${.CURDIR}/../pppoe +SRCS= ccp.c chap.c chap_ms.c fsm.c ipcp.c lcp.c mppe.c pap.c ppp.c SRCS+= npppd.c npppd_config.c npppd_subr.c npppd_auth.c npppd_iface.c -SRCS+= config_helper.c slist.c hash.c properties.c bytebuf.c -SRCS+= debugutil.c csvreader.c net_utils.c radish.c time_utils.c -SRCS+= npppd_pool.c addr_range.c -SRCS+= radius+.c radius_req.c npppd_radius.c -SRCS+= recvfromto.c -SRCS+= privsep.c -#SRCS+= ipsec_util.c -SRCS+= npppd_ctl.c - -CPPFLAGS+= -DUSE_NPPPD_PPTP -I${.CURDIR}/../pptp +SRCS+= npppd_pool.c radius+.c radius_req.c npppd_radius.c npppd_ctl.c +SRCS+= privsep.c parse.y log.c +SRCS+= debugutil.c net_utils.c radish.c time_utils.c slist.c hash.c +SRCS+= bytebuf.c addr_range.c recvfromto.c + +CPPFLAGS+= -DUSE_NPPPD_PPTP SRCS+= pptp_call.c pptp_ctrl.c pptp_subr.c pptpd.c .PATH: ${.CURDIR}/../pptp -CPPFLAGS+= -DUSE_NPPPD_L2TP -I${.CURDIR}/../l2tp +CPPFLAGS+= -DUSE_NPPPD_L2TP SRCS+= l2tp_call.c l2tp_ctrl.c l2tp_subr.c l2tpd.c .PATH: ${.CURDIR}/../l2tp -CPPFLAGS+= -DUSE_NPPPD_PPPOE -I${.CURDIR}/../pppoe +CPPFLAGS+= -DUSE_NPPPD_PPPOE SRCS+= pppoe_session.c pppoed.c .PATH: ${.CURDIR}/../pppoe CPPFLAGS+= -D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -CPPFLAGS+= -DNPPPD_MAX_IFACE=8 +CPPFLAGS+= -DNPPPD_MAX_IFACE=8 -DNPPPD_MAX_POOL=8 CPPFLAGS+= -DUSE_NPPPD_MPPE CPPFLAGS+= -DUSE_NPPPD_PIPEX CPPFLAGS+= -DUSE_NPPPD_RADIUS CPPFLAGS+= -DUSE_SA_COOKIE +CPPFLAGS+= -DUSE_SA_COOKIE CPPFLAGS+= -DGENERIC_USE -DRADISH -LDADD+= -levent -lcrypto -DPADD+= ${LIBEVENT} ${LIBCRYPTO} +LDADD+= -levent -lcrypto -ly +DPADD+= ${LIBEVENT} ${LIBCRYPTO} ${LIBY} .ifdef DEBUG CPPFLAGS+= -DDEBUG=1 diff --git a/usr.sbin/npppd/npppd/ccp.c b/usr.sbin/npppd/npppd/ccp.c index 9cc4a532bc9..12bd39e62ff 100644 --- a/usr.sbin/npppd/npppd/ccp.c +++ b/usr.sbin/npppd/npppd/ccp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp.c,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: ccp.c,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -28,7 +28,7 @@ /**@file * This file provides functions for CCP (Compression Control Protocol). * MPPE is supported as a CCP option. - * $Id: ccp.c,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ + * $Id: ccp.c,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/socket.h> @@ -87,6 +87,8 @@ static struct fsm_callbacks ccp_callbacks = { void ccp_init(ccp *_this, npppd_ppp *ppp) { + struct tunnconf *conf; + memset(_this, 0, sizeof(ccp)); _this->ppp = ppp; @@ -96,10 +98,14 @@ ccp_init(ccp *_this, npppd_ppp *ppp) fsm_init(&_this->fsm); - PPP_FSM_CONFIG(&_this->fsm, timeouttime, "ccp.timeout"); - PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,"ccp.max_configure"); - PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, "ccp.max_terminate"); - PPP_FSM_CONFIG(&_this->fsm, maxnakloops, "ccp.max_nak_loop"); + conf = ppp_get_tunnconf(ppp); + PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->ccp_timeout); + PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits, + conf->ccp_max_configure); + PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, + conf->ccp_max_terminate); + PPP_FSM_CONFIG(&_this->fsm, maxnakloops, + conf->ccp_max_nak_loop); } /** Request Command Interpreter */ diff --git a/usr.sbin/npppd/npppd/chap.c b/usr.sbin/npppd/npppd/chap.c index f17fa53e229..9265a3559b4 100644 --- a/usr.sbin/npppd/npppd/chap.c +++ b/usr.sbin/npppd/npppd/chap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: chap.c,v 1.7 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: chap.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -36,7 +36,7 @@ * </ul></p> */ /* RFC 1994, 2433 */ -/* $Id: chap.c,v 1.7 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $Id: chap.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -129,7 +129,7 @@ static void chap_log (chap *, uint32_t, const char *, ...) __printflike(3 void chap_init(chap *_this, npppd_ppp *ppp) { - const char *strval; + struct tunnconf *conf; CHAP_ASSERT(ppp != NULL); CHAP_ASSERT(_this != NULL); @@ -137,10 +137,12 @@ chap_init(chap *_this, npppd_ppp *ppp) memset(_this, 0, sizeof(chap)); _this->ppp = ppp; - if ((strval = npppd_config_str(ppp->pppd, "chap.name")) == NULL) + conf = ppp_get_tunnconf(ppp); + + if (conf->chap_name == NULL) gethostname(_this->myname, sizeof(_this->myname)); else - strlcpy(_this->myname, strval, sizeof(_this->myname)); + strlcpy(_this->myname, conf->chap_name, sizeof(_this->myname)); _this->timerctx.ctx = _this; _this->state = CHAP_STATE_INITIAL; @@ -188,7 +190,7 @@ chap_start(chap *_this) #ifdef USE_NPPPD_MPPE /* The peer must use MS-CHAP-V2 as the type */ - if (MPPE_REQUIRED(_this->ppp) && + if (MPPE_IS_REQUIRED(_this->ppp) && _this->type != PPP_AUTH_CHAP_MS_V2) { chap_log(_this, LOG_ALERT, "mppe is required but try to start chap " @@ -508,7 +510,7 @@ chap_proxy_authen_prepare(chap *_this, dialin_proxy_info *dpi) _this->pktid = dpi->auth_id; #ifdef USE_NPPPD_MPPE - if (MPPE_REQUIRED(_this->ppp) && + if (MPPE_IS_REQUIRED(_this->ppp) && _this->type != PPP_AUTH_CHAP_MS_V2) { chap_log(_this, LOG_ALERT, "mppe is required but try to start chap " @@ -760,8 +762,8 @@ chap_radius_authenticate(chap *_this, int id, char *username, if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST)) == NULL) goto fail; - if (radius_prepare(rad_setting, _this, &radctx, chap_radius_response, - _this->ppp->auth_timeout) != 0) { + if (radius_prepare(rad_setting, _this, &radctx, chap_radius_response) + != 0) { radius_delete_packet(radpkt); goto fail; } diff --git a/usr.sbin/npppd/npppd/ipcp.c b/usr.sbin/npppd/npppd/ipcp.c index 94d2544f36a..a6b33dc34ca 100644 --- a/usr.sbin/npppd/npppd/ipcp.c +++ b/usr.sbin/npppd/npppd/ipcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipcp.c,v 1.4 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: ipcp.c,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -32,7 +32,7 @@ /* * RFC 1332, 1877 */ -/* $Id: ipcp.c,v 1.4 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $Id: ipcp.c,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> @@ -105,6 +105,8 @@ static struct fsm_callbacks ipcp_callbacks = { void ipcp_init(ipcp *_this, npppd_ppp *ppp) { + struct tunnconf *conf; + memset(_this, 0, sizeof(ipcp)); _this->ppp = ppp; @@ -114,10 +116,15 @@ ipcp_init(ipcp *_this, npppd_ppp *ppp) _this->fsm.callbacks = &ipcp_callbacks; _this->fsm.protocol = PPP_PROTO_NCP | NCP_IPCP; - PPP_FSM_CONFIG(&_this->fsm, timeouttime, "ipcp.timeout"); - PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,"ipcp.max_configure"); - PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, "ipcp.max_terminate"); - PPP_FSM_CONFIG(&_this->fsm, maxnakloops, "ipcp.max_nak_loop"); + + conf = ppp_get_tunnconf(ppp); + PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->ipcp_timeout); + PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits, + conf->ipcp_max_configure); + PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, + conf->ipcp_max_terminate); + PPP_FSM_CONFIG(&_this->fsm, maxnakloops, + conf->ipcp_max_nak_loop); } static void diff --git a/usr.sbin/npppd/npppd/lcp.c b/usr.sbin/npppd/npppd/lcp.c index 278d94b3c0a..12bdd0220b5 100644 --- a/usr.sbin/npppd/npppd/lcp.c +++ b/usr.sbin/npppd/npppd/lcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lcp.c,v 1.7 2012/05/08 13:26:12 yasuoka Exp $ */ +/* $OpenBSD: lcp.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: lcp.c,v 1.7 2012/05/08 13:26:12 yasuoka Exp $ */ +/* $Id: lcp.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * This file provides LCP related functions. *<pre> @@ -115,6 +115,8 @@ static struct fsm_callbacks lcp_callbacks = { void lcp_init(lcp *_this, npppd_ppp *ppp) { + struct tunnconf *conf; + fsm_init(&_this->fsm); _this->fsm.ppp = ppp; @@ -127,19 +129,23 @@ lcp_init(lcp *_this, npppd_ppp *ppp) _this->recv_reqs = 0; _this->magic_number = ((0xffff & random()) << 16) | (0xffff & random()); - PPP_FSM_CONFIG(&_this->fsm, timeouttime, "lcp.timeout"); - PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,"lcp.max_configure"); - PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, "lcp.max_terminate"); - PPP_FSM_CONFIG(&_this->fsm, maxnakloops, "lcp.max_nak_loop"); + conf = ppp_get_tunnconf(ppp); + PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->lcp_timeout); + PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits, + conf->lcp_max_configure); + PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits, + conf->lcp_max_terminate); + PPP_FSM_CONFIG(&_this->fsm, maxnakloops, + conf->lcp_max_nak_loop); - /* - * PPTP and L2TP are able to detect lost carrier, so LCP ECHO is off - * by default. - */ - _this->echo_interval = 0; _this->echo_failures = 0; - _this->echo_max_retries = 0; - + if (!conf->lcp_keepalive) + _this->echo_interval = 0; + else { + _this->echo_interval = conf->lcp_keepalive_interval; + _this->echo_retry_interval = conf->lcp_keepalive_retry_interval; + _this->echo_max_retries = conf->lcp_keepalive_max_retries; + } _this->auth_order[0] = -1; } @@ -1040,58 +1046,26 @@ lcp_ext(fsm *f, int code, int id, u_char *inp, int inlen) static void lcp_load_authconfig(fsm *f) { - int i, f_none; - const char *val; - lcp *_this; + int i; + lcp *_this; + struct tunnconf *conf; - _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); - } + _this = &f->ppp->lcp; + conf = ppp_get_tunnconf(f->ppp); + if ((conf->auth_methods & NPPPD_AUTH_METHODS_MSCHAPV2) != 0) { + _this->auth_order[i++] = PPP_AUTH_CHAP_MS_V2; + psm_opt_set_enabled(_this,chapms_v2, 1); + } + if ((conf->auth_methods & NPPPD_AUTH_METHODS_CHAP) != 0) { + _this->auth_order[i++] = PPP_AUTH_CHAP_MD5; + psm_opt_set_enabled(_this, chap, 1); } - if (f_none && i != 0) { - ppp_log(f->ppp, LOG_WARNING, "auth protocol 'none' " - "must be specified individually"); - f_none = 0; + if ((conf->auth_methods & NPPPD_AUTH_METHODS_PAP) != 0) { + _this->auth_order[i++] = PPP_AUTH_PAP; + psm_opt_set_enabled(_this, pap, 1); } + _this->auth_order[i] = -1; } diff --git a/usr.sbin/npppd/npppd/log.c b/usr.sbin/npppd/npppd/log.c new file mode 100644 index 00000000000..b0f67d6428d --- /dev/null +++ b/usr.sbin/npppd/npppd/log.c @@ -0,0 +1,158 @@ +/* $OpenBSD: log.c,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include <errno.h> +#include <netdb.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include "debugutil.h" +#include "npppd.h" + +int debug; +extern int debugsyslog; + +void logit(int, const char *, ...); + +void +log_init(int n_debug) +{ + extern char *__progname; + + debug = n_debug; + + if (!debug) + openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); + + tzset(); +} + +void +logit(int pri, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vlog(pri, fmt, ap); + va_end(ap); +} + +void +vlog(int pri, const char *fmt, va_list ap) +{ + vlog_printf(pri, fmt, ap); +} + + +void +log_warn(const char *emsg, ...) +{ + char *nfmt; + va_list ap; + + /* best effort to even work in out of memory situations */ + if (emsg == NULL) + logit(LOG_CRIT, "%s", strerror(errno)); + else { + va_start(ap, emsg); + + if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { + /* we tried it... */ + vlog(LOG_CRIT, emsg, ap); + logit(LOG_CRIT, "%s", strerror(errno)); + } else { + vlog(LOG_CRIT, nfmt, ap); + free(nfmt); + } + va_end(ap); + } +} + +void +log_warnx(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vlog(LOG_CRIT, emsg, ap); + va_end(ap); +} + +void +log_info(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vlog(LOG_INFO, emsg, ap); + va_end(ap); +} + +void +log_debug(const char *emsg, ...) +{ + va_list ap; + + if (debug || debugsyslog) { + va_start(ap, emsg); + vlog(LOG_DEBUG, emsg, ap); + va_end(ap); + } +} + +void +fatal(const char *emsg) +{ + if (emsg == NULL) + logit(LOG_CRIT, "fatal: %s", strerror(errno)); + else + if (errno) + logit(LOG_CRIT, "fatal: %s: %s", + emsg, strerror(errno)); + else + logit(LOG_CRIT, "fatal: %s", emsg); + + exit(1); +} + +void +fatalx(const char *emsg) +{ + errno = 0; + fatal(emsg); +} + +const char * +log_sockaddr(struct sockaddr *sa) +{ + static char buf[NI_MAXHOST]; + + if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST)) + return ("(unknown)"); + else + return (buf); +} diff --git a/usr.sbin/npppd/npppd/mppe.c b/usr.sbin/npppd/npppd/mppe.c index f02a6d26881..46994c174b0 100644 --- a/usr.sbin/npppd/npppd/mppe.c +++ b/usr.sbin/npppd/npppd/mppe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mppe.c,v 1.7 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: mppe.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: mppe.c,v 1.7 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $Id: mppe.c,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * * The implementation of MPPE(Microsoft Point-To-Point Encryption Protocol) @@ -100,8 +100,7 @@ static void GetNewKeyFromSHA __P((u_char *, u_char *, int, u_char *)); void mppe_init(mppe *_this, npppd_ppp *ppp) { - const char *sval; - int ival; + struct tunnconf *conf; MPPE_ASSERT(ppp != NULL); MPPE_ASSERT(_this != NULL); @@ -112,59 +111,35 @@ mppe_init(mppe *_this, npppd_ppp *ppp) _this->mode_auto = 1; _this->mode_stateless = 0; - _this->keylen_auto = 1; - _this->keylenbits = 128; - - _this->enabled = (ppp_config_str_equal(_this->ppp, - "mppe.disabled", "true", 0) != 0)? 0 : 1; + conf = ppp_get_tunnconf(ppp); + _this->enabled = conf->mppe_yesno; if (_this->enabled == 0) goto mppe_config_done; - _this->required = (ppp_config_str_equal(_this->ppp, - "mppe.required", "true", 0) != 0)? 1 : 0; + _this->required = conf->mppe_required; if (_this->required == 0) goto mppe_config_done; - sval = ppp_config_str(_this->ppp, "mppe.mode"); - if (sval != NULL) { - if (strcmp(sval, "stateless") == 0) { - _this->mode_auto = 0; - _this->mode_stateless = 1; - } else if (strcmp(sval, "stateful") == 0) { - _this->mode_auto = 0; - _this->mode_stateless = 0; - } else if (strcmp(sval, "auto") == 0 || - strcmp(sval, "*") == 0) { - /* no changes from default. */ - } else { - mppe_log(_this, LOG_WARNING, - "configuration \"mppe.mode\" has bad value"); - _this->mode_auto = 1; - _this->mode_stateless = 0; - } - } - if (ppp_config_str_equal(_this->ppp, "mppe.keylen", "auto", 0) || - ppp_config_str_equal(_this->ppp, "mppe.keylen", "*", 0)) { - /* no changes from default. */ - } else { - ival = ppp_config_int(_this->ppp, "mppe.keylen", -1); - if (ival != -1) { - switch (ival) { - case 40: - case 56: - case 128: - _this->keylenbits = ival; - _this->keylen_auto = 0; - break; - default: - mppe_log(_this, LOG_WARNING, - "configuration \"mppe.keylen\" has bad " - "value"); - } - } + if (conf->mppe_keystate == (NPPPD_MPPE_STATEFUL|NPPPD_MPPE_STATELESS)) { + /* no need to change from default. */ + } else if (conf->mppe_keystate == NPPPD_MPPE_STATELESS) { + _this->mode_auto = 0; + _this->mode_stateless = 1; + } else if (conf->mppe_keystate == NPPPD_MPPE_STATEFUL) { + _this->mode_auto = 0; + _this->mode_stateless = 0; } + + _this->keylenbits = 0; + if ((conf->mppe_keylen & NPPPD_MPPE_40BIT) != 0) + _this->keylenbits |= CCP_MPPE_NT_40bit; + if ((conf->mppe_keylen & NPPPD_MPPE_56BIT) != 0); + _this->keylenbits |= CCP_MPPE_NT_56bit; + if ((conf->mppe_keylen & NPPPD_MPPE_128BIT) != 0) + _this->keylenbits |= CCP_MPPE_NT_128bit; + mppe_config_done: /* nothing */; } @@ -280,30 +255,16 @@ uint32_t mppe_create_our_bits(mppe *_this, uint32_t peer_bits) { uint32_t our_bits; + /* default proposal */ - our_bits = CCP_MPPE_NT_128bit; - - if (_this->keylen_auto == 0) { - switch (_this->keylenbits) { - case 40: - our_bits = CCP_MPPE_NT_40bit; break; - case 56: - our_bits = CCP_MPPE_NT_56bit; break; - case 128: - our_bits = CCP_MPPE_NT_128bit; break; - } - } else { - /* auto */ - our_bits = CCP_MPPE_NT_128bit | CCP_MPPE_NT_56bit - | CCP_MPPE_NT_40bit; - if (peer_bits != 0) { - if ((peer_bits & CCP_MPPE_NT_128bit) != 0) - our_bits = CCP_MPPE_NT_128bit; - else if ((peer_bits & CCP_MPPE_NT_56bit) != 0) - our_bits = CCP_MPPE_NT_56bit; - else if ((peer_bits & CCP_MPPE_NT_40bit) != 0) - our_bits = CCP_MPPE_NT_40bit; - } + our_bits = _this->keylenbits; + if (peer_bits != 0 && (peer_bits & our_bits) != 0) { + if ((peer_bits & CCP_MPPE_NT_128bit) != 0) + our_bits = CCP_MPPE_NT_128bit; + else if ((peer_bits & CCP_MPPE_NT_56bit) != 0) + our_bits = CCP_MPPE_NT_56bit; + else if ((peer_bits & CCP_MPPE_NT_40bit) != 0) + our_bits = CCP_MPPE_NT_40bit; } if (_this->mode_auto != 0) { diff --git a/usr.sbin/npppd/npppd/npppd-users.5 b/usr.sbin/npppd/npppd/npppd-users.5 new file mode 100644 index 00000000000..ed17c4cc2f1 --- /dev/null +++ b/usr.sbin/npppd/npppd/npppd-users.5 @@ -0,0 +1,68 @@ +.\" $OpenBSD: npppd-users.5,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ +.\" +.\" The following requests are required for all man pages. +.\" +.\" Remove `\&' from the line below. +.Dd $Mdocdate: September 18 2012 $ +.Dt NPPPD-USERS 5 +.Os +.Sh NAME +.Nm npppd-users +.Nd user database file +.Sh SYNOPSIS +.Nm /etc/npppd/npppd-users +.Sh DESCRIPTION +The +.Nm +file describes +the various attributes of users. +Refer to +.Xr getcap 3 +for a description of the file layout. +Each entry in the database is used to describe one user. +The record name is the username. +Following attributes can be specified: +.Bl -column "framed-ip-network" +.It Sy Name Ta Sy Description +.It password Ta +User's password +.It framed-ip-address Ta +IPv4 address to be assigned for the user. +.It framed-ip-network Ta +IPv4 netmask to be used for the user. +.It calling-number Ta +Calling phone number to check user's phone number. +.El +.\" The following requests should be uncommented and used where appropriate. +.\" .Sh RETURN VALUES +.\" For sections 2, 3, and 9 function return values only. +.\" .Sh ENVIRONMENT +.\" For sections 1, 6, 7 & 8 only. +.\" .Sh FILES +.\" .Sh EXIT STATUS +.\" For sections 1, 6, & 8 only. +.Pp +.Sh EXAMPLES +.Bd -literal +taro:\\ + :password=taro's password:\\ + :framed-ip-address=192.168.0.101: + +hana:\\ + :password=hana's password:\\ + :framed-ip-address=192.168.0.102: +.Ed +.\" .Sh DIAGNOSTICS +.\" For sections 1, 4, 6, 7, and 8 only. +.\" .Sh ERRORS +.\" For sections 2, 3, and 9 error and signal handling only. +.Sh SEE ALSO +.Xr npppd 8 , +.Xr npppd.conf 5 , +.Xr getcap 3 +.\" .Xr foobar 1 +.\" .Sh STANDARDS +.\" .Sh HISTORY +.\" .Sh AUTHORS +.\" .Sh CAVEATS +.\" .Sh BUGS diff --git a/usr.sbin/npppd/npppd/npppd.8 b/usr.sbin/npppd/npppd/npppd.8 new file mode 100644 index 00000000000..9bf4d9020fc --- /dev/null +++ b/usr.sbin/npppd/npppd/npppd.8 @@ -0,0 +1,117 @@ +.\" $OpenBSD: npppd.8,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ +.\" +.\" Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" The following requests are required for all man pages. +.\" +.Dd $Mdocdate: September 18 2012 $ +.Dt NPPPD 8 +.Os +.Sh NAME +.Nm npppd +.Nd New Point-to-Point Protocol daemon +.Sh SYNOPSIS +.Nm npppd +.Op Fl hdn +.Op Fl f Ar config_file +.Sh DESCRIPTION +The +.Nm +is a Point-to-Point Protocol and tunneling protocols daemon +which does L2TP, PPTP and PPPoE servers. +.Bl -tag -width Ds +.It Fl d +Do not daemonize. +If this option is specified, +.Nm +will run in the foreground and log to +.Em stderr . +.It Fl f Ar file +Specify an alternative configuration file. +.It Fl n +Configtest mode. +Only check the configuration file for validity. +.It Fl h +Show the usage. +.El +.Pp +Normally +.Nm +works with +.Xr pipex 4 +to accelerate IP packet forwarding, but +.Xr pipex 4 +is disabled by default. To enable it, +set the +.Va net.pipex.enable +to `1' by +.Xr sysctl 8 +or +.Xr sysctl.conf 5 . +.Pp +When +.Nm +uses PPTP, receiving GRE packets is required, but it is disabled by default. +To enable it, set the +.Va net.inet.gre.allow +to `1' by +.Xr sysctl 8 +or +.Xr sysctl.conf 5 . +.\" The following requests should be uncommented and used where appropriate. +.\" .Sh RETURN VALUES +.\" For sections 2, 3, and 9 function return values only. +.\" .Sh ENVIRONMENT +.\" For sections 1, 6, 7 & 8 only. +.Sh FILES +.Bl -tag -width "/etc/npppd/npppd.conf" -compact +.It Pa /etc/npppd/npppd.conf +default +.Xr npppd 8 +configuration file +.El +.\" .Sh EXIT STATUS +.\" For sections 1, 6, & 8 only. +.\" .Sh EXAMPLES +.\" .Sh DIAGNOSTICS +.\" For sections 1, 4, 6, 7, and 8 only. +.\" .Sh ERRORS +.\" For sections 2, 3, and 9 error and signal handling only. +.Sh SEE ALSO +.Xr npppctl 8 , +.Xr npppd.conf 5 , +.Xr pipex 4 , +.Xr tun 4 , +.Xr pppx 4 , +.Xr gre 4 , +.Xr sysctl 8 , +.Xr sysctl.conf 5 +.\" .Xr foobar 1 +.\" .Sh STANDARDS +.Sh HISTORY +The +.Nm +program first appeared in +.Ox +5.3. +.Sh AUTHORS +The +.Nm +program was written by Internet Initiative Japan Inc. +. +.\" .Sh CAVEATS +.Sh BUGS +If +.Ic l2tp-require-ipsec +yes to L2TP tunnel, all incoming packets will be dropped. diff --git a/usr.sbin/npppd/npppd/npppd.c b/usr.sbin/npppd/npppd/npppd.c index 9b34890f99f..b08ee3dddf5 100644 --- a/usr.sbin/npppd/npppd/npppd.c +++ b/usr.sbin/npppd/npppd/npppd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd.c,v 1.20 2012/07/17 03:18:57 yasuoka Exp $ */ +/* $OpenBSD: npppd.c,v 1.21 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -29,7 +29,7 @@ * Next pppd(nppd). This file provides a npppd daemon process and operations * for npppd instance. * @author Yasuoka Masahiko - * $Id: npppd.c,v 1.20 2012/07/17 03:18:57 yasuoka Exp $ + * $Id: npppd.c,v 1.21 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/cdefs.h> #include "version.h" @@ -106,10 +106,10 @@ __COPYRIGHT( static npppd s_npppd; /* singleton */ -static void npppd_reload0(npppd *); +static void npppd_reload0 (npppd *); +static void npppd_update_pool_reference (npppd *); static int npppd_rd_walktree_delete(struct radish_head *); static void usage (void); -static void npppd_start (npppd *); static void npppd_stop_really (npppd *); static uint32_t str_hash(const void *, int); static void npppd_on_sighup (int, short, void *); @@ -145,28 +145,27 @@ static void pipex_periodic(npppd *); * Daemon process ***********************************************************************/ int main (int, char *[]); +int debugsyslog = 0; /* used by log.c */ int main(int argc, char *argv[]) { - int ch, stop_by_error, ll_adjust = 0, runasdaemon = 0; - extern char *optarg; - const char *npppd_conf0 = DEFAULT_NPPPD_CONF; + int ch, stop_by_error, runasdaemon = 1, nflag = 0; + extern char *optarg; + const char *npppd_conf0 = DEFAULT_NPPPD_CONF; struct passwd *pw; - while ((ch = getopt(argc, argv, "Dc:dhs")) != -1) { + while ((ch = getopt(argc, argv, "nf:dh")) != -1) { switch (ch) { - case 's': - ll_adjust++; + case 'n': + nflag = 1; break; - case 'c': + case 'f': npppd_conf0 = optarg; break; - case 'D': - runasdaemon = 1; - break; case 'd': debuglevel++; + runasdaemon = 0; break; case '?': case 'h': @@ -174,15 +173,26 @@ main(int argc, char *argv[]) exit(1); } } + argc -= optind; + argv += optind; + if (argc != 0) { + usage(); + exit(1); + } + if (nflag) { + debuglevel++; + runasdaemon = 0; + } + + /* for log.c */ + log_init(debuglevel); if (debuglevel > 0) { + /* for ../common/debugutil.c */ debug_set_debugfp(stderr); debug_use_syslog(0); - } else { - debug_set_syslog_level_adjust(ll_adjust); - openlog(NULL, LOG_PID, LOG_NPPPD); - if (runasdaemon) - daemon(0, 0); } + if (runasdaemon) + daemon(0, 0); /* check for root privileges */ if (geteuid()) @@ -194,6 +204,13 @@ main(int argc, char *argv[]) if (privsep_init() != 0) err(1, "cannot drop privileges"); + if (nflag) { + if (npppd_config_check(npppd_conf0) == 0) { + fprintf(stderr, "configuration OK\n"); + exit(EXIT_SUCCESS); + } + exit(EXIT_FAILURE); + } if (npppd_init(&s_npppd, npppd_conf0) != 0) exit(EXIT_FAILURE); @@ -221,15 +238,7 @@ main(int argc, char *argv[]) static void usage() { - fprintf(stderr, - "usage: npppd [-sDdh] [-c config_file]\n" - "\t-d: increase debuglevel. Output log to standard error.\n" - "\t-c: specify configuration file. default=\"%s\".\n" - "\t-s: adjust syslog level to be silent.\n" - "\t-D: run as a daemon.\n" - "\t-h: show usage.\n" - , DEFAULT_NPPPD_CONF - ); + fprintf(stderr, "usage: npppd [-hdn] [-f config_file]\n"); } /** Returns the singleton npppd instance */ @@ -247,11 +256,8 @@ int npppd_init(npppd *_this, const char *config_file) { int i, status = -1; - char pidpath[MAXPATHLEN]; const char *pidpath0; - const char *coredir; FILE *pidfp = NULL; - char cwd[MAXPATHLEN]; long seed; memset(_this, 0, sizeof(npppd)); @@ -264,6 +270,7 @@ npppd_init(npppd *_this, const char *config_file) pidpath0 = NULL; _this->pid = getpid(); slist_init(&_this->realms); + npppd_conf_init(&_this->conf); log_printf(LOG_NOTICE, "Starting npppd pid=%u version=%s", _this->pid, VERSION); @@ -305,24 +312,7 @@ npppd_init(npppd *_this, const char *config_file) return -1; } - if ((pidpath0 = npppd_config_str(_this, "pidfile")) == NULL) - pidpath0 = DEFAULT_NPPPD_PIDFILE; - - /* Runtime directory */ - if ((coredir = npppd_config_str(_this, "coredir")) == NULL) { - /* diretory for pid file */ - strlcpy(pidpath, pidpath0, sizeof(pidpath)); - strlcpy(cwd, dirname(pidpath), sizeof(cwd)); - } - else { - /* directory for dumping core */ - strlcpy(cwd, coredir, sizeof(cwd)); - } - if (chdir(cwd) != 0) { - log_printf(LOG_ERR, "chdir(%s,) failed in %s(): %m", __func__, - cwd); - return -1; - } + pidpath0 = DEFAULT_NPPPD_PIDFILE; /* initialize event(3) */ event_init(); @@ -374,7 +364,12 @@ npppd_init(npppd *_this, const char *config_file) npppd_ctl_init(&_this->ctl, _this, NPPPD_CTL_SOCK_PATH); if ((status = npppd_ctl_start(&_this->ctl)) != 0) return status; - return npppd_modules_reload(_this); + if ((status = npppd_modules_reload(_this)) != 0) + return status; + + npppd_update_pool_reference(_this); + + return 0; } /** start the npppd */ @@ -445,8 +440,7 @@ npppd_stop_really(npppd *_this) } #endif for (i = countof(_this->iface) - 1; i >= 0; i--) { - if (_this->iface[i].initialized != 0) - npppd_iface_fini(&_this->iface[i]); + npppd_iface_fini(&_this->iface[i]); } _this->finalized = 1; } @@ -476,8 +470,6 @@ npppd_fini(npppd *_this) if (_this->iface[i].initialized != 0) npppd_iface_fini(&_this->iface[i]); } - for (i = 0; i < countof(_this->iface_bind); i++) - slist_fini(&_this->iface_bind[i].pools); for (i = countof(_this->pool) - 1; i >= 0; i--) { if (_this->pool[i].initialized != 0) @@ -489,8 +481,7 @@ npppd_fini(npppd *_this) signal_del(&_this->ev_sighup); signal_del(&_this->ev_sigchld); - if (_this->properties != NULL) - properties_destroy(_this->properties); + npppd_conf_fini(&_this->conf); slist_fini(&_this->realms); @@ -660,38 +651,24 @@ npppd_get_user_framed_ip_address(npppd *_this, npppd_ppp *ppp, } NPPPD_ASSERT(ppp->realm != NULL); - if (ppp->realm_framed_ip_address.s_addr != 0) { -#if 1 -/* - * FIXME: This fix is ad hok, it overwrites the ip address here if assigning - * FIXME: IP address by RADIUS is prohibited. This will make a bug when a - * FIXME: new authentication type is add. Fix this until then. - */ - if ((ppp_ipcp(ppp)->ip_assign_flags & NPPPD_IP_ASSIGN_RADIUS) - == 0) { - ppp->realm_framed_ip_netmask.s_addr = 0; - } else -#endif + if (ppp->realm_framed_ip_address.s_addr != 0) return &ppp->realm_framed_ip_address; - } - ppp->realm_framed_ip_netmask.s_addr = 0xffffffffL; - if ((ppp_ipcp(ppp)->ip_assign_flags & NPPPD_IP_ASSIGN_FIXED) != 0) { - /* assign by the authentication realm */ - if (npppd_auth_get_framed_ip(ppp->realm, username, - &ppp->realm_framed_ip_address, - &ppp->realm_framed_ip_netmask) != 0) - ppp->realm_framed_ip_address.s_addr = 0; - } + /* assign by the authentication realm */ + if (npppd_auth_get_framed_ip(ppp->realm, username, + &ppp->realm_framed_ip_address, + &ppp->realm_framed_ip_netmask) != 0) + ppp->realm_framed_ip_address.s_addr = 0; do_default: /* Use USER_SELECT if the realm doesn't specify the ip address */ if (ppp->realm_framed_ip_address.s_addr == 0) ppp->realm_framed_ip_address.s_addr = INADDR_USER_SELECT; + + if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) { /* Use NAS_SELECT if USER_SELECT is not allowed by the config */ - if ((ppp_ipcp(ppp)->ip_assign_flags & - NPPPD_IP_ASSIGN_USER_SELECT) == 0) + if (!ppp_ipcp(ppp)->allow_user_select) ppp->realm_framed_ip_address.s_addr = INADDR_NAS_SELECT; } NPPPD_DBG((LOG_DEBUG, "%s() = %s", __func__, @@ -704,20 +681,18 @@ do_default: int npppd_check_calling_number(npppd *_this, npppd_ppp *ppp) { - int lnumber, rval, strict, loose; - char number[NPPPD_PHONE_NUMBER_LEN + 1]; - - strict = ppp_config_str_equal(ppp, "check_callnum", "strict", 0); - loose = ppp_config_str_equal(ppp, "check_callnum", "loose", 0); + struct tunnconf *conf; + int lnumber, rval; + char number[NPPPD_PHONE_NUMBER_LEN + 1]; - if (strict || loose) { + conf = ppp_get_tunnconf(ppp); + if (conf->callnum_check != 0) { lnumber = sizeof(number); if ((rval = npppd_auth_get_calling_number(ppp->realm, - ppp->username, - number, &lnumber)) == 0) + ppp->username, number, &lnumber)) == 0) return (strcmp(number, ppp->calling_number) == 0)? 1 : 0; - if (strict) + if ((conf->callnum_check & NPPPD_CALLNUM_CHECK_STRICT) != 0) return 0; } @@ -817,7 +792,7 @@ npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp) slist *uppp; /* user_max_session == 0 means unlimit */ - if (ppp_iface(ppp)->user_max_session == 0) + if (_this->user_max_session == 0) return 1; count = 0; @@ -830,7 +805,7 @@ npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp) } } - return (count < ppp_iface(ppp)->user_max_session)? 1 : 0; + return (count < _this->user_max_session)? 1 : 0; } /*********************************************************************** @@ -976,7 +951,7 @@ npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) switch (ppp->tunnel_type) { #ifdef USE_NPPPD_PPPOE - case PPP_TUNNEL_PPPOE: + case NPPPD_TUNNEL_PPPOE: { struct sockaddr *sa; struct ether_header *eh; @@ -1003,7 +978,7 @@ npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) } #endif #ifdef USE_NPPPD_PPTP - case PPP_TUNNEL_PPTP: + case NPPPD_TUNNEL_PPTP: call = (pptp_call *)ppp->phy_context; /* PPTP specific informations */ @@ -1029,7 +1004,7 @@ npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_L2TP - case PPP_TUNNEL_L2TP: + case NPPPD_TUNNEL_L2TP: l2tp = (l2tp_call *)ppp->phy_context; l2tpctrl = l2tp->ctrl; @@ -1119,7 +1094,7 @@ npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) bzero(&req, sizeof(req)); switch(ppp->tunnel_type) { #ifdef USE_NPPPD_PPPOE - case PPP_TUNNEL_PPPOE: + case NPPPD_TUNNEL_PPPOE: pppoe = (pppoe_session *)ppp->phy_context; /* PPPoE specific informations */ @@ -1128,7 +1103,7 @@ npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_PPTP - case PPP_TUNNEL_PPTP: + case NPPPD_TUNNEL_PPTP: call = (pptp_call *)ppp->phy_context; /* PPTP specific informations */ @@ -1137,7 +1112,7 @@ npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_L2TP - case PPP_TUNNEL_L2TP: + case NPPPD_TUNNEL_L2TP: l2tp = (l2tp_call *)ppp->phy_context; /* L2TP specific context */ @@ -1185,7 +1160,7 @@ npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) bzero(&req, sizeof(req)); switch(ppp->tunnel_type) { #ifdef USE_NPPPD_PPPOE - case PPP_TUNNEL_PPPOE: + case NPPPD_TUNNEL_PPPOE: pppoe = (pppoe_session *)ppp->phy_context; /* PPPoE specific informations */ @@ -1194,7 +1169,7 @@ npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_PPTP - case PPP_TUNNEL_PPTP: + case NPPPD_TUNNEL_PPTP: call = (pptp_call *)ppp->phy_context; /* PPTP specific informations */ @@ -1203,7 +1178,7 @@ npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_L2TP - case PPP_TUNNEL_L2TP: + case NPPPD_TUNNEL_L2TP: l2tp = (l2tp_call *)ppp->phy_context; /* L2TP specific context */ @@ -1222,11 +1197,11 @@ npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) static void pipex_periodic(npppd *_this) { - struct pipex_session_list_req req; - npppd_ppp *ppp; - int i, error; - u_int ppp_id; - slist dlist, users; + struct pipex_session_list_req req; + npppd_ppp *ppp; + int i, error; + u_int ppp_id; + slist dlist, users; slist_init(&dlist); slist_init(&users); @@ -1296,6 +1271,7 @@ pipex_done: int npppd_prepare_ip(npppd *_this, npppd_ppp *ppp) { + if (ppp_ipcp(ppp) == NULL) return 1; @@ -1307,15 +1283,10 @@ npppd_prepare_ip(npppd *_this, npppd_ppp *ppp) ppp->ipcp.ip4_our = _this->iface[0].ip4addr; else return -1; - if (ppp_ipcp(ppp)->dns_use_tunnel_end != 0) { - ppp->ipcp.dns_pri = ppp->ipcp.ip4_our; - ppp->ipcp.dns_sec.s_addr = INADDR_NONE; - } else { - ppp->ipcp.dns_pri = ppp_ipcp(ppp)->dns_pri; - ppp->ipcp.dns_sec = ppp_ipcp(ppp)->dns_sec; - } - ppp->ipcp.nbns_pri = ppp_ipcp(ppp)->nbns_pri; - ppp->ipcp.nbns_sec = ppp_ipcp(ppp)->nbns_sec; + ppp->ipcp.dns_pri = ppp_ipcp(ppp)->dns_servers[0]; + ppp->ipcp.dns_sec = ppp_ipcp(ppp)->dns_servers[1]; + ppp->ipcp.nbns_pri = ppp_ipcp(ppp)->nbns_servers[0]; + ppp->ipcp.nbns_sec = ppp_ipcp(ppp)->nbns_servers[1]; return 0; } @@ -1494,7 +1465,7 @@ int npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) { uint32_t ip4, ip4mask; - int flag, dyna, rval, fallback_dyna; + int dyna, rval, fallback_dyna; const char *reason = "out of the pool"; struct sockaddr_npppd *snp; npppd_pool *pool; @@ -1507,7 +1478,6 @@ npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) ip4 = INADDR_ANY; ip4mask = 0xffffffffL; - flag = ppp_ipcp(ppp)->ip_assign_flags; realm = ppp->realm; dyna = 0; fallback_dyna = 0; @@ -1520,19 +1490,9 @@ npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) dyna = 1; } else { NPPPD_ASSERT(realm != NULL); - /* We cannot assign a fixed ip address without realm */ - - if ((npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_RADIUS && - (flag & NPPPD_IP_ASSIGN_RADIUS) == 0 && - (flag & NPPPD_IP_ASSIGN_FIXED) == 0) || - (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL && - (flag & NPPPD_IP_ASSIGN_FIXED) == 0)) - dyna = 1; - else { - fallback_dyna = 1; - req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr); - ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr); - } + fallback_dyna = 1; + req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr); + ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr); } if (!dyna) { /* @@ -1540,43 +1500,38 @@ npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) * doesn't belong any address pool. Fallback to dynamic * assignment. */ - for (slist_itr_first(ppp_pools(ppp)); - slist_itr_has_next(ppp_pools(ppp));){ - pool = slist_itr_next(ppp_pools(ppp)); - rval = npppd_pool_get_assignability(pool, req_ip4, - ip4mask, &snp); - switch (rval) { - case ADDRESS_OK: - if (snp->snp_type == SNP_POOL) { - /* - * Fixed address pool can be used - * only if the realm specified to use - * it. - */ - if (ppp->realm_framed_ip_address - .s_addr != INADDR_USER_SELECT) - ip4 = req_ip4; - break; - } - ppp->assign_dynapool = 1; - ip4 = req_ip4; - break; - case ADDRESS_RESERVED: - reason = "reserved"; - continue; - case ADDRESS_OUT_OF_POOL: - reason = "out of the pool"; - continue; /* try next */ - case ADDRESS_BUSY: - fallback_dyna = 0; - reason = "busy"; - break; - default: - case ADDRESS_INVALID: - fallback_dyna = 0; - reason = "invalid"; + pool = ppp_pool(ppp); + rval = npppd_pool_get_assignability(pool, req_ip4, ip4mask, + &snp); + switch (rval) { + case ADDRESS_OK: + if (snp->snp_type == SNP_POOL) { + /* + * Fixed address pool can be used only if the + * realm specified to use it. + */ + if (ppp->realm_framed_ip_address + .s_addr != INADDR_USER_SELECT) + ip4 = req_ip4; break; } + ppp->assign_dynapool = 1; + ip4 = req_ip4; + break; + case ADDRESS_RESERVED: + reason = "reserved"; + break; + case ADDRESS_OUT_OF_POOL: + reason = "out of the pool"; + break; + case ADDRESS_BUSY: + fallback_dyna = 0; + reason = "busy"; + break; + default: + case ADDRESS_INVALID: + fallback_dyna = 0; + reason = "invalid"; break; } #define IP_4OCT(v) ((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16),\ @@ -1590,19 +1545,13 @@ npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) goto dyna_assign; return 1; } - ppp->assigned_pool = pool; ppp->ppp_framed_ip_address.s_addr = htonl(ip4); ppp->ppp_framed_ip_netmask.s_addr = htonl(ip4mask); } else { dyna_assign: - for (slist_itr_first(ppp_pools(ppp)); - slist_itr_has_next(ppp_pools(ppp));){ - pool = slist_itr_next(ppp_pools(ppp)); - ip4 = npppd_pool_get_dynamic(pool, ppp); - if (ip4 != 0) - break; - } + pool = ppp_pool(ppp); + ip4 = npppd_pool_get_dynamic(pool, ppp); if (ip4 == 0) { ppp_log(ppp, LOG_NOTICE, "No free address in the pool."); @@ -1690,7 +1639,6 @@ npppd_set_radish(npppd *_this, void *radish_head) slist_itr_remove(&rtlist0); /* clear informations about old pool configuration */ - ppp->assigned_pool = NULL; snp->snp_next = NULL; delppp0 = 0; @@ -1860,6 +1808,8 @@ rd2slist(struct radish_head *h, slist *list) static void npppd_reload0(npppd *_this) { + int i; + npppd_reload_config(_this); #ifdef USE_NPPPD_ARP arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); @@ -1870,16 +1820,39 @@ npppd_reload0(npppd *_this) #endif npppd_modules_reload(_this); npppd_ifaces_load_config(_this); -#ifdef NPPPD_RESET_IP_ADDRESS - { - int i; - for (i = 0; i < countof(_this->iface); i++) { - if (_this->iface[i].initialized != 0) - npppd_iface_reinit(&_this->iface[i]); - } - } -#endif + npppd_update_pool_reference(_this); npppd_auth_finalizer_periodic(_this); + + for (i = 0; i < countof(_this->iface); i++) { + if (_this->iface[i].initialized != 0 && + _this->iface[i].started == 0) + npppd_iface_start(&_this->iface[i]); + } +} + +static void +npppd_update_pool_reference(npppd *_this) +{ + int i, j; + /* update iface to pool reference */ + for (i = 0; i < countof(_this->iface_pool); i++) { + _this->iface_pool[i] = NULL; + if (_this->iface[i].initialized == 0) + continue; + if (_this->iface[i].ipcpconf == NULL) + continue; /* no IPCP for this interface */ + + for (j = 0; j < countof(_this->pool); j++) { + if (_this->pool[j].initialized == 0) + continue; + if (strcmp(_this->iface[i].ipcpconf->name, + _this->pool[j].ipcp_name) == 0) { + /* found the ipcp that has the pool */ + _this->iface_pool[i] = &_this->pool[j]; + break; + } + } + } } /*********************************************************************** @@ -1966,10 +1939,10 @@ int npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int eap_required) { - int lsuffix, lprefix, lusername, lmax; - const char *val; - char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ], buf1[MAX_USERNAME_LENGTH]; + struct confbind *bind; npppd_auth_base *realm = NULL, *realm0 = NULL, *realm1 = NULL; + char buf1[MAX_USERNAME_LENGTH]; + int lsuffix, lprefix, lusername, lmax; NPPPD_ASSERT(_this != NULL); NPPPD_ASSERT(ppp != NULL); @@ -1983,88 +1956,51 @@ npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int lmax = -1; realm = NULL; - if ((val = ppp_config_str(ppp, "realm_list")) == NULL) { -#ifndef NO_DEFAULT_REALM - /* - * If the realm is not a list, because of compatibility for - * past versions, we try fallback from LOCAL to RADIUS. - */ + TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) { + if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) + continue; + realm0 = NULL; slist_itr_first(&_this->realms); while (slist_itr_has_next(&_this->realms)) { realm1 = slist_itr_next(&_this->realms); if (!npppd_auth_is_usable(realm1)) continue; - switch (npppd_auth_get_type(realm1)) { - case NPPPD_AUTH_TYPE_LOCAL: - if (npppd_auth_get_user_password( - realm1, npppd_auth_username_for_auth( - realm1, username, buf1), - NULL, NULL) == 0) { - realm = realm1; - goto found; - } + if (eap_required && !npppd_auth_is_eap_capable(realm1)) + continue; + if (strcmp(npppd_auth_get_name(realm1), + bind->authconf->name) == 0) { + realm0 = realm1; break; - - case NPPPD_AUTH_TYPE_RADIUS: - realm = realm1; - goto found; } } -#else - /* Nothing to do */ -#endif - } else { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, " ,\t\r\n")) != NULL) { - if (tok[0] == '\0') - continue; - realm0 = NULL; - slist_itr_first(&_this->realms); - while (slist_itr_has_next(&_this->realms)) { - realm1 = slist_itr_next(&_this->realms); - if (!npppd_auth_is_usable(realm1)) - continue; - if (eap_required && - !npppd_auth_is_eap_capable(realm1)) - continue; - if (strcmp(npppd_auth_get_label(realm1), tok) - == 0) { - realm0 = realm1; - break; - } - } - if (realm0 == NULL) + if (realm0 == NULL) + continue; + + lsuffix = strlen(npppd_auth_get_suffix(realm0)); + if (lsuffix > lmax && + (lsuffix == 0 || + (lsuffix < lusername && strcmp(username + lusername + - lsuffix, npppd_auth_get_suffix(realm0)) + == 0))) { + /* check prefix */ + lprefix = strlen(npppd_auth_get_prefix(realm0)); + if (lprefix > 0 && + strncmp(username, npppd_auth_get_prefix(realm0), + lprefix) != 0) continue; - lsuffix = strlen(npppd_auth_get_suffix(realm0)); - if (lsuffix > lmax && - (lsuffix == 0 || (lsuffix < lusername && - strcmp(username + lusername - lsuffix, - npppd_auth_get_suffix(realm0)) == 0))) { - /* check prefix */ - lprefix = strlen(npppd_auth_get_prefix(realm0)); - if (lprefix > 0 && - strncmp(username, - npppd_auth_get_prefix(realm0), - lprefix) != 0) - continue; - lmax = lsuffix; - realm = realm0; - } + lmax = lsuffix; + realm = realm0; } } + if (realm == NULL) { log_printf(LOG_INFO, "user='%s' could not bind any realms", username); return 1; } -#ifndef NO_DEFAULT_REALM -found: -#endif - NPPPD_DBG((LOG_DEBUG, "%s bind realm %s(%s)", - username, npppd_auth_get_label(realm), npppd_auth_get_name(realm))); + NPPPD_DBG((LOG_DEBUG, "bind realm %s", npppd_auth_get_name(realm))); if (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL) /* hook the auto reload */ @@ -2144,62 +2080,46 @@ npppd_ppp_iface_is_ready(npppd *_this, npppd_ppp *ppp) int npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp) { - int i, ifidx, ntotal_session; - const char *ifname, *label; - char buf[BUFSIZ]; - npppd_auth_base *realm; + int i, ifidx; + struct confbind *bind; NPPPD_ASSERT(_this != NULL); NPPPD_ASSERT(ppp != NULL); if (ppp->ifidx >= 0) return 0; - if (ppp->peer_auth == 0) { - strlcpy(buf, "no_auth.concentrate", sizeof(buf)); - } else { - realm = (npppd_auth_base *)ppp->realm; - strlcpy(buf, "realm.", sizeof(buf)); - NPPPD_ASSERT(ppp->realm != NULL); - label = npppd_auth_get_label(realm); - if (label[0] != '\0') { - strlcat(buf, label, sizeof(buf)); - strlcat(buf, ".concentrate", sizeof(buf)); - } else - strlcat(buf, "concentrate", sizeof(buf)); - } - - ifname = ppp_config_str(ppp, buf); - if (ifname == NULL) + + TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) { + if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) + continue; + if (ppp->realm == NULL) { + if (bind->authconf == NULL) + break; + } else if (strcmp(bind->authconf->name, + npppd_auth_get_name(ppp->realm)) == 0) + break; + } + if (bind == NULL) return 1; /* Search a interface */ ifidx = -1; - ntotal_session = 0; for (i = 0; i < countof(_this->iface); i++) { if (_this->iface[i].initialized == 0) continue; - ntotal_session += _this->iface[i].nsession; - if (strcmp(_this->iface[i].ifname, ifname) == 0) + if (strcmp(_this->iface[i].ifname, bind->iface->name) == 0) ifidx = i; } if (ifidx < 0) return 1; - if (ntotal_session >= _this->max_session) { + if (_this->max_session > 0 && _this->nsession++ >= _this->max_session) { ppp_log(ppp, LOG_WARNING, "Number of sessions reaches out of the limit=%d", _this->max_session); return 1; } - if (_this->iface[ifidx].nsession >= _this->iface[ifidx].max_session) { - ppp_log(ppp, LOG_WARNING, - "Number of sessions reaches out of the interface limit=%d", - _this->iface[ifidx].max_session); - return 1; - } - ppp->ifidx = ifidx; - ppp_iface(ppp)->nsession++; return 0; } @@ -2208,9 +2128,7 @@ npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp) void npppd_ppp_unbind_iface(npppd *_this, npppd_ppp *ppp) { - if (ppp->ifidx >= 0) - ppp_iface(ppp)->nsession--; - + _this->nsession--; ppp->ifidx = -1; } @@ -2355,21 +2273,40 @@ seed_random(long *seed) } const char * -npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp) +npppd_tunnel_protocol_name(int tunn_protocol) { - switch (ppp->tunnel_type) { - case PPP_TUNNEL_NONE: + switch (tunn_protocol) { + case NPPPD_TUNNEL_NONE: return "None"; - case PPP_TUNNEL_L2TP: + case NPPPD_TUNNEL_L2TP: return "L2TP"; - case PPP_TUNNEL_PPTP: + case NPPPD_TUNNEL_PPTP: return "PPTP"; - case PPP_TUNNEL_PPPOE: + case NPPPD_TUNNEL_PPPOE: return "PPPoE"; - case PPP_TUNNEL_SSTP: + case NPPPD_TUNNEL_SSTP: return "SSTP"; } - NPPPD_ASSERT(0); return "Error"; } + +const char * +npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp) +{ + return npppd_tunnel_protocol_name(ppp->tunnel_type); +} + +struct tunnconf * +npppd_get_tunnconf(npppd *_this, const char *name) +{ + struct tunnconf *conf; + + TAILQ_FOREACH(conf, &_this->conf.tunnconfs, entry) { + if (strcmp(conf->name, name) == 0) + return conf; + } + + return NULL; +} + diff --git a/usr.sbin/npppd/npppd/npppd.conf.5 b/usr.sbin/npppd/npppd/npppd.conf.5 new file mode 100644 index 00000000000..29245694e20 --- /dev/null +++ b/usr.sbin/npppd/npppd/npppd.conf.5 @@ -0,0 +1,642 @@ +.\" $OpenBSD: npppd.conf.5,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ +.\" +.\" Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" +.Dd $Mdocdate: September 18 2012 $ +.Dt NPPPD.CONF 5 +.Os +.Sh NAME +.Nm npppd.conf +.Nd npppd configuration file +.Sh DESCRIPTION +.Nm +is the configuration file for the PPP daemon, +.Xr npppd 8 . +.Sh SECTIONS +.Nm +is devided six sections: +.Bl -tag -compact -width Authentications +.It Sy Globals +Global setting +.It Sy Tunnels +Tunnel setting describes the tunneling protocol and PPP settings. +.It Sy IPCPs +IPCP setting describes the Internet Protocol Configuration Protocol(IPCP) +of PPP. +.It Sy Interfaces +Inteface setting +.It Sy Authentications +Authenticaton setting +.It Sy Binds +Bind the setting +.El +.Sh GLOBAL +Global options are following: +.Bl -tag -width Ds +.It Ic set max-session Ar number +Specify the maximum number of sessions. +`0' means no limit. Default value is `0'. +.It Ic set user-max-session Ar number +Specify the maximum number of sessions for each user. +`0' means no limit. Default value is `0'. +.El +.Sh TUNNEL +.Pp +The +.Ic tunnel +setting are described below: +.Bd +.Ic tunnel Ar name Ic protocol Ar protocol Ic { Ar options Ic } +.Ed +.Pp +Specify +.Ar name +of this tunnel protocol setting. +For +.Ar protocol , +specify one of the following that this tunnel setting accepts from: +.Pp +.Bl -offset indent -compact -tag -width pppoe -indent +.It Ic l2tp +Layer Two Tunneling Protocol (RFC 2661) +.It Ic pptp +Point-to-Point Tunneling Protocol (RFC 2637) +.It Ic pppoe +PPP Over Ethernet (RFC 2516) +.El +.El +.Pp +Supported options are following: +.Bl -tag -width Ds +.It Ic listen on Ar address Op Ic port Ar port +Specify IP address that this tunnel protocol listens on. +Both IPv4 and IPv6 address can be used. If the port is ommited, the default +port numbers are used. +The default port number is 1723 for PPTP and 1701 for L2TP. +Default value is `0.0.0.0'. +This option can be specified if the tunnel protocol is not PPPoE. +.It Ic listen on interface Ar interface-name +Specify the interface name that this PPPoE tunnel listens on. +The interface must be ethernet interface. +This option can be specified if the tunnel protocol is PPPoE. +.It Ic l2tp-hostname Ar string +Specify a hostname that are used by L2TP. +Default value is the value that is returned by +.Xr gethostname 2 . +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-vendor-name Ar string +Specify a vendor name that are used by L2TP. +Default value is "" (empty string). +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-hello-interval Ar number +Specify the interval time between L2TP hello request in seconds. +The default value is `60'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-hello-timeout Ar number +Specify the maximim time that +.Nm +waits L2TP hello response in seconds. +The default value is `30'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-accept-dialin Ar yes | no +If `yes' is specified, +.Xr npppd 8 +accepts Proxy-LCP and Proxy-Authentication AVPs from LAC +that is to do `compulsory tunneling mode'. +The default is `no'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-lcp-renegotiation Ar yes | no +If `yes' is specified, +.Xr npppd 8 +will basically use the LCP that is received by Proxied-LCP AVPs, +but when if the LCP is not acceptable +.Xr npppd 8 +will negotiate LCP again. +The default is `yes'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-force-lcp-renegotiation Ar yes | no +If `yes' is specified, +.Xr npppd 8 +will not use the LCP that is received by Proxied-LCP AVPs, +it will negotiate LCP again. +The default is `no'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-data-use-seq Ar yes | no +Specify `yes' to use sequencling for L2TP Data comunication. +The default is `yes'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic l2tp-require-ipsec Ar yes | no +Specify `yes' to refuse L2TP connections without IPsec encapsulation. +The default is `no'. +This option can be specified if the tunnel protocol is L2TP. +.It Ic pptp-hostname Ar string +Specify a hostname that are used by PPTP. +Default value is the value that is returned by +.Xr gethostname 2 . +This option can be specified if the tunnel protocol is PPTP. +.It Ic pptp-vendor-name Ar string +Specify a vendor name that are used by PPTP. +Default value is "" (empty string). +This option can be specified if the tunnel protocol is PPTP. +.It Ic pptp-echo-interval Ar number +Specify the interval time between PPTP echo request in seconds. +The default value is `60'. +This option can be specified if the tunnel protocol is PPTP. +.It Ic pptp-echo-timeout Ar number +Specify the maximim time that +.Nm +waits PPTP echo reply in seconds. +The default value is `60'. +This option can be specified if the tunnel protocol is PPTP. +.It Ic pppoe-service-name Ar string +Specify a service name. The default is "" (empty string). +This option can be specified if the tunnel protocol is PPPoE. +.It Ic pppoe-accept-any-service Ar yes | no +If `yes' is specified +.Xr npppd 8 +accepts request from the clients that are accepting any service names +Default value is `yes'. +This option can be specified if the tunnel protocol is PPPoE. +.It Ic pppoe-ac-name Ar string +Specify the access concentrator(ac) name. +The default value is created by the MAC Address +of the listening interface. +This option can be specified if the tunnel protocol is PPPoE. +.It Ic mru Ar number +Specified the MRU(Maximum Receive Unit) value. +This value is used for LCP negotiation with the tunnel peer. +The default value is `1360' for L2TP, `1400' for pptp and '1492' for PPPoE. +.It Ic lcp-keepalive Ar yes | no +Specify whether +.Xr npppd 8 +uses LCP keep alive. +The default value `no' for L2TP, `yes' for PPTP and PPPoE. +.It Ic lcp-keepalive-interval Ar number +Specify the interval time between LCP echo request in seconds. +The default value is `300'. +.It Ic lcp-keepalive-retry-interval Ar number +Specify the interval time between retrying LCP echo request +without receiving the echo reply from the peer. +The value must be specified in seconds. +The default value is `60'. +.It Ic lcp-keepalive-max-retries Ar number +Specify the maximum number of retrying LCP echo. +If the peer doesn't respond and the number of retry reaches this value, +.Xr npppd 8 +treats the link is dead and it closes the link. +The default value is `3'. +.It Ic lcp-timeout Ar number +Specify the timeout value for LCP retransmission in seconds. +Default value is `3'. +.It Ic lcp-max-configure Ar number +Specify the maximum number of LCP configure reqeuest transmission. +Default value is `10'. +.It Ic lcp-max-terminate Ar number +Specify the maximum number of LCP terminate reqeuest transmission. +Default value is `2'. +.It Ic lcp-max-nak-loop Ar number +Specify the maximum number of LCP configure NAK loops. +Default value is `5'. +.It Ic authentication-method Ar authentication-method ... +Specify authentication methods. +.Pp +Following authentication methods can be used: +.Bl -tag -width mschapv2 -compact -indent +.It Ic pap +Password Authentication Protocol +.It Ic chap +PPP Challenge Handshake Authentication Protocol (RFC 1994) +.It Ic mschapv2 +Microsoft PPP CHAP Extensions, Version 2 (RFC 2749) +.El +.Pp +`mschapv2' is used as the default for PPTP, +`pap chap mschapv2' will be used as the default for other protocols. +.It Ic ccp-timeout Ar number +Specify the timeout value for CCP retransmission in seconds. +Default value is `3'. +.It Ic ccp-max-configure Ar number +Specify the maximum number of CCP configure reqeuest transmission. +Default value is `10'. +.It Ic ccp-max-terminate Ar number +Specify the maximum number of CCP terminate reqeuest transmission. +Default value is `2'. +.It Ic ccp-max-nak-loop Ar number +Specify the maximum number of CCP configure NAK loops. +Default value is `5'. +.It Ic ipcp-timeout Ar number +Specify the timeout value for IPCP retransmission in seconds. +Default value is `3'. +.It Ic ipcp-max-configure Ar number +Specify the maximum number of IPCP configure reqeuest transmission. +Default value is `10'. +.It Ic ipcp-max-terminate Ar number +Specify the maximum number of IPCP terminate reqeuest transmission. +Default value is `2'. +.It Ic ipcp-max-nak-loop Ar number +Specify the maximum number of IPCP configure NAK loops. +Default value is `5'. +.It Ic mppe-key-length Ar key-length ... +Specify key lengths that this configuration use. +.Pp +Following key lengths can be used: +.Bl -tag -width 128 -compact -indent +.It Ic 128 +128 bits encryption +.It Ic 56 +56 bits encryption +.It Ic 40 +40 bits encryption +.El +.It Ic mppe-key-state Ar mode ... +Specify the key change modes that this configuration supports to. +.Pp +Following modes can be used: +.Bl -tag -width stateless -compact -indent +.It Ic stateful +Stateful mode key changes +.It Ic stateless +Stateless mode key changes +.El +.It Ic idle-timeout Ar number +Specify the timeout value for the idle timer in seconds. +The idle timer disconnects the link if the link keeps idle for the time +specified by this value. +The link is treated as `idle' if the no data packet are sent or received. +0 means disable the idle timer. +Default value is `0'. +.It Ic tcp-mss-adjust Ar yes | no +If `yes' is specified, +.Xr npppd 8 +adjusts TCP SYN packets so that the value of TCP MSS (maximum segment +size) option is less than the value calculated from the link MTU. +The default value is `no'. +.It Ic ingress-filter Ar yes | no +If `yes' is specified, +.Xr npppd 8 +applies ingress filter for incoming packets. +The ingress filter drops all packets that source address does not match to +the address assigned by +.Xr npppd 8 +for the link. Default value is `no'. +.It Ic pipex Ar yes | no +Specify whether +.Xr npppd 8 +uses +.Xr pipex 4 . +Default is `yes'. +.It Ic debug-dump-pktin Ar protocol ... +If this option is specified, +.Xr npppd 8 +dumps received packets which match the specified protocol. +Following protocols can be specified: +.Bl -tag -width mppe -compact -indent +.It Ic ip +Internet Protocol (IP) +.It Ic lcp +Link Configuration Protocol (LCP) +.It Ic pap +Password Authentication Protocol (PAP) +.It Ic chap +Challenge Handshake Authentication Protocol (CHAP) +.\" .It Ic eap +.\" Extended Authentication Protocol (EAP) +.It Ic mppe +Microsoft Point-to-Point Encryption (MPPE) +.It Ic ccp +Compression Control Protocol (CCP) +.It Ic ipcp +IP Configuration Protocol (IPCP) +.El +.It Ic debug-dump-pktout Ar protocol ... +If this option is specified, +.Xr npppd 8 +dumps sending packets which match the specified protocol. +See +.Ic debug-dump-pktin +section for +.Ar protocol . +.It Ic l2tp-ctrl-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received L2TP control packets for debug. +Default is `no'. +.It Ic l2tp-ctrl-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending L2TP control packets for debug. +Default is `no'. +.It Ic l2tp-data-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received L2TP data packets for debug. +Default is `no'. +.It Ic l2tp-data-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending L2TP data packets for debug. +Default is `no'. +.It Ic pptp-ctrl-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received PPTP control packets for debug. +Default is `no'. +.It Ic pptp-ctrl-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending PPTP control packets for debug. +Default is `no'. +.It Ic pptp-data-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received PPTP data packets for debug. +Default is `no'. +.It Ic pptp-data-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending PPTP data packets for debug. +Default is `no'. +.It Ic pppoe-desc-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received PPPoE discovery packets for debug. +Default is `no'. +.It Ic pppoe-desc-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending PPPoE discovery packets for debug. +Default is `no'. +.It Ic pppoe-session-in-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps received PPPoE session packets for debug. +Default is `no'. +.It Ic pppoe-session-out-pktdump Ar yes | no +Specify whether +.Xr npppd 8 +dumps sending PPPoE session packets for debug. +Default is `no'. +.El +.Sh IPCP +The +.Ic icpp +setting are described below: +.Bd +.Ic ipcp Ar name { Ar option ... Ic } +.Ed +.Pp +Specify name of this +.Ic ipcp +setting. +The maximum number of +.Ic ipcp +settings is 8. +.Pp +Supported options are following: +.Bl -tag -width Ds +.It Ic pool-address Ar address-range | address-mask Op Ic for Ar dynamic | static +Specify the IP address space that is pooled for this IPCP setting. +The address space can be specified by +.Ar address-range +(eg. 192.168.0.2-192.168.0.254) +or +.Ar address-mask +(eg. 192.168.0.0/24) . +.Ic for +.Ar dynamic +means the address space is reserved for dynamic allocation, +.Ar static +means the address space is reserved for static allocation. Default is +.Ar dynamic . +This option can be used in multiple times. +.It Ic dns-servers Ar primary-server-address Op secondary-server-address +Specify the DNS servers' IP address. +.It Ic nbns-servers Ar primary-server-address Op secondary-server-address +Specify the NetBIOS name servers' IP address. +.It Ic allow-user-selected-address Ar yes | no +Specify whether +.Xr npppd 8 +is allowed to assign prior the address that is selected by the user. +Default is `yes'. +.El +.Sh INTERFACE +.Pp +The +.Ic interface +setting is described below: +.Bd +.Ic interface Ar ifname Ic address Ar address Ic ipcp Ar ipcp +.Ed +.Pp +Use +.Xr tun 4 +or +.Xr pppx 4 +and +specify its name to +.Ar ifname . +.Ar address +is the IP address of this interface, and it is noticed as the tunnel address +to the tunnel peer. +Specify the +.Ic ipcp +setting name that are used with this interface. +The maximum number of +.Ic interface +settings is 8. +.Sh AUTHENTICATION +.Pp +The +.Ic authentication +setting are described below: +.Bd +.Ic authentication Ar name Ic type Ar type { Ar option ... Ic } +.Ed +.Pp +Specify +.Ar name +for this authentication setting. +For +.Ar type , +one of the following can be specified: +.Pp +.Bl -offset indent -compact -tag -width radius -indent +.It Ic local +authenticates by the local file. +.It Ic radius +authenticates by the remote RADIUS servers. +.El +.Pp +Supported options are following: +.Bl -tag -width Ds +.It Ic username-suffix Ar string +Specify the suffix of the username +so that +.Xr npppd 8 +selects this authentication setting only for a user who has the username +that matches this suffix pattern. +.It Ic username-prefix Ar string +Specify the prefix of the username +so that +.Xr npppd 8 +selects this authentication setting only for a user who has the username +that matches this prefix pattern. +.\" .It Ic eap-capable Ar yes | no +.\" Specify whether this authentcation server is able to use EAP. +.\" Default is `yes'. +.It Ic strip-nt-domain Ar yes | no +Specify whether +.Xr npppd 8 +remove the NT domain prefix like '\\\\NTDOMAIN\\' from the username +before requesting the authentication server. +Default is `no'. +.It Ic strip-atmark-realm Ar yes | no +Specify whether +.Xr npppd 8 +remove the realm part that begins '@' (atmark) +from the username before requesting the authentication server. +Default is `no'. +.It Ic users-file Ar string +Specify the path for +.Xr npppd-users 7 +that describes users' account information. +The path must be under `/etc/npppd/', because +.Xr npppd 8 +is restricted to access the files only in limited directories. +.It Ic authentication-server { Ar radius-config Ic } +This option describes the settings for RADIUS authentication server. +This option can be used in RADIUS type only. +.Bl -tag -width max-failovers -compact -indent +.It Ic address Ar address Oo Ic port Ar port Oc Op Ic secret Ar secret +Specify the IP address and port of RADIUS server to +.Ar address +and +.Ar port , +and +the shared secret to +.Ar secret . +.Ar secret +must be less than 127 chars. +Default port is 1812 for +.Ic authentication-server, +1813 for +.Ic accouting-server . +This option can be specified multiple times (max 16 times) in a +.Ar radius-config . +.It Ic timeout Ar number +Specify the maximum time for waiting the response in seconds. +Default is `9'. +.It Ic max-tries Ar number +Specify the maximum number of retransmission. +Default is `3'. +.It Ic max-failovers Ar number +Specify the maximum number of failovers. +Default is `1'. +.El +.It Ic accounting-server { Ar radius-config Ic } +This option describes the settings for RADIUS accounting server. +See +.Ic authentication-server +section for +.Ar radius-config +This option can be used in RADIUS type only. +.El +.Sh BIND +.Pp +.Ic bind +describes a set of the +.Ar tunnel +setting, +.Ar authentication +setting and +.Ar interface +setting so that they are used together. +.Bd +.Ic bind Ic tunnel from Ar tunnel Ic authenticated by Ar authentication +.Ic to Ar ifname +.Ed +.\" The following requests should be uncommented and used where appropriate. +.\" .Sh RETURN VALUES +.\" For sections 2, 3, and 9 function return values only. +.\" .Sh ENVIRONMENT +.\" For sections 1, 6, 7 & 8 only. +.\" .Sh FILES +.\" .Sh EXIT STATUS +.\" For sections 1, 6, & 8 only. +.Sh EXAMPLES +.Pp +Very simple configuration example is below: +.Bd -literal -offset indent +tunnel L2TP protocol l2tp +tunnel PPTP protocol pptp +ipcp IPCP { + pool-address 10.0.0.2-10.0.0.254 + dns-servers 8.8.8.8 +} +interface pppx0 address 10.0.0.1 ipcp IPCP +authentication LOCAL type local { + users-file "/etc/npppd/npppd-users" +} +bind tunnel from L2TP authenticated by LOCAL to pppx0 +bind tunnel from PPTP authenticated by LOCAL to pppx0 +.Ed +.Pp +Simple configuration but has two authentication realms: +.Bd -literal -offset indent +tunnel L2TP protocol l2tp { + listen on 203.0.113.100 +} +ipcp IPCP { + pool-address 10.0.0.2-10.0.0.254 + dns-servers 8.8.8.8 +} +interface tun0 address 10.0.0.1 ipcp IPCP +interface tun1 address 10.0.0.1 ipcp IPCP +authentication RADIUS type radius { + username-suffix "@example.com" + authentication-server { + address 192.168.0.1 secret "hogehoge" + } + accounting-server { + address 192.168.0.1 secret "hogehoge" + } +} +authentication LOCAL type local { + username-suffix "@local" + users-file "/etc/npppd/npppd-users" +} +bind tunnel from L2TP authenticated by RADIUS to tun0 +bind tunnel from L2TP authenticated by LOCAL to tun1 +.Ed +.\" .Sh DIAGNOSTICS +.\" For sections 1, 4, 6, 7, and 8 only. +.\" .Sh ERRORS +.\" For sections 2, 3, and 9 error and signal handling only. +.Sh SEE ALSO +.Xr npppctl 8 , +.Xr npppd 8 , +.Xr pipex 4 , +.Xr tun 4 , +.Xr pppx 4 +.\" .Sh STANDARDS +.\" .Sh HISTORY +.\" .Sh AUTHORS +.\" .Sh CAVEATS +.Sh BUGS +Current version of +.Xr npppd 8 +does not support adding or removing tunnel settings or changing its listener +settings(listen address, port and l2tp-ipsec-require). diff --git a/usr.sbin/npppd/npppd/npppd.h b/usr.sbin/npppd/npppd/npppd.h index 4e1fb84838c..7db48afd1c1 100644 --- a/usr.sbin/npppd/npppd/npppd.h +++ b/usr.sbin/npppd/npppd/npppd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd.h,v 1.9 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: npppd.h,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -28,28 +28,179 @@ #ifndef NPPPD_H #define NPPPD_H 1 + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <stdbool.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <event.h> + +#include "slist.h" +#include "addr_range.h" + +#include "l2tp_conf.h" +#include "pptp_conf.h" +#include "pppoe_conf.h" + #define NPPPD_USER "_ppp" +#define NPPPD_GENERIC_NAME_LEN 32 -#ifndef NPPPD_DEFAULT_TUN_IFNAME -#define NPPPD_DEFAULT_TUN_IFNAME "tun0" -#endif +/** Constants of tunnel type */ +#define NPPPD_TUNNEL_NONE 0 /** None Tunnel Type */ +#define NPPPD_TUNNEL_L2TP 1 /** L2TP Tunnel Type */ +#define NPPPD_TUNNEL_PPTP 2 /** PPTP Tunnel Type */ +#define NPPPD_TUNNEL_PPPOE 3 /** PPPoE Tunnel Type */ +#define NPPPD_TUNNEL_SSTP 4 /** SSTP Tunnel Type */ + +#define NPPPD_AUTH_METHODS_PAP 0x0001 +#define NPPPD_AUTH_METHODS_CHAP 0x0002 +#define NPPPD_AUTH_METHODS_MSCHAPV2 0x0004 + +#define NPPPD_MPPE_DISABLED 0x0000 +#define NPPPD_MPPE_ENABLED 0x0001 +#define NPPPD_MPPE_REQUIRED 0x0002 + +#define NPPPD_MPPE_40BIT 0x0001 +#define NPPPD_MPPE_56BIT 0x0002 +#define NPPPD_MPPE_128BIT 0x0004 + +#define NPPPD_MPPE_STATEFUL 0x0001 +#define NPPPD_MPPE_STATELESS 0x0002 + +#define NPPPD_PROTO_BIT_IP 0x0001 +#define NPPPD_PROTO_BIT_LCP 0x0002 +#define NPPPD_PROTO_BIT_PAP 0x0004 +#define NPPPD_PROTO_BIT_CHAP 0x0008 +#define NPPPD_PROTO_BIT_EAP 0x0010 +#define NPPPD_PROTO_BIT_MPPE 0x0020 +#define NPPPD_PROTO_BIT_CCP 0x0040 +#define NPPPD_PROTO_BIT_IPCP 0x0080 + +#define NPPPD_CALLNUM_CHECK_NONE 0 +#define NPPPD_CALLNUM_CHECK_STRICT 1 +#define NPPPD_CALLNUM_CHECK_LOOSE 2 + +struct tunnconf { + TAILQ_ENTRY(tunnconf) entry; + const char *name; + int protocol; + + union { + struct l2tp_conf l2tp; + struct pptp_conf pptp; + struct pppoe_conf pppoe; + } proto; + + int lcp_timeout; + int lcp_max_configure; + int lcp_max_terminate; + int lcp_max_nak_loop; + int mru; + bool lcp_keepalive; + int lcp_keepalive_interval; + int lcp_keepalive_retry_interval; + int lcp_keepalive_max_retries; + + u_int auth_methods; + + int ipcp_timeout; + int ipcp_max_configure; + int ipcp_max_terminate; + int ipcp_max_nak_loop; + int ccp_timeout; + int ccp_max_configure; + int ccp_max_terminate; + int ccp_max_nak_loop; + char *chap_name; + + bool mppe_yesno; + bool mppe_required; + u_int mppe_keylen; + u_int mppe_keystate; + + int idle_timeout; + bool tcp_mss_adjust; + bool ingress_filter; + int callnum_check; + bool pipex; -#define DEFAULT_RADIUS_AUTH_PORT 1812 -#define DEFAULT_RADIUS_ACCT_PORT 1813 -#define DEFAULT_RADIUS_TIMEOUT 9 -#define DEFAULT_RADIUS_MAX_TRIES 3 -#define DEFAULT_RADIUS_MAX_FAILOVERS 1 -#define DEFAULT_AUTH_TIMEOUT 30 + u_int debug_dump_pktin; + u_int debug_dump_pktout; +}; + +struct radserver { + TAILQ_ENTRY(radserver) entry; + struct sockaddr_storage address; + char *secret; +}; + +struct radconf { + TAILQ_HEAD(radservers, radserver) servers; + int timeout; + int max_tries; + int max_failovers; +}; + +struct authconf { + TAILQ_ENTRY(authconf) entry; + char name[NPPPD_GENERIC_NAME_LEN]; + int auth_type; + char *username_suffix; + char *username_prefix; + bool eap_capable; + bool strip_nt_domain; + bool strip_atmark_realm; + char users_file_path[MAXPATHLEN]; + union { + struct { + struct radconf auth; + struct radconf acct; + } radius; + }; +}; + +struct ipcpconf { + TAILQ_ENTRY(ipcpconf) entry; + char name[NPPPD_GENERIC_NAME_LEN]; + bool dns_use_resolver; + struct in_addr dns_servers[2]; + struct in_addr nbns_servers[2]; + bool allow_user_select; + struct in_addr_range *dynamic_pool; + struct in_addr_range *static_pool; +}; -/** assign fixed IP address */ -#define NPPPD_IP_ASSIGN_FIXED 0x0001 +struct iface { + TAILQ_ENTRY(iface) entry; + char name[IFNAMSIZ]; + struct in_addr ip4addr; + struct ipcpconf *ipcpconf; + bool is_pppx; +}; -/** accept IP address which is proposed by peer and assign it */ -#define NPPPD_IP_ASSIGN_USER_SELECT 0x0002 +struct confbind { + TAILQ_ENTRY(confbind) entry; + struct tunnconf *tunnconf; + struct authconf *authconf; + struct iface *iface; +}; -/** use RADIUS Framed-IP-Address */ -#define NPPPD_IP_ASSIGN_RADIUS 0x0004 +struct npppd_conf { + int max_session; + int user_max_session; + TAILQ_HEAD(tunnconfs, tunnconf) tunnconfs; + TAILQ_HEAD(authconfs, authconf) authconfs; + TAILQ_HEAD(ipcpconfs, ipcpconf) ipcpconfs; + TAILQ_HEAD(ifaces, iface) ifaces; + TAILQ_HEAD(confbinds, confbind) confbinds; + struct l2tp_confs l2tp_confs; + struct pptp_confs pptp_confs; + struct pppoe_confs pppoe_confs; +}; /** sockaddr_npppd */ struct sockaddr_npppd { @@ -73,60 +224,66 @@ typedef struct _npppd npppd; #include "ppp.h" -#ifdef __cplusplus -extern "C" { -#endif +#include <sys/cdefs.h> +__BEGIN_DECLS +npppd *npppd_get_npppd (void); +int npppd_init (npppd *, const char *); +void npppd_start (npppd *); +void npppd_stop (npppd *); +void npppd_fini (npppd *); +int npppd_reset_routing_table (npppd *, int); +int npppd_get_user_password (npppd *, npppd_ppp *, const char *, char *, int *); +struct in_addr *npppd_get_user_framed_ip_address (npppd *, npppd_ppp *, const char *); +int npppd_check_calling_number (npppd *, npppd_ppp *); +npppd_ppp *npppd_get_ppp_by_ip (npppd *, struct in_addr); +slist *npppd_get_ppp_by_user (npppd *, const char *); +npppd_ppp *npppd_get_ppp_by_id (npppd *, u_int); +int npppd_check_user_max_session (npppd *, npppd_ppp *); +void npppd_network_output (npppd *, npppd_ppp *, int, u_char *, int); +int npppd_ppp_pipex_enable (npppd *, npppd_ppp *); +int npppd_ppp_pipex_disable (npppd *, npppd_ppp *); +int npppd_prepare_ip (npppd *, npppd_ppp *); +void npppd_release_ip (npppd *, npppd_ppp *); +void npppd_set_ip_enabled (npppd *, npppd_ppp *, int); +int npppd_assign_ip_addr (npppd *, npppd_ppp *, uint32_t); +int npppd_set_radish (npppd *, void *); +int npppd_get_all_users (npppd *, slist *); +int npppd_ppp_bind_realm (npppd *, npppd_ppp *, const char *, int); +int npppd_ppp_is_realm_local (npppd *, npppd_ppp *); +int npppd_ppp_is_realm_radius (npppd *, npppd_ppp *); +int npppd_ppp_is_realm_ready (npppd *, npppd_ppp *); +const char *npppd_ppp_get_realm_name (npppd *, npppd_ppp *); +const char *npppd_ppp_get_iface_name (npppd *, npppd_ppp *); +int npppd_ppp_iface_is_ready (npppd *, npppd_ppp *); +int npppd_ppp_bind_iface (npppd *, npppd_ppp *); +void npppd_ppp_unbind_iface (npppd *, npppd_ppp *); +void *npppd_get_radius_auth_setting (npppd *, npppd_ppp *); +int sockaddr_npppd_match (void *, void *); +const char *npppd_ppp_get_username_for_auth (npppd *, npppd_ppp *, const char *, char *); +const char *npppd_ppp_tunnel_protocol_name (npppd *, npppd_ppp *); +const char *npppd_tunnel_protocol_name (int); +struct tunnconf *npppd_get_tunnconf (npppd *, const char *); +int npppd_reload_config (npppd *); +int npppd_modules_reload (npppd *); +int npppd_ifaces_load_config (npppd *); + +int npppd_conf_parse (struct npppd_conf *, const char *); +void npppd_conf_init (struct npppd_conf *); +void npppd_conf_fini (struct npppd_conf *); +int npppd_config_check (const char *); + +void log_init (int); +void vlog (int, const char *, __va_list); +void log_warn (const char *, ...); +void log_warnx (const char *, ...); +void log_info (const char *, ...); +void log_debug (const char *, ...); +void fatal (const char *); +void fatalx (const char *); +const char *log_sockaddr (struct sockaddr *); + + +__END_DECLS -npppd *npppd_get_npppd (void); -int npppd_init (npppd *, const char *); -void npppd_stop (npppd *); -void npppd_fini (npppd *); -int npppd_prepare_ip (npppd *, npppd_ppp *); -void npppd_release_ip (npppd *, npppd_ppp *); -int nppp_load_user_setting(npppd *, npppd_ppp *); -void npppd_set_ip_enabled (npppd *, npppd_ppp *, int); -int npppd_get_user_password (npppd *, npppd_ppp *, const char *, char *, int *); -struct in_addr *npppd_get_user_framed_ip_address(npppd *, npppd_ppp *, const char *); -int npppd_check_calling_number (npppd *, npppd_ppp *); -void npppd_network_output (npppd *, npppd_ppp *, int, u_char *, int); -void npppd_network_input (npppd *, uint8_t *, int); -npppd_ppp *npppd_get_ppp_by_ip (npppd *, struct in_addr); -slist *npppd_get_ppp_by_user (npppd *, const char *); -int npppd_check_user_max_session(npppd *, npppd_ppp *); -int npppd_get_all_users (npppd *, slist *); -int npppd_set_radish (npppd *, void *); -int npppd_ppp_iface_is_ready(npppd *, npppd_ppp *); -int sockaddr_npppd_match(void *, void *); -npppd_ppp *npppd_get_ppp_by_id(npppd *, u_int); - -const char *npppd_config_str (npppd *, const char *); -int npppd_config_int (npppd *, const char *, int); -int npppd_config_str_equal (npppd *, const char *, const char *, int); -int npppd_config_str_equali (npppd *, const char *, const char *, int); -int npppd_modules_reload (npppd *); -int npppd_ifaces_load_config(npppd *); -int npppd_reload_config (npppd *); -int npppd_assign_ip_addr (npppd *, npppd_ppp *, uint32_t); -void npppd_release_ip_addr (npppd *, npppd_ppp *); - -int npppd_ppp_bind_realm(npppd *, npppd_ppp *, const char *, int); -int npppd_ppp_is_realm_local(npppd *, npppd_ppp *); -int npppd_ppp_is_realm_radius(npppd *, npppd_ppp *); -int npppd_ppp_is_realm_ready(npppd *, npppd_ppp *); -const char *npppd_ppp_get_realm_name(npppd *, npppd_ppp *); -int npppd_ppp_bind_iface(npppd *, npppd_ppp *); -void npppd_ppp_unbind_iface(npppd *, npppd_ppp *); -const char *npppd_ppp_get_iface_name(npppd *, npppd_ppp *); -void * npppd_get_radius_auth_setting(npppd *, npppd_ppp *); -const char *npppd_ppp_tunnel_protocol_name(npppd *, npppd_ppp *); - -void npppd_radius_auth_server_failure_notify(npppd *, npppd_ppp *, void *, const char *); -int npppd_ppp_pipex_enable(npppd *, npppd_ppp *); -int npppd_ppp_pipex_disable(npppd *, npppd_ppp *); -const char *npppd_ppp_get_username_for_auth(npppd *, npppd_ppp *, const char *, char *); -int npppd_reset_routing_table(npppd *, int); -#ifdef __cplusplus -} -#endif #endif diff --git a/usr.sbin/npppd/npppd/npppd_auth.c b/usr.sbin/npppd/npppd/npppd_auth.c index c06f3a7d3a1..b6d838c2de7 100644 --- a/usr.sbin/npppd/npppd/npppd_auth.c +++ b/usr.sbin/npppd/npppd/npppd_auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_auth.c,v 1.9 2012/06/05 06:31:27 yasuoka Exp $ */ +/* $OpenBSD: npppd_auth.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,8 +26,7 @@ * SUCH DAMAGE. */ /**@file authentication realm */ -/* $Id: npppd_auth.c,v 1.9 2012/06/05 06:31:27 yasuoka Exp $ */ -/* I hope to write the source code in npppd-independent as possible. */ +/* $Id: npppd_auth.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> @@ -45,24 +44,20 @@ #include <errno.h> #include "debugutil.h" -#include "hash.h" #include "slist.h" #include "npppd_local.h" #include "npppd_auth.h" -#include "config_helper.h" #include "net_utils.h" -#include "csvreader.h" #include "npppd_auth_local.h" -static const char *npppd_auth_default_label(npppd_auth_base *); /** * Create a npppd_auth_base object. * @param auth_type the authentication type. * specify {@link ::NPPPD_AUTH_TYPE_LOCAL} to authenticate by the local * file, or specify {@link ::NPPPD_AUTH_TYPE_RADIUS} for RADIUS * authentication. - * @param label the configuration label + * @param name the configuration name * @param _npppd the parent {@link ::npppd} object * @see ::NPPPD_AUTH_TYPE_LOCAL * @see ::NPPPD_AUTH_TYPE_RADIUS @@ -70,21 +65,20 @@ static const char *npppd_auth_default_label(npppd_auth_base *); * in case success otherwise NULL will be returned. */ npppd_auth_base * -npppd_auth_create(int auth_type, const char *label, void *_npppd) +npppd_auth_create(int auth_type, const char *name, void *_npppd) { npppd_auth_base *base; - NPPPD_AUTH_ASSERT(label != NULL); + NPPPD_AUTH_ASSERT(name != NULL); switch (auth_type) { case NPPPD_AUTH_TYPE_LOCAL: if ((base = malloc(sizeof(npppd_auth_local))) != NULL) { memset(base, 0, sizeof(npppd_auth_local)); base->type = NPPPD_AUTH_TYPE_LOCAL; - base->users_hash = NULL; base->strip_nt_domain = 1; base->strip_atmark_realm = 0; - strlcpy(base->label, label, sizeof(base->label)); + strlcpy(base->name, name, sizeof(base->name)); base->npppd = _npppd; return base; @@ -98,7 +92,7 @@ npppd_auth_create(int auth_type, const char *label, void *_npppd) memset(base, 0, sizeof(npppd_auth_radius)); base->type = NPPPD_AUTH_TYPE_RADIUS; base->strip_nt_domain = 0; - strlcpy(base->label, label, sizeof(base->label)); + strlcpy(base->name, name, sizeof(base->name)); base->npppd = _npppd; if ((_this->rad_auth_setting = radius_req_setting_create()) == NULL) @@ -144,9 +138,6 @@ npppd_auth_dispose(npppd_auth_base *base) base->disposing = 1; - if (base->users_hash != NULL) - hash_delete_all(base->users_hash, 1); - return; } @@ -158,11 +149,6 @@ npppd_auth_destroy(npppd_auth_base *base) if (base->disposing == 0) npppd_auth_dispose(base); - if (base->users_hash != NULL) { - hash_free(base->users_hash); - base->users_hash = NULL; - } - npppd_auth_base_log(base, LOG_INFO, "Finalized"); switch(base->type) { @@ -194,56 +180,40 @@ npppd_auth_destroy(npppd_auth_base *base) int npppd_auth_reload(npppd_auth_base *base) { - const char *val; - - val = npppd_auth_config_str(base, "name"); - if (val == NULL) - /* use the label if .name is not defined. */ - strlcpy(base->name, npppd_auth_default_label(base), - sizeof(base->name)); - else - strlcpy(base->name, val, sizeof(base->name)); - - if ((val = npppd_auth_config_str(base, "pppsuffix")) != NULL) - strlcpy(base->pppsuffix, val, sizeof(base->pppsuffix)); - else - base->pppsuffix[0] = '\0'; - - if ((val = npppd_auth_config_str(base, "pppprefix")) != NULL) - strlcpy(base->pppprefix, val, sizeof(base->pppprefix)); - else - base->pppprefix[0] = '\0'; - - base->eap_capable = - npppd_auth_config_str_equal(base, "eap_capable", "true", 1); - base->strip_nt_domain = - npppd_auth_config_str_equal(base, "strip_nt_domain", "true", 1); - base->strip_atmark_realm = - npppd_auth_config_str_equal(base, "strip_atmark_realm", "true", 0); - - base->has_acctlist = 0; - base->acctlist_ready = 0; + struct authconf *auth; + + TAILQ_FOREACH(auth, &base->npppd->conf.authconfs, entry) { + if (strcmp(auth->name, base->name) == 0) + break; + } + if (auth == NULL) + return 1; + + base->pppprefix[0] = '\0'; + base->pppsuffix[0] = '\0'; + if (auth != NULL) { + if (auth->username_suffix != NULL) + strlcpy(base->pppsuffix, auth->username_suffix, + sizeof(base->pppsuffix)); + if (auth->username_prefix != NULL) + strlcpy(base->pppprefix, auth->username_prefix, + sizeof(base->pppprefix)); + base->eap_capable = auth->eap_capable; + base->strip_nt_domain = auth->strip_nt_domain; + base->strip_atmark_realm = auth->strip_atmark_realm; + } + + base->has_users_file = 0; base->radius_ready = 0; - if ((val = npppd_auth_config_str(base, "acctlist")) != NULL) { - strlcpy(base->acctlist_path, val, sizeof(base->acctlist_path)); - if (base->users_hash == NULL) { - if ((base->users_hash = hash_create( - (int (*)(const void *, const void *))strcmp, - str_hash, 1021)) == NULL) { - npppd_auth_base_log(base, - LOG_WARNING, "hash_create() failed: %m."); - goto fail; - } - } - base->reloadable = NPPPD_DEFAULT_AUTH_LOCAL_RELOADABLE; - base->has_acctlist = 1; - if (npppd_auth_reload_acctlist(base) != 0) - goto fail; + if (auth->users_file_path != NULL) { + strlcpy(base->users_file_path, auth->users_file_path, + sizeof(base->users_file_path)); + base->has_users_file = 1; } else { if (base->type == NPPPD_AUTH_TYPE_LOCAL) { npppd_auth_base_log(base, - LOG_WARNING, "missing acctlist property."); + LOG_WARNING, "missing users_file property."); goto fail; } } @@ -251,7 +221,7 @@ npppd_auth_reload(npppd_auth_base *base) switch (base->type) { #ifdef USE_NPPPD_RADIUS case NPPPD_AUTH_TYPE_RADIUS: - if (npppd_auth_radius_reload(base) != 0) + if (npppd_auth_radius_reload(base, auth) != 0) goto fail; break; #endif @@ -262,8 +232,7 @@ npppd_auth_reload(npppd_auth_base *base) fail: base->initialized = 0; - base->has_acctlist = 0; - base->acctlist_ready = 0; + base->has_users_file = 0; base->radius_ready = 0; return 1; @@ -287,35 +256,47 @@ int npppd_auth_get_user_password(npppd_auth_base *base, const char *username, char *password, int *plpassword) { - int sz, lpassword; + int retval, sz, lpassword; npppd_auth_user *user; NPPPD_AUTH_ASSERT(base != NULL); NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username)); - if (base->has_acctlist == 0 || base->acctlist_ready == 0) - return -1; - - if (base->reloadable != 0) - npppd_auth_reload_acctlist(base); - - if ((user = npppd_auth_find_user(base, username)) == NULL) - return 1; - - if (password == NULL && plpassword == NULL) - return 0; - if (plpassword == NULL) - return -1; + user = NULL; + retval = 0; + if (base->has_users_file == 0) { + retval = -1; + goto out; + } + if ((user = npppd_auth_get_user(base, username)) == NULL) { + retval = 1; + goto out; + } + if (password == NULL && plpassword == NULL) { + retval = 0; + goto out; + } + if (plpassword == NULL) { + retval = -1; + goto out; + } lpassword = strlen(user->password) + 1; sz = *plpassword; *plpassword = lpassword; - if (password == NULL) - return 0; - if (sz < lpassword) - return 2; - + if (password == NULL) { + retval = 0; + goto out; + } + if (sz < lpassword) { + retval = 2; + goto out; + } strlcpy(password, user->password, sz); - return 0; +out: + if (user != NULL) + free(user); + + return retval; } /** @@ -340,10 +321,10 @@ npppd_auth_get_framed_ip(npppd_auth_base *base, const char *username, NPPPD_AUTH_ASSERT(base != NULL); NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username)); - if (base->has_acctlist == 0 || base->acctlist_ready == 0) + if (base->has_users_file == 0) return -1; - if ((user = npppd_auth_find_user(base, username)) == NULL) + if ((user = npppd_auth_get_user(base, username)) == NULL) return 1; if (user->framed_ip_address.s_addr != 0) { @@ -351,8 +332,10 @@ npppd_auth_get_framed_ip(npppd_auth_base *base, const char *username, if (ip4netmask != NULL) *ip4netmask = user->framed_ip_netmask; + free(user); return 0; } + free(user); return 1; } @@ -374,27 +357,39 @@ int npppd_auth_get_calling_number(npppd_auth_base *base, const char *username, char *number, int *plnumber) { - int lcallnum, sz; + int retval, lcallnum, sz; npppd_auth_user *user; - if (base->has_acctlist == 0 || base->acctlist_ready == 0) + user = NULL; + retval = 0; + if (base->has_users_file == 0) return -1; - if ((user = npppd_auth_find_user(base, username)) == NULL) + if ((user = npppd_auth_get_user(base, username)) == NULL) return 1; - if (number == NULL && plnumber == NULL) - return 0; - if (plnumber == NULL) - return -1; + if (number == NULL && plnumber == NULL) { + retval = 0; + goto out; + } + if (plnumber == NULL) { + retval = -1; + goto out; + } lcallnum = strlen(user->calling_number) + 1; sz = *plnumber; *plnumber = lcallnum; - if (sz < lcallnum) - return 2; + if (sz < lcallnum) { + retval = 2; + goto out; + } strlcpy(number, user->calling_number, sz); - return 0; +out: + if (user != NULL) + free(user); + + return retval; } int @@ -417,11 +412,11 @@ npppd_auth_is_ready(npppd_auth_base *base) switch(base->type) { case NPPPD_AUTH_TYPE_LOCAL: - return (base->acctlist_ready != 0)? 1 : 0; + return (base->has_users_file)? 1 : 0; /* NOTREACHED */ case NPPPD_AUTH_TYPE_RADIUS: - return (base->acctlist_ready != 0 || + return (base->has_users_file != 0 || base->radius_ready != 0)? 1 : 0; /* NOTREACHED */ } @@ -443,12 +438,6 @@ npppd_auth_is_eap_capable(npppd_auth_base *base) } const char * -npppd_auth_get_label(npppd_auth_base *base) -{ - return base->label; -} - -const char * npppd_auth_get_name(npppd_auth_base *base) { return base->name; @@ -495,209 +484,13 @@ npppd_auth_username_for_auth(npppd_auth_base *base, const char *username, /*********************************************************************** * Account list related functions ***********************************************************************/ -/** Reload the account list */ -static int -npppd_auth_reload_acctlist(npppd_auth_base *base) -{ - CSVREADER_STATUS status; - int linno, ncols, usersz, nuser, eof, off; - const char **cols, *passwd, *callnum; - char line[8192]; - csvreader *csv; - npppd_auth_user *user; - struct in_addr ip4, ip4mask; - slist users; - FILE *file; - struct stat st; - - if (base->acctlist_ready != 0 && lstat(base->acctlist_path, &st) == 0) { - if (st.st_mtime == base->last_load) - return 0; - base->last_load = st.st_mtime; - } - - slist_init(&users); - csv = NULL; - if ((file = priv_fopen(base->acctlist_path)) == NULL) { - /* hash is empty if file is not found. */ - if (errno == ENOENT) - hash_delete_all(base->users_hash, 1); - npppd_auth_base_log(base, - (errno == ENOENT)? LOG_DEBUG : LOG_ERR, - "Open %s failed: %m", base->acctlist_path); - return 0; - } - if ((csv = csvreader_create()) == NULL) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: csvreader_create(): %m"); - goto fail; - } - - for (linno = 0, eof = 0; !eof;) { - ip4.s_addr = 0; - ip4mask.s_addr = 0xffffffffL; - if (fgets(line, sizeof(line), file) != NULL) { - int linelen; - - linelen = strlen(line); - if (linelen <= 0) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: lineno=%d " - "line too short", linno + 1); - goto fail; - } - if (line[linelen - 1] != '\n' && !feof(file)) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: lineno=%d " - "line too long", linno + 1); - goto fail; - } - - status = csvreader_parse(csv, line); - } else { - if (!feof(file)) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: %m"); - goto fail; - } - status = csvreader_parse_flush(csv); - eof = 1; - } - if (status != CSVREADER_NO_ERROR) { - if (status == CSVREADER_OUT_OF_MEMORY) - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: %m"); - else - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list " - "failed: lineno=%d parse error", linno); - goto fail; - } - ncols = csvreader_get_number_of_column(csv); - if ((cols = csvreader_get_column(csv)) == NULL) - continue; - linno++; /* count up here because line number is treated as CSV. */ - if (linno == 1) { - /* skip a title line */ - continue; - } - if (ncols < 1) { - npppd_auth_base_log(base, LOG_ERR, - "account list lineno=%d has only %d fields.", - linno, ncols); - continue; - } - if (strlen(cols[0]) <= 0) - continue; /* skip if the user-name is empty */ - if (ncols >= 3) { - if (*cols[2] != '\0' && inet_aton(cols[2], &ip4) != 1) { - npppd_auth_base_log(base, LOG_ERR, - "account list lineno=%d parse error: " - "invalid 'Framed-IP-Address' field: %s", - linno, cols[2]); - continue; - } - } - if (ncols >= 4) { - if ((*cols[3] != '\0' && - inet_aton(cols[3], &ip4mask) != 1) || - netmask2prefixlen(htonl(ip4mask.s_addr)) < 0) { - npppd_auth_base_log(base, LOG_ERR, - "account list lineno=%d parse error: " - "invalid 'Framed-IP-Netmask' field: %s", - linno, cols[3]); - continue; - } - } - - passwd = ""; - if (cols[1] != NULL) - passwd = cols[1]; - callnum = ""; - if (ncols >= 6 && cols[5] != NULL) - callnum = cols[5]; - - usersz = sizeof(npppd_auth_user); - usersz += strlen(cols[0]) + 1; - usersz += strlen(passwd) + 1; - usersz += strlen(callnum) + 1; - if ((user = malloc(usersz)) == NULL) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: %m"); - goto fail; - } - memset(user, 0, usersz); - - off = 0; - - user->username = user->space + off; - off += strlcpy(user->username, cols[0], usersz - off); - ++off; - - user->password = user->space + off; - off += strlcpy(user->password, passwd, usersz - off); - ++off; - - user->calling_number = user->space + off; - strlcpy(user->calling_number, callnum, usersz - off); - - user->framed_ip_address = ip4; - user->framed_ip_netmask = ip4mask; - - slist_add(&users, user); - } - hash_delete_all(base->users_hash, 1); - - nuser = 0; - for (slist_itr_first(&users); slist_itr_has_next(&users);) { - user = slist_itr_next(&users); - if (hash_lookup(base->users_hash, user->username) != NULL) { - npppd_auth_base_log(base, LOG_WARNING, - "Record for user='%s' is redefined, the first " - "record will be used.", user->username); - free(user); - goto next_user; - } - if (hash_insert(base->users_hash, user->username, user) != 0) { - npppd_auth_base_log(base, LOG_ERR, - "Loading a account list failed: hash_insert(): %m"); - goto fail; - } - nuser++; -next_user: - slist_itr_remove(&users); - } - slist_fini(&users); - csvreader_destroy(csv); - - fclose(file); - npppd_auth_base_log(base, LOG_INFO, - "Loaded users from='%s' successfully. %d users", - base->acctlist_path, nuser); - base->acctlist_ready = 1; - - return 0; -fail: - fclose(file); - if (csv != NULL) - csvreader_destroy(csv); - hash_delete_all(base->users_hash, 1); - for (slist_itr_first(&users); slist_itr_has_next(&users);) { - user = slist_itr_next(&users); - free(user); - } - slist_fini(&users); - - return 1; -} - static npppd_auth_user * -npppd_auth_find_user(npppd_auth_base *base, const char *username) +npppd_auth_get_user(npppd_auth_base *base, const char *username) { - int lsuffix, lusername; - const char *un; - char buf[MAX_USERNAME_LENGTH]; - hash_link *hl; + int lsuffix, lusername; + const char *un; + char buf[MAX_USERNAME_LENGTH]; + npppd_auth_user *u; un = username; lsuffix = strlen(base->pppsuffix); @@ -711,82 +504,86 @@ npppd_auth_find_user(npppd_auth_base *base, const char *username) buf[lusername - lsuffix] = '\0'; un = buf; } + + if (priv_get_user_info(base->users_file_path, un, &u) == 0) + return u; - if ((hl = hash_lookup(base->users_hash, un)) == NULL) - return NULL; - - return hl->item; + return NULL; } #ifdef USE_NPPPD_RADIUS /*********************************************************************** * RADIUS ***********************************************************************/ - -static int -radius_server_address_load(radius_req_setting *radius, int idx, - const char *address, enum RADIUS_SERVER_TYPE type) -{ - struct addrinfo *ai; - struct sockaddr_in *sin4; - - memset(&radius->server[idx], 0, sizeof(radius->server[0])); - - if (addrport_parse(address, IPPROTO_TCP, &ai) !=0) - return 1; - - switch (ai->ai_family) { - default: - freeaddrinfo(ai); - return 1; - case AF_INET: - case AF_INET6: - break; - } - - sin4 = (struct sockaddr_in *)(ai->ai_addr); - if (sin4->sin_port == 0) - sin4->sin_port = htons((type == RADIUS_SERVER_TYPE_AUTH) - ? DEFAULT_RADIUS_AUTH_PORT : DEFAULT_RADIUS_ACCT_PORT); - - memcpy(&radius->server[idx].peer, ai->ai_addr, - MIN(sizeof(radius->server[idx].peer), ai->ai_addrlen)); - - freeaddrinfo(ai); - radius->server[idx].enabled = 1; - - return 0; -} - -#define VAL_SEP " \t\r\n" /** reload the configuration of RADIUS authentication realm */ static int -npppd_auth_radius_reload(npppd_auth_base *base) +npppd_auth_radius_reload(npppd_auth_base *base, struct authconf *auth) { - npppd_auth_radius *_this = (npppd_auth_radius *)base; - int i, nauth, nacct; - - _this->rad_acct_setting->timeout = _this->rad_auth_setting->timeout = - npppd_auth_config_int(base, "timeout", DEFAULT_RADIUS_TIMEOUT); - + npppd_auth_radius *_this = (npppd_auth_radius *)base; + radius_req_setting *rad; + struct radserver *server; + int i, nauth, nacct; + + _this->rad_auth_setting->timeout = + (auth->radius.auth.timeout == 0) + ? DEFAULT_RADIUS_TIMEOUT : auth->radius.auth.timeout; + _this->rad_acct_setting->timeout = + (auth->radius.acct.timeout == 0) + ? DEFAULT_RADIUS_TIMEOUT : auth->radius.acct.timeout; + + + _this->rad_auth_setting->max_tries = + (auth->radius.auth.max_tries == 0) + ? DEFAULT_RADIUS_MAX_TRIES : auth->radius.auth.max_tries; _this->rad_acct_setting->max_tries = - _this->rad_auth_setting->max_tries = - npppd_auth_config_int(base, "max_tries", - DEFAULT_RADIUS_MAX_TRIES); + (auth->radius.acct.max_tries == 0) + ? DEFAULT_RADIUS_MAX_TRIES : auth->radius.acct.max_tries; + _this->rad_auth_setting->max_failovers = + (auth->radius.auth.max_failovers == 0) + ? DEFAULT_RADIUS_MAX_FAILOVERS + : auth->radius.auth.max_failovers; _this->rad_acct_setting->max_failovers = - _this->rad_auth_setting->max_failovers = - npppd_auth_config_int(base, "max_failovers", - DEFAULT_RADIUS_MAX_FAILOVERS); + (auth->radius.acct.max_failovers == 0) + ? DEFAULT_RADIUS_MAX_FAILOVERS + : auth->radius.acct.max_failovers; _this->rad_acct_setting->curr_server = _this->rad_auth_setting->curr_server = 0; - if ((nauth = radius_loadconfig(base, _this->rad_auth_setting, - RADIUS_SERVER_TYPE_AUTH)) < 0) - goto fail; - if ((nacct = radius_loadconfig(base, _this->rad_acct_setting, - RADIUS_SERVER_TYPE_ACCT)) < 0) - goto fail; + + /* load configs for authentication server */ + rad = _this->rad_auth_setting; + for (i = 0; i < countof(rad->server); i++) + memset(&rad->server[i], 0, sizeof(rad->server[0])); + i = 0; + TAILQ_FOREACH(server, &auth->radius.auth.servers, entry) { + if (i >= countof(rad->server)) + break; + memcpy(&rad->server[i].peer, &server->address, + server->address.ss_len); + strlcpy(rad->server[i].secret, server->secret, + sizeof(rad->server[i].secret)); + rad->server[i].enabled = 1; + i++; + } + nauth = i; + + /* load configs for accounting server */ + rad = _this->rad_acct_setting; + for (i = 0; i < countof(rad->server); i++) + memset(&rad->server[i], 0, sizeof(rad->server[0])); + i = 0; + TAILQ_FOREACH(server, &auth->radius.acct.servers, entry) { + if (i >= countof(rad->server)) + break; + memcpy(&rad->server[i].peer, &server->address, + server->address.ss_len); + strlcpy(rad->server[i].secret, server->secret, + sizeof(rad->server[i].secret)); + rad->server[i].enabled = 1; + i++; + } + nacct = i; for (i = 0; i < countof(_this->rad_auth_setting->server); i++) { if (_this->rad_auth_setting->server[i].enabled) @@ -795,102 +592,10 @@ npppd_auth_radius_reload(npppd_auth_base *base) npppd_auth_base_log(&_this->nar_base, LOG_INFO, "Loaded configuration. %d authentication server%s, %d accounting " - "server%s. timeout=%dsec", - nauth, (nauth > 1)? "s" : "", nacct, (nacct > 1)? "s" : "", - _this->rad_auth_setting->timeout); + "server%s.", + nauth, (nauth > 1)? "s" : "", nacct, (nacct > 1)? "s" : ""); return 0; -fail: - npppd_auth_destroy(base); - - return 1; -} - -static int -radius_loadconfig(npppd_auth_base *base, radius_req_setting *radius, - enum RADIUS_SERVER_TYPE srvtype) -{ - npppd_auth_radius *_this = (npppd_auth_radius *)base; - int i, n; - const char *val; - char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ]; - char label[256]; - struct rad_cfglabel { - const char *list; - const char *address; - const char *secret; - const char *addressL; - const char *secretL; - } const rad_auth_cfglabel = { - .list = "server_list", - .address = "server.address", - .secret = "server.secret", - .addressL = "server.%s.address", - .secretL = "server.%s.secret" - }, rad_acct_cfglabel = { - .list = "acct_server_list", - .address = "acct_server.address", - .secret = "acct_server.secret", - .addressL = "acct_server.%s.address", - .secretL = "acct_server.%s.secret" - }, *cfglabel; - - if (srvtype == RADIUS_SERVER_TYPE_AUTH) - cfglabel = &rad_auth_cfglabel; - else - cfglabel = &rad_acct_cfglabel; - - for (i = 0; i < countof(radius->server); i++) - radius->server[i].enabled = 0; - - n = 0; - if ((val = npppd_auth_config_str(base, cfglabel->list)) != NULL) { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - snprintf(label, sizeof(label), cfglabel->addressL,tok); - if ((val = npppd_auth_config_str(base, label)) == NULL){ - npppd_auth_base_log(&_this->nar_base, LOG_INFO, - "property %s is not found", label); - goto fail; - } - if (radius_server_address_load(radius, n, val, srvtype) - != 0) { - npppd_auth_base_log(base, LOG_INFO, - "parse error at %s", label); - goto fail; - } - snprintf(label, sizeof(label), cfglabel->secretL, tok); - if ((val = npppd_auth_config_str(base, label)) != NULL) - strlcpy(radius->server[n].secret, val, - sizeof(radius->server[n].secret)); - else - radius->server[n].secret[0] = '\0'; - n++; - } - } else if ((val = npppd_auth_config_str(base, cfglabel->address)) - != NULL) { - if (radius_server_address_load(radius, n, val, srvtype) != 0) { - npppd_auth_base_log(base, LOG_INFO, - "parse error at %s", label); - goto fail; - } - if ((val = npppd_auth_config_str(base, cfglabel->secret)) - != NULL) - strlcpy(radius->server[n].secret, val, - sizeof(radius->server[n].secret)); - else - radius->server[n].secret[0] = '\0'; - n++; - } - for (i = n; i < countof(radius->server); i++) - memset(&radius->server[i], 0, sizeof(radius->server[0])); - - return n; -fail: - return -1; } /** @@ -928,80 +633,10 @@ npppd_auth_base_log(npppd_auth_base *_this, int prio, const char *fmt, ...) NPPPD_AUTH_ASSERT(_this != NULL); va_start(ap, fmt); - snprintf(logbuf, sizeof(logbuf), "realm name=%s(%s) %s", - _this->name, (_this->label[0] == '\0')? "default" : _this->label, - fmt); + snprintf(logbuf, sizeof(logbuf), "realm name=%s %s", + _this->name, fmt); status = vlog_printf(prio, logbuf, ap); va_end(ap); return status; } - -static uint32_t -str_hash(const void *ptr, int sz) -{ - u_int32_t hash = 0; - int i, len; - const char *str; - - str = ptr; - len = strlen(str); - for (i = 0; i < len; i++) - hash = hash*0x1F + str[i]; - hash = (hash << 16) ^ (hash & 0xffff); - - return hash % sz; -} - -static const char * -npppd_auth_default_label(npppd_auth_base *base) -{ - switch(base->type) { - case NPPPD_AUTH_TYPE_LOCAL: - return "local"; - case NPPPD_AUTH_TYPE_RADIUS: - return "radius"; - } - NPPPD_AUTH_ASSERT(0); - - return NULL; -} - -static inline const char * -npppd_auth_config_prefix(npppd_auth_base *base) -{ - switch(base->type) { - case NPPPD_AUTH_TYPE_LOCAL: - return "auth.local.realm"; - - case NPPPD_AUTH_TYPE_RADIUS: - return "auth.radius.realm"; - - } - NPPPD_AUTH_ASSERT(0); - - return NULL; -} - -static const char * -npppd_auth_config_str(npppd_auth_base *base, const char *confKey) -{ - return config_named_prefix_str(((npppd *)base->npppd)->properties, - npppd_auth_config_prefix(base), base->label, confKey); -} - -static int -npppd_auth_config_int(npppd_auth_base *base, const char *confKey, int defVal) -{ - return config_named_prefix_int(((npppd *)base->npppd)->properties, - npppd_auth_config_prefix(base), base->label, confKey, defVal); -} - -static int -npppd_auth_config_str_equal(npppd_auth_base *base, const char *confKey, - const char *confVal, int defVal) -{ - return config_named_prefix_str_equal(((npppd *)base->npppd)->properties, - npppd_auth_config_prefix(base), base->label, confKey, confVal, - defVal); -} diff --git a/usr.sbin/npppd/npppd/npppd_auth.h b/usr.sbin/npppd/npppd/npppd_auth.h index e0fe830d052..138674726cc 100644 --- a/usr.sbin/npppd/npppd/npppd_auth.h +++ b/usr.sbin/npppd/npppd/npppd_auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_auth.h,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: npppd_auth.h,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -44,6 +44,21 @@ typedef struct _npppd_auth_base npppd_auth_base; typedef struct _npppd_auth_radius npppd_auth_radius; typedef struct _npppd_auth_local npppd_auth_local; +/** the type of user account */ +typedef struct _npppd_auth_user { + /** username */ + char *username; + /** password */ + char *password; + /** Framed-IP-Address */ + struct in_addr framed_ip_address; + /** Framed-IP-Netmask */ + struct in_addr framed_ip_netmask; + /** Calling-Number */ + char *calling_number; + /** field for space assignment */ + char space[0]; +} npppd_auth_user; #ifdef __cplusplus extern "C" { @@ -61,7 +76,6 @@ int npppd_auth_is_usable (npppd_auth_base *); int npppd_auth_is_ready (npppd_auth_base *); int npppd_auth_is_disposing (npppd_auth_base *); int npppd_auth_is_eap_capable (npppd_auth_base *); -const char *npppd_auth_get_label (npppd_auth_base *); const char *npppd_auth_get_name (npppd_auth_base *); const char *npppd_auth_get_suffix (npppd_auth_base *); const char *npppd_auth_get_prefix (npppd_auth_base *); diff --git a/usr.sbin/npppd/npppd/npppd_auth_local.h b/usr.sbin/npppd/npppd/npppd_auth_local.h index c6f0daadfc6..d1947b77640 100644 --- a/usr.sbin/npppd/npppd/npppd_auth_local.h +++ b/usr.sbin/npppd/npppd/npppd_auth_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_auth_local.h,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: npppd_auth_local.h,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -27,12 +27,10 @@ */ struct _npppd_auth_base { - /** name of label */ - char label[NPPPD_GENERIC_NAME_LEN]; /** name of realm */ char name[NPPPD_GENERIC_NAME_LEN]; /** reference indicated to parent npppd */ - void *npppd; + npppd *npppd; /** type of authentication realm */ int type; /** PPP suffix */ @@ -42,12 +40,8 @@ struct _npppd_auth_base { uint32_t /** whether initialized or not */ initialized:1, - /** whether reloadable or not */ - reloadable:1, /** in disposing */ disposing:1, - /** Is the account list ready */ - acctlist_ready:1, /** Is the radius configuration ready */ radius_ready:1, /** whether EAP capable or not */ @@ -56,14 +50,12 @@ struct _npppd_auth_base { strip_nt_domain:1, /** whether force to strip after the '@' of PPP username or not */ strip_atmark_realm:1, - /** has account-list */ - has_acctlist:1, - reserved:24; + /** has users list */ + has_users_file:1, + reserved:25; - /** username => npppd_auth_user hash */ - hash_table *users_hash; /** path name of account list */ - char acctlist_path[64]; + char users_file_path[64]; /** last load time */ time_t last_load; }; @@ -87,31 +79,8 @@ struct _npppd_auth_local { npppd_auth_base nal_base; }; -/** the type of user account */ -typedef struct _npppd_auth_user { - /** username */ - char *username; - /** password */ - char *password; - /** Framed-IP-Address */ - struct in_addr framed_ip_address; - /** Framed-IP-Netmask */ - struct in_addr framed_ip_netmask; - /** Calling-Number */ - char *calling_number; - /** field for space assignment */ - char space[0]; -} npppd_auth_user; - -static int npppd_auth_reload_acctlist (npppd_auth_base *); -static npppd_auth_user *npppd_auth_find_user (npppd_auth_base *, const char *); -static int npppd_auth_base_log (npppd_auth_base *, int, const char *, ...); -static uint32_t str_hash (const void *, int); -static const char * npppd_auth_default_label(npppd_auth_base *); -static inline const char *npppd_auth_config_prefix (npppd_auth_base *); -static const char *npppd_auth_config_str (npppd_auth_base *, const char *); -static int npppd_auth_config_int (npppd_auth_base *, const char *, int) __unused; -static int npppd_auth_config_str_equal (npppd_auth_base *, const char *, const char *, int); +static npppd_auth_user *npppd_auth_get_user (npppd_auth_base *, const char *); +static int npppd_auth_base_log (npppd_auth_base *, int, const char *, ...); #ifdef USE_NPPPD_RADIUS enum RADIUS_SERVER_TYPE { @@ -119,9 +88,7 @@ enum RADIUS_SERVER_TYPE { RADIUS_SERVER_TYPE_ACCT }; -static int npppd_auth_radius_reload (npppd_auth_base *); -static int radius_server_address_load (radius_req_setting *, int, const char *, enum RADIUS_SERVER_TYPE); -static int radius_loadconfig(npppd_auth_base *, radius_req_setting *, enum RADIUS_SERVER_TYPE); +static int npppd_auth_radius_reload (npppd_auth_base *, struct authconf *); #endif #ifdef NPPPD_AUTH_DEBUG @@ -131,3 +98,10 @@ static int radius_loadconfig(npppd_auth_base *, radius_req_settin #define NPPPD_AUTH_DBG(x) #define NPPPD_AUTH_ASSERT(x) #endif + +#define DEFAULT_RADIUS_AUTH_PORT 1812 +#define DEFAULT_RADIUS_ACCT_PORT 1813 +#define DEFAULT_RADIUS_TIMEOUT 9 +#define DEFAULT_RADIUS_MAX_TRIES 3 +#define DEFAULT_RADIUS_MAX_FAILOVERS 1 + diff --git a/usr.sbin/npppd/npppd/npppd_config.c b/usr.sbin/npppd/npppd/npppd_config.c index cc118285509..10cae9454e7 100644 --- a/usr.sbin/npppd/npppd/npppd_config.c +++ b/usr.sbin/npppd/npppd/npppd_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_config.c,v 1.8 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: npppd_config.c,v 1.9 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,11 +25,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: npppd_config.c,v 1.8 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $Id: npppd_config.c,v 1.9 2012/09/18 13:14:08 yasuoka Exp $ */ /*@file * This file provides functions which operates configuration and so on. */ -#include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> #include <netinet/in.h> @@ -54,7 +53,6 @@ #include "npppd_ctl.h" #include "npppd_auth.h" #include "npppd_iface.h" -#include "config_helper.h" #include "radish.h" #include "pathnames.h" @@ -67,26 +65,18 @@ #define NPPPD_CONFIG_ASSERT(x) #endif +static int npppd_pool_load(npppd *); +static int npppd_auth_realm_reload (npppd *); +static npppd_auth_base *realm_list_remove (slist *, const char *); -#define CFG_KEY(p, s) config_key_prefix((p), (s)) -#define VAL_SEP " \t\r\n" - -static void npppd_ipcp_config_load (npppd *); -static void npppd_ipcp_config_load0 (npppd_ipcp_config *, const char *); -static void npppd_debug_log_reload (npppd *); -static int npppd_ip_addr_pool_load(npppd *); -static int npppd_auth_realm_reload (npppd *); -static void npppd_iface_binding_reload(npppd *, npppd_iface *, npppd_iface_binding *); -static int realm_list_contains (slist *, const char *); -static npppd_auth_base *realm_list_remove (slist *, const char *); - -CONFIG_FUNCTIONS(npppd_config, npppd, properties); -PREFIXED_CONFIG_FUNCTIONS(ppp_config, npppd_ppp, pppd->properties, phy_label); +int +npppd_config_check(const char *path) +{ + struct npppd_conf conf; -NAMED_PREFIX_CONFIG_DECL(npppd_ipcp_config, npppd_ipcp_config, - npppd->properties, "ipcp", label); -NAMED_PREFIX_CONFIG_FUNCTIONS(npppd_ipcp_config, npppd_ipcp_config, - npppd->properties, "ipcp", label); + npppd_conf_init(&conf); + return npppd_conf_parse(&conf, path); +} /*********************************************************************** * Reading the configuration. This is the export function which @@ -101,51 +91,18 @@ NAMED_PREFIX_CONFIG_FUNCTIONS(npppd_ipcp_config, npppd_ipcp_config, int npppd_reload_config(npppd *_this) { - int retval = -1; - FILE *conffp = NULL; - struct properties *proptmp = NULL; + int retval = -1; + struct npppd_conf conf; - if ((conffp = priv_fopen(_this->config_file)) == NULL) { - log_printf(LOG_ERR, "Load configuration from='%s' failed: %m", - _this->config_file); - retval = -1; - goto fail; - } - if ((proptmp = properties_create(1061)) == NULL) { - log_printf(LOG_ERR, "Load configuration from='%s' failed: %m", - _this->config_file); - retval = -1; - goto fail; - } - if (properties_load(proptmp, conffp) != 0) { - log_printf(LOG_ERR, "Load configuration from='%s' failed: %m", + npppd_conf_init(&conf); + if (npppd_conf_parse(&conf, _this->config_file) != 0) { + log_printf(LOG_ERR, "Load configuration from='%s' failed", _this->config_file); retval = -1; goto fail; } - if (_this->properties != NULL) { - /* swap */ - properties_remove_all(_this->properties); - properties_put_all(_this->properties, proptmp); - properties_destroy(proptmp); - } else - _this->properties = proptmp; - proptmp = NULL; - - /* It is suitable for here as process sequence because of logging. */ - npppd_debug_log_reload(_this); - -#ifndef NO_DELAYED_RELOAD - _this->delayed_reload = npppd_config_int(_this, "delayed_reload", 0); - if (_this->delayed_reload < 0) { - log_printf(LOG_WARNING, "Parse error at 'delayed_reload'"); - _this->delayed_reload = 0; - } -#endif - - _this->max_session = npppd_config_int(_this, "max_session", - NPPPD_DEFAULT_MAX_PPP); + _this->conf = conf; retval = 0; log_printf(LOG_NOTICE, "Load configuration from='%s' successfully.", @@ -153,10 +110,6 @@ npppd_reload_config(npppd *_this) /* FALLTHROUGH */ fail: - if (conffp != NULL) - fclose(conffp); - if (proptmp != NULL) - properties_destroy(proptmp); return retval; } @@ -165,29 +118,22 @@ fail: int npppd_modules_reload(npppd *_this) { - int i, rval; + int rval; rval = 0; - /* address pool */ - if (npppd_ip_addr_pool_load(_this) != 0) + if (npppd_pool_load(_this) != 0) return -1; - npppd_ipcp_config_load(_this); - npppd_auth_realm_reload(_this); #ifdef USE_NPPPD_L2TP - rval |= l2tpd_reload(&_this->l2tpd, _this->properties, "l2tpd", 1); + rval |= l2tpd_reload(&_this->l2tpd, &_this->conf.l2tp_confs); #endif #ifdef USE_NPPPD_PPTP - rval |= pptpd_reload(&_this->pptpd, _this->properties, "pptpd", - 1); + rval |= pptpd_reload(&_this->pptpd, &_this->conf.pptp_confs); #endif #ifdef USE_NPPPD_PPPOE - rval |= pppoed_reload(&_this->pppoed, _this->properties, "pppoed", 0); + rval |= pppoed_reload(&_this->pppoed, &_this->conf.pppoe_confs); #endif - for (i = 0; i < countof(_this->iface_bind); i++) - npppd_iface_binding_reload(_this, &_this->iface[i], - &_this->iface_bind[i]); return rval; } @@ -195,152 +141,14 @@ npppd_modules_reload(npppd *_this) /*********************************************************************** * reload the configuration on each part ***********************************************************************/ -static void -npppd_ipcp_config_load(npppd *_this) -{ - int n; - const char *val; - char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ]; - - for (n = 0; n < countof(_this->ipcp_config); n++) - memset(&_this->ipcp_config[n], 0, sizeof(npppd_ipcp_config)); - n = 0; - if ((val = npppd_config_str(_this, "ipcp_list")) != NULL) { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - if (n >= countof(_this->ipcp_config)) { - log_printf(LOG_WARNING, - "number of the ipcp configuration reached " - "limit=%d", - (int)countof(_this->ipcp_config)); - break; - } - _this->ipcp_config[n].npppd = _this; - npppd_ipcp_config_load0(&_this->ipcp_config[n], tok); - n++; - } - } else { - _this->ipcp_config[n].npppd = _this; - npppd_ipcp_config_load0(&_this->ipcp_config[n++], NULL); - } -} - -/** load IPCP configuration */ -static void -npppd_ipcp_config_load0(npppd_ipcp_config *_this, const char *label) -{ - uint32_t ip_assign_flags; - const char *val; - - if (label != NULL) - strlcpy(_this->label, label, sizeof(_this->label)); - else - memset(_this->label, 0, sizeof(_this->label)); - - _this->initialized = 1; - - val = npppd_ipcp_config_str(_this, "name"); - if (val == NULL) { - if (_this->label[0] == '\0') - val = "default"; - else - val = _this->label; - } - strlcpy(_this->name, val, sizeof(_this->name)); - - /* IP address assignment policy */ - ip_assign_flags = 0; - if (npppd_ipcp_config_str_equal(_this, "assign_userselect", "true", 1)) - ip_assign_flags |= NPPPD_IP_ASSIGN_USER_SELECT; - else - ip_assign_flags &= ~NPPPD_IP_ASSIGN_USER_SELECT; - - if (npppd_ipcp_config_str_equal(_this, "assign_fixed", "true", 1)) - ip_assign_flags |= NPPPD_IP_ASSIGN_FIXED; - else - ip_assign_flags &= ~NPPPD_IP_ASSIGN_FIXED; - - if (npppd_ipcp_config_str_equal(_this, "assign_radius", "true", 0)) - ip_assign_flags |= NPPPD_IP_ASSIGN_RADIUS; - else - ip_assign_flags &= ~NPPPD_IP_ASSIGN_RADIUS; - _this->ip_assign_flags = ip_assign_flags; - -#define LOAD_IPADDR_SETTING(field, conf) \ - if ((val = npppd_ipcp_config_str(_this, conf)) == NULL || \ - strlen(val) <= 0) { \ - _this->field.s_addr = INADDR_NONE; \ - } else { \ - if (inet_aton(val, &_this->field) != 1) { \ - log_printf(LOG_ERR, "configuration error at " \ - conf ": parse error"); \ - } \ - _this->field = _this->field; \ - } - - _this->dns_use_tunnel_end = npppd_ipcp_config_str_equal(_this, - "dns_use_tunnel_end", "true", 0); - if (npppd_ipcp_config_str_equal(_this, "dns_use_resolver", - "true", 0)) { - if (load_resolv_conf(&_this->dns_pri, &_this->dns_sec) != 0) - log_printf(LOG_ERR, "loading resolv.conf failed: %m"); - } else { - LOAD_IPADDR_SETTING(dns_pri, "dns_primary"); - LOAD_IPADDR_SETTING(dns_sec, "dns_secondary"); - } - LOAD_IPADDR_SETTING(nbns_pri, "nbns_primary"); - LOAD_IPADDR_SETTING(nbns_sec, "nbns_secondary"); -#undef LOAD_IPADDR_SETTING -} - -/** reload the configuration for debug and the log file */ -static void -npppd_debug_log_reload(npppd *_this) -{ - int ival, oval; - FILE *debugfp; - const char *sval; - - if ((ival = npppd_config_int(_this, "debug.level", debuglevel)) == - debuglevel) - return; - - /* change debug level */ - oval = debuglevel; - debuglevel = ival; - log_printf(LOG_NOTICE, "Debug level is changed %d => %d", oval, ival); - - debugfp = debug_get_debugfp(); - if (debugfp != stderr) { - sval = npppd_config_str(_this, "debug.logpath"); - /* It is not foreground mode. */ - if (debugfp != NULL) - fclose(debugfp); - if (sval != NULL) { - if ((debugfp = fopen(sval, "a+")) == NULL) { - log_printf(LOG_ERR, - "Failed to open logfile %s: %m", sval); - } else { - log_printf(LOG_INFO, - "open logfile successfully %s", sval); - debug_set_debugfp(debugfp); - } - } - } -} - /** load the configuration for IP address pool */ static int -npppd_ip_addr_pool_load(npppd *_this) +npppd_pool_load(npppd *_this) { int n, i, j; - const char *val; - char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ]; - npppd_pool pool0[NPPPD_MAX_POOL]; + npppd_pool pool0[NPPPD_MAX_IFACE]; struct radish_head *rd_curr, *rd_new; + struct ipcpconf *ipcp; rd_curr = _this->rd; rd_new = NULL; @@ -354,36 +162,20 @@ npppd_ip_addr_pool_load(npppd *_this) } _this->rd = rd_new; - /* load the configuration */ - if ((val = npppd_config_str(_this, "pool_list")) != NULL) { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - if (n >= countof(_this->pool)) { - log_printf(LOG_WARNING, - "number of the pool reached " - "limit=%d",(int)countof(_this->pool)); - break; - } - if (npppd_pool_init(&pool0[n], _this, tok) != 0) { - log_printf(LOG_WARNING, "Failed to initialize " - "npppd_pool '%s': %m", tok); - goto fail; - } - if (npppd_pool_reload(&pool0[n]) != 0) - goto fail; - n++; + TAILQ_FOREACH(ipcp, &_this->conf.ipcpconfs, entry) { + if (n >= countof(_this->pool)) { + log_printf(LOG_WARNING, "number of the pool reached " + "limit=%d",(int)countof(_this->pool)); + break; } - } else { - if (npppd_pool_init(&pool0[n], _this, "default") != 0) { + if (npppd_pool_init(&pool0[n], _this, ipcp->name) != 0) { log_printf(LOG_WARNING, "Failed to initialize " - "npppd_pool 'default': %m"); + "npppd_pool '%s': %m", ipcp->name); goto fail; } - if (npppd_pool_reload(&pool0[n++]) != 0) + if (npppd_pool_reload(&pool0[n]) != 0) goto fail; + n++; } for (; n < countof(pool0); n++) pool0[n].initialized = 0; @@ -433,10 +225,9 @@ fail: static int npppd_auth_realm_reload(npppd *_this) { - int rval, ndef; - const char *val; - char buf[NPPPD_CONFIG_BUFSIZ * 2], *bufp, *tok; - slist realms0, nrealms; + int rval; + slist realms0, nrealms; + struct authconf *auth; npppd_auth_base *auth_base; rval = 0; @@ -449,115 +240,36 @@ npppd_auth_realm_reload(npppd *_this) goto fail; } - ndef = 0; - /* get the label of the local realm */ - if ((val = npppd_config_str(_this, "auth.local.realm_list")) != NULL) { - ndef++; - strlcpy(buf, val, sizeof(buf)); - bufp = buf; - while ((tok = strsep(&bufp, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - if (realm_list_contains(&nrealms, tok)) { - log_printf(LOG_WARNING, - "label '%s' for auth.*.realm_list is not " - "unique", tok); - goto fail; - } - auth_base = realm_list_remove(&realms0, tok); - if (auth_base != NULL && - npppd_auth_get_type(auth_base) - != NPPPD_AUTH_TYPE_LOCAL) { - /* - * The type of authentication realm was changed in the - * same label name. - */ - slist_add(&realms0, auth_base); - auth_base = NULL; - } - if (auth_base == NULL) { - /* create newly */ - if ((auth_base = npppd_auth_create( - NPPPD_AUTH_TYPE_LOCAL, tok, _this)) - == NULL) { - log_printf(LOG_WARNING, - "npppd_auth_create() failed in " - "%s(): %m", __func__); - goto fail; - } - } - slist_add(&nrealms, auth_base); - } - } -#ifdef USE_NPPPD_RADIUS - /* get the label of the RADIUS realm */ - if ((val = npppd_config_str(_this, "auth.radius.realm_list")) != NULL) { - ndef++; - strlcpy(buf, val, sizeof(buf)); - bufp = buf; - while ((tok = strsep(&bufp, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - if (realm_list_contains(&nrealms, tok)) { - log_printf(LOG_WARNING, - "label '%s' for auth.*.realm_list is not " - "unique", tok); - goto fail; - } - auth_base = realm_list_remove(&realms0, tok); - if (auth_base != NULL && - npppd_auth_get_type(auth_base) - != NPPPD_AUTH_TYPE_RADIUS) { - /* - * The type of authentication realm was changed in the - * same label name. - */ - slist_add(&realms0, auth_base); - auth_base = NULL; - } - if (auth_base == NULL) { - /* create newly */ - if ((auth_base = npppd_auth_create( - NPPPD_AUTH_TYPE_RADIUS, tok, _this)) - == NULL) { - log_printf(LOG_WARNING, - "npppd_auth_create() failed in " - "%s(): %m", __func__); - goto fail; - } - } - slist_add(&nrealms, auth_base); + TAILQ_FOREACH(auth, &_this->conf.authconfs, entry) { +#ifndef USE_NPPPD_RADIUS + if (auth->auth_type == NPPPD_AUTH_TYPE_RADIUS) { + log_printf(LOG_WARNING, "radius support is not " + "enabled by compile time."); + continue; } - } #endif -#ifndef NO_DEFAULT_REALM - if (ndef == 0) { - /* - * Compatibility for current implementation. Use default realm. - */ - if (slist_length(&realms0) > 0) { - slist_add_all(&nrealms, &realms0); - slist_remove_all(&realms0); - } else { - if ((auth_base = npppd_auth_create( - NPPPD_AUTH_TYPE_LOCAL, "", _this)) == NULL) { - log_printf(LOG_WARNING, - "malloc() failed in %s(): %m", __func__); - goto fail; - } - slist_add(&nrealms, auth_base); -#ifdef USE_NPPPD_RADIUS - if ((auth_base = npppd_auth_create( - NPPPD_AUTH_TYPE_RADIUS, "", _this)) == NULL) { - log_printf(LOG_WARNING, - "malloc() failed in %s(): %m", __func__); + auth_base = realm_list_remove(&realms0, auth->name); + if (auth_base != NULL && + npppd_auth_get_type(auth_base) != auth->auth_type) { + /* + * The type of authentication has been changed in the + * same label name. + */ + slist_add(&realms0, auth_base); + auth_base = NULL; + } + + if (auth_base == NULL) { + /* create newly */ + if ((auth_base = npppd_auth_create(auth->auth_type, + auth->name, _this)) == NULL) { + log_printf(LOG_WARNING, "npppd_auth_create() " + "failed in %s(): %m", __func__); goto fail; } slist_add(&nrealms, auth_base); -#endif } } -#endif if (slist_set_size(&_this->realms, slist_length(&nrealms)) != 0) { log_printf(LOG_WARNING, "slist_set_size() failed in %s(): %m", __func__); @@ -598,22 +310,6 @@ fail: return 1; } -static int -realm_list_contains(slist *list0, const char *label) -{ - npppd_auth_base *base; - - for (slist_itr_first(list0); slist_itr_has_next(list0); ) { - base = slist_itr_next(list0); - if (npppd_auth_is_disposing(base)) - continue; - if (strcmp(npppd_auth_get_label(base), label) == 0) - return 1; - } - - return 0; -} - static npppd_auth_base * realm_list_remove(slist *list0, const char *label) { @@ -623,7 +319,7 @@ realm_list_remove(slist *list0, const char *label) base = slist_itr_next(list0); if (npppd_auth_is_disposing(base)) continue; - if (strcmp(npppd_auth_get_label(base), label) == 0) + if (strcmp(npppd_auth_get_name(base), label) == 0) return slist_itr_remove(list0); } @@ -634,140 +330,48 @@ realm_list_remove(slist *list0, const char *label) int npppd_ifaces_load_config(npppd *_this) { - int rval, n, nsession; - const char *val; - char *tok, *buf0, buf[BUFSIZ], buf1[128]; + int i, n; + struct iface *iface; + npppd_iface *niface; - rval = 0; - n = 0; - if ((val = npppd_config_str(_this, "interface_list")) != NULL) { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, VAL_SEP)) != NULL) { - if (tok[0] == '\0') - continue; - if (n >= countof(_this->iface)) { - log_printf(LOG_WARNING, - "number of the interface reached " - "limit=%d",(int)countof(_this->iface)); + for (i = 0; i < countof(_this->iface); i++) { + if (_this->iface[i].initialized == 0) + continue; + TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) { + if (strcmp(_this->iface[i].ifname, iface->name) == 0) break; - } - - strlcpy(buf1, "interface.", sizeof(buf1)); - strlcat(buf1, tok, sizeof(buf1)); - - if (_this->iface[n].initialized != 0) - nsession = _this->iface[n].nsession; - else { - int pppx; - - pppx = npppd_config_str_equal(_this, - config_key_prefix(buf1, "pppx_mode"), - "true", 0); - npppd_iface_init(&_this->iface[n], tok, pppx); - nsession = 0; - } - - _this->iface[n].set_ip4addr = 0; - if ((val = npppd_config_str(_this, - config_key_prefix(buf1, "ip4addr"))) != NULL){ - if (inet_pton(AF_INET, val, - &_this->iface[n].ip4addr) != 1) { - log_printf(LOG_ERR, - "configuration error at %s", - config_key_prefix(buf1, - "ip4addr")); - return 1; - } - _this->iface[n].set_ip4addr = 1; - } - - _this->iface[n].user_max_session = npppd_config_int( - _this, config_key_prefix(buf1, "user_max_session"), - NPPPD_DEFAULT_USER_MAX_PPP); - _this->iface[n].max_session = npppd_config_int(_this, - config_key_prefix(buf1, "max_session"), - _this->max_session); - - _this->iface[n].nsession = nsession; - _this->iface[n].npppd = _this; - _this->iface[n].initialized = 1; - n++; } - } - - return rval; -} - -static void -npppd_iface_binding_reload(npppd *_this, npppd_iface *iface, - npppd_iface_binding *binding) -{ - int i, using_default, had_ipcp; - const char *val; - char key[128], *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ]; - - NPPPD_CONFIG_ASSERT(_this != NULL); - NPPPD_CONFIG_ASSERT(iface != NULL); - NPPPD_CONFIG_ASSERT(binding != NULL); - - had_ipcp = (binding->ipcp != NULL)? 1 : 0; - slist_fini(&binding->pools); - memset(binding, 0, sizeof(npppd_iface_binding)); - if (iface->initialized == 0) - return; - - - /* create the key */ - strlcpy(key, "interface.", sizeof(key)); - strlcat(key, iface->ifname, sizeof(key)); - strlcat(key, ".ipcp_configuration", sizeof(key)); - - using_default = 0; - if ((val = npppd_config_str(_this, key)) != NULL) { - for (i = 0; i < countof(_this->ipcp_config); i++){ - if (_this->ipcp_config[i].initialized == 0) - continue; - if (strcmp(_this->ipcp_config[i].label, val) == 0) { - binding->ipcp = &_this->ipcp_config[i]; - break; - } + if (iface == NULL) { + npppd_iface_stop(&_this->iface[i]); + npppd_iface_fini(&_this->iface[i]); } - } else if (_this->ipcp_config[0].initialized != 0 && - _this->ipcp_config[0].label[0] == '\0') { -#ifndef NO_DEFAULT_IPCP - /* There is default IPCP configuration. */ - binding->ipcp = &_this->ipcp_config[0]; - using_default = 1; -#else - using_default = 0; -#endif - } - slist_init(&binding->pools); - if (binding->ipcp == NULL) { - if (had_ipcp) - log_printf(LOG_INFO, "%s has no ipcp", iface->ifname); - return; } - if ((val = npppd_ipcp_config_str(binding->ipcp, "pool_list")) != NULL) { - strlcpy(buf, val, sizeof(buf)); - buf0 = buf; - while ((tok = strsep(&buf0, VAL_SEP)) != NULL) { - if (tok[0] == '\0') + TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) { + /* find the existing entry or first free entry */ + niface = NULL; + for (i = 0; i < countof(_this->iface); i++) { + if (_this->iface[i].initialized == 0) { + if (niface == NULL) + niface = &_this->iface[i]; continue; - for (i = 0; i < countof(_this->pool); i++) { - if (_this->pool[i].initialized == 0) - continue; - if (strcmp(tok, _this->pool[i].label) != 0) - continue; - slist_add(&binding->pools, &_this->pool[i]); + } + if (strcmp(_this->iface[i].ifname, iface->name) == 0) { + niface = &_this->iface[i]; break; } } - } else if (using_default) { - if (_this->pool[0].initialized != 0) - slist_add(&binding->pools, &_this->pool[0]); + if (niface == NULL) { + log_printf(LOG_WARNING, + "number of the interface reached limit=%d", + (int)countof(_this->iface)); + break; + } + if (niface->initialized == 0) + npppd_iface_init(_this, niface, iface); + else + npppd_iface_reinit(niface, iface); + n++; } - log_printf(LOG_INFO, "%s is using ipcp=%s(%d pools).", - iface->ifname, binding->ipcp->name, slist_length(&binding->pools)); + + return 0; } diff --git a/usr.sbin/npppd/npppd/npppd_ctl.c b/usr.sbin/npppd/npppd/npppd_ctl.c index a190a02ac61..b99993e750d 100644 --- a/usr.sbin/npppd/npppd/npppd_ctl.c +++ b/usr.sbin/npppd/npppd/npppd_ctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_ctl.c,v 1.9 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: npppd_ctl.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -30,7 +30,7 @@ * This file provides to open UNIX domain socket which located in * /var/run/npppd_ctl and accept commmands from the npppdctl command. */ -/* $Id: npppd_ctl.c,v 1.9 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $Id: npppd_ctl.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -495,7 +495,7 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp) memset(&req, 0, sizeof(req)); switch(ppp->tunnel_type) { #ifdef USE_NPPPD_PPPOE - case PPP_TUNNEL_PPPOE: + case NPPPD_TUNNEL_PPPOE: pppoe = (pppoe_session *)ppp->phy_context; /* PPPOE specific information */ @@ -504,7 +504,7 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_PPTP - case PPP_TUNNEL_PPTP: + case NPPPD_TUNNEL_PPTP: call = (pptp_call *)ppp->phy_context; /* PPTP specific information */ @@ -513,7 +513,7 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp) break; #endif #ifdef USE_NPPPD_L2TP - case PPP_TUNNEL_L2TP: + case NPPPD_TUNNEL_L2TP: l2tp = (l2tp_call *)ppp->phy_context; /* L2TP specific information */ diff --git a/usr.sbin/npppd/npppd/npppd_defs.h b/usr.sbin/npppd/npppd/npppd_defs.h index a8553afa214..08a53c0f256 100644 --- a/usr.sbin/npppd/npppd/npppd_defs.h +++ b/usr.sbin/npppd/npppd/npppd_defs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_defs.h,v 1.7 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: npppd_defs.h,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -83,32 +83,6 @@ #define LOOPBACK_IFNAME "lo0" #endif -#ifndef NPPPD_DEFAULT_IP_ASSIGN_USER_SELECT -#define NPPPD_DEFAULT_IP_ASSIGN_USER_SELECT 1 -#endif -#ifndef NPPPD_DEFAULT_IP_ASSIGN_FIXED -#define NPPPD_DEFAULT_IP_ASSIGN_FIXED 1 -#endif -#ifndef NPPPD_DEFAULT_IP_ASSIGN_RADIUS -#define NPPPD_DEFAULT_IP_ASSIGN_RADIUS 0 -#endif - -#ifndef DEFAULT_RTSOCK_EVENT_DELAY -/** - * delay time in seconds until npppd starts working when routing socket event - * receive - */ -#define DEFAULT_RTSOCK_EVENT_DELAY 5 -#endif -#ifndef DEFAULT_RTSOCK_SEND_NPKTS -/** numbers of packets to write to routing socket once */ -#define DEFAULT_RTSOCK_SEND_NPKTS 16 -#endif -#ifndef DEFAULT_RTSOCK_SEND_WAIT_MILLISEC -/** wait time in milliseconds to write to routing socket in-sequence */ -#define DEFAULT_RTSOCK_SEND_WAIT_MILLISEC 0 -#endif - #ifndef countof #define countof(x) (sizeof(x) / sizeof((x)[0])) #endif diff --git a/usr.sbin/npppd/npppd/npppd_iface.c b/usr.sbin/npppd/npppd/npppd_iface.c index 137ebc5cc06..fa19fbaaa59 100644 --- a/usr.sbin/npppd/npppd/npppd_iface.c +++ b/usr.sbin/npppd/npppd/npppd_iface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_iface.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: npppd_iface.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: npppd_iface.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $Id: npppd_iface.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * The interface of npppd and kernel. * This is an implementation to use tun(4) or pppx(4). @@ -35,12 +35,14 @@ #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/uio.h> +#include <sys/sockio.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <net/if_dl.h> #include <net/if_tun.h> +#include <net/if_types.h> #include <fcntl.h> @@ -100,15 +102,20 @@ static int npppd_iface_pipex_disable(npppd_iface *_this); /** initialize npppd_iface */ void -npppd_iface_init(npppd_iface *_this, const char *ifname, int pppx_mode) +npppd_iface_init(npppd *npppd, npppd_iface *_this, struct iface *iface) { + NPPPD_IFACE_ASSERT(_this != NULL); memset(_this, 0, sizeof(npppd_iface)); + _this->npppd = npppd; + strlcpy(_this->ifname, iface->name, sizeof(_this->ifname)); + _this->using_pppx = iface->is_pppx; + _this->set_ip4addr = 1; + _this->ip4addr = iface->ip4addr; + _this->ipcpconf = iface->ipcpconf; _this->devf = -1; - strlcpy(_this->ifname, ifname, sizeof(_this->ifname)); - - _this->using_pppx = pppx_mode; + _this->initialized = 1; } static int @@ -135,35 +142,28 @@ npppd_iface_setup_ip(npppd_iface *_this) strlcpy(ifra.ifra_name, _this->ifname, sizeof(ifra.ifra_name)); sin0 = (struct sockaddr_in *)&ifr.ifr_addr; - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - npppd_iface_log(_this, LOG_ERR, - "socket() failed in %s(): %m", __func__); - goto fail; - } - if (ioctl(sock, SIOCGIFADDR, &ifr) != 0) { + if (priv_get_if_addr(_this->ifname, &assigned) != 0) { if (errno != EADDRNOTAVAIL) { npppd_iface_log(_this, LOG_ERR, "get ip address failed: %m"); goto fail; } assigned.s_addr = 0; - } else - assigned = sin0->sin_addr; + } if (assigned.s_addr != _this->ip4addr.s_addr) changed = 1; - memset(&ifr.ifr_ifru, 0, sizeof(ifr.ifr_ifru)); - if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { + if (priv_get_if_flags(_this->ifname, &if_flags) != 0) { npppd_iface_log(_this, LOG_ERR, "ioctl(,SIOCGIFFLAGS) failed: %m"); goto fail; } if_flags = ifr.ifr_flags; - if (_this->set_ip4addr != 0 && changed) { do { - if (ioctl(sock, SIOCDIFADDR, &ifr) != 0) { + struct in_addr dummy; + if (priv_delete_if_addr(_this->ifname) != 0) { if (errno == EADDRNOTAVAIL) break; npppd_iface_log(_this, LOG_ERR, @@ -171,7 +171,7 @@ npppd_iface_setup_ip(npppd_iface *_this) _this->ifname); goto fail; } - if (ioctl(sock, SIOCGIFADDR, &ifr) != 0) { + if (priv_get_if_addr(_this->ifname, &dummy) != 0) { if (errno == EADDRNOTAVAIL) break; npppd_iface_log(_this, LOG_ERR, @@ -181,34 +181,15 @@ npppd_iface_setup_ip(npppd_iface *_this) } } while (1); - /* ifconfig tun1 down */ - ifr.ifr_flags = if_flags & ~(IFF_UP | IFF_BROADCAST); - if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { + if (priv_set_if_flags(_this->ifname, + if_flags & ~(IFF_UP | IFF_BROADCAST)) != 0) { npppd_iface_log(_this, LOG_ERR, "disabling %s failed: %m", _this->ifname); goto fail; } - - sin0 = (struct sockaddr_in *)&ifra.ifra_addr; - sin0->sin_addr.s_addr = _this->ip4addr.s_addr; - sin0->sin_family = AF_INET; - sin0->sin_len = sizeof(struct sockaddr_in); - - sin0 = (struct sockaddr_in *)&ifra.ifra_mask; - sin0->sin_addr.s_addr = 0xffffffffL; - sin0->sin_family = AF_INET; - sin0->sin_len = sizeof(struct sockaddr_in); - - sin0 = (struct sockaddr_in *)&ifra.ifra_broadaddr; - sin0->sin_addr.s_addr = 0; - sin0->sin_family = AF_INET; - sin0->sin_len = sizeof(struct sockaddr_in); - - if (ioctl(sock, SIOCAIFADDR, &ifra) != 0 && errno != EEXIST) { - /* - * alias request, so EEXIST? - */ + if (priv_set_if_addr(_this->ifname, &_this->ip4addr) != 0 && + errno != EEXIST) { npppd_iface_log(_this, LOG_ERR, "Cannot assign tun device ip address: %m"); goto fail; @@ -220,7 +201,8 @@ npppd_iface_setup_ip(npppd_iface *_this) if (npppd_iface_ip_is_ready(_this)) { if (changed) { /* - * If there is a PPP session which was assigned interface IP address, disconnect it. + * If there is a PPP session which was assigned + * interface IP address, disconnect it. */ ppp = npppd_get_ppp_by_ip(_this->npppd, _this->ip4addr); if (ppp != NULL) { @@ -232,14 +214,15 @@ npppd_iface_setup_ip(npppd_iface *_this) } } /* ifconfig tun1 up */ - ifr.ifr_flags = if_flags | IFF_UP | IFF_MULTICAST; - if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { + if (priv_set_if_flags(_this->ifname, + if_flags | IFF_UP | IFF_MULTICAST) != 0) { npppd_iface_log(_this, LOG_ERR, "enabling %s failed: %m", _this->ifname); goto fail; } /* - * Add routing entry to communicate from host itself to _this->ip4addr. + * Add routing entry to communicate from host itself to + * _this->ip4addr. */ gw.s_addr = htonl(INADDR_LOOPBACK); in_host_route_add(&_this->ip4addr, &gw, LOOPBACK_IFNAME, 0); @@ -256,16 +239,18 @@ fail: /** set tunnel end address */ int -npppd_iface_reinit(npppd_iface *_this) +npppd_iface_reinit(npppd_iface *_this, struct iface *iface) { int rval; struct in_addr backup; char buf0[128], buf1[128]; + _this->ipcpconf = iface->ipcpconf; + backup = _this->ip4addr; + _this->ip4addr = iface->ip4addr; + if (_this->using_pppx) return 0; - - backup = _this->ip4addr; if ((rval = npppd_iface_setup_ip(_this)) != 0) return rval; @@ -287,14 +272,14 @@ npppd_iface_reinit(npppd_iface *_this) int npppd_iface_start(npppd_iface *_this) { - int x; - char buf[MAXPATHLEN]; + int x; + char buf[MAXPATHLEN]; NPPPD_IFACE_ASSERT(_this != NULL); /* open device file */ snprintf(buf, sizeof(buf), "/dev/%s", _this->ifname); - if ((_this->devf = open(buf, O_RDWR, 0600)) < 0) { + if ((_this->devf = priv_open(buf, O_RDWR, 0600)) < 0) { npppd_iface_log(_this, LOG_ERR, "open(%s) failed: %m", buf); goto fail; } @@ -310,8 +295,8 @@ npppd_iface_start(npppd_iface *_this) x = IFF_BROADCAST; if (ioctl(_this->devf, TUNSIFMODE, &x) != 0) { npppd_iface_log(_this, LOG_ERR, - "ioctl(TUNSIFMODE=IFF_BROADCAST) failed in %s(): %m", - __func__); + "ioctl(TUNSIFMODE=IFF_BROADCAST) failed " + "in %s(): %m", __func__); goto fail; } } @@ -343,9 +328,10 @@ npppd_iface_start(npppd_iface *_this) } else { npppd_iface_log(_this, LOG_INFO, "Started ip4addr=%s", (npppd_iface_ip_is_ready(_this))? - inet_ntop(AF_INET, &_this->ip4addr, buf, sizeof(buf)) - : "(not assigned)"); + inet_ntop(AF_INET, &_this->ip4addr, buf, + sizeof(buf)) : "(not assigned)"); } + _this->started = 1; return 0; fail: @@ -362,8 +348,14 @@ fail: void npppd_iface_stop(npppd_iface *_this) { - NPPPD_IFACE_ASSERT(_this != NULL); + struct in_addr gw; + NPPPD_IFACE_ASSERT(_this != NULL); + if (_this->using_pppx == 0) { + priv_delete_if_addr(_this->ifname); + gw.s_addr = htonl(INADDR_LOOPBACK); + in_host_route_delete(&_this->ip4addr, &gw); + } if (_this->devf >= 0) { #ifdef USE_NPPPD_PIPEX if (npppd_iface_pipex_disable(_this) != 0) { @@ -377,7 +369,7 @@ npppd_iface_stop(npppd_iface *_this) npppd_iface_log(_this, LOG_INFO, "Stopped"); } _this->devf = -1; - _this->initialized = 0; + _this->started = 0; event_del(&_this->ev); } @@ -386,8 +378,7 @@ void npppd_iface_fini(npppd_iface *_this) { NPPPD_IFACE_ASSERT(_this != NULL); - - npppd_iface_stop(_this); + _this->initialized = 0; } @@ -480,7 +471,7 @@ npppd_iface_network_input_delegate(struct radish *radish, void *args0) /* output via MPPE if MPPE started */ mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, args->pktp, args->lpktp); - } else if (MPPE_REQUIRED(ppp)) { + } else if (MPPE_IS_REQUIRED(ppp)) { /* in case MPPE not started but MPPE is mandatory, */ /* it is not necessary to log because of multicast. */ return 0; @@ -541,7 +532,7 @@ npppd_iface_network_input_ipv4(npppd_iface *_this, u_char *pktp, int lpktp) /* output via MPPE if MPPE started */ mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, pktp, lpktp); return; - } else if (MPPE_REQUIRED(ppp)) { + } 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."); diff --git a/usr.sbin/npppd/npppd/npppd_iface.h b/usr.sbin/npppd/npppd/npppd_iface.h index 9ae21ce2e98..7a1b76f0496 100644 --- a/usr.sbin/npppd/npppd/npppd_iface.h +++ b/usr.sbin/npppd/npppd/npppd_iface.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_iface.h,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: npppd_iface.h,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,8 +25,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#ifndef NPPPD_INTERFACE_H -#define NPPPD_INTERFACE_H 1 +#ifndef NPPPD_IFACE_H +#define NPPPD_IFACE_H 1 typedef struct _npppd_iface { /** base of npppd structure */ @@ -41,13 +41,7 @@ typedef struct _npppd_iface { /** for event(3) */ struct event ev; - /** maximum PPP sessions per user */ - int user_max_session; - /** maximum PPP sessions */ - int max_session; - - /** PPP sessions already connected */ - int nsession; + struct ipcpconf *ipcpconf; int /** * whether set IP address as npppd_iface's work or not. @@ -56,20 +50,22 @@ typedef struct _npppd_iface { set_ip4addr:1, /** set if using pppx(4) rather than tun(4) */ using_pppx:1, - /** initialized flag */ - initialized:1; + /** is initialized */ + initialized:1, + /** is started */ + started:1; } npppd_iface; /** whether interface IP address is usable or not */ -#define npppd_iface_ip_is_ready(int) \ - ((int)->initialized != 0 && (int)->ip4addr.s_addr != INADDR_ANY) +#define npppd_iface_ip_is_ready(_iface) \ + ((_iface)->initialized != 0 && (_iface)->ip4addr.s_addr != INADDR_ANY) #ifdef __cplusplus extern "C" { #endif -void npppd_iface_init (npppd_iface *, const char *, int); -int npppd_iface_reinit (npppd_iface *); +void npppd_iface_init (npppd *, npppd_iface *, struct iface *); +int npppd_iface_reinit (npppd_iface *, struct iface *); int npppd_iface_start (npppd_iface *); void npppd_iface_stop (npppd_iface *); void npppd_iface_fini (npppd_iface *); diff --git a/usr.sbin/npppd/npppd/npppd_local.h b/usr.sbin/npppd/npppd/npppd_local.h index 5a224da7a7a..366b22e082c 100644 --- a/usr.sbin/npppd/npppd/npppd_local.h +++ b/usr.sbin/npppd/npppd/npppd_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_local.h,v 1.10 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: npppd_local.h,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -40,7 +40,6 @@ #include "slist.h" #include "hash.h" -#include "properties.h" #include "debugutil.h" #ifdef USE_NPPPD_RADIUS @@ -67,8 +66,8 @@ #include "pppoe.h" #endif #include "npppd_auth.h" -#include "npppd_iface.h" #include "npppd.h" +#include "npppd_iface.h" #include "privsep.h" @@ -93,10 +92,8 @@ typedef struct _npppd_ctl { struct _npppd_pool { /** base of npppd structure */ npppd *npppd; - /** name of label */ - char label[NPPPD_GENERIC_NAME_LEN]; - /** name */ - char name[NPPPD_GENERIC_NAME_LEN]; + /** ipcp name */ + char ipcp_name[NPPPD_GENERIC_NAME_LEN]; /** size of sockaddr_npppd array */ int addrs_size; /** pointer indicated to sockaddr_npppd array */ @@ -109,58 +106,6 @@ struct _npppd_pool { running:1; }; -/** structure of IPCP configuration */ -typedef struct _npppd_ipcp_config { - /** name */ - char name[NPPPD_GENERIC_NAME_LEN]; - /** label (to associate with npppd structure) */ - char label[NPPPD_GENERIC_NAME_LEN]; - /** pointer indicated to parent npppd structure */ - npppd *npppd; - /** - * primary DNS server. INADDR_NONE if not inform peer this. - * specified in network byte order. - */ - struct in_addr dns_pri; - - /** secondary DNS server. INADDR_NONE if not inform peer this. - * specified in network byte order. - */ - struct in_addr dns_sec; - - /** - * primary WINS server. INADDR_NONE if not inform peer this. - * specified in network byte order. - */ - struct in_addr nbns_pri; - - /** - * secondary WINS server. INADDR_NONE if not inform peer this. - * specified in network byte order. - */ - struct in_addr nbns_sec; - - /** - * bit flag which specifies the way of IP address assignment. - * @see #NPPPD_IP_ASSIGN_FIXED - * @see #NPPPD_IP_ASSIGN_USER_SELECT - * @see #NPPPD_IP_ASSIGN_RADIUS - */ - int ip_assign_flags; - - int /** whether use tunnel end point address as DNS server or not */ - dns_use_tunnel_end:1, - /** whether initialized or not */ - initialized:1, - reserved:30; -} npppd_ipcp_config; - -/** structure which holds an interface of IPCP configuration and references of pool address */ -typedef struct _npppd_iface_binding { - npppd_ipcp_config *ipcp; - slist pools; -} npppd_iface_binding; - /** * npppd */ @@ -170,8 +115,8 @@ struct _npppd { /** interface which concentrates PPP */ npppd_iface iface[NPPPD_MAX_IFACE]; - /** reference of interface of IPCP configuration and pool address */ - npppd_iface_binding iface_bind[NPPPD_MAX_IFACE]; + + npppd_pool *iface_pool[NPPPD_MAX_IFACE]; /** address pool */ npppd_pool pool[NPPPD_MAX_POOL]; @@ -179,9 +124,6 @@ struct _npppd { /** radish pool which uses to manage allocated address */ struct radish_head *rd; - /** IPCP configuration */ - npppd_ipcp_config ipcp_config[NPPPD_MAX_IPCP_CONFIG]; - /** map of username to slist of npppd_ppp */ hash_table *map_user_ppp; @@ -216,10 +158,7 @@ struct _npppd { pppoed pppoed; #endif /** configuration file */ - struct properties * properties; - - /** user properties file */ - struct properties * users_props; + struct npppd_conf conf; npppd_ctl ctl; /** the time in seconds which process was started.*/ @@ -230,7 +169,8 @@ struct _npppd { /** counter of reload configuration */ int16_t reloading_count; - /** maximum PPP sessions */ + int nsession; + int user_max_session; int max_session; u_int /** whether finalizing or not */ @@ -241,15 +181,9 @@ struct _npppd { stop_by_error:1; }; -#ifndef NPPPD_CONFIG_BUFSIZ -#define NPPPD_CONFIG_BUFSIZ 65536 // 64K -#endif -#ifndef NPPPD_KEY_BUFSIZ -#define NPPPD_KEY_BUFSIZ 512 -#endif #define ppp_iface(ppp) (&(ppp)->pppd->iface[(ppp)->ifidx]) -#define ppp_ipcp(ppp) ((ppp)->pppd->iface_bind[(ppp)->ifidx].ipcp) -#define ppp_pools(ppp) (&(ppp)->pppd->iface_bind[(ppp)->ifidx].pools) +#define ppp_ipcp(ppp) ((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf) +#define ppp_pool(ppp) ((ppp)->pppd->iface_pool[(ppp)->ifidx]) #define SIN(sa) ((struct sockaddr_in *)(sa)) @@ -259,12 +193,18 @@ struct _npppd { : (interval) + NPPPD_TIMER_TICK_IVAL \ - ((interval) % NPPPD_TIMER_TICK_IVAL)) + + +#ifdef __cplusplus +extern "C" { +#endif + void npppd_ctl_init (npppd_ctl *, npppd *, const char *); int npppd_ctl_start (npppd_ctl *); void npppd_ctl_stop (npppd_ctl *); -#define sin46_port(x) (((x)->sa_family == AF_INET6) \ - ? ((struct sockaddr_in6 *)(x))->sin6_port \ - : ((struct sockaddr_in *)(x))->sin_port) +#ifdef __cplusplus +} +#endif #endif diff --git a/usr.sbin/npppd/npppd/npppd_pool.c b/usr.sbin/npppd/npppd/npppd_pool.c index c9f4160463c..1deb0aa1f8a 100644 --- a/usr.sbin/npppd/npppd/npppd_pool.c +++ b/usr.sbin/npppd/npppd/npppd_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_pool.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: npppd_pool.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -47,10 +47,8 @@ #include "slist.h" #include "debugutil.h" -#include "properties.h" #include "addr_range.h" #include "radish.h" -#include "config_helper.h" #include "npppd_local.h" #include "npppd_pool.h" #include "npppd_subr.h" @@ -75,7 +73,6 @@ #define SHUFLLE_MARK 0xffffffffL static int npppd_pool_log __P((npppd_pool *, int, const char *, ...)) __printflike(3, 4); -static int in_addr_range_list_add_all (struct in_addr_range **, const char *); static int is_valid_host_address (uint32_t); static int npppd_pool_regist_radish(npppd_pool *, struct in_addr_range *, struct sockaddr_npppd *, int ); @@ -90,7 +87,7 @@ npppd_pool_init(npppd_pool *_this, npppd *base, const char *name) { memset(_this, 0, sizeof(npppd_pool)); - strlcpy(_this->label, name, sizeof(_this->label)); + strlcpy(_this->ipcp_name, name, sizeof(_this->ipcp_name)); _this->npppd = base; slist_init(&_this->dyna_addrs); @@ -106,12 +103,6 @@ npppd_pool_start(npppd_pool *_this) return 0; /* nothing to do */ } -/* expand config template */; -NAMED_PREFIX_CONFIG_DECL(npppd_pool_config, npppd_pool, npppd->properties, - "pool", label); -NAMED_PREFIX_CONFIG_FUNCTIONS(npppd_pool_config, npppd_pool, npppd->properties, - "pool", label); - /** Finalize npppd_poll. */ void npppd_pool_uninit(npppd_pool *_this) @@ -133,45 +124,21 @@ npppd_pool_reload(npppd_pool *_this) int i, count, addrs_size; struct sockaddr_npppd *addrs; struct in_addr_range *pool, *dyna_pool, *range; - const char *val, *val0; char buf0[BUFSIZ], buf1[BUFSIZ]; + struct ipcpconf *ipcp; addrs = NULL; pool = NULL; dyna_pool = NULL; buf0[0] = '\0'; - val = npppd_pool_config_str(_this, "name"); - if (val == NULL) - val = _this->label; - strlcpy(_this->name, val, sizeof(_this->name)); - - /* dynamic address pool */ - val0 = NULL; - val = npppd_pool_config_str(_this, "dyna_pool"); - if (val != NULL) { - if (in_addr_range_list_add_all(&dyna_pool, val) != 0) { - npppd_pool_log(_this, LOG_WARNING, - "parse error at 'dyna_pool': %s", val); - goto fail; + TAILQ_FOREACH(ipcp, &_this->npppd->conf.ipcpconfs, entry) { + if (strcmp(ipcp->name, _this->ipcp_name) == 0) { + dyna_pool = ipcp->dynamic_pool; + pool = ipcp->static_pool; } - val0 = val; } - /* static address pool */ - val = npppd_pool_config_str(_this, "pool"); - if (val != NULL) { - if (in_addr_range_list_add_all(&pool, val) != 0) { - npppd_pool_log(_this, LOG_WARNING, - "parse error at 'pool': %s", val); - goto fail; - } - if (val0 != NULL) - /* Aggregate */ - in_addr_range_list_add_all(&pool, val0); - } - - /* preparing to register address with RADISH. */ addrs_size = 0; for (range = dyna_pool; range != NULL; range = range->next) addrs_size++; @@ -240,14 +207,9 @@ npppd_pool_reload(npppd_pool *_this) free(_this->addrs); _this->addrs = addrs; _this->addrs_size = addrs_size; - in_addr_range_list_remove_all(&pool); - in_addr_range_list_remove_all(&dyna_pool); return 0; fail: - in_addr_range_list_remove_all(&pool); - in_addr_range_list_remove_all(&dyna_pool); - if (addrs != NULL) free(addrs); @@ -296,7 +258,7 @@ npppd_pool_regist_radish(npppd_pool *_this, struct in_addr_range *range, npppd_pool_log(_this, LOG_WARNING, "%d.%d.%d.%d/%d is already defined as '%s'(%s)", A(range->addr), netmask2prefixlen(range->mask), - npool0->name, (snp0->snp_type == SNP_POOL) + npool0->ipcp_name, (snp0->snp_type == SNP_POOL) ? "static" : "dynamic"); goto fail; } @@ -610,27 +572,10 @@ npppd_pool_log(npppd_pool *_this, int prio, const char *fmt, ...) * so it can't NPPPD_POOL_ASSERT(_this != NULL). */ va_start(ap, fmt); - snprintf(logbuf, sizeof(logbuf), "pool name=%s %s", - (_this == NULL)? "null" : _this->name, fmt); + snprintf(logbuf, sizeof(logbuf), "ipcp=%s pool %s", + (_this == NULL)? "null" : _this->ipcp_name, fmt); status = vlog_printf(prio, logbuf, ap); va_end(ap); return status; } - -static int -in_addr_range_list_add_all(struct in_addr_range **range, const char *str) -{ - char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ]; - - strlcpy(buf, str, sizeof(buf)); - buf0 = buf; - - while ((tok = strsep(&buf0, " \r\n\t")) != NULL) { - if (tok[0] == '\0') - continue; - if (in_addr_range_list_add(range, tok) != 0) - return 1; - } - return 0; -} diff --git a/usr.sbin/npppd/npppd/npppd_radius.c b/usr.sbin/npppd/npppd/npppd_radius.c index 02db2dd8fbc..a405862de9f 100644 --- a/usr.sbin/npppd/npppd/npppd_radius.c +++ b/usr.sbin/npppd/npppd/npppd_radius.c @@ -1,4 +1,4 @@ -/* $Id: npppd_radius.c,v 1.4 2012/06/05 06:31:27 yasuoka Exp $ */ +/* $Id: npppd_radius.c,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. @@ -199,7 +199,7 @@ radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop) goto fail; if (radius_prepare(rad_setting, (void *)(uintptr_t)ppp->id, &radctx, - npppd_ppp_radius_acct_reqcb, 0) != 0) + npppd_ppp_radius_acct_reqcb) != 0) goto fail; /* NAS Information */ @@ -222,13 +222,13 @@ radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop) /* Tunnel Protocol Information */ switch (ppp->tunnel_type) { - case PPP_TUNNEL_L2TP: + case NPPPD_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: + case NPPPD_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) diff --git a/usr.sbin/npppd/npppd/pap.c b/usr.sbin/npppd/npppd/pap.c index aff752dd3d0..73eb31da384 100644 --- a/usr.sbin/npppd/npppd/pap.c +++ b/usr.sbin/npppd/npppd/pap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pap.c,v 1.6 2012/05/08 13:23:53 yasuoka Exp $ */ +/* $OpenBSD: pap.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: pap.c,v 1.6 2012/05/08 13:23:53 yasuoka Exp $ */ +/* $Id: pap.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * This file provides Password Authentication Protocol (PAP) handlers. * @author Yasuoka Masahiko @@ -401,8 +401,8 @@ pap_radius_authenticate(pap *_this, const char *username, const char *password) == NULL) goto fail; - if (radius_prepare(rad_setting, _this, &radctx, - pap_radius_response, _this->ppp->auth_timeout) != 0) { + if (radius_prepare(rad_setting, _this, &radctx, pap_radius_response) + != 0) { radius_delete_packet(radpkt); goto fail; } diff --git a/usr.sbin/npppd/npppd/parse.y b/usr.sbin/npppd/npppd/parse.y new file mode 100644 index 00000000000..cd2845da4f4 --- /dev/null +++ b/usr.sbin/npppd/npppd/parse.y @@ -0,0 +1,1551 @@ +/* $OpenBSD: parse.y,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ */ + +/* + * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. + * Copyright (c) 2001 Theo de Raadt. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +%{ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <netdb.h> +#include <event.h> + +#include <stdbool.h> +#include <stdarg.h> +#include "npppd_auth.h" +#include "slist.h" +#include "npppd.h" +#ifdef USE_NPPPD_RADIUS +#include "radius_req.h" +#endif +#include "privsep.h" + +TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); +static struct file { + TAILQ_ENTRY(file) entry; + FILE *stream; + char *name; + int lineno; + int errors; +} *file, *topfile; +struct file *pushfile(const char *); +int popfile(void); +int yyparse(void); +int yylex(void); +int yyerror(const char *, ...); +int kw_cmp(const void *, const void *); +int lookup(char *); +int lgetc(int); +int lungetc(int); +int findeol(void); + +static void tunnconf_init (struct tunnconf *, int); +static void tunnconf_fini (struct tunnconf *); +static struct tunnconf *tunnconf_find (const char *); +static void authconf_init (struct authconf *); +static void authconf_fini (struct authconf *); +static void radconf_fini (struct radconf *); +static struct authconf *authconf_find (const char *); +static void ipcpconf_init (struct ipcpconf *); +static void ipcpconf_fini (struct ipcpconf *); +static struct ipcpconf *ipcpconf_find (const char *); +struct iface *iface_find (const char *); + +struct npppd_conf *conf; +struct ipcpconf *curr_ipcpconf; +struct tunnconf *curr_tunnconf; +struct authconf *curr_authconf; +struct radconf *curr_radconf; + +typedef struct { + union { + int64_t number; + char *string; + struct sockaddr_storage address; + struct in_addr in4_addr; + bool yesno; + } v; + int lineno; +} YYSTYPE; + +%} + +%token SET MAX_SESSION USER_MAX_SESSION +%token TUNNEL LISTEN ON PROTOCOL +%token MRU +%token IP LCP PAP CHAP EAP MPPE CCP MSCHAPV2 STATEFUL STATELESS REQUIRED +%token YES NO +%token L2TP PPTP PPPOE L2TP_HOSTNAME L2TP_VENDOR_NAME L2TP_DATA_USE_SEQ +%token L2TP_REQUIRE_IPSEC L2TP_LCP_RENEGOTIATION L2TP_FORCE_LCP_RENEGOTIATION +%token L2TP_CTRL_IN_PKTDUMP L2TP_CTRL_OUT_PKTDUMP L2TP_DATA_IN_PKTDUMP +%token L2TP_DATA_OUT_PKTDUMP PPTP_HOSTNAME +%token PPTP_VENDOR_NAME PPTP_ECHO_INTERVAL PPTP_ECHO_TIMEOUT +%token PPTP_CTRL_IN_PKTDUMP PPTP_CTRL_OUT_PKTDUMP PPTP_DATA_IN_PKTDUMP +%token PPTP_DATA_OUT_PKTDUMP +%token PPPOE_SERVICE_NAME PPPOE_ACCEPT_ANY_SERVICE PPPOE_AC_NAME +%token PPPOE_DESC_IN_PKTDUMP PPPOE_DESC_OUT_PKTDUMP PPPOE_SESSION_IN_PKTDUMP +%token PPPOE_SESSION_OUT_PKTDUMP +%token LCP_TIMEOUT LCP_MAX_CONFIGURE LCP_MAX_TERMINATE LCP_MAX_NAK_LOOP +%token LCP_KEEPALIVE LCP_KEEPALIVE_INTERVAL LCP_KEEPALIVE_RETRY_INTERVAL +%token LCP_KEEPALIVE_MAX_RETRIES AUTHENTICATION_METHOD CHAP_NAME +%token IPCP_TIMEOUT IPCP_MAX_CONFIGURE IPCP_MAX_TERMINATE IPCP_MAX_NAK_LOOP +%token CCP_TIMEOUT CCP_MAX_CONFIGURE CCP_MAX_TERMINATE CCP_MAX_NAK_LOOP +%token L2TP_HELLO_INTERVAL L2TP_HELLO_TIMEOUT L2TP_ACCEPT_DIALIN +%token MPPE MPPE_KEY_LENGTH MPPE_KEY_STATE +%token IDLE_TIMEOUT TCP_MSS_ADJUST INGRESS_FILTER CALLNUM_CHECK +%token PIPEX DEBUG_DUMP_PKTIN DEBUG_DUMP_PKTOUT +%token AUTHENTICATION TYPE LOCAL USERNAME_SUFFIX USERNAME_PREFIX EAP_CAPABLE +%token STRIP_NT_DOMAIN STRIP_ATMARK_REALM USERS_FILE +%token RADIUS AUTHENTICATION_SERVER ACCOUNTING_SERVER PORT +%token X_TIMEOUT MAX_TRIES MAX_FAILOVERS SECRET +%token POOL_ADDRESS DNS_SERVERS NBNS_SERVERS FOR STATIC DYNAMIC +%token RESOLVER ALLOW_USER_SELECTED_ADDRESS +%token INTERFACE ADDRESS IPCP +%token BIND FROM AUTHENTICATED BY TO +%token ERROR +%token <v.string> STRING +%token <v.number> NUMBER +%type <v.yesno> yesno +%type <v.address> address +%type <v.address> addressport +%type <v.number> optport +%type <v.in4_addr> in4_addr +%type <v.number> tunnelproto +%type <v.number> mppeyesno +%type <v.number> mppekeylen +%type <v.number> mppekeylen_l +%type <v.number> mppekeystate +%type <v.number> mppekeystate_l +%type <v.number> protobit +%type <v.number> protobit_l +%type <v.number> authtype +%type <v.number> authmethod +%type <v.number> authmethod_l +%type <v.number> ipcppooltype + +%% + +grammar : /* empty */ + | grammar '\n' + | grammar set '\n' + | grammar tunnel '\n' + | grammar authentication '\n' + | grammar ipcp '\n' + | grammar interface '\n' + | grammar bind '\n' + | grammar error '\n' { file->errors++; } + ; + + +set : SET MAX_SESSION NUMBER { conf->max_session = $3; } + | SET USER_MAX_SESSION NUMBER { conf->user_max_session = $3; } + ; + +/* + * tunnel { } + */ +tunnel : TUNNEL STRING PROTOCOL tunnelproto { + struct tunnconf *n; + + if (tunnconf_find($2) != NULL) { + yyerror("tunnel name = %s is already in use.", + $2); + free($2); + YYERROR; + } + + if ((n = malloc(sizeof(struct tunnconf))) == NULL) { + yyerror("out of memory"); + free($2); + YYERROR; + } + tunnconf_init(n, $4); + switch ($4) { + case NPPPD_TUNNEL_L2TP: + strlcpy(n->proto.l2tp.name, $2, + sizeof(n->proto.l2tp.name)); + n->name = n->proto.l2tp.name; + break; + case NPPPD_TUNNEL_PPTP: + strlcpy(n->proto.pptp.name, $2, + sizeof(n->proto.pptp.name)); + n->name = n->proto.pptp.name; + break; + case NPPPD_TUNNEL_PPPOE: + strlcpy(n->proto.pppoe.name, $2, + sizeof(n->proto.pppoe.name)); + n->name = n->proto.pppoe.name; + break; + } + free($2); + n->protocol = $4; + curr_tunnconf = n; + } tunnopts { + TAILQ_INSERT_TAIL(&conf->tunnconfs, curr_tunnconf, + entry); + switch (curr_tunnconf->protocol) { +#ifdef USE_NPPPD_L2TP + case NPPPD_TUNNEL_L2TP: + TAILQ_INSERT_TAIL(&conf->l2tp_confs, + &curr_tunnconf->proto.l2tp, entry); + break; +#endif +#ifdef USE_NPPPD_PPTP + case NPPPD_TUNNEL_PPTP: + TAILQ_INSERT_TAIL(&conf->pptp_confs, + &curr_tunnconf->proto.pptp, entry); + break; +#endif +#ifdef USE_NPPPD_PPPOE + case NPPPD_TUNNEL_PPPOE: + TAILQ_INSERT_TAIL(&conf->pppoe_confs, + &curr_tunnconf->proto.pppoe, entry); + break; +#endif + default: + yyerror("%s is not enabled.", + npppd_tunnel_protocol_name( + curr_tunnconf->protocol)); + tunnconf_fini(curr_tunnconf); + free(curr_tunnconf); + YYERROR; + } + curr_tunnconf = NULL; + } + ; + + +tunnopts : + | '{' optnl tunnopt_l '}' + ; + +tunnopt_l : /* empty */ + | tunnopt_l tunnopt nl + | tunnopt optnl + ; + +tunnopt : LISTEN ON addressport { + switch (curr_tunnconf->protocol) { + case NPPPD_TUNNEL_L2TP: + curr_tunnconf->proto.l2tp.address = $3; + break; + case NPPPD_TUNNEL_PPTP: + curr_tunnconf->proto.pptp.address = $3; + break; + default: + yyerror("listen on address is not supported " + "for specified protocol.\n"); + YYERROR; + } + } + | LISTEN ON INTERFACE STRING { + switch (curr_tunnconf->protocol) { + case NPPPD_TUNNEL_PPPOE: + strlcpy(curr_tunnconf->proto.pppoe.if_name, $4, + sizeof(curr_tunnconf->proto.pppoe.if_name)); + free($4); + break; + default: + free($4); + yyerror("listen on interface is not supported " + "for specified protocol.\n"); + YYERROR; + } + } + | LCP_TIMEOUT NUMBER { + curr_tunnconf->lcp_timeout = $2; + } + | LCP_MAX_CONFIGURE NUMBER { + curr_tunnconf->lcp_max_configure = $2; + } + | LCP_MAX_TERMINATE NUMBER { + curr_tunnconf->lcp_max_terminate = $2; + } + | LCP_MAX_NAK_LOOP NUMBER { + curr_tunnconf->lcp_max_nak_loop = $2; + } + | MRU NUMBER { + curr_tunnconf->mru = $2; + } + | LCP_KEEPALIVE yesno { + curr_tunnconf->lcp_keepalive = $2; + } + | LCP_KEEPALIVE_INTERVAL NUMBER { + curr_tunnconf->lcp_keepalive_interval = $2; + } + | LCP_KEEPALIVE_RETRY_INTERVAL NUMBER { + curr_tunnconf->lcp_keepalive_retry_interval = $2; + } + | LCP_KEEPALIVE_MAX_RETRIES NUMBER { + curr_tunnconf->lcp_keepalive_max_retries = $2; + } + | AUTHENTICATION_METHOD authmethod_l { + curr_tunnconf->auth_methods = $2; + } + | CHAP_NAME STRING { + curr_tunnconf->chap_name = $2; + } + | IPCP_TIMEOUT NUMBER { + curr_tunnconf->ipcp_timeout = $2; + } + | IPCP_MAX_CONFIGURE NUMBER { + curr_tunnconf->ipcp_max_configure = $2; + } + | IPCP_MAX_TERMINATE NUMBER { + curr_tunnconf->ipcp_max_terminate = $2; + } + | IPCP_MAX_NAK_LOOP NUMBER { + curr_tunnconf->ipcp_max_nak_loop = $2; + } + | CCP_TIMEOUT NUMBER { + curr_tunnconf->ccp_timeout = $2; + } + | CCP_MAX_CONFIGURE NUMBER { + curr_tunnconf->ccp_max_configure = $2; + } + | CCP_MAX_TERMINATE NUMBER { + curr_tunnconf->ccp_max_terminate = $2; + } + | CCP_MAX_NAK_LOOP NUMBER { + curr_tunnconf->ccp_max_nak_loop = $2; + } + | L2TP_HOSTNAME STRING { + curr_tunnconf->proto.l2tp.hostname = $2; + } + | L2TP_VENDOR_NAME STRING { + curr_tunnconf->proto.l2tp.vendor_name = $2; + } + | L2TP_HELLO_INTERVAL NUMBER { + curr_tunnconf->proto.l2tp.hello_interval = $2; + } + | L2TP_HELLO_TIMEOUT NUMBER { + curr_tunnconf->proto.l2tp.hello_timeout = $2; + } + | L2TP_ACCEPT_DIALIN yesno { + curr_tunnconf->proto.l2tp.accept_dialin = $2; + } + | L2TP_DATA_USE_SEQ yesno { + curr_tunnconf->proto.l2tp.data_use_seq = $2; + } + | L2TP_REQUIRE_IPSEC yesno { + curr_tunnconf->proto.l2tp.require_ipsec = $2; + } + | L2TP_LCP_RENEGOTIATION yesno { + curr_tunnconf->proto.l2tp.lcp_renegotiation = $2; + } + | L2TP_FORCE_LCP_RENEGOTIATION yesno { + curr_tunnconf->proto.l2tp.force_lcp_renegotiation = $2; + } + | L2TP_CTRL_IN_PKTDUMP yesno { + curr_tunnconf->proto.l2tp.ctrl_in_pktdump = $2; + } + | L2TP_CTRL_OUT_PKTDUMP yesno { + curr_tunnconf->proto.l2tp.ctrl_out_pktdump = $2; + } + | L2TP_DATA_IN_PKTDUMP yesno { + curr_tunnconf->proto.l2tp.data_in_pktdump = $2; + } + | L2TP_DATA_OUT_PKTDUMP yesno { + curr_tunnconf->proto.l2tp.data_out_pktdump = $2; + } + | PPTP_HOSTNAME STRING { + curr_tunnconf->proto.pptp.hostname = $2; + } + | PPTP_VENDOR_NAME STRING { + curr_tunnconf->proto.pptp.vendor_name = $2; + } + | PPTP_ECHO_INTERVAL NUMBER { + curr_tunnconf->proto.pptp.echo_interval = $2; + } + | PPTP_ECHO_TIMEOUT NUMBER { + curr_tunnconf->proto.pptp.echo_timeout = $2; + } + | PPTP_CTRL_IN_PKTDUMP yesno { + curr_tunnconf->proto.pptp.ctrl_in_pktdump = $2; + } + | PPTP_CTRL_OUT_PKTDUMP yesno { + curr_tunnconf->proto.pptp.ctrl_out_pktdump = $2; + } + | PPTP_DATA_IN_PKTDUMP yesno { + curr_tunnconf->proto.pptp.data_in_pktdump = $2; + } + | PPTP_DATA_OUT_PKTDUMP yesno { + curr_tunnconf->proto.pptp.data_out_pktdump = $2; + } + | PPPOE_SERVICE_NAME STRING { + curr_tunnconf->proto.pppoe.service_name = $2; + } + | PPPOE_ACCEPT_ANY_SERVICE yesno { + curr_tunnconf->proto.pppoe.accept_any_service = $2; + } + | PPPOE_AC_NAME STRING { + curr_tunnconf->proto.pppoe.ac_name = $2; + } + | PPPOE_DESC_IN_PKTDUMP yesno { + curr_tunnconf->proto.pppoe.desc_in_pktdump = $2; + } + | PPPOE_DESC_OUT_PKTDUMP yesno { + curr_tunnconf->proto.pppoe.desc_out_pktdump = $2; + } + | PPPOE_SESSION_IN_PKTDUMP yesno { + curr_tunnconf->proto.pppoe.session_in_pktdump = $2; + } + | PPPOE_SESSION_OUT_PKTDUMP yesno { + curr_tunnconf->proto.pppoe.session_out_pktdump = $2; + } + | MPPE mppeyesno { + curr_tunnconf->mppe_yesno = $2; + } + | MPPE_KEY_LENGTH mppekeylen_l { + curr_tunnconf->mppe_keylen = $2; + } + | MPPE_KEY_STATE mppekeystate_l { + curr_tunnconf->mppe_keystate = $2; + } + | TCP_MSS_ADJUST yesno { + curr_tunnconf->tcp_mss_adjust = $2; + } + | IDLE_TIMEOUT NUMBER { + curr_tunnconf->idle_timeout = $2; + } + | INGRESS_FILTER yesno { + curr_tunnconf->ingress_filter = $2; + } + | CALLNUM_CHECK yesno { + curr_tunnconf->callnum_check = $2; + } + | PIPEX yesno { + curr_tunnconf->pipex = $2; + } + | DEBUG_DUMP_PKTIN protobit_l { + curr_tunnconf->debug_dump_pktin = $2; + } + | DEBUG_DUMP_PKTOUT protobit_l { + curr_tunnconf->debug_dump_pktout = $2; + } + ; + +tunnelproto : L2TP { $$ = NPPPD_TUNNEL_L2TP; } + | PPTP { $$ = NPPPD_TUNNEL_PPTP; } + | PPPOE { $$ = NPPPD_TUNNEL_PPPOE; } + ; + +mppeyesno : YES { $$ = NPPPD_MPPE_ENABLED; } + | NO { $$ = NPPPD_MPPE_DISABLED; } + | REQUIRED { $$ = NPPPD_MPPE_REQUIRED; } + ; + +address : STRING { + int retval; + struct addrinfo hint, *res; + + memset(&hint, 0, sizeof(hint)); + hint.ai_family = PF_UNSPEC; + hint.ai_socktype = SOCK_DGRAM; /* dummy */ + hint.ai_flags = AI_NUMERICHOST; + + if ((retval = getaddrinfo($1, NULL, &hint, &res)) + != 0) { + yyerror("could not parse the address %s: %s", + $1, gai_strerror(retval)); + free($1); + YYERROR; + } + free($1); + + if (res->ai_family != AF_INET && + res->ai_family != AF_INET6) { + yyerror("address family(%d) is not supported", + res->ai_family); + freeaddrinfo(res); + YYERROR; + } + memcpy(&($$), res->ai_addr, res->ai_addrlen); + + freeaddrinfo(res); + } + ; + +addressport : address optport { + $$ = $1; + ((struct sockaddr_in *)&($$))->sin_port = htons($2); + } + ; + +in4_addr : STRING { + if (inet_aton($1, &($$)) != 1) { + yyerror("could not parse the address %s"); + free($1); + YYERROR; + } + } + ; + +authmethod_l : authmethod { $$ = $1; } + | authmethod_l authmethod { $$ |= $2; } + ; + +authmethod : PAP { $$ = NPPPD_AUTH_METHODS_PAP; } + | CHAP { $$ = NPPPD_AUTH_METHODS_CHAP; } + | MSCHAPV2 { + $$ = NPPPD_AUTH_METHODS_MSCHAPV2; + } + ; + +mppekeylen_l : mppekeylen { $$ = $1; } + | mppekeylen_l mppekeylen { $$ |= $2; } + ; + +mppekeylen : NUMBER { + if ($1 == 40) $$ = NPPPD_MPPE_40BIT; + else if ($1 == 56) $$ = NPPPD_MPPE_56BIT; + else if ($1 == 128) $$ = NPPPD_MPPE_128BIT; + else { + yyerror("%d: unknown mppe key length", $$); + YYERROR; + } + } + ; + +mppekeystate_l : mppekeystate { $$ = $1; } + | mppekeystate_l mppekeystate { $$ |= $2; } + ; + +mppekeystate : STATEFUL { $$ = NPPPD_MPPE_STATEFUL; } + | STATELESS { $$ = NPPPD_MPPE_STATELESS; } + ; + +protobit_l : protobit { $$ = $1; } + | protobit_l protobit { $$ |= $2; } + ; + +protobit : IP { $$ = NPPPD_PROTO_BIT_IP; } + | LCP { $$ = NPPPD_PROTO_BIT_LCP; } + | PAP { $$ = NPPPD_PROTO_BIT_PAP; } + | CHAP { $$ = NPPPD_PROTO_BIT_CHAP; } + | EAP { $$ = NPPPD_PROTO_BIT_EAP; } + | MPPE { $$ = NPPPD_PROTO_BIT_MPPE; } + | CCP { $$ = NPPPD_PROTO_BIT_CCP; } + | IPCP { $$ = NPPPD_PROTO_BIT_IPCP; } + ; + +/* + * authentication { } + */ +authentication : AUTHENTICATION STRING TYPE authtype { + struct authconf *n; + + if (authconf_find($2) != NULL) { + yyerror("authentication name %s is already in " + "use.", $2); + free($2); + YYERROR; + } + if ((n = malloc(sizeof(struct authconf))) == NULL) { + yyerror("out of memory"); + free($2); + YYERROR; + } + authconf_init(n); + strlcpy(n->name, $2, sizeof(n->name)); + free($2); + n->auth_type = $4; + if ($4 == NPPPD_AUTH_TYPE_RADIUS) { + TAILQ_INIT(&n->radius.auth.servers); + TAILQ_INIT(&n->radius.acct.servers); + } + curr_authconf = n; + } '{' optnl authopt_l '}' { + TAILQ_INSERT_TAIL(&conf->authconfs, curr_authconf, + entry); + curr_authconf = NULL; + } + ; + +authopt_l : /* empty */ + | authopt_l authopt nl + | authopt optnl + ; + +authopt : USERNAME_SUFFIX STRING { + curr_authconf->username_suffix = $2; + } + | USERNAME_PREFIX STRING { + curr_authconf->username_prefix = $2; + } + | EAP_CAPABLE yesno { + curr_authconf->eap_capable = $2; + } + | STRIP_NT_DOMAIN yesno { + curr_authconf->eap_capable = $2; + } + | STRIP_ATMARK_REALM yesno { + curr_authconf->eap_capable = $2; + } + | USERS_FILE STRING { + strlcpy(curr_authconf->users_file_path, $2, + sizeof(curr_authconf->users_file_path)); + free($2); + } + | AUTHENTICATION_SERVER { + if (curr_authconf->auth_type != NPPPD_AUTH_TYPE_RADIUS){ + yyerror("`authentication-server' can not be " + "used for this type."); + YYERROR; + } + curr_radconf = &curr_authconf->radius.auth; + } '{' optnl radopt_l '}' { + curr_radconf = NULL; + } + | ACCOUNTING_SERVER { + if (curr_authconf->auth_type != NPPPD_AUTH_TYPE_RADIUS){ + yyerror("`accounting-server' can not be used " + "for this type."); + YYERROR; + } + curr_radconf = &curr_authconf->radius.acct; + TAILQ_INIT(&curr_radconf->servers); + } '{' optnl radopt_l '}' { + curr_radconf = NULL; + } + ; + +optport : /* empty */ { $$ = 0; } + | PORT NUMBER { $$ = $2; } + ; + +authtype : LOCAL { $$ = NPPPD_AUTH_TYPE_LOCAL; } + | RADIUS { $$ = NPPPD_AUTH_TYPE_RADIUS; } + ; + +radopt_l : + | radopt_l radopt nl + | radopt optnl + ; + +radopt : ADDRESS address optport SECRET STRING { + int cnt; + struct radserver *n; + + if (strlen($5) > MAX_RADIUS_SECRET - 1) { + yyerror("`secret' is too long. " + "use less than %d chars.", + MAX_RADIUS_SECRET - 1); + YYERROR; + } + cnt = 0; + TAILQ_FOREACH(n, &curr_radconf->servers, entry) { + cnt++; + } + if (cnt >= MAX_RADIUS_SERVERS) { + yyerror("too many radius servers. use less " + "than or equal to %d servers.", + MAX_RADIUS_SERVERS); + YYERROR; + } + if ((n = malloc(sizeof(struct radserver))) == NULL) { + yyerror("out of memory"); + YYERROR; + } + n->address = $2; + ((struct sockaddr_in *)&n->address)->sin_port = $3; + n->secret = $5; + TAILQ_INSERT_TAIL(&curr_radconf->servers, n, entry); + } + | X_TIMEOUT NUMBER { + curr_radconf->timeout = $2; + } + | MAX_TRIES NUMBER { + curr_radconf->max_tries = $2; + } + | MAX_FAILOVERS NUMBER { + curr_radconf->max_failovers = $2; + } + ; +/* + * ipcp { } + */ +ipcp : IPCP STRING { + int cnt; + struct ipcpconf *n; + + cnt = 0; + /* + TAILQ_FOREACH(n, &conf->ipcpconfs, entry) { + cnt++; + } + if (cnt >= NPPPD_MAX_POOL) { + yyerror("too many `ipcp' settings. it must be " + "less than or euals to %d.", + NPPPD_MAX_POOL); + YYERROR; + } + */ + + if (ipcpconf_find($2) != NULL) { + yyerror("ipcp name %s is already in use.", $2); + free($2); + YYERROR; + } + if ((n = malloc(sizeof(struct ipcpconf))) == NULL) { + yyerror("out of memory"); + free($2); + YYERROR; + } + ipcpconf_init(n); + strlcpy(n->name, $2, sizeof(n->name)); + free($2); + curr_ipcpconf = n; + } '{' optnl ipcpopt_l '}' { + TAILQ_INSERT_TAIL(&conf->ipcpconfs, curr_ipcpconf, + entry); + curr_ipcpconf = NULL; + } + ; + +ipcpopt_l : /* empty */ + | ipcpopt_l ipcpopt nl + | ipcpopt optnl + ; + +ipcpopt : POOL_ADDRESS STRING ipcppooltype { + if ($3 != 1) { + if (in_addr_range_list_add( + &curr_ipcpconf->dynamic_pool, $2) != 0) { + yyerror("out of memory"); + free($2); + YYERROR; + } + } + if (in_addr_range_list_add( + &curr_ipcpconf->static_pool, $2) != 0) { + yyerror("out of memory"); + free($2); + YYERROR; + } + free($2); + } + | DNS_SERVERS RESOLVER { + curr_ipcpconf->dns_use_resolver = true; + curr_ipcpconf->dns_servers[0].s_addr = 0; + curr_ipcpconf->dns_servers[1].s_addr = 0; + } + | DNS_SERVERS in4_addr in4_addr { + curr_ipcpconf->dns_use_resolver = false; + curr_ipcpconf->dns_servers[0] = $2; + curr_ipcpconf->dns_servers[1] = $3; + } + | DNS_SERVERS in4_addr { + curr_ipcpconf->dns_use_resolver = false; + curr_ipcpconf->dns_servers[0] = $2; + curr_ipcpconf->dns_servers[1].s_addr = 0; + } + | NBNS_SERVERS in4_addr in4_addr { + curr_ipcpconf->nbns_servers[0] = $2; + curr_ipcpconf->nbns_servers[1] = $3; + } + | NBNS_SERVERS in4_addr { + curr_ipcpconf->nbns_servers[0] = $2; + curr_ipcpconf->nbns_servers[1].s_addr = 0; + } + | ALLOW_USER_SELECTED_ADDRESS yesno { + curr_ipcpconf->allow_user_select = $2; + } + ; + +ipcppooltype : /* empty */ { $$ = 0; } + | FOR DYNAMIC { $$ = 0; } + | FOR STATIC { $$ = 1; } + ; + + +/* + * interface + */ +interface : INTERFACE STRING ADDRESS in4_addr IPCP STRING { + int cnt; + struct iface *n; + struct ipcpconf *ipcp; + + cnt = 0; + TAILQ_FOREACH(n, &conf->ifaces, entry) { + cnt++; + } + if (cnt >= NPPPD_MAX_IFACE) { + yyerror("too many interfaces. use less than " + "or equal to %d", NPPPD_MAX_IFACE); + YYERROR; + } + + if ((ipcp = ipcpconf_find($6)) == NULL) { + yyerror("ipcp %s is not found", $6); + free($2); + YYERROR; + } + if (iface_find($2) != NULL) { + yyerror("interface %s is already in used.", $2); + free($2); + YYERROR; + } + + if ((n = malloc(sizeof(struct iface))) == NULL) { + yyerror("out of memory"); + free($2); + YYERROR; + } + strlcpy(n->name, $2, sizeof(n->name)); + free($2); + n->ip4addr = $4; + if (strncmp(n->name, "pppx", 4) == 0) + n->is_pppx = true; + + n->ipcpconf = ipcp; + TAILQ_INSERT_TAIL(&conf->ifaces, n, entry); + } + ; + +/* + * bind + */ +bind : BIND TUNNEL FROM STRING AUTHENTICATED BY STRING TO STRING { + struct authconf *auth; + struct tunnconf *tunn; + struct iface *iface; + struct confbind *n; + + if ((tunn = tunnconf_find($4)) == NULL) { + yyerror("tunnel %s is not found", $4); + free($4); + free($7); + free($9); + YYERROR; + } + if ((auth = authconf_find($7)) == NULL) { + yyerror("authentication %s is not found", $7); + free($4); + free($7); + free($9); + YYERROR; + } + if ((iface = iface_find($9)) == NULL) { + yyerror("interface %s is not found", $9); + free($4); + free($7); + free($9); + YYERROR; + } + if ((n = malloc(sizeof(struct confbind))) == NULL) { + yyerror("out of memory"); + free($4); + free($7); + free($9); + YYERROR; + } + n->tunnconf = tunn; + n->authconf = auth; + n->iface = iface; + TAILQ_INSERT_TAIL(&conf->confbinds, n, entry); + } + ; + +yesno : YES { $$ = true; } + | NO { $$ = false; } + ; + +optnl : '\n' optnl + | + ; + +nl : '\n' optnl + ; + +%% + +struct keywords { + const char *k_name; + int k_val; +}; + +int +yyerror(const char *fmt, ...) +{ + va_list ap; + char *nfmt; + + file->errors++; + va_start(ap, fmt); + if (asprintf(&nfmt, "%s:%d: %s", file->name, yylval.lineno, fmt) == -1) + fatalx("yyerror asprintf"); + vlog(LOG_CRIT, nfmt, ap); + va_end(ap); + free(nfmt); + return (0); +} + +int +kw_cmp(const void *k, const void *e) +{ + return (strcmp(k, ((const struct keywords *)e)->k_name)); +} + +int +lookup(char *s) +{ + /* this has to be sorted always */ + static const struct keywords keywords[] = { + { "accounting-server", ACCOUNTING_SERVER}, + { "address", ADDRESS}, + { "allow-user-selected-address", ALLOW_USER_SELECTED_ADDRESS}, + { "authenticated", AUTHENTICATED}, + { "authentication", AUTHENTICATION}, + { "authentication-method", AUTHENTICATION_METHOD}, + { "authentication-server", AUTHENTICATION_SERVER}, + { "bind", BIND}, + { "by", BY}, + { "callnum-check", CALLNUM_CHECK}, + { "ccp", CCP}, + { "ccp-max-configure", CCP_MAX_CONFIGURE}, + { "ccp-max-nak-loop", CCP_MAX_NAK_LOOP}, + { "ccp-max-terminate", CCP_MAX_TERMINATE}, + { "ccp-timeout", CCP_TIMEOUT}, + { "chap", CHAP}, + { "chap-name", CHAP_NAME}, + { "debug-dump-pktin", DEBUG_DUMP_PKTIN}, + { "debug-dump-pktout", DEBUG_DUMP_PKTOUT}, + { "dns-servers", DNS_SERVERS}, + { "dynamic", DYNAMIC}, + { "eap", EAP}, + { "eap-capable", EAP_CAPABLE}, + { "for", FOR}, + { "from", FROM}, + { "idle-timeout", IDLE_TIMEOUT}, + { "ingress-filter", INGRESS_FILTER}, + { "interface", INTERFACE}, + { "ip", IP}, + { "ipcp", IPCP}, + { "ipcp-max-configure", IPCP_MAX_CONFIGURE}, + { "ipcp-max-nak-loop", IPCP_MAX_NAK_LOOP}, + { "ipcp-max-terminate", IPCP_MAX_TERMINATE}, + { "ipcp-timeout", IPCP_TIMEOUT}, + { "l2tp", L2TP}, + { "l2tp-accept-dialin", L2TP_ACCEPT_DIALIN}, + { "l2tp-ctrl-in-pktdump", L2TP_CTRL_IN_PKTDUMP}, + { "l2tp-ctrl-out-pktdump", L2TP_CTRL_OUT_PKTDUMP}, + { "l2tp-data-in-pktdump", L2TP_DATA_IN_PKTDUMP}, + { "l2tp-data-out-pktdump", L2TP_DATA_OUT_PKTDUMP}, + { "l2tp-data-use-seq", L2TP_DATA_USE_SEQ}, + { "l2tp-force-lcp-renegotiation", L2TP_FORCE_LCP_RENEGOTIATION}, + { "l2tp-hello-interval", L2TP_HELLO_INTERVAL}, + { "l2tp-hello-timeout", L2TP_HELLO_TIMEOUT}, + { "l2tp-hostname", L2TP_HOSTNAME}, + { "l2tp-lcp-renegotiation", L2TP_LCP_RENEGOTIATION}, + { "l2tp-require-ipsec", L2TP_REQUIRE_IPSEC}, + { "l2tp-vendor-name", L2TP_VENDOR_NAME}, + { "lcp", LCP}, + { "lcp-keepalive", LCP_KEEPALIVE}, + { "lcp-keepalive-interval", LCP_KEEPALIVE_INTERVAL}, + { "lcp-keepalive-max-retries", LCP_KEEPALIVE_MAX_RETRIES }, + { "lcp-keepalive-retry-interval", LCP_KEEPALIVE_RETRY_INTERVAL}, + { "lcp-max-configure", LCP_MAX_CONFIGURE}, + { "lcp-max-nak-loop", LCP_MAX_NAK_LOOP}, + { "lcp-max-terminate", LCP_MAX_TERMINATE}, + { "lcp-timeout", LCP_TIMEOUT}, + { "listen", LISTEN}, + { "local", LOCAL}, + { "max-failovers", MAX_FAILOVERS}, + { "max-session", MAX_SESSION}, + { "max-tries", MAX_TRIES}, + { "mppe", MPPE}, + { "mppe", MPPE}, + { "mppe-key-length", MPPE_KEY_LENGTH}, + { "mppe-key-state", MPPE_KEY_STATE}, + { "mru", MRU}, + { "mschapv2", MSCHAPV2}, + { "nbns-servers", NBNS_SERVERS}, + { "no", NO}, + { "on", ON}, + { "pap", PAP}, + { "pipex", PIPEX}, + { "pool-address", POOL_ADDRESS}, + { "port", PORT}, + { "pppoe", PPPOE}, + { "pppoe-ac-name", PPPOE_AC_NAME}, + { "pppoe-accept-any-service", PPPOE_ACCEPT_ANY_SERVICE}, + { "pppoe-desc-in-pktdump", PPPOE_DESC_IN_PKTDUMP}, + { "pppoe-desc-out-pktdump", PPPOE_DESC_OUT_PKTDUMP}, + { "pppoe-service-name", PPPOE_SERVICE_NAME}, + { "pppoe-session-in-pktdump", PPPOE_SESSION_IN_PKTDUMP}, + { "pppoe-session-out-pktdump", PPPOE_SESSION_OUT_PKTDUMP}, + { "pptp", PPTP}, + { "pptp-ctrl-in-pktdump", PPTP_CTRL_IN_PKTDUMP}, + { "pptp-ctrl-out-pktdump", PPTP_CTRL_OUT_PKTDUMP}, + { "pptp-data-in-pktdump", PPTP_DATA_IN_PKTDUMP}, + { "pptp-data-out-pktdump", PPTP_DATA_OUT_PKTDUMP}, + { "pptp-echo-interval", PPTP_ECHO_INTERVAL}, + { "pptp-echo-timeout", PPTP_ECHO_TIMEOUT}, + { "pptp-hostname", PPTP_HOSTNAME}, + { "pptp-vendor-name", PPTP_VENDOR_NAME}, + { "protocol", PROTOCOL}, + { "radius", RADIUS}, + { "required", REQUIRED}, + { "resolver", RESOLVER}, + { "secret", SECRET}, + { "set", SET}, + { "stateful", STATEFUL}, + { "stateless", STATELESS}, + { "static", STATIC}, + { "strip-atmark-realm", STRIP_ATMARK_REALM}, + { "strip-nt-domain", STRIP_NT_DOMAIN}, + { "tcp-mss-adjust", TCP_MSS_ADJUST}, + { "timeout", X_TIMEOUT}, + { "to", TO}, + { "tunnel", TUNNEL}, + { "type", TYPE}, + { "user-max-session", USER_MAX_SESSION}, + { "username-prefix", USERNAME_PREFIX}, + { "username-suffix", USERNAME_SUFFIX}, + { "users-file", USERS_FILE}, + { "yes", YES} + }; + const struct keywords *p; + + p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), + sizeof(keywords[0]), kw_cmp); + + if (p) + return (p->k_val); + else + return (STRING); +} + +#define MAXPUSHBACK 128 + +char *parsebuf; +int parseindex; +char pushback_buffer[MAXPUSHBACK]; +int pushback_index = 0; + +int +lgetc(int quotec) +{ + int c, next; + + if (parsebuf) { + /* Read character from the parsebuffer instead of input. */ + if (parseindex >= 0) { + c = parsebuf[parseindex++]; + if (c != '\0') + return (c); + parsebuf = NULL; + } else + parseindex++; + } + + if (pushback_index) + return (pushback_buffer[--pushback_index]); + + if (quotec) { + if ((c = getc(file->stream)) == EOF) { + yyerror("reached end of file while parsing " + "quoted string"); + if (file == topfile || popfile() == EOF) + return (EOF); + return (quotec); + } + return (c); + } + + while ((c = getc(file->stream)) == '\\') { + next = getc(file->stream); + if (next != '\n') { + c = next; + break; + } + yylval.lineno = file->lineno; + file->lineno++; + } + + while (c == EOF) { + if (file == topfile || popfile() == EOF) + return (EOF); + c = getc(file->stream); + } + return (c); +} + +int +lungetc(int c) +{ + if (c == EOF) + return (EOF); + if (parsebuf) { + parseindex--; + if (parseindex >= 0) + return (c); + } + if (pushback_index < MAXPUSHBACK-1) + return (pushback_buffer[pushback_index++] = c); + else + return (EOF); +} + +int +findeol(void) +{ + int c; + + parsebuf = NULL; + + /* skip to either EOF or the first real EOL */ + while (1) { + if (pushback_index) + c = pushback_buffer[--pushback_index]; + else + c = lgetc(0); + if (c == '\n') { + file->lineno++; + break; + } + if (c == EOF) + break; + } + return (ERROR); +} + +int +yylex(void) +{ + char buf[8096]; + char *p; + int quotec, next, c; + int token; + + p = buf; + while ((c = lgetc(0)) == ' ' || c == '\t') + ; /* nothing */ + + yylval.lineno = file->lineno; + if (c == '#') + while ((c = lgetc(0)) != '\n' && c != EOF) + ; /* nothing */ + + switch (c) { + case '\'': + case '"': + quotec = c; + while (1) { + if ((c = lgetc(quotec)) == EOF) + return (0); + if (c == '\n') { + file->lineno++; + continue; + } else if (c == '\\') { + if ((next = lgetc(quotec)) == EOF) + return (0); + if (next == quotec || c == ' ' || c == '\t') + c = next; + else if (next == '\n') { + file->lineno++; + continue; + } else + lungetc(next); + } else if (c == quotec) { + *p = '\0'; + break; + } + if (p + 1 >= buf + sizeof(buf) - 1) { + yyerror("string too long"); + return (findeol()); + } + *p++ = (char)c; + } + yylval.v.string = strdup(buf); + if (yylval.v.string == NULL) + fatal("yylex: strdup"); + return (STRING); + } + +#define allowed_to_end_number(x) \ + (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') + + if (c == '-' || isdigit(c)) { + do { + *p++ = c; + if ((unsigned)(p-buf) >= sizeof(buf)) { + yyerror("string too long"); + return (findeol()); + } + } while ((c = lgetc(0)) != EOF && isdigit(c)); + lungetc(c); + if (p == buf + 1 && buf[0] == '-') + goto nodigits; + if (c == EOF || allowed_to_end_number(c)) { + const char *errstr = NULL; + + *p = '\0'; + yylval.v.number = strtonum(buf, LLONG_MIN, + LLONG_MAX, &errstr); + if (errstr) { + yyerror("\"%s\" invalid number: %s", + buf, errstr); + return (findeol()); + } + return (NUMBER); + } else { +nodigits: + while (p > buf + 1) + lungetc(*--p); + c = *--p; + if (c == '-') + return (c); + } + } + +#define allowed_in_string(x) \ + (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ + x != '{' && x != '}' && x != '<' && x != '>' && \ + x != '!' && x != '=' && x != '/' && x != '#' && \ + x != ',')) + + if (isalnum(c) || c == ':' || c == '_' || c == '*') { + do { + *p++ = c; + if ((unsigned)(p-buf) >= sizeof(buf)) { + yyerror("string too long"); + return (findeol()); + } + } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); + lungetc(c); + *p = '\0'; + if ((token = lookup(buf)) == STRING) + if ((yylval.v.string = strdup(buf)) == NULL) + fatal("yylex: strdup"); + return (token); + } + if (c == '\n') { + yylval.lineno = file->lineno; + file->lineno++; + } + if (c == EOF) + return (0); + return (c); +} + +struct file * +pushfile(const char *name) +{ + struct file *nfile; + + if ((nfile = calloc(1, sizeof(struct file))) == NULL) { + log_warn("malloc"); + return (NULL); + } + if ((nfile->name = strdup(name)) == NULL) { + log_warn("malloc"); + free(nfile); + return (NULL); + } +#ifdef NO_PRIVSEP + if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { +#else + if ((nfile->stream = priv_fopen(nfile->name)) == NULL) { +#endif + log_warn("%s", nfile->name); + free(nfile->name); + free(nfile); + return (NULL); + } + nfile->lineno = 1; + TAILQ_INSERT_TAIL(&files, nfile, entry); + return (nfile); +} + +int +popfile(void) +{ + struct file *prev; + + if ((prev = TAILQ_PREV(file, files, entry)) != NULL) + prev->errors += file->errors; + + TAILQ_REMOVE(&files, file, entry); + fclose(file->stream); + free(file->name); + free(file); + file = prev; + return (file ? 0 : EOF); +} + +int +npppd_conf_parse(struct npppd_conf *xconf, const char *filename) +{ + int errors = 0; + + conf = xconf; + + if ((file = pushfile(filename)) == NULL) { + return (-1); + } + topfile = file; + + yyparse(); + errors = file->errors; + popfile(); + + if (curr_tunnconf != NULL) { + tunnconf_fini(curr_tunnconf); + free(curr_tunnconf); + } + curr_tunnconf = NULL; + if (curr_authconf != NULL) { + authconf_fini(curr_authconf); + free(curr_authconf); + } + curr_authconf = NULL; + if (curr_ipcpconf != NULL) { + ipcpconf_fini(curr_ipcpconf); + free(curr_ipcpconf); + } + curr_ipcpconf = NULL; + + if (errors) + npppd_conf_fini(xconf); + + return (errors ? -1 : 0); +} + +void +npppd_conf_init(struct npppd_conf *xconf) +{ + memset(xconf, 0, sizeof(struct npppd_conf)); + TAILQ_INIT(&xconf->tunnconfs); + TAILQ_INIT(&xconf->authconfs); + TAILQ_INIT(&xconf->ipcpconfs); + TAILQ_INIT(&xconf->ifaces); + TAILQ_INIT(&xconf->confbinds); + TAILQ_INIT(&xconf->l2tp_confs); + TAILQ_INIT(&xconf->pptp_confs); + TAILQ_INIT(&xconf->pppoe_confs); +} + +void +npppd_conf_fini(struct npppd_conf *xconf) +{ + struct tunnconf *tunn, *tunn0; + struct authconf *auth, *auth0; + struct ipcpconf *ipcp, *ipcp0; + struct iface *iface, *iface0; + struct confbind *confbind, *confbind0; + + TAILQ_FOREACH_SAFE(tunn, &xconf->tunnconfs, entry, tunn0) { + tunnconf_fini(tunn); + } + if (curr_radconf != NULL) { + radconf_fini(curr_radconf); + curr_radconf = NULL; + } + TAILQ_FOREACH_SAFE(auth, &xconf->authconfs, entry, auth0) { + authconf_fini(auth); + } + TAILQ_FOREACH_SAFE(ipcp, &xconf->ipcpconfs, entry, ipcp0) { + ipcpconf_fini(ipcp); + } + TAILQ_FOREACH_SAFE(iface, &xconf->ifaces, entry, iface0) { + free(iface); + } + TAILQ_FOREACH_SAFE(confbind, &xconf->confbinds, entry, confbind0) { + free(confbind); + } + TAILQ_INIT(&xconf->l2tp_confs); + TAILQ_INIT(&xconf->pptp_confs); + TAILQ_INIT(&xconf->pppoe_confs); +} + +void +tunnconf_fini(struct tunnconf *tun) +{ + if (tun->chap_name != NULL) + free(tun->chap_name); + tun->chap_name = NULL; + + switch (tun->protocol) { + case NPPPD_TUNNEL_L2TP: + if (tun->proto.l2tp.hostname != NULL) + free(tun->proto.l2tp.hostname); + tun->proto.l2tp.hostname = NULL; + if (tun->proto.l2tp.vendor_name != NULL) + free(tun->proto.l2tp.vendor_name); + tun->proto.l2tp.vendor_name = NULL; + break; + case NPPPD_TUNNEL_PPTP: + if (tun->proto.pptp.hostname != NULL) + free(tun->proto.pptp.hostname); + tun->proto.pptp.hostname = NULL; + if (tun->proto.pptp.vendor_name != NULL) + free(tun->proto.pptp.vendor_name); + tun->proto.pptp.vendor_name = NULL; + break; + case NPPPD_TUNNEL_PPPOE: + if (tun->proto.pppoe.service_name != NULL) + free(tun->proto.pppoe.service_name); + tun->proto.pppoe.service_name = NULL; + if (tun->proto.pppoe.ac_name != NULL) + free(tun->proto.pppoe.ac_name); + tun->proto.pppoe.ac_name = NULL; + break; + } +} + +void +tunnconf_init(struct tunnconf *tun, int protocol) +{ + extern struct tunnconf tunnconf_default_l2tp, tunnconf_default_pptp; + extern struct tunnconf tunnconf_default_pppoe; + + switch (protocol) { + case NPPPD_TUNNEL_L2TP: + memcpy(tun, &tunnconf_default_l2tp, sizeof(struct tunnconf)); + break; + case NPPPD_TUNNEL_PPTP: + memcpy(tun, &tunnconf_default_pptp, sizeof(struct tunnconf)); + break; + case NPPPD_TUNNEL_PPPOE: + memcpy(tun, &tunnconf_default_pppoe, sizeof(struct tunnconf)); + break; + } +} + +struct tunnconf * +tunnconf_find(const char *name) +{ + struct tunnconf *tunn; + + TAILQ_FOREACH(tunn, &conf->tunnconfs, entry) { + if (strcmp(tunn->name, name) == 0) + return tunn; + } + + return NULL; +} + +void +authconf_init(struct authconf *auth) +{ + memset(auth, 0, sizeof(struct authconf)); + auth->eap_capable = true; + auth->strip_nt_domain = true; + auth->strip_atmark_realm = false; +} + +void +authconf_fini(struct authconf *auth) +{ + if (auth->username_suffix != NULL) + free(auth->username_suffix); + auth->username_suffix = NULL; + + if (auth->username_prefix != NULL) + free(auth->username_prefix); + auth->username_prefix = NULL; + + switch (auth->auth_type) { + case NPPPD_AUTH_TYPE_RADIUS: + radconf_fini(&auth->radius.auth); + radconf_fini(&auth->radius.acct); + break; + } +} + +void +radconf_fini(struct radconf *radconf) +{ + struct radserver *server, *server0; + + TAILQ_FOREACH_SAFE(server, &radconf->servers, entry, server0) { + if (server->secret != NULL) + free(server->secret); + server->secret = NULL; + } +} + +struct authconf * +authconf_find(const char *name) +{ + struct authconf *auth; + + TAILQ_FOREACH(auth, &conf->authconfs, entry) { + if (strcmp(auth->name, name) == 0) + return auth; + } + + return NULL; +} + +void +ipcpconf_init(struct ipcpconf *ipcp) +{ + memset(ipcp, 0, sizeof(struct ipcpconf)); +} + +void +ipcpconf_fini(struct ipcpconf *ipcp) +{ + if (ipcp->dynamic_pool != NULL) + in_addr_range_list_remove_all(&ipcp->dynamic_pool); + if (ipcp->static_pool != NULL) + in_addr_range_list_remove_all(&ipcp->static_pool); +} + +struct ipcpconf * +ipcpconf_find(const char *name) +{ + struct ipcpconf *ipcp; + + TAILQ_FOREACH(ipcp, &conf->ipcpconfs, entry) { + if (strcmp(ipcp->name, name) == 0) + return ipcp; + } + + return NULL; +} + +struct iface * +iface_find(const char *name) +{ + struct iface *iface; + + TAILQ_FOREACH(iface, &conf->ifaces, entry) { + if (strcmp(iface->name, name) == 0) + return iface; + } + + return NULL; +} diff --git a/usr.sbin/npppd/npppd/ppp.c b/usr.sbin/npppd/npppd/ppp.c index 5ce30531174..4ffe1cb8c0e 100644 --- a/usr.sbin/npppd/npppd/ppp.c +++ b/usr.sbin/npppd/npppd/ppp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ppp.c,v 1.15 2012/09/07 10:47:42 yasuoka Exp $ */ +/* $OpenBSD: ppp.c,v 1.16 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: ppp.c,v 1.15 2012/09/07 10:47:42 yasuoka Exp $ */ +/* $Id: ppp.c,v 1.16 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * This file provides PPP(Point-to-Point Protocol, RFC 1661) and * {@link :: _npppd_ppp PPP instance} related functions. @@ -79,13 +79,14 @@ static u_int ppp_seq = 0; -static void ppp_stop0 __P((npppd_ppp *)); -static int ppp_recv_packet (npppd_ppp *, unsigned char *, int, int); -static const char * ppp_peer_auth_string(npppd_ppp *); -static void ppp_idle_timeout(int, short, void *); +static void ppp_stop0 (npppd_ppp *); +static int ppp_recv_packet (npppd_ppp *, unsigned char *, int, int); +static const char *ppp_peer_auth_string (npppd_ppp *); +static void ppp_idle_timeout (int, short, void *); #ifdef USE_NPPPD_PIPEX -static void ppp_on_network_pipex(npppd_ppp *); +static void ppp_on_network_pipex(npppd_ppp *); #endif +static uint32_t ppp_proto_bit(int); #define AUTH_IS_PAP(ppp) ((ppp)->peer_auth == PPP_AUTH_PAP) #define AUTH_IS_CHAP(ppp) ((ppp)->peer_auth == PPP_AUTH_CHAP_MD5 ||\ @@ -129,6 +130,7 @@ ppp_create() int ppp_init(npppd *pppd, npppd_ppp *_this) { + struct tunnconf *conf; PPP_ASSERT(_this != NULL); PPP_ASSERT(strlen(_this->phy_label) > 0); @@ -142,7 +144,9 @@ ppp_init(npppd *pppd, npppd_ppp *_this) lcp_init(&_this->lcp, _this); - _this->mru = ppp_config_int(_this, "lcp.mru", DEFAULT_MRU); + conf = ppp_get_tunnconf(_this); + _this->mru = conf->mru; + if (_this->outpacket_buf == NULL) { _this->outpacket_buf = malloc(_this->mru + 64); if (_this->outpacket_buf == NULL){ @@ -151,19 +155,13 @@ ppp_init(npppd *pppd, npppd_ppp *_this) return -1; } } - _this->adjust_mss = ppp_config_str_equal(_this, "ip.adjust_mss", "true", - 0); + _this->adjust_mss = (conf->tcp_mss_adjust)? 1 : 0; + #ifdef USE_NPPPD_PIPEX - _this->use_pipex = ppp_config_str_equal(_this, "pipex.enabled", "true", - 1); + _this->use_pipex = (conf->pipex)? 1 : 0; #endif /* load the logging configuration */ - _this->log_dump_in = - ppp_config_str_equal(_this, "log.in.pktdump", "true", 0); - _this->log_dump_out = - ppp_config_str_equal(_this, "log.out.pktdump", "true", 0); - _this->ingress_filter = ppp_config_str_equal(_this, "ingress_filter", - "true", 0); + _this->ingress_filter = (conf->ingress_filter)? 1 : 0; #ifdef USE_NPPPD_MPPE mppe_init(&_this->mppe, _this); @@ -174,19 +172,23 @@ ppp_init(npppd *pppd, npppd_ppp *_this) chap_init(&_this->chap, _this); /* load the idle timer configuration */ - _this->timeout_sec = ppp_config_int(_this, "idle_timeout", 0); + _this->timeout_sec = conf->idle_timeout; + if (!evtimer_initialized(&_this->idle_event)) evtimer_set(&_this->idle_event, ppp_idle_timeout, _this); - _this->auth_timeout = ppp_config_int(_this, "auth.timeout", - DEFAULT_AUTH_TIMEOUT); - - _this->lcp.echo_interval = ppp_config_int(_this, - "lcp.echo_interval", DEFAULT_LCP_ECHO_INTERVAL); - _this->lcp.echo_max_retries = ppp_config_int(_this, - "lcp.echo_max_retries", DEFAULT_LCP_ECHO_MAX_RETRIES); - _this->lcp.echo_retry_interval = ppp_config_int(_this, - "lcp.echo_retry_interval", DEFAULT_LCP_ECHO_RETRY_INTERVAL); + if (conf->lcp_keepalive) { + _this->lcp.echo_interval = conf->lcp_keepalive_interval; + _this->lcp.echo_retry_interval = + conf->lcp_keepalive_retry_interval; + _this->lcp.echo_max_retries = conf->lcp_keepalive_max_retries; + } else { + _this->lcp.echo_interval = 0; + _this->lcp.echo_retry_interval = 0; + _this->lcp.echo_max_retries = 0; + } + _this->log_dump_in = (conf->debug_dump_pktin == 0)? 0 : 1; + _this->log_dump_out = (conf->debug_dump_pktout == 0)? 0 : 1; return 0; } @@ -251,11 +253,13 @@ int ppp_dialin_proxy_prepare(npppd_ppp *_this, dialin_proxy_info *dpi) { int renego_force, renego; + struct tunnconf *conf; + + conf = ppp_get_tunnconf(_this); + + renego = conf->proto.l2tp.lcp_renegotiation; + renego_force = conf->proto.l2tp.force_lcp_renegotiation; - 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; @@ -463,7 +467,7 @@ void ppp_lcp_up(npppd_ppp *_this) { #ifdef USE_NPPPD_MPPE - if (MPPE_REQUIRED(_this) && !MPPE_MUST_NEGO(_this)) { + if (MPPE_IS_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"); @@ -806,11 +810,8 @@ ppp_recv_packet(npppd_ppp *_this, unsigned char *pkt, int lpkt, int flags) 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) { + struct tunnconf *conf = ppp_get_tunnconf(_this); + if ((ppp_proto_bit(proto) & conf->debug_dump_pktin) != 0) { ppp_log(_this, LOG_DEBUG, "PPP input dump proto=%s(%d/%04x)", proto_name(proto), proto, proto); @@ -819,7 +820,7 @@ ppp_recv_packet(npppd_ppp *_this, unsigned char *pkt, int lpkt, int flags) } #ifdef USE_NPPPD_PIPEX if (_this->pipex_enabled != 0 && - _this->tunnel_type == PPP_TUNNEL_PPPOE) { + _this->tunnel_type == NPPPD_TUNNEL_PPPOE) { switch (proto) { case PPP_PROTO_IP: return 2; /* handled by PIPEX */ @@ -842,7 +843,7 @@ ppp_recv_packet(npppd_ppp *_this, unsigned char *pkt, int lpkt, int flags) case PPP_PROTO_IP: /* Checks for MPPE */ if ((flags & PPP_IO_FLAGS_MPPE_ENCRYPTED) == 0) { - if (MPPE_REQUIRED(_this)) { + if (MPPE_IS_REQUIRED(_this)) { /* MPPE is required but naked ip */ if (_this->logged_naked_ip == 0) { @@ -1020,11 +1021,8 @@ ppp_output(npppd_ppp *_this, uint16_t proto, u_char code, u_char id, 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) { + struct tunnconf *conf = ppp_get_tunnconf(_this); + if ((ppp_proto_bit(proto) & conf->debug_dump_pktout) != 0) { ppp_log(_this, LOG_DEBUG, "PPP output dump proto=%s(%d/%04x)", proto_name(proto), proto, proto); @@ -1135,9 +1133,9 @@ 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) + if (_this->tunnel_type != NPPPD_TUNNEL_PPTP && + _this->tunnel_type != NPPPD_TUNNEL_PPPOE && + _this->tunnel_type != NPPPD_TUNNEL_L2TP) return; if (_this->pipex_started != 0) @@ -1156,3 +1154,136 @@ ppp_on_network_pipex(npppd_ppp *_this) /* else wait CCP or IPCP */ } #endif + +static uint32_t +ppp_proto_bit(int proto) +{ + switch (proto) { + case PPP_PROTO_IP: return NPPPD_PROTO_BIT_IP; + case PPP_PROTO_LCP: return NPPPD_PROTO_BIT_LCP; + case PPP_PROTO_PAP: return NPPPD_PROTO_BIT_PAP; + case PPP_PROTO_CHAP: return NPPPD_PROTO_BIT_CHAP; + case PPP_PROTO_EAP: return NPPPD_PROTO_BIT_EAP; + case PPP_PROTO_MPPE: return NPPPD_PROTO_BIT_MPPE; + case PPP_PROTO_NCP | NCP_CCP: return NPPPD_PROTO_BIT_CCP; + case PPP_PROTO_NCP | NCP_IPCP: return NPPPD_PROTO_BIT_IPCP; + } + return 0; +} + +struct tunnconf tunnconf_default_l2tp = { + .mru = 1360, + .tcp_mss_adjust = false, + .pipex = true, + .ingress_filter = false, + .lcp_keepalive = false, + .lcp_keepalive_interval = DEFAULT_LCP_ECHO_INTERVAL, + .lcp_keepalive_retry_interval = DEFAULT_LCP_ECHO_RETRY_INTERVAL, + .lcp_keepalive_max_retries = DEFAULT_LCP_ECHO_MAX_RETRIES, + .auth_methods = NPPPD_AUTH_METHODS_CHAP | NPPPD_AUTH_METHODS_MSCHAPV2, + .mppe_yesno = true, + .mppe_required = false, + .mppe_keylen = NPPPD_MPPE_40BIT | NPPPD_MPPE_56BIT | NPPPD_MPPE_128BIT, + .mppe_keystate = NPPPD_MPPE_STATELESS | NPPPD_MPPE_STATEFUL, + .callnum_check = 0, + .proto = { + .l2tp = { + .hostname = NULL, + .vendor_name = NULL, + .address = { + .ss_family = AF_INET, + .ss_len = sizeof(struct sockaddr_in) + }, + /* .hello_interval, */ + /* .hello_timeout, */ + .data_use_seq = true, + .require_ipsec = false, + /* .accept_dialin, */ + .lcp_renegotiation = true, + .force_lcp_renegotiation = false, + /* .ctrl_in_pktdump, */ + /* .ctrl_out_pktdump, */ + /* .data_in_pktdump, */ + /* .data_out_pktdump, */ + } + } +}; +struct tunnconf tunnconf_default_pptp = { + .mru = 1400, + .tcp_mss_adjust = false, + .pipex = true, + .ingress_filter = false, + .lcp_keepalive = true, + .lcp_keepalive_interval = DEFAULT_LCP_ECHO_INTERVAL, + .lcp_keepalive_retry_interval = DEFAULT_LCP_ECHO_RETRY_INTERVAL, + .lcp_keepalive_max_retries = DEFAULT_LCP_ECHO_MAX_RETRIES, + .auth_methods = NPPPD_AUTH_METHODS_CHAP | NPPPD_AUTH_METHODS_MSCHAPV2, + .mppe_yesno = true, + .mppe_required = true, + .mppe_keylen = NPPPD_MPPE_40BIT | NPPPD_MPPE_56BIT | NPPPD_MPPE_128BIT, + .mppe_keystate = NPPPD_MPPE_STATELESS | NPPPD_MPPE_STATEFUL, + .callnum_check = 0, + .proto = { + .pptp = { + .hostname = NULL, + .vendor_name = NULL, + .address = { + .ss_family = AF_INET, + .ss_len = sizeof(struct sockaddr_in) + }, + /* .echo_interval, */ + /* .echo_timeout, */ + } + } +}; +struct tunnconf tunnconf_default_pppoe = { + .mru = 1492, + .tcp_mss_adjust = false, + .pipex = true, + .ingress_filter = false, + .lcp_keepalive = true, + .lcp_keepalive_interval = DEFAULT_LCP_ECHO_INTERVAL, + .lcp_keepalive_retry_interval = DEFAULT_LCP_ECHO_RETRY_INTERVAL, + .lcp_keepalive_max_retries = DEFAULT_LCP_ECHO_MAX_RETRIES, + .auth_methods = NPPPD_AUTH_METHODS_CHAP | NPPPD_AUTH_METHODS_MSCHAPV2, + .mppe_yesno = true, + .mppe_required = false, + .mppe_keylen = NPPPD_MPPE_40BIT | NPPPD_MPPE_56BIT | NPPPD_MPPE_128BIT, + .mppe_keystate = NPPPD_MPPE_STATELESS | NPPPD_MPPE_STATEFUL, + .callnum_check = 0, + .proto = { + .pppoe = { + /* .service_name */ + .accept_any_service = true, + /* .ac_name */ + /* .desc_in_pktdump */ + /* .desc_out_pktdump */ + /* .session_in_pktdump */ + /* .session_out_pktdump */ + } + } +}; + +struct tunnconf * +ppp_get_tunnconf(npppd_ppp *_this) +{ + struct tunnconf *conf; + + conf = npppd_get_tunnconf(_this->pppd, _this->phy_label); + if (conf != NULL) + return conf; + + switch (_this->tunnel_type) { + case NPPPD_TUNNEL_L2TP: + return &tunnconf_default_l2tp; + break; + case NPPPD_TUNNEL_PPTP: + return &tunnconf_default_pptp; + break; + case NPPPD_TUNNEL_PPPOE: + return &tunnconf_default_pppoe; + break; + } + + return NULL; +} diff --git a/usr.sbin/npppd/npppd/ppp.h b/usr.sbin/npppd/npppd/ppp.h index 24fd21730c3..3492df4937c 100644 --- a/usr.sbin/npppd/npppd/ppp.h +++ b/usr.sbin/npppd/npppd/ppp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ppp.h,v 1.12 2012/09/07 10:47:42 yasuoka Exp $ */ +/* $OpenBSD: ppp.h,v 1.13 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -100,13 +100,6 @@ #define INADDR_USER_SELECT (htonl(0xFFFFFFFFL)) #define INADDR_NAS_SELECT (htonl(0xFFFFFFFEL)) -/** Constants of tunnel type */ -#define PPP_TUNNEL_NONE 0 /** None Tunnel Type */ -#define PPP_TUNNEL_L2TP 1 /** L2TP Tunnel Type */ -#define PPP_TUNNEL_PPTP 2 /** PPTP Tunnel Type */ -#define PPP_TUNNEL_PPPOE 3 /** PPPoE Tunnel Type */ -#define PPP_TUNNEL_SSTP 4 /** SSTP Tunnel Type */ - /** Default LCP ECHO interval (sec) */ #define DEFAULT_LCP_ECHO_INTERVAL 300 @@ -427,9 +420,8 @@ typedef struct _mppe { /* if 1 don't forward packet without MPPE */ required :1, mode_auto :1, - keylen_auto :1, mode_stateless :1, - reserved :11; + reserved :12; uint16_t keylenbits; mppe_rc4_t send, recv; @@ -515,7 +507,6 @@ struct _npppd_ppp { * </pre> */ uint16_t peer_auth; - u_short auth_timeout; #ifdef USE_NPPPD_MPPE uint8_t mppe_started; @@ -650,7 +641,7 @@ typedef struct _dialin_proxy_info { ((ppp)->peer_auth == PPP_AUTH_EAP))) /** MPPE is required */ -#define MPPE_REQUIRED(ppp) \ +#define MPPE_IS_REQUIRED(ppp) \ (((ppp)->mppe.enabled != 0) && ((ppp)->mppe.required != 0)) /** MPPE is ready to use */ @@ -751,8 +742,12 @@ typedef struct _dialin_proxy_info { #endif #endif -#define PPP_FSM_CONFIG(fsm, memb, confl) \ - (fsm)->memb = ppp_config_int((fsm)->ppp, confl, (fsm)->memb) +#define PPP_FSM_CONFIG(_fsm, _memb, _val) \ + do { \ + (_fsm)->_memb = ((_val) == 0) \ + ? (_fsm)->_memb : (_val); \ + } while (0 /* CONSTCOND */) + #ifdef __cplusplus extern "C" { @@ -777,16 +772,13 @@ void ppp_ccp_opened (npppd_ppp *); void ppp_ccp_stopped (npppd_ppp *); inline void ppp_output (npppd_ppp *, uint16_t, u_char, u_char, u_char *, int); u_char *ppp_packetbuf (npppd_ppp *, int); -const char *ppp_config_str (npppd_ppp *, const char *); -int ppp_config_int (npppd_ppp *, const char *, int); -int ppp_config_str_equal (npppd_ppp *, const char *, const char *, int); -int ppp_config_str_equali (npppd_ppp *, const char *, const char *, int); int ppp_log (npppd_ppp *, int, const char *, ...) __printflike(3,4); void ppp_reset_idle_timeout(npppd_ppp *); #ifdef USE_NPPPD_RADIUS void ppp_process_radius_framed_ip (npppd_ppp *, RADIUS_PACKET *); int ppp_set_radius_attrs_for_authreq (npppd_ppp *, radius_req_setting *, RADIUS_PACKET *); #endif +struct tunnconf *ppp_get_tunnconf(npppd_ppp *); void ccp_init (ccp *, npppd_ppp *); void ipcp_init (ipcp *, npppd_ppp *); diff --git a/usr.sbin/npppd/npppd/privsep.c b/usr.sbin/npppd/npppd/privsep.c index cd10d3062dd..947aa8252d1 100644 --- a/usr.sbin/npppd/npppd/privsep.c +++ b/usr.sbin/npppd/npppd/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: privsep.c,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /* * Copyright (c) 2010 Yasuoka Masahiko <yasuoka@openbsd.org> @@ -20,9 +20,12 @@ #include <sys/uio.h> #include <sys/time.h> #include <sys/un.h> +#include <sys/ioctl.h> #include <netinet/in.h> #include <net/pfkeyv2.h> +#include <net/if.h> +#include <arpa/inet.h> #include <stddef.h> #include <stdio.h> @@ -37,6 +40,9 @@ #include "pathnames.h" #include "privsep.h" +#include "npppd.h" +#include "ppp.h" + #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #endif @@ -46,7 +52,13 @@ enum PRIVSEP_CMD { PRIVSEP_SOCKET, PRIVSEP_BIND, PRIVSEP_SENDTO, - PRIVSEP_UNLINK + PRIVSEP_UNLINK, + PRIVSEP_GET_USER_INFO, + PRIVSEP_GET_IF_ADDR, + PRIVSEP_SET_IF_ADDR, + PRIVSEP_DEL_IF_ADDR, + PRIVSEP_GET_IF_FLAGS, + PRIVSEP_SET_IF_FLAGS }; struct PRIVSEP_OPEN_ARG { @@ -83,11 +95,66 @@ struct PRIVSEP_UNLINK_ARG { char path[PATH_MAX]; }; +struct PRIVSEP_GET_USER_INFO_ARG { + enum PRIVSEP_CMD cmd; + char path[PATH_MAX]; + char username[MAX_USERNAME_LENGTH]; +}; + +struct PRIVSEP_GET_IF_ADDR_ARG { + enum PRIVSEP_CMD cmd; + char ifname[IFNAMSIZ]; +}; + +struct PRIVSEP_GET_IF_ADDR_RESP { + int retval; + int rerrno; + struct in_addr addr; +}; + +struct PRIVSEP_SET_IF_ADDR_ARG { + enum PRIVSEP_CMD cmd; + char ifname[IFNAMSIZ]; + struct in_addr addr; +}; + +struct PRIVSEP_DEL_IF_ADDR_ARG { + enum PRIVSEP_CMD cmd; + char ifname[IFNAMSIZ]; +}; + +struct PRIVSEP_GET_IF_FLAGS_ARG { + enum PRIVSEP_CMD cmd; + char ifname[IFNAMSIZ]; + int flags; +}; + +struct PRIVSEP_GET_IF_FLAGS_RESP { + int retval; + int rerrno; + int flags; +}; + +struct PRIVSEP_SET_IF_FLAGS_ARG { + enum PRIVSEP_CMD cmd; + char ifname[IFNAMSIZ]; + int flags; +}; + struct PRIVSEP_COMMON_RESP { int retval; int rerrno; }; +struct PRIVSEP_GET_USER_INFO_RESP { + int retval; + int rerrno; + char password[MAX_PASSWORD_LENGTH]; + struct in_addr framed_ip_address; + struct in_addr framed_ip_netmask; + char calling_number[NPPPD_PHONE_NUMBER_LEN + 1]; +}; + static void privsep_priv_main (int, int); static void privsep_priv_on_sockio (int, short, void *); static void privsep_priv_on_monpipeio (int, short, void *); @@ -99,6 +166,12 @@ static int privsep_npppd_check_socket (struct PRIVSEP_SOCKET_ARG *); static int privsep_npppd_check_bind (struct PRIVSEP_BIND_ARG *); static int privsep_npppd_check_sendto (struct PRIVSEP_SENDTO_ARG *); static int privsep_npppd_check_unlink (struct PRIVSEP_UNLINK_ARG *); +static int privsep_npppd_check_get_user_info (struct PRIVSEP_GET_USER_INFO_ARG *); +static int privsep_npppd_check_get_if_addr (struct PRIVSEP_GET_IF_ADDR_ARG *); +static int privsep_npppd_check_set_if_addr (struct PRIVSEP_SET_IF_ADDR_ARG *); +static int privsep_npppd_check_del_if_addr (struct PRIVSEP_DEL_IF_ADDR_ARG *); +static int privsep_npppd_check_get_if_flags (struct PRIVSEP_GET_IF_FLAGS_ARG *); +static int privsep_npppd_check_set_if_flags (struct PRIVSEP_SET_IF_FLAGS_ARG *); static int privsep_sock = -1, privsep_monpipe = -1;; static pid_t privsep_pid; @@ -136,6 +209,7 @@ privsep_init(void) _exit(0); /* NOTREACHED */ } + setproctitle("main"); close(pairsock[0]); close(monpipe[0]); privsep_sock = pairsock[1]; @@ -330,6 +404,149 @@ priv_unlink(const char *path) return privsep_common_resp(); } +int +priv_get_user_info(const char *path, const char *username, + npppd_auth_user **puser) +{ + int n, sz, retval; + char *cp; + struct PRIVSEP_GET_USER_INFO_ARG a; + struct PRIVSEP_GET_USER_INFO_RESP r; + npppd_auth_user *u; + + a.cmd = PRIVSEP_GET_USER_INFO; + strlcpy(a.path, path, sizeof(a.path)); + strlcpy(a.username, username, sizeof(a.username)); + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + + if (recv(privsep_sock, &r, sizeof(r), 0) != sizeof(r)) + return -1; + if (r.retval != 0) { + errno = r.rerrno; + return r.retval; + } + + sz = strlen(username) + strlen(r.password) + + strlen(r.calling_number) + 3; + + if ((u = malloc(offsetof(npppd_auth_user, space[sz]))) == NULL) + return -1; + + cp = u->space; + + u->username = cp; + n = strlcpy(cp, username, sz); + cp += ++n; sz -= n; + + u->password = cp; + n = strlcpy(cp, r.password, sz); + cp += ++n; sz -= n; + + u->calling_number = cp; + n = strlcpy(cp, r.calling_number, sz); + cp += ++n; sz -= n; + + *puser = u; + + return 0; +} + +int +priv_get_if_addr(const char *ifname, struct in_addr *addr) +{ + int retval; + struct PRIVSEP_GET_IF_ADDR_ARG a; + struct PRIVSEP_GET_IF_ADDR_RESP r; + + a.cmd = PRIVSEP_GET_IF_ADDR; + strlcpy(a.ifname, ifname, sizeof(ifname)); + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + if ((retval = recv(privsep_sock, &r, sizeof(r), 0)) < 0) { + if (retval < 0) + return retval; + errno = EACCES; + return -1; + } + + if (r.retval != -1) + *addr = r.addr; + else + errno = r.rerrno; + + return 0; +} + +int +priv_delete_if_addr(const char *ifname) +{ + int retval; + struct PRIVSEP_DEL_IF_ADDR_ARG a; + + a.cmd = PRIVSEP_DEL_IF_ADDR; + strlcpy(a.ifname, ifname, sizeof(ifname)); + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + retval = privsep_common_resp(); + + return retval; +} + +int +priv_set_if_addr(const char *ifname, struct in_addr *addr) +{ + int retval; + struct PRIVSEP_SET_IF_ADDR_ARG a; + + a.cmd = PRIVSEP_SET_IF_ADDR; + strlcpy(a.ifname, ifname, sizeof(ifname)); + a.addr = *addr; + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + + return privsep_common_resp(); +} + +int +priv_get_if_flags(const char *ifname, int *pflags) +{ + int retval; + struct PRIVSEP_GET_IF_FLAGS_ARG a; + struct PRIVSEP_GET_IF_FLAGS_RESP r; + + a.cmd = PRIVSEP_GET_IF_FLAGS; + strlcpy(a.ifname, ifname, sizeof(ifname)); + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + if ((retval = recv(privsep_sock, &r, sizeof(r), 0)) < 0) { + if (retval < 0) + return retval; + errno = EACCES; + return -1; + } + *pflags = r.flags; + + if (r.retval != 0) + errno = r.rerrno; + + return 0; +} + +int +priv_set_if_flags(const char *ifname, int flags) +{ + int retval; + struct PRIVSEP_SET_IF_FLAGS_ARG a; + + a.cmd = PRIVSEP_SET_IF_FLAGS; + strlcpy(a.ifname, ifname, sizeof(ifname)); + a.flags = flags; + if ((retval = send(privsep_sock, &a, sizeof(a), 0)) < 0) + return retval; + return privsep_common_resp(); +} + static int privsep_recvfd(void) { @@ -506,6 +723,61 @@ privsep_priv_on_sockio(int sock, short evmask, void *ctx) (void)send(sock, &r, sizeof(r), 0); } break; + case PRIVSEP_GET_USER_INFO: { + struct PRIVSEP_GET_USER_INFO_ARG *a; + struct PRIVSEP_GET_USER_INFO_RESP r; + int retval; + char *str, *buf, *db[2] = { NULL, NULL }; + + a = (struct PRIVSEP_GET_USER_INFO_ARG *)rbuf; + memset(&r, 0, sizeof(r)); + db[0] = a->path; + + if (privsep_npppd_check_get_user_info(a)) { + r.retval = -1; + r.rerrno = EACCES; + } else if ((retval = cgetent(&buf, db, a->username)) + == 0) { + if ((retval = cgetstr(buf, "password", &str)) + >= 0) { + if (strlcpy(r.password, str, + sizeof(r.password)) >= + sizeof(r.password)) + goto on_broken_entry; + } + if ((retval = cgetstr(buf, "calling-number", + &str)) >= 0) { + if (strlcpy(r.calling_number, str, + sizeof(r.calling_number)) >= + sizeof(r.calling_number)) + goto on_broken_entry; + } + if ((retval = cgetstr(buf, "framed-ip-address", + &str)) >= 0) { + if (inet_aton(str, + &r.framed_ip_address) != 1) + goto on_broken_entry; + } + + if ((retval = cgetstr(buf, "framed-ip-netmask", + &str)) >= 0) { + if (inet_aton(str, + &r.framed_ip_netmask) != 1) + goto on_broken_entry; + } + cgetclose(); + r.retval = 0; + } else if (retval == -1) { +on_broken_entry: + r.retval = -1; + r.rerrno = ENOENT; + } else { + r.retval = retval; + r.rerrno = errno; + } + (void)send(sock, &r, sizeof(r), 0); + } + break; case PRIVSEP_SENDTO: { struct PRIVSEP_SENDTO_ARG *a; struct PRIVSEP_COMMON_RESP r; @@ -538,6 +810,158 @@ privsep_priv_on_sockio(int sock, short evmask, void *ctx) (void)send(sock, &r, sizeof(r), 0); } break; + case PRIVSEP_GET_IF_ADDR: { + int s; + struct ifreq ifr; + struct PRIVSEP_GET_IF_ADDR_ARG *a; + struct PRIVSEP_GET_IF_ADDR_RESP r; + + a = (struct PRIVSEP_GET_IF_ADDR_ARG *)rbuf; + if (privsep_npppd_check_get_if_addr(a)) { + r.rerrno = EACCES; + r.retval = -1; + } else { + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, a->ifname, + sizeof(ifr.ifr_name)); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || + ioctl(s, SIOCGIFADDR, &ifr) != 0) { + r.retval = -1; + r.rerrno = errno; + } else + r.addr = ((struct sockaddr_in *) + &ifr.ifr_addr)->sin_addr; + if (s >= 0) + close(s); + } + (void)send(sock, &r, sizeof(r), 0); + } + break; + case PRIVSEP_SET_IF_ADDR: { + int s; + struct ifaliasreq ifra; + struct PRIVSEP_SET_IF_ADDR_ARG *a; + struct PRIVSEP_COMMON_RESP r; + struct sockaddr_in *sin4; + + a = (struct PRIVSEP_SET_IF_ADDR_ARG *)rbuf; + if (privsep_npppd_check_set_if_addr(a)) { + r.rerrno = EACCES; + r.retval = -1; + } else { + memset(&ifra, 0, sizeof(ifra)); + strlcpy(ifra.ifra_name, a->ifname, + sizeof(ifra.ifra_name)); + + sin4 = (struct sockaddr_in *)&ifra.ifra_addr; + sin4->sin_family = AF_INET; + sin4->sin_len = sizeof(struct sockaddr_in); + sin4->sin_addr = a->addr; + + sin4 = (struct sockaddr_in *)&ifra.ifra_mask; + sin4->sin_family = AF_INET; + sin4->sin_len = sizeof(struct sockaddr_in); + sin4->sin_addr.s_addr = 0xffffffffUL; + + sin4 = + (struct sockaddr_in *)&ifra.ifra_broadaddr; + sin4->sin_family = AF_INET; + sin4->sin_len = sizeof(struct sockaddr_in); + sin4->sin_addr.s_addr = 0; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || + ioctl(s, SIOCAIFADDR, &ifra) != 0) { + r.retval = -1; + r.rerrno = errno; + } else + r.retval = 0; + if (s >= 0) + close(s); + } + (void)send(sock, &r, sizeof(r), 0); + } + break; + case PRIVSEP_DEL_IF_ADDR: { + int s; + struct ifreq ifr; + struct PRIVSEP_DEL_IF_ADDR_ARG *a; + struct PRIVSEP_COMMON_RESP r; + + a = (struct PRIVSEP_DEL_IF_ADDR_ARG *)rbuf; + if (privsep_npppd_check_del_if_addr(a)) { + r.rerrno = EACCES; + r.retval = -1; + } else { + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, a->ifname, + sizeof(ifr.ifr_name)); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || + ioctl(s, SIOCDIFADDR, &ifr) != 0) { + r.retval = -1; + r.rerrno = errno; + } else + r.retval = 0; + if (s >= 0) + close(s); + } + (void)send(sock, &r, sizeof(r), 0); + } + break; + case PRIVSEP_GET_IF_FLAGS: { + int s; + struct ifreq ifr; + struct PRIVSEP_GET_IF_FLAGS_ARG *a; + struct PRIVSEP_GET_IF_FLAGS_RESP r; + + a = (struct PRIVSEP_GET_IF_FLAGS_ARG *)rbuf; + if (privsep_npppd_check_get_if_flags(a)) { + r.rerrno = EACCES; + r.retval = -1; + } else { + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, a->ifname, + sizeof(ifr.ifr_name)); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || + ioctl(s, SIOCGIFFLAGS, &ifr) != 0) { + r.retval = -1; + r.rerrno = errno; + } else { + r.retval = 0; + r.flags = ifr.ifr_flags; + } + if (s >= 0) + close(s); + } + (void)send(sock, &r, sizeof(r), 0); + } + break; + case PRIVSEP_SET_IF_FLAGS: { + int s; + struct ifreq ifr; + struct PRIVSEP_SET_IF_FLAGS_ARG *a; + struct PRIVSEP_COMMON_RESP r; + + a = (struct PRIVSEP_SET_IF_FLAGS_ARG *)rbuf; + if (privsep_npppd_check_set_if_flags(a)) { + r.rerrno = EACCES; + r.retval = -1; + } else { + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, a->ifname, + sizeof(ifr.ifr_name)); + ifr.ifr_flags = a->flags; + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || + ioctl(s, SIOCGIFFLAGS, &ifr) != 0) { + r.retval = -1; + r.rerrno = errno; + } else + r.retval = 0; + if (s >= 0) + close(s); + } + (void)send(sock, &r, sizeof(r), 0); + } + break; } } } @@ -601,7 +1025,9 @@ privsep_npppd_check_open(struct PRIVSEP_OPEN_ARG *arg) } const allow_paths[] = { { NPPPD_DIR "/", 1, 1 }, { "/dev/bpf", 1, 0 }, - { "/etc/resolv.conf", 0, 1 } + { "/etc/resolv.conf", 0, 1 }, + { "/dev/tun", 1, 0 }, + { "/dev/pppx", 1, 0 } }; for (i = 0; i < nitems(allow_paths); i++) { @@ -668,3 +1094,65 @@ privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG *arg) return 1; } + +static int +privsep_npppd_check_get_user_info(struct PRIVSEP_GET_USER_INFO_ARG *arg) +{ + int l; + + l = strlen(NPPPD_DIR "/"); + if (strncmp(arg->path, NPPPD_DIR "/", l) == 0) + return 0; + + return 1; +} + +static int +privsep_npppd_check_get_if_addr(struct PRIVSEP_GET_IF_ADDR_ARG *arg) +{ + if (strncmp(arg->ifname, "tun", 3) == 0 || + strncmp(arg->ifname, "pppx", 4)) + return 0; + + return 1; +} + +static int +privsep_npppd_check_set_if_addr(struct PRIVSEP_SET_IF_ADDR_ARG *arg) +{ + if (strncmp(arg->ifname, "tun", 3) == 0 || + strncmp(arg->ifname, "pppx", 4)) + return 0; + + return 1; +} + +static int +privsep_npppd_check_del_if_addr(struct PRIVSEP_DEL_IF_ADDR_ARG *arg) +{ + if (strncmp(arg->ifname, "tun", 3) == 0 || + strncmp(arg->ifname, "pppx", 4)) + return 0; + + return 1; +} + +static int +privsep_npppd_check_get_if_flags(struct PRIVSEP_GET_IF_FLAGS_ARG *arg) +{ + if (strncmp(arg->ifname, "tun", 3) == 0 || + strncmp(arg->ifname, "pppx", 4)) + return 0; + + return 1; +} + +static int +privsep_npppd_check_set_if_flags(struct PRIVSEP_SET_IF_FLAGS_ARG *arg) +{ + if (strncmp(arg->ifname, "tun", 3) == 0 || + strncmp(arg->ifname, "pppx", 4)) + return 0; + + return 1; +} diff --git a/usr.sbin/npppd/npppd/privsep.h b/usr.sbin/npppd/npppd/privsep.h index 0486dbef5c1..7b06ec5590e 100644 --- a/usr.sbin/npppd/npppd/privsep.h +++ b/usr.sbin/npppd/npppd/privsep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.h,v 1.4 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: privsep.h,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ /* * Copyright (c) 2010 Yasuoka Masahiko <yasuoka@openbsd.org> @@ -20,6 +20,8 @@ #define PRIVSEP_BUFSIZE 4092 +#include "npppd_auth.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,6 +36,12 @@ int priv_socket (int, int, int); int priv_open (const char *, int, mode_t); int priv_send (int, const void *, int, int); int priv_sendto (int, const void *, int, int, const struct sockaddr *, socklen_t); +int priv_get_user_info(const char *, const char *, npppd_auth_user **); +int priv_set_if_addr(const char *, struct in_addr *); +int priv_get_if_addr(const char *, struct in_addr *); +int priv_delete_if_addr(const char *); +int priv_set_if_flags(const char *, int); +int priv_get_if_flags(const char *, int *); #ifdef __cplusplus } diff --git a/usr.sbin/npppd/npppd/radius_req.c b/usr.sbin/npppd/npppd/radius_req.c index 98f9b84f6a2..162b32612b7 100644 --- a/usr.sbin/npppd/npppd/radius_req.c +++ b/usr.sbin/npppd/npppd/radius_req.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radius_req.c,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: radius_req.c,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -28,7 +28,7 @@ /**@file * This file provides functions for RADIUS request using radius+.c and event(3). * @author Yasuoka Masahiko - * $Id: radius_req.c,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ + * $Id: radius_req.c,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> @@ -265,7 +265,7 @@ radius_prepare_socket(struct overlapped *lap) */ int radius_prepare(radius_req_setting *setting, void *context, - RADIUS_REQUEST_CTX *pctx, radius_response response_fn, int timeout) + RADIUS_REQUEST_CTX *pctx, radius_response response_fn) { struct overlapped *lap; @@ -284,13 +284,7 @@ radius_prepare(radius_req_setting *setting, void *context, lap->socket = -1; lap->setting = setting; - if (timeout != 0 && - (setting->max_tries == 0 || - timeout < setting->max_tries * setting->timeout)) - lap->max_tries = timeout / setting->timeout; - else - lap->max_tries = setting->max_tries; - + lap->max_tries = setting->max_tries; if (lap->max_tries <= 0) lap->max_tries = 3; /* default max tries */ diff --git a/usr.sbin/npppd/npppd/radius_req.h b/usr.sbin/npppd/npppd/radius_req.h index 6704c731db7..2b354979112 100644 --- a/usr.sbin/npppd/npppd/radius_req.h +++ b/usr.sbin/npppd/npppd/radius_req.h @@ -1,4 +1,4 @@ -/* $OpenBSD: radius_req.h,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: radius_req.h,v 1.6 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -94,7 +94,7 @@ void radius_request (RADIUS_REQUEST_CTX, RADIUS_PACKET *); int radius_prepare_nas_address (radius_req_setting *, RADIUS_PACKET *); int radius_request_can_failover (RADIUS_REQUEST_CTX); int radius_request_failover (RADIUS_REQUEST_CTX); -int radius_prepare (radius_req_setting *, void *, RADIUS_REQUEST_CTX *, radius_response, int); +int radius_prepare (radius_req_setting *, void *, RADIUS_REQUEST_CTX *, radius_response); void radius_cancel_request (RADIUS_REQUEST_CTX); const char *radius_get_server_secret (RADIUS_REQUEST_CTX); struct sockaddr *radius_get_server_address (RADIUS_REQUEST_CTX); diff --git a/usr.sbin/npppd/pppoe/pppoe.h b/usr.sbin/npppd/pppoe/pppoe.h index d0c896dca0e..6c3c04e1f40 100644 --- a/usr.sbin/npppd/pppoe/pppoe.h +++ b/usr.sbin/npppd/pppoe/pppoe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pppoe.h,v 1.4 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pppoe.h,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -82,7 +82,9 @@ struct pppoe_tlv { /* * Constant variables and types for implementions */ -/** Default data link layer label */ +#include "pppoe_conf.h" + +/** Default data link layer */ #define PPPOED_DEFAULT_LAYER2_LABEL "PPPoE" #define PPPOED_CONFIG_BUFSIZ 65535 @@ -118,7 +120,9 @@ typedef struct _pppoed_listener { /** Listening interface name */ char listen_ifname[IF_NAMESIZE]; /** Label of physcal layer */ - char phy_label[PPPOED_PHY_LABEL_SIZE]; + char tun_name[PPPOED_PHY_LABEL_SIZE]; + /** Configuration */ + struct pppoe_conf *conf; } pppoed_listener; /** PPPoE daemon type */ @@ -140,17 +144,10 @@ typedef struct _pppoed { /** Next cookie number */ uint32_t acookie_next; - /** Configuration {@link struct properties properties} */ - struct properties *config; - /** Flags */ uint32_t - desc_in_pktdump:1, - desc_out_pktdump:1, - session_in_pktdump:1, - session_out_pktdump:1, listen_incomplete:1, - reserved:27; + reserved:31; } pppoed; /** PPPoE session type */ @@ -196,26 +193,16 @@ int pppoe_session_recv_PADT (pppoe_session *, slist *); void pppoe_session_input (pppoe_session *, u_char *, int); void pppoe_session_disconnect (pppoe_session *); - int pppoed_add_listener (pppoed *, int, const char *, const char *); int pppoed_reload_listeners(pppoed *); -int pppoed_init (pppoed *); -int pppoed_start (pppoed *); -void pppoed_stop (pppoed *); -void pppoed_uninit (pppoed *); -void pppoed_pppoe_session_close_notify(pppoed *, pppoe_session *); -const char * pppoed_tlv_value_string(struct pppoe_tlv *); -int pppoed_reload(pppoed *, struct properties *, const char *, int); -const char *pppoed_config_str (pppoed *, const char *); -int pppoed_config_int (pppoed *, const char *, int); -int pppoed_config_str_equal (pppoed *, const char *, const char *, int); -int pppoed_config_str_equali (pppoed *, const char *, const char *, int); - -const char *pppoed_listener_config_str (pppoed_listener *, const char *); -int pppoed_listener_config_int (pppoed_listener *, const char *, int); -int pppoed_listener_config_str_equal (pppoed_listener *, const char *, const char *, int); -int pppoed_listener_config_str_equali (pppoed_listener *, const char *, const char *, int); +int pppoed_init (pppoed *); +int pppoed_start (pppoed *); +void pppoed_stop (pppoed *); +void pppoed_uninit (pppoed *); +void pppoed_pppoe_session_close_notify(pppoed *, pppoe_session *); +const char *pppoed_tlv_value_string(struct pppoe_tlv *); +int pppoed_reload(pppoed *, struct pppoe_confs *); #ifdef __cplusplus } diff --git a/usr.sbin/npppd/pppoe/pppoe_conf.h b/usr.sbin/npppd/pppoe/pppoe_conf.h new file mode 100644 index 00000000000..c6adccfbca1 --- /dev/null +++ b/usr.sbin/npppd/pppoe/pppoe_conf.h @@ -0,0 +1,46 @@ +/* $OpenBSD: pppoe_conf.h,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ */ + +/* + * Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef PPPOE_CONF_H +#define PPPOE_CONF_H 1 + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#include <stdbool.h> + +#define PPPOE_NAME_LEN 16 + +TAILQ_HEAD(pppoe_confs, pppoe_conf); + +#include <net/if.h> + +struct pppoe_conf { + TAILQ_ENTRY(pppoe_conf) entry; + char name[PPPOE_NAME_LEN]; + char if_name[IF_NAMESIZE]; + char *service_name; + char *ac_name; + bool accept_any_service; + bool desc_in_pktdump; + bool desc_out_pktdump; + bool session_in_pktdump; + bool session_out_pktdump; +}; + +#endif diff --git a/usr.sbin/npppd/pppoe/pppoe_local.h b/usr.sbin/npppd/pppoe/pppoe_local.h index e741f46a3dc..94e213c2118 100644 --- a/usr.sbin/npppd/pppoe/pppoe_local.h +++ b/usr.sbin/npppd/pppoe/pppoe_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pppoe_local.h,v 1.4 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pppoe_local.h,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -51,9 +51,9 @@ (session)->listener_index))->bpf /** macro is to get the physical layer label by {@link pppoe_session} */ -#define PPPOE_SESSION_LISTENER_LABEL(session) \ +#define PPPOE_SESSION_LISTENER_TUN_NAME(session) \ ((pppoed_listener *)slist_get(&(session)->pppoed->listener, \ - (session)->listener_index))->phy_label + (session)->listener_index))->tun_name /** macro is to get the interface name by {@link pppoe_session} */ #define PPPOE_SESSION_LISTENER_IFNAME(session) \ ((pppoed_listener *)slist_get(&(session)->pppoed->listener, \ diff --git a/usr.sbin/npppd/pppoe/pppoe_session.c b/usr.sbin/npppd/pppoe/pppoe_session.c index 87842baf535..982bcf7d556 100644 --- a/usr.sbin/npppd/pppoe/pppoe_session.c +++ b/usr.sbin/npppd/pppoe/pppoe_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pppoe_session.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pppoe_session.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -28,7 +28,7 @@ /**@file * Session management of PPPoE protocol - * $Id: pppoe_session.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ + * $Id: pppoe_session.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> @@ -494,12 +494,12 @@ pppoe_session_bind_ppp(pppoe_session *_this) _this->ppp = ppp; - ppp->tunnel_type = PPP_TUNNEL_PPPOE; + ppp->tunnel_type = NPPPD_TUNNEL_PPPOE; ppp->phy_context = _this; ppp->send_packet = pppoe_session_ppp_output; ppp->phy_close = pppoe_session_close_by_ppp; - strlcpy(ppp->phy_label, PPPOE_SESSION_LISTENER_LABEL(_this), + strlcpy(ppp->phy_label, PPPOE_SESSION_LISTENER_TUN_NAME(_this), sizeof(ppp->phy_label)); memset(&sdl, 0, sizeof(sdl)); diff --git a/usr.sbin/npppd/pppoe/pppoed.c b/usr.sbin/npppd/pppoe/pppoed.c index acf60fa8b3d..490a3bf9087 100644 --- a/usr.sbin/npppd/pppoe/pppoed.c +++ b/usr.sbin/npppd/pppoe/pppoed.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pppoed.c,v 1.10 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: pppoed.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -28,7 +28,7 @@ /**@file * This file provides the PPPoE(RFC2516) server(access concentrator) * implementaion. - * $Id: pppoed.c,v 1.10 2012/05/08 13:18:37 yasuoka Exp $ + * $Id: pppoed.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> @@ -64,8 +64,6 @@ #include "slist.h" #include "bytebuf.h" #include "hash.h" -#include "properties.h" -#include "config_helper.h" #include "privsep.h" #include "pppoe.h" @@ -329,7 +327,7 @@ pppoed_listener_start(pppoed_listener *_this, int restart) pppoed_log(_pppoed, LOG_INFO, "Listening on %s (PPPoE) [%s] using=%s " "address=%02x:%02x:%02x:%02x:%02x:%02x", _this->listen_ifname, - _this->phy_label, buf, _this->ether_addr[0], _this->ether_addr[1], + _this->tun_name, buf, _this->ether_addr[0], _this->ether_addr[1], _this->ether_addr[2], _this->ether_addr[3], _this->ether_addr[4], _this->ether_addr[5]); @@ -386,7 +384,7 @@ pppoed_listener_stop(pppoed_listener *_this) close(_this->bpf); pppoed_log(_pppoed, LOG_INFO, "Shutdown %s (PPPoE) [%s] " "address=%02x:%02x:%02x:%02x:%02x:%02x", - _this->listen_ifname, _this->phy_label, + _this->listen_ifname, _this->tun_name, _this->ether_addr[0], _this->ether_addr[1], _this->ether_addr[2], _this->ether_addr[3], _this->ether_addr[4], _this->ether_addr[5]); @@ -440,8 +438,6 @@ pppoed_uninit(pppoed *_this) slist_fini(&_this->session_free_list); /* listener themself has been released already */ slist_fini(&_this->listener); - - _this->config = NULL; } /* it called when the PPPoE session was closed */ @@ -465,127 +461,39 @@ pppoed_pppoe_session_close_notify(pppoed *_this, pppoe_session *session) /* * PPPoE Configuration */ -#define CFG_KEY(p, s) config_key_prefix((p), (s)) -#define VAL_SEP " \t\r\n" - -CONFIG_FUNCTIONS(pppoed_config, pppoed, config); -PREFIXED_CONFIG_FUNCTIONS(pppoed_listener_config, pppoed_listener, self->config, - phy_label); - /* reload configurations for the PPPoE daemon */ int -pppoed_reload(pppoed *_this, struct properties *config, const char *name, - int default_enabled) +pppoed_reload(pppoed *_this, struct pppoe_confs *pppoe_conf) { - struct sockaddr_dl *sdl; - int i, count, found; - hash_link *hl; - const char *val; - char *tok, *cp, buf[PPPOED_CONFIG_BUFSIZ], *label; - pppoed_listener *l; - int do_start; + int i, count, do_start, found; + struct pppoe_conf *conf; + struct ifaddrs *ifa0; + slist rmlist, newlist; struct { - char ifname[IF_NAMESIZE]; - char label[PPPOED_PHY_LABEL_SIZE]; + char ifname[IF_NAMESIZE]; + char name[PPPOED_PHY_LABEL_SIZE]; } listeners[PPPOE_NLISTENER]; - struct ifaddrs *ifa0, *ifa; - slist rmlist, newlist; - pppoe_session *session; + pppoed_listener *l; + pppoe_session *session; + hash_link *hl; do_start = 0; - - _this->config = config; - if (pppoed_config_str_equal(_this, CFG_KEY(name, "enabled"), "true", - default_enabled)) { - /* avoid false->true flapping */ - if (pppoed_is_stopped(_this) || !pppoed_is_running(_this)) - do_start = 1; - } else { - if (!pppoed_is_stopped(_this)) - pppoed_stop(_this); - return 0; - } - - if (do_start) { - if (pppoed_init(_this) != 0) - return 1; - _this->config = config; - } - ifa0 = NULL; slist_init(&rmlist); slist_init(&newlist); - _this->desc_in_pktdump = pppoed_config_str_equal(_this, - "log.pppoe.desc.in.pktdump", "true", 0); - _this->desc_out_pktdump = pppoed_config_str_equal(_this, - "log.pppoe.desc.out.pktdump", "true", 0); - - _this->session_in_pktdump = pppoed_config_str_equal(_this, - "log.pppoe.session.in.pktdump", "true", 0); - _this->session_out_pktdump = pppoed_config_str_equal(_this, - "log.pppoe.session.out.pktdump", "true", 0); - if (getifaddrs(&ifa0) != 0) { pppoed_log(_this, LOG_ERR, "getifaddrs() failed on %s(): %m", __func__); goto fail; } count = 0; - val = pppoed_config_str(_this, CFG_KEY(name, "interface")); - if (val != NULL) { - if (strlen(val) >= sizeof(buf)) { - log_printf(LOG_ERR, "configuration error at " - "%s: too long", CFG_KEY(name, "interface")); - return 1; - } - strlcpy(buf, val, sizeof(buf)); - - label = NULL; - /* it accepts multiple entries with tab/space separation */ - for (i = 0, cp = buf; - (tok = strsep(&cp, VAL_SEP)) != NULL;) { - if (*tok == '\0') - continue; - if (label == NULL) { - label = tok; - continue; - } - PPPOED_ASSERT(count < countof(listeners)); - if (count >= countof(listeners)) { - pppoed_log(_this, LOG_ERR, - "Too many listeners"); - goto fail; - } - /* check the interface exist or not */ - found = 0; - for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) { - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - if (sdl->sdl_family == AF_LINK && - IFTYPE_IS_LAN(sdl->sdl_type) && - strcmp(ifa->ifa_name, tok) == 0) { - found = 1; - break; - } - } - if (!found) { - pppoed_log(_this, LOG_ERR, - "interface %s is not found", tok); - goto fail; - } - strlcpy(listeners[count].ifname, tok, - sizeof(listeners[count].ifname)); - strlcpy(listeners[count].label, label, - sizeof(listeners[count].label)); - - label = NULL; - count++; - } - if (label != NULL) { - log_printf(LOG_ERR, "configuration error at %s: %s", - CFG_KEY(name, "interface"), label); - return 1; - } + TAILQ_FOREACH(conf, pppoe_conf, entry) { + strlcpy(listeners[count].ifname, conf->if_name, + sizeof(listeners[count].ifname)); + strlcpy(listeners[count].name, conf->name, + sizeof(listeners[count].name)); + count++; } if (slist_add_all(&rmlist, &_this->listener) != 0) @@ -609,8 +517,7 @@ pppoed_reload(pppoed *_this, struct properties *config, const char *name, pppoed_listener_init(_this, l); } l->self = _this; - strlcpy(l->phy_label, listeners[i].label, - sizeof(l->phy_label)); + strlcpy(l->tun_name, listeners[i].name, sizeof(l->tun_name)); strlcpy(l->listen_ifname, listeners[i].ifname, sizeof(l->listen_ifname)); if (slist_add(&newlist, l) == NULL) { @@ -959,8 +866,8 @@ static void pppoed_recv_PADI(pppoed_listener *_this, uint8_t shost[ETHER_ADDR_LEN], slist *tag_list) { - int len, accept_any_service_req; - const char *val, *service_name, *ac_name; + int len; + const char *service_name, *ac_name; u_char bufspace[2048]; u_char sn[2048], ac_name0[40]; struct pppoe_header pppoe; @@ -978,11 +885,8 @@ pppoed_recv_PADI(pppoed_listener *_this, uint8_t shost[ETHER_ADDR_LEN], tlv_service_name = NULL; service_name = ""; - if ((val = pppoed_listener_config_str(_this, "pppoe.service_name")) - != NULL) - service_name = val; - accept_any_service_req = pppoed_listener_config_str_equal(_this, - "pppoe.accept_any_service_request", "true", 1); + if (_this->conf->service_name != NULL) + service_name = _this->conf->service_name; for (slist_itr_first(tag_list); slist_itr_has_next(tag_list);) { tlv0 = slist_itr_next(tag_list); @@ -998,7 +902,7 @@ pppoed_recv_PADI(pppoed_listener *_this, uint8_t shost[ETHER_ADDR_LEN], sn[len] = '\0'; if (strcmp(service_name, sn) == 0 || - (sn[0] == '\0' && accept_any_service_req)) + (sn[0] == '\0' && _this->conf->accept_any_service)) tlv_service_name = tlv0; } } @@ -1042,7 +946,7 @@ pppoed_recv_PADI(pppoed_listener *_this, uint8_t shost[ETHER_ADDR_LEN], /* * Tag - Access Concentrator Name */ - ac_name = pppoed_listener_config_str(_this, "pppoe.ac_name"); + ac_name = _this->conf->ac_name; if (ac_name == NULL) { /* * use the ethernet address as default AC-Name. diff --git a/usr.sbin/npppd/pptp/pptp.h b/usr.sbin/npppd/pptp/pptp.h index 00cdb88a188..9fc786c8d28 100644 --- a/usr.sbin/npppd/pptp/pptp.h +++ b/usr.sbin/npppd/pptp/pptp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pptp.h,v 1.7 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pptp.h,v 1.8 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -141,6 +141,8 @@ /* * Constants of the NPPPD implementation */ +#include "pptp_conf.h" + /* pptpd status */ #define PPTPD_STATE_INIT 0 #define PPTPD_STATE_RUNNING 1 @@ -230,7 +232,8 @@ typedef struct _pptpd_listener { int sock_gre; /* GRE socket */ struct sockaddr_in bind_sin; /* listing TCP address */ struct sockaddr_in bind_sin_gre; /* listing GRE address */ - char phy_label[16]; + char tun_name[PPTP_NAME_LEN]; + struct pptp_conf *conf; } pptpd_listener; typedef struct _pptpd { @@ -240,20 +243,12 @@ typedef struct _pptpd { struct event ev_timer; /* timer event context */ slist ctrl_list; /* list of PPTP controls */ - struct properties *config; - slist call_free_list; /* Free call lists */ hash_table *call_id_map; /* table to map between callid and call */ /* ipv4 networks that is permitted to connect */ - struct in_addr_range *ip4_allow; uint32_t /* flags */ - initialized:1, - ctrl_in_pktdump:1, - ctrl_out_pktdump:1, - data_in_pktdump:1, - data_out_pktdump:1, - phy_label_with_ifname:1; + initialized:1; } pptpd; #define pptp_ctrl_sock_gre(ctrl) \ @@ -261,16 +256,19 @@ typedef struct _pptpd { (ctrl)->listener_index))->sock_gre /* get listner's physical layer label from pptp_ctrl */ -#define PPTP_CTRL_LISTENER_LABEL(ctrl) \ +#define PPTP_CTRL_LISTENER_TUN_NAME(ctrl) \ ((pptpd_listener *)slist_get(&(ctrl)->pptpd->listener,\ - (ctrl)->listener_index))->phy_label + (ctrl)->listener_index))->tun_name + +#define PPTP_CTRL_CONF(ctrl) \ + ((pptpd_listener *)slist_get(&(ctrl)->pptpd->listener, \ + (ctrl)->listener_index))->conf typedef struct _pptp_ctrl { pptpd *pptpd; /* parents */ uint16_t listener_index; unsigned id; int state; - char phy_label[16]; int sock; struct sockaddr_storage peer; @@ -336,7 +334,7 @@ int pptpd_start (pptpd *); void pptpd_stop (pptpd *); void pptpd_stop_immediatly (pptpd *); void pptpd_ctrl_finished_notify(pptpd *, pptp_ctrl *); -int pptpd_add_listener(pptpd *, int, const char *, struct sockaddr *); +int pptpd_add_listener(pptpd *, int, struct pptp_conf *); pptp_ctrl *pptp_ctrl_create (void); int pptp_ctrl_init (pptp_ctrl *); @@ -353,17 +351,7 @@ void pptp_call_destroy (pptp_call *); void pptp_call_input (pptp_call *, int, u_char *, int); void pptp_call_gre_input (pptp_call *, uint32_t, uint32_t, int, u_char *, int); void pptp_call_disconnect(pptp_call *, int, int, const char *); -int pptpd_reload(pptpd *, struct properties *, const char *, int); - -/* config_helper */ -const char *pptpd_config_str (pptpd *, const char *); -int pptpd_config_int (pptpd *, const char *, int); -int pptpd_config_str_equal (pptpd *, const char *, const char *, int); -int pptpd_config_str_equali (pptpd *, const char *, const char *, int); -const char *pptp_ctrl_config_str (pptp_ctrl *, const char *); -int pptp_ctrl_config_int (pptp_ctrl *, const char *, int); -int pptp_ctrl_config_str_equal (pptp_ctrl *, const char *, const char *, int); -int pptp_ctrl_config_str_equali (pptp_ctrl *, const char *, const char *, int); +int pptpd_reload(pptpd *, struct pptp_confs *); #ifdef __cplusplus } diff --git a/usr.sbin/npppd/pptp/pptp_call.c b/usr.sbin/npppd/pptp/pptp_call.c index 49587359b66..a9ff1276cbb 100644 --- a/usr.sbin/npppd/pptp/pptp_call.c +++ b/usr.sbin/npppd/pptp/pptp_call.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pptp_call.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pptp_call.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: pptp_call.c,v 1.6 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $Id: pptp_call.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file PPTP Call */ /* currently it supports PAC mode only */ #include <sys/types.h> @@ -624,7 +624,8 @@ pptp_call_gre_output(pptp_call *_this, int fseq, int fack, u_char *pkt, default: return 1; } - if (_this->ctrl->pptpd->data_out_pktdump != 0) { + + if (PPTP_CTRL_CONF(_this->ctrl)->data_out_pktdump != 0) { pptp_call_log(_this, LOG_DEBUG, "PPTP Data output packet dump"); show_hd(debug_get_debugfp(), buf, opkt - buf); } @@ -743,11 +744,12 @@ pptp_call_bind_ppp(pptp_call *_this) _this->ppp = ppp; ppp->phy_context = _this; - ppp->tunnel_type = PPP_TUNNEL_PPTP; + ppp->tunnel_type = NPPPD_TUNNEL_PPTP; ppp->send_packet = pptp_call_ppp_output; ppp->phy_close = pptp_call_closed_by_ppp; - strlcpy(ppp->phy_label, _this->ctrl->phy_label, sizeof(ppp->phy_label)); + strlcpy(ppp->phy_label, PPTP_CTRL_LISTENER_TUN_NAME(_this->ctrl), + sizeof(ppp->phy_label)); PPTP_CALL_ASSERT(sizeof(ppp->phy_info) >= _this->ctrl->peer.ss_len); memcpy(&ppp->phy_info, &_this->ctrl->peer, diff --git a/usr.sbin/npppd/pptp/pptp_conf.h b/usr.sbin/npppd/pptp/pptp_conf.h new file mode 100644 index 00000000000..c9c0d6af2b4 --- /dev/null +++ b/usr.sbin/npppd/pptp/pptp_conf.h @@ -0,0 +1,45 @@ +/* $OpenBSD: pptp_conf.h,v 1.1 2012/09/18 13:14:08 yasuoka Exp $ */ + +/* + * Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef PPTP_CONF_H +#define PPTP_CONF_H 1 + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#include <stdbool.h> + +#define PPTP_NAME_LEN 16 + +TAILQ_HEAD(pptp_confs, pptp_conf); + +struct pptp_conf { + TAILQ_ENTRY(pptp_conf) entry; + char name[PPTP_NAME_LEN]; + char *hostname; + char *vendor_name; + int echo_interval; + int echo_timeout; + struct sockaddr_storage address; + bool ctrl_in_pktdump; + bool ctrl_out_pktdump; + bool data_in_pktdump; + bool data_out_pktdump; +}; + +#endif diff --git a/usr.sbin/npppd/pptp/pptp_ctrl.c b/usr.sbin/npppd/pptp/pptp_ctrl.c index 8c555faf96c..a983b5051a1 100644 --- a/usr.sbin/npppd/pptp/pptp_ctrl.c +++ b/usr.sbin/npppd/pptp/pptp_ctrl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pptp_ctrl.c,v 1.6 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: pptp_ctrl.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -29,7 +29,7 @@ * PPTP(RFC 2637) control connection implementation. * currently it only support PAC part */ -/* $Id: pptp_ctrl.c,v 1.6 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $Id: pptp_ctrl.c,v 1.7 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -529,7 +529,7 @@ pptp_ctrl_output_flush(pptp_ctrl *_this) bytebuffer_flip(_this->send_buf); - if (_this->pptpd->ctrl_out_pktdump != 0) { + if (PPTP_CTRL_CONF(_this)->ctrl_out_pktdump != 0) { pptp_ctrl_log(_this, LOG_DEBUG, "PPTP Control output packet"); show_hd(debug_get_debugfp(), bytebuffer_pointer(_this->send_buf), @@ -746,14 +746,14 @@ pptp_ctrl_send_SCCRP(pptp_ctrl *_this, int result, int error) /* this implementation only support these strings up to * 63 character */ /* host name */ - if ((val = pptp_ctrl_config_str(_this, "pptp.host_name")) == NULL) + + if (PPTP_CTRL_CONF(_this)->hostname == NULL) val = ""; strlcpy(scc->host_name, val, sizeof(scc->host_name)); /* vender name */ - if ((val = pptp_ctrl_config_str(_this, "pptp.vendor_name")) == NULL) + if (PPTP_CTRL_CONF(_this)->vendor_name == NULL) val = PPTPD_DEFAULT_VENDOR_NAME; - strlcpy(scc->vendor_string, val, sizeof(scc->vendor_string)); pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); @@ -919,7 +919,7 @@ pptp_ctrl_input(pptp_ctrl *_this, u_char *pkt, int lpkt) _this->last_rcv_ctrl = curr_time; - if (_this->pptpd->ctrl_in_pktdump != 0) { + if (PPTP_CTRL_CONF(_this)->ctrl_in_pktdump != 0) { pptp_ctrl_log(_this, LOG_DEBUG, "PPTP Control input packet dump: mestype=%s(%d)", pptp_ctrl_mes_type_string(hdr->control_message_type), diff --git a/usr.sbin/npppd/pptp/pptpd.c b/usr.sbin/npppd/pptp/pptpd.c index cb5b86bf78f..e685a2cfd1a 100644 --- a/usr.sbin/npppd/pptp/pptpd.c +++ b/usr.sbin/npppd/pptp/pptpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pptpd.c,v 1.10 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $OpenBSD: pptpd.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,12 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: pptpd.c,v 1.10 2012/05/08 13:15:12 yasuoka Exp $ */ +/* $Id: pptpd.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ /**@file * This file provides a implementation of PPTP daemon. Currently it * provides functions for PAC (PPTP Access Concentrator) only. - * $Id: pptpd.c,v 1.10 2012/05/08 13:15:12 yasuoka Exp $ + * $Id: pptpd.c,v 1.11 2012/09/18 13:14:08 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> @@ -64,8 +64,6 @@ #include "hash.h" #include "slist.h" #include "addr_range.h" -#include "properties.h" -#include "config_helper.h" #include "pptp.h" #include "pptp_local.h" @@ -99,23 +97,11 @@ int pptpd_init(pptpd *_this) { int i, m; - struct sockaddr_in sin0; uint16_t call0, call[UINT16_MAX - 1]; memset(_this, 0, sizeof(pptpd)); _this->id = pptpd_seqno++; - slist_init(&_this->listener); - memset(&sin0, 0, sizeof(sin0)); - sin0.sin_len = sizeof(sin0); - sin0.sin_family = AF_INET; - if (pptpd_add_listener(_this, 0, PPTPD_DEFAULT_LAYER2_LABEL, - (struct sockaddr *)&sin0) != 0) { - return 1; - } - - _this->ip4_allow = NULL; - slist_init(&_this->ctrl_list); slist_init(&_this->call_free_list); @@ -142,8 +128,7 @@ pptpd_init(pptpd *_this) /* add a listner to pptpd daemon context */ int -pptpd_add_listener(pptpd *_this, int idx, const char *label, - struct sockaddr *bindaddr) +pptpd_add_listener(pptpd *_this, int idx, struct pptp_conf *conf) { int inaddr_any; pptpd_listener *plistener, *plstn; @@ -174,9 +159,10 @@ pptpd_add_listener(pptpd *_this, int idx, const char *label, } memset(plistener, 0, sizeof(pptpd_listener)); - PPTPD_ASSERT(sizeof(plistener->bind_sin) >= bindaddr->sa_len); - memcpy(&plistener->bind_sin, bindaddr, bindaddr->sa_len); - memcpy(&plistener->bind_sin_gre, bindaddr, bindaddr->sa_len); + PPTPD_ASSERT(sizeof(plistener->bind_sin) >= conf->address.ss_len); + memcpy(&plistener->bind_sin, &conf->address, conf->address.ss_len); + memcpy(&plistener->bind_sin_gre, &conf->address, + conf->address.ss_len); if (plistener->bind_sin.sin_port == 0) plistener->bind_sin.sin_port = htons(PPTPD_DEFAULT_TCP_PORT); @@ -205,7 +191,8 @@ pptpd_add_listener(pptpd *_this, int idx, const char *label, plistener->sock_gre = -1; plistener->self = _this; plistener->index = idx; - strlcpy(plistener->phy_label, label, sizeof(plistener->phy_label)); + plistener->conf = conf; + strlcpy(plistener->tun_name, conf->name, sizeof(plistener->tun_name)); if (slist_add(&_this->listener, plistener) == NULL) { pptpd_log(_this, LOG_ERR, "slist_add() failed in %s: %m", @@ -236,13 +223,9 @@ pptpd_uninit(pptpd *_this) free(plstn); } slist_fini(&_this->listener); - if (_this->call_id_map != NULL) { + if (_this->call_id_map != NULL) hash_free(_this->call_id_map); - } - if (_this->ip4_allow != NULL) - in_addr_range_list_remove_all(&_this->ip4_allow); _this->call_id_map = NULL; - _this->config = NULL; } #define CALL_ID_KEY(call_id, listener_idx) \ @@ -309,9 +292,6 @@ pptpd_listener_start(pptpd_listener *_this) memcpy(&bind_sin, &_this->bind_sin, sizeof(bind_sin)); memcpy(&bind_sin_gre, &_this->bind_sin_gre, sizeof(bind_sin_gre)); - if (_this->phy_label[0] == '\0') - strlcpy(_this->phy_label, PPTPD_DEFAULT_LAYER2_LABEL, - sizeof(_this->phy_label)); if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { pptpd_log(_this->self, LOG_ERR, "socket() failed at %s(): %m", __func__); @@ -363,7 +343,7 @@ pptpd_listener_start(pptpd_listener *_this) #endif pptpd_log(_this->self, LOG_INFO, "Listening %s:%u/tcp (PPTP PAC) [%s]", inet_ntoa(_this->bind_sin.sin_addr), - ntohs(_this->bind_sin.sin_port), _this->phy_label); + ntohs(_this->bind_sin.sin_port), _this->tun_name); /* GRE */ bind_sin_gre.sin_port = 0; @@ -591,156 +571,46 @@ pptpd_stop(pptpd *_this) /* * PPTP Configuration */ -#define CFG_KEY(p, s) config_key_prefix((p), (s)) -#define VAL_SEP " \t\r\n" - -CONFIG_FUNCTIONS(pptpd_config, pptpd, config); -PREFIXED_CONFIG_FUNCTIONS(pptp_ctrl_config, pptp_ctrl, pptpd->config, - phy_label); int -pptpd_reload(pptpd *_this, struct properties *config, const char *name, - int default_enabled) +pptpd_reload(pptpd *_this, struct pptp_confs *pptp_conf) { - int i, do_start, aierr; - const char *val; - char *tok, *cp, buf[PPTPD_CONFIG_BUFSIZ], *label; - struct addrinfo *ai; - - ASSERT(_this != NULL); - ASSERT(config != NULL); - - _this->config = config; - do_start = 0; - if (pptpd_config_str_equal(_this, CFG_KEY(name, "enabled"), "true", - default_enabled)) { - /* avoid false-true flap */ - if (pptpd_is_shutting_down(_this)) - pptpd_stop_immediatly(_this); - if (pptpd_is_stopped(_this)) - do_start = 1; - } else { - if (!pptpd_is_stopped(_this)) - pptpd_stop(_this); - return 0; - } - if (do_start && pptpd_init(_this) != 0) - return 1; - /* set again as pptpd_init will reset it */ - _this->config = config; - - _this->ctrl_in_pktdump = pptpd_config_str_equal(_this, - "log.pptp.ctrl.in.pktdump", "true", 0); - _this->data_in_pktdump = pptpd_config_str_equal(_this, - "log.pptp.data.in.pktdump", "true", 0); - _this->ctrl_out_pktdump = pptpd_config_str_equal(_this, - "log.pptp.ctrl.out.pktdump", "true", 0); - _this->data_out_pktdump = pptpd_config_str_equal(_this, - "log.pptp.data.out.pktdump", "true", 0); - _this->phy_label_with_ifname = pptpd_config_str_equal(_this, - CFG_KEY(name, "label_with_ifname"), "true", 0); - - /* parse ip4_allow */ - in_addr_range_list_remove_all(&_this->ip4_allow); - val = pptpd_config_str(_this, CFG_KEY(name, "ip4_allow")); - if (val != NULL) { - if (strlen(val) >= sizeof(buf)) { - log_printf(LOG_ERR, "configuration error at " - "%s: too long", CFG_KEY(name, "ip4_allow")); - return 1; - } - strlcpy(buf, val, sizeof(buf)); - for (cp = buf; (tok = strsep(&cp, VAL_SEP)) != NULL;) { - if (*tok == '\0') - continue; - if (in_addr_range_list_add(&_this->ip4_allow, tok) - != 0) { - pptpd_log(_this, LOG_ERR, - "configuration error at %s: %s", - CFG_KEY(name, "ip4_allow"), tok); - return 1; - } - } - } - - if (do_start) { - /* in the case of 1) cold-booted and 2) pptpd.enable - * toggled "false" to "true" do this, because we can - * assume that all pptpd listner are initialized. */ - - val = pptpd_config_str(_this, CFG_KEY(name, "listener_in")); - if (val != NULL) { - if (strlen(val) >= sizeof(buf)) { - pptpd_log(_this, LOG_ERR, - "configuration error at " - "%s: too long", CFG_KEY(name, "listener")); - return 1; - } - strlcpy(buf, val, sizeof(buf)); - - label = NULL; - /* it can accept multple velues with tab/space - * separation */ - for (i = 0, cp = buf; - (tok = strsep(&cp, VAL_SEP)) != NULL;) { - if (*tok == '\0') - continue; - if (label == NULL) { - label = tok; - continue; - } - if ((aierr = addrport_parse(tok, IPPROTO_TCP, - &ai)) != 0) { - pptpd_log(_this, LOG_ERR, - "configuration error at " - "%s: %s: %s", - CFG_KEY(name, "listener_in"), tok, - gai_strerror(aierr)); - return 1; - } - PPTPD_ASSERT(ai != NULL && - ai->ai_family == AF_INET); - if (pptpd_add_listener(_this, i, label, - ai->ai_addr) != 0) { - freeaddrinfo(ai); - label = NULL; + int i; + struct pptp_conf *conf; + pptpd_listener *listener; + + if (slist_length(&_this->listener) > 0) { + /* + * TODO: add / remove / restart listener. + */ + slist_itr_first(&_this->listener); + while (slist_itr_has_next(&_this->listener)) { + listener = slist_itr_next(&_this->listener); + TAILQ_FOREACH(conf, pptp_conf, entry) { + if (strcmp(listener->tun_name, + conf->name) == 0) { + listener->conf = conf; break; } - freeaddrinfo(ai); - label = NULL; - i++; - } - if (label != NULL) { - pptpd_log(_this, LOG_ERR, - "configuration error at %s: %s", - CFG_KEY(name, "listner_in"), label); - return 1; } } - if (pptpd_start(_this) != 0) - return 1; + + return 0; } + if (pptpd_init(_this) != 0) + return -1; + i = 0; + TAILQ_FOREACH(conf, pptp_conf, entry) + pptpd_add_listener(_this, i++, conf); + if (pptpd_start(_this) != 0) + return -1; + return 0; } /* * I/O functions */ -static void -pptpd_log_access_deny(pptpd *_this, const char *reason, struct sockaddr *peer) -{ - char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV]; - - if (getnameinfo(peer, peer->sa_len, hostbuf, sizeof(hostbuf), - servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - pptpd_log(_this, LOG_ERR, "getnameinfo() failed at %s(): %m", - __func__); - return; - } - pptpd_log(_this, LOG_ALERT, "denied a connection from %s:%s/tcp: %s", - hostbuf, servbuf, reason); -} - /* I/O event handler of 1723/tcp */ static void pptpd_io_event(int fd, short evmask, void *ctx) @@ -783,27 +653,13 @@ pptpd_io_event(int fd, short evmask, void *ctx) /* check peer */ switch (peer.ss_family) { case AF_INET: - if (!in_addr_range_list_includes( - &_this->ip4_allow, - &((struct sockaddr_in *)&peer)->sin_addr)) { - reason = "not allowed by acl."; - break; - } - goto accept; + pptp_ctrl_start_by_pptpd(_this, newsock, + listener->index, (struct sockaddr *)&peer); + break; default: reason = "address family is not supported."; break; } - /* not permitted */ - pptpd_log_access_deny(_this, reason, - (struct sockaddr *)&peer); - close(newsock); - continue; - /* NOTREACHED */ -accept: - /* permitted, can accepted */ - pptp_ctrl_start_by_pptpd(_this, newsock, - listener->index, (struct sockaddr *)&peer); } } } @@ -874,7 +730,7 @@ pptpd_gre_input(pptpd_listener *listener, struct sockaddr *peer, u_char *pkt, "getnameinfo() failed at %s(): %m", __func__); goto fail; } - if (_this->data_in_pktdump != 0) { + if (listener->conf->data_in_pktdump != 0) { pptpd_log(_this, LOG_DEBUG, "PPTP Data input packet dump"); show_hd(debug_get_debugfp(), pkt, lpkt); } @@ -976,10 +832,8 @@ static void pptp_ctrl_start_by_pptpd(pptpd *_this, int sock, int listener_index, struct sockaddr *peer) { - int ival; pptp_ctrl *ctrl; - socklen_t sslen; - char ifname[IF_NAMESIZE], msgbuf[128]; + socklen_t sslen; ctrl = NULL; if ((ctrl = pptp_ctrl_create()) == NULL) @@ -1001,38 +855,10 @@ pptp_ctrl_start_by_pptpd(pptpd *_this, int sock, int listener_index, goto fail; } - /* change with interface name, ex) "L2TP%em0.mru" */ - if (_this->phy_label_with_ifname != 0) { - if (get_ifname_by_sockaddr((struct sockaddr *)&ctrl->our, - ifname) == NULL) { - pptpd_log_access_deny(_this, - "could not get interface informations", peer); - goto fail; - } - if (pptpd_config_str_equal(_this, - config_key_prefix("pptpd.interface", ifname), "accept", 0)){ - snprintf(ctrl->phy_label, sizeof(ctrl->phy_label), - "%s%%%s", PPTP_CTRL_LISTENER_LABEL(ctrl), ifname); - } else if (pptpd_config_str_equal(_this, - config_key_prefix("pptpd.interface", "any"), "accept", 0)){ - snprintf(ctrl->phy_label, sizeof(ctrl->phy_label), - "%s", PPTP_CTRL_LISTENER_LABEL(ctrl)); - } else { - /* the interface is not permitted */ - snprintf(msgbuf, sizeof(msgbuf), - "'%s' is not allowed by config.", ifname); - pptpd_log_access_deny(_this, msgbuf, peer); - goto fail; - } - } else - strlcpy(ctrl->phy_label, PPTP_CTRL_LISTENER_LABEL(ctrl), - sizeof(ctrl->phy_label)); - - if ((ival = pptp_ctrl_config_int(ctrl, "pptp.echo_interval", 0)) != 0) - ctrl->echo_interval = ival; - - if ((ival = pptp_ctrl_config_int(ctrl, "pptp.echo_timeout", 0)) != 0) - ctrl->echo_timeout = ival; + if (PPTP_CTRL_CONF(ctrl)->echo_interval != 0) + ctrl->echo_interval = PPTP_CTRL_CONF(ctrl)->echo_interval; + if (PPTP_CTRL_CONF(ctrl)->echo_timeout != 0) + ctrl->echo_timeout = PPTP_CTRL_CONF(ctrl)->echo_timeout; if (pptp_ctrl_start(ctrl) != 0) goto fail; |