Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sstp: fix proxy-protocol-v2 sanity checks
|
|
|
|
|
|
|
|
Rework the conditionals to make __ipoe_session_activate() and
ipoe_session_finished() follow the same logic:
* Drop the second '!serv->opt_ifcfg' test in __ipoe_session_activate(),
which is is already checked by the parent conditional.
* Invert the order of the tests in ipoe_session_finished(), so that
it uses the same conditions as __ipoe_session_activate().
Finally, set the 'src' parameter in iproute_del(), so that we can be
sure that the deleted route matches the one added by
__ipoe_session_activate().
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Using NLM_F_ACK in these functions is confusing because they don't
parse any netlink response.
In fact, NLM_F_ACK is only required internally by rtnl_talk(), which
already adds it when its 'answer' parameter is NULL. Therefore it's
useless to manually set it in functions that don't set 'answer'.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
These are deletion requests. NLM_F_CREATE is confusing for readers and
ignored by kernel.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
No need to be clever here. All IPv6 routes have global scope (kernel
ignores rtm_scope for IPv6 and always reports RT_SCOPE_UNIVERSE when
dumping such routes).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
From a logical point of view, we have link scope if no gateway is
present, and global scope otherwise. Therefore it makes more sense
to set rtm_scope depending on 'gw' rather than on 'ifindex'.
Currently, callers of iproute_add() and iproute_del() either set
'ifindex' or 'gw', but never both. So even if confusing, the current
code results in right scope selection. However one can't figure this
out without analysing every caller.
We should set rtm_scope based on the presence of the gateway instead.
Given the current code base, that doesn't change the end result, but
that better maches the scope concept. Also, that's the way iproute2
does its selection.
Furthermore, it'd be perfectly valid to have both 'iface' and 'gw' set.
In that case, scope should be RT_SCOPE_UNIVERSE instead of
RT_SCOPE_LINK. Basing scope selection on 'gw' makes this case work
correctly.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Be more specific about which route we want to remove. By not specifying
the gateway we could remove a different route than the one we
originally inserted.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Rework iproute_del() to have the same parameters as iproute_add().
This will allow callers to specify more precisely the route they want
to delete.
Callers will later be converted to make use of these parameters to
ensure that the removed route precisely matches the one that was
originaly inserted.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Now that we have primitives for parsing IPv4 ranges, let's use them to
simplify parse_iprange().
Try u_parse_ip4cidr() first. In case of failure, try u_parse_ip4range().
If any of them succeeds, verify that there aren't spurious data
following the range definition. If everything is valid, either load the
range or disable the module (if the range is 0.0.0.0/0).
The diff is a bit ugly, but the implementation should be much clearer.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Define the IPv4 counterparts of u_ip6str() and u_parse_ip6cidr().
Also add the special u_parse_ip4range() which will be useful for
parsing the [client-ip-range] section of accel-ppp.conf.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Redefine u_parse_ip4addr() to match the behaviour of other u_parse_*()
functions:
* Drop the err_msg parameter.
* Return the number of bytes parsed instead of an error number.
* Remove support for fancy IPv4 address notations.
There is currently only one user of u_parse_ip4addr() (in iprange.c).
Dropping the fancy IPv4 address representations is probably not going
to harm anyone (quite the opposite as many users don't realise that
leading 0 means octal and that plain integers can be considered IPv4
addresses).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
u_parse_endstr() used to be u_parse_eos() in my internal repository.
I forgot to update the documentation when I renamed it.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Framed-IPv6-Route is the IPv6 counterpart of Framed-Route. It's only
used for defining routes to be added locally by accel-ppp. Routes that
should be announced to the peer using Router Advertisements should be
defined in the Route-IPv6-Information attribute (but that's currently
not implemented).
Framed-IPv6-Route format is:
<network in CIDR notation> [<gateway IPv6 address> [<route metric>]]
The gateway address and the route metric are optionals, but the metric
can only be set if a gateway address is given. One can use the
unspecified address '::' to define a route with no gateway and a
non-default route metric.
When no gateway address is defined, the session's network interface is
used directly.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Define parsers for IPv6 addresses and CIDR notations, unsigned
integers, separators (variable number of space characters) and end of
strings (variable number of spaces followed by '\0').
All of these functions work on constant string and return the number
bytes parsed. If the input string doesn't have the expected format,
these functions return 0 (no forward progress).
Also implement a convenient wrapper around inet_ntop() that can be used
easily in printf-like functions.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Let callers set a gateway and a priority to IPv6 routes. This is
necessary for implementing the RADIUS Framed-IPv6-Route attribute.
Also let ip6route_del() configure .rtm_protocol. This is already
implemented in ip6route_add(), so we need to add the ip6route_del()
counterpart. Otherwise, we couldn't delete routes that were added using
a non-zero protocol.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
In DSL setups, it's common to have an intermediate equipment,
potentially managed by a different operator, between the two PPP
endpoints. In such setups, the client establishes a PPPoE or L2TP
session with the intermediate equipment. They perform LCP negotiation
and eventually get to the authentication phase. Based on the client's
username, the intermediate equipment then establishes another L2TP
session with the final PPP endpoint (accel-ppp). At this point, the
intermediate equipment forwards any PPP frame received on one side to
the other side, so that it becomes transparent to PPP frames.
Then accel-ppp starts an LCP negotiation again, performs
authentication, negotiates NCPs and finally forwards IP packets to and
from the client.
+--------+ +--------------+ +-----------+
| Client |------------------------| Intermediate |--------------------| accel-ppp |
| | | equipment | | |
+--------+ +--------------+ +-----------+
<-- First hop PPPoE --> <-- Second hop -->
or L2TP session L2TP session
<----------------- End to end PPP session ----------------->
Therefore, from the client point of view, two LCP negotiations occur.
LCP re-negotiation is explicitly handled by RFC 1661 and even
non-conforming PPP clients generally cope with this situation well
enough (as long as LCP re-negotiation occurs before the authentication
phase completes).
However, accel-ppp always starts its LCP negotiation with an identifier
set to 1. If the previous LCP negotiation also used identifier 1, then
some clients (at least MikroTik products) consider that the
Configure-Request sent by accel-ppp is part of the previous LCP
negotiation and refuse to return to link establishment phase as
mandated by section 3.4 of RFC 1661.
We can easily work around this problem by using random identifiers.
This maximises the chances that accel-ppp picks a different identifier
than the intermediate equipment and avoids falling into the MikroTik
problem. In case of bad luck and the chosen identifier is the same as
the one used for the original LCP negotiation, then PPP establishment
fails and the client tries to reconnect until the intermediate
equipment and accel-ppp pick up different numbers. So the connection
eventually succeeds.
The identifier is set in ppp_fsm_init(), so it also affects NCPs.
Therefore, IPCP and IPv6CP now also use random identifiers.
We need to define 'id' and 'recv_id' in struct ppp_fsm_t as uint8_t,
otherwise they could be chosen larger than 255 and comparing their
value with the 8-bits values found in received packets would fail (this
was generally not a problem when id was initially set to 1 and wouldn't
grow much).
Also, let's seed random() at startup, so that we don't end up with the
same sequences across restarts. This also benefits other users of
random(), like LCP magic numbers.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
This callback isn't used anymore. Let's remove it from all
authentication backends.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
If we receive a Configure-Request packet, that means the peer wants us
to authenticate to him. However, none of our authentication backends
(PAP, CHAP and MSCHAP v1/v2) supports authenticating ourself to the
peer. Therefore, the LCP negotiation completes, but we hang in the
authentication phase because accel-ppp never sends any credential.
We should reject the Authentication-Protocol option found in
Configure-Request packets sent by the peer. This way, the peer knows
that we won't authenticate to him. Then it's up to him to keep
connecting without authentication from our side or to drop the
connection.
This doesn't change the way we request the peer to authenticate to us.
That part of the negotiation is handled by Configure-Request packets
that are sent by us (not those sent by the peer).
In practice some PPP clients wouldn't connect with the previous
behaviour, but are perfectly happy with their Authentication-Protocol
option being rejected. They just resend their Configure-Request without
requesting authentication from our side.
Also, since the peer_auth field of struct auth_option_t is never set
anymore, we can remove the conditionals in auth_recv_conf_nak() and
auth_recv_conf_rej().
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
The openssl/ssl.h header file is already included at the beginning of
this file.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
It's often useful to let a program crash on SIGSEGV and let an external
daemon, like monit or systemd, restart it when needed. This allows to
generate core dumps and do post-mortem analysis based on the collected
traces.
This patch add the new '--no-sigsegv' option to disable accel-ppp's
SIGSEGV handler and use the system's core(5) mechanism instead.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
SIGSEGV, SIGILL, SIGFPE and SIGBUS aren't blocked, but they're added to
the set of signals passed to sigwait(). This is confusing (should these
signals be consumed by sigwait() or by their respective signal
handler?) and is undefined according to the POSIX man page
(http://man7.org/linux/man-pages/man3/sigwait.3p.html).
In practice, sigwait() was only triggered when manually sending the
signals to accel-pppd ("pkill -FPE accel-pppd"). On normal
circumstances though, these signals are triggered by invalid
operations run by the program. In these cases the signal handler was
run and sigwait() wasn't woken up.
So let's remove SIGSEGV, SIGILL, SIGFPE and SIGBUS from the set passed
to sigwait(). This simplifies the code, avoids undefined behaviour and
doesn't change accel-ppp behaviour for real-world use cases.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
If wins_opt->addr is NULL, then we have no address to propose (none
defined in accel-ppp.conf and none provided by RADIUS). Currently,
in that case, accel-ppp accepts and acks the address found in the peer's
configuration request. But the peer would normally use the undefined IP
address, so if we ack it, we explicitely tell the peer that 0.0.0.0 is
the primary/secondary NBNS server.
If the peer already knows a NBNS server IP address, it doesn't have to
negociate it with accel-ppp. It can just use it directly, after it
retrieved its own IP address. Therefore there is no need for accel-ppp
to blindly accept addresses proposed by the peer.
This patch rejects *-NBNS-Address if accel-ppp has no NBNS server to
propose, making it explicit to the peer that its request can't be
satisfied.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
When handling the EV_WINS event, IPCP assumes that the ->wins1 and
->wins2 fields of the event structure are properly set. But that may
not be the case.
If only one of the MS-Primary-NBNS-Server or MS-Secondary-NBNS-Server
RADIUS attributes was received, then only ->wins1 or ->wins2 is set,
while the other keeps a non initialised value. This uninitialised value
is then copied by ev_wins() and proposed to the peer when negociating
the Primary-NBNS-Address or Secondary-NBNS-Address IPCP options.
That leaks four bytes of the stack to the network and prevents using
the values found in the [wins] section of accel-ppp.conf as fallback.
Fix this by initialising the whole event structure in rad_proc_attrs().
Then, in ev_wins(), we can check if ->wins1 or ->wins2 is properly set
before copying them. That allows to propery fallback to accel-ppp.conf
values when one of the values was not provided by RADIUS.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
If dns_opt->addr is NULL, then we have no address to propose (none
defined in accel-ppp.conf and none provided by RADIUS). Currently,
in that case, accel-ppp accepts and acks the address found in the peer's
configuration request. But the peer would normally use the undefined IP
address, so if we ack it, we explicitely tell the peer that 0.0.0.0 is
the primary/secondary DNS server.
If the peer already knows a DNS server IP address, it doesn't have to
negociate it with accel-ppp. It can just use it directly, after it
retrieved its own IP address. Therefore there is no need for accel-ppp
to blindly accept addresses proposed by the peer.
This patch rejects *-DNS-Address if accel-ppp has no DNS server to
propose, making it explicit to the peer that its request can't be
satisfied.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
When handling the EV_DNS event, IPCP assumes that the ->dns1 and ->dns2
fields of the event structure are properly set. But that may not be the
case.
If only one of the MS-Primary-DNS-Server or MS-Secondary-DNS-Server
RADIUS attributes was received, then only ->dns1 or ->dns2 is set,
while the other keeps a non initialised value. This uninitialised value
is then copied by ev_dns() and proposed to the peer when negociating
the Primary-DNS-Address or Secondary-DNS-Address IPCP options.
That leaks four bytes of the stack to the network and prevents using
the values found in the [dns] section of accel-ppp.conf as fallback.
Fix this by initialising the whole event structure in rad_proc_attrs().
Then, in ev_dns(), we can check if ->dns1 or ->dns2 is properly set
before copying them. That allows to propery fallback to accel-ppp.conf
values when one of the values was not provided by RADIUS.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
When accel-ppp is under stress (for example because of massive
disconnections) it may enter a state where no session could be
created or destroyed anymore.
This happens when at least one of the pppd_compat fork() fail. In this
case, the error code path doesn't unlock the sigchld handler, which
prevents it from running the completion callbacks of running scripts.
If the "fork-limit" option is used, failure to call the completion
callback will prevent other scripts from running. This will block
setting up and tearing down sessions, as those will wait indefinitely
for their pppd_compat scripts to run.
Therefore, we have to unlock the sigchld handler when fork() fails.
We also need to call fork_queue_wakeup(), because the previous
check_fork_limit() call already took one reference in the fork limit.
Finally, ev_ses_pre_up() is a bit special because it has to tear the
session down if the ip-pre-up script failed. Therefore it also has to
call ap_session_terminate() upon fork() failures.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Allow triton_context_wakeup() to run before triton_context_schedule().
When that happens, triton_context_schedule() now lets the context
running instead of putting it in sleep mode.
Note that, even though triton now allows triton_context_wakeup() to
happen before triton_context_schedule(), these two functions still need
to be paired and not nested. That is, in a sequence like the following,
triton_context_wakeup()
triton_context_wakeup()
triton_context_schedule()
triton_context_schedule()
the second triton_context_schedule() would put the context in sleep
mode. No matter how many triton_context_wakeup() have been called, the
first triton_context_schedule() "consumes" them all.
Being immune to schedule/wakeup inversion allows to fix the pppd_compat
module. This module needs to fork() to execute external programs. The
parent then waits for completion of its child using
triton_context_schedule(). When child terminates, the sigchld module
runs a callback that has to call triton_context_wakeup() to resume
execution of the parent.
The problem is that there is no synchronisation between the parent and
its child. When under stress, the child may execute faster than its
parent and the sigchld callback might run triton_context_wakeup()
before the parent had time to call triton_context_schedule().
Then accel-ppp might crash because the triton thread might have reset
ctx->thread to NULL, making triton_context_wakeup() write to invalid
memory when trying to insert the context in ctx->thread->wakeup_list[].
Synchronising the parent and its child completion's callback would
require cooperation from triton_context_schedule(). Otherwise we would
still have a time frame between the moment we let the callback waking
up the context and the moment we put the context in sleep mode.
Allowing schedule/wakeup call inversion in triton looks simpler since
it avoids modifying the current API.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
sstp: fix build w/o openssl & with 1.1.0-1.1.0g
|
|
|
|
|
|
|
|
list.h is an accel-ppp internal file.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|