From be0b237e7ea9e4f3cbd1dd68c78ca585c2aa3410 Mon Sep 17 00:00:00 2001 From: Jaco Kroon Date: Mon, 16 May 2022 13:48:28 +0200 Subject: [PATCH] pppd/ipv6cp: Add ipv6-pre-up script. This is required because either ipcp or ipv6cp can come up first, or as the only protocol, and once IPv6 parameters has been established, there are actions that may need to be executed prior to bringing the interface up. Prior to this we can have an execution order like: pppd[26615]: Script /etc/ppp/ipv6-up started (pid 28183) pppd[26615]: Script /etc/ppp/ip-pre-up started (pid 28186) pppd[26615]: Script /etc/ppp/ip-pre-up finished (pid 28186), status = 0x0 pppd[26615]: Script /etc/ppp/ip-up started (pid 28238) pppd[26615]: Script /etc/ppp/ipv6-up finished (pid 28183), status = 0x0 pppd[26615]: Script /etc/ppp/ip-up finished (pid 28238), status = 0x0 ip ad sh shows that during ip-pre-up the interface state was already up: ppp-ip-pre-up(ppp1)[28208]: 423: ppp1: mtu 1480 qdisc pfifo_fast state UNKNOWN group default qlen 3 ppp-ip-pre-up(ppp1)[28208]: link/ppp ppp-ip-pre-up(ppp1)[28208]: inet 10.1.0.0 peer 192.168.50.0/32 scope global ppp1 ppp-ip-pre-up(ppp1)[28208]: valid_lft forever preferred_lft forever ulsdns_monitor[28216]: 192.168.50.0 dev ppp1 proto kernel scope link src 10.1.0.0 ppp-ip-pre-up(ppp1)[28208]: inet6 fe80::b4a3:c896:22bc:151f peer fe80::6/128 scope link ppp-ip-pre-up(ppp1)[28208]: valid_lft forever preferred_lft forever In order to make this work properly, a system admin would need to take the same action from ip-up and ipv6-up (probably in a locked manner) if and only if the interface oper status is down. As things stand one cannot depende on ip-up being executed whilst interface is still in down state, and as such, the scription in the man page is wrong too. Signed-off-by: Jaco Kroon --- pppd/ipv6cp.c | 24 ++++++++++++++++-------- pppd/pathnames.h | 1 + pppd/pppd.8 | 9 +++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index 130819dc6..e4a9fb2b8 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -323,7 +323,7 @@ struct protent ipv6cp_protent = { }; static void ipv6cp_clear_addrs (int, eui64_t, eui64_t); -static void ipv6cp_script (char *); +static void ipv6cp_script (char *, int wait); static void ipv6cp_script_done (void *); /* @@ -1236,6 +1236,8 @@ ipv6_demand_conf(int u) eui64_magic_nz(wo->ourid); } + ipv6cp_script(_PATH_IPV6PREUP, 1); + if (!sif6up(u)) return 0; if (!sif6addr(u, wo->ourid, wo->hisid)) @@ -1343,6 +1345,9 @@ ipv6cp_up(fsm *f) sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); } else { + /* run the pre-up script, if any, and wait for it to finish */ + ipv6cp_script(_PATH_IPV6PREUP, 1); + /* bring the interface up for IPv6 */ if (!sif6up(f->unit)) { if (debug) @@ -1382,7 +1387,7 @@ ipv6cp_up(fsm *f) */ if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { ipv6cp_script_state = s_up; - ipv6cp_script(path_ipv6up); + ipv6cp_script(path_ipv6up, 0); } } @@ -1433,7 +1438,7 @@ ipv6cp_down(fsm *f) /* Execute the ipv6-down script */ if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { ipv6cp_script_state = s_down; - ipv6cp_script(path_ipv6down); + ipv6cp_script(path_ipv6down, 0); } } @@ -1471,13 +1476,13 @@ ipv6cp_script_done(void *arg) case s_up: if (ipv6cp_fsm[0].state != OPENED) { ipv6cp_script_state = s_down; - ipv6cp_script(path_ipv6down); + ipv6cp_script(path_ipv6down, 0); } break; case s_down: if (ipv6cp_fsm[0].state == OPENED) { ipv6cp_script_state = s_up; - ipv6cp_script(path_ipv6up); + ipv6cp_script(path_ipv6up, 0); } break; } @@ -1489,7 +1494,7 @@ ipv6cp_script_done(void *arg) * interface-name tty-name speed local-LL remote-LL. */ static void -ipv6cp_script(char *script) +ipv6cp_script(char *script, int wait) { char strspeed[32], strlocal[32], strremote[32]; char *argv[8]; @@ -1507,8 +1512,11 @@ ipv6cp_script(char *script) argv[6] = ipparam; argv[7] = NULL; - ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, - NULL, 0); + if (wait) + run_program(script, argv, 0, NULL, NULL, 1); + else + ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, + NULL, 0); } /* diff --git a/pppd/pathnames.h b/pppd/pathnames.h index 915db67a0..4ed9c43a4 100644 --- a/pppd/pathnames.h +++ b/pppd/pathnames.h @@ -60,6 +60,7 @@ #define _PATH_PSEUDONYM ".ppp_pseudonym" #ifdef INET6 +#define _PATH_IPV6PREUP _ROOT_PATH "/etc/ppp/ipv6-pre-up" #define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up" #define _PATH_IPV6DOWN _ROOT_PATH "/etc/ppp/ipv6-down" #endif diff --git a/pppd/pppd.8 b/pppd/pppd.8 index 60932c2f6..f4b91be45 100644 --- a/pppd/pppd.8 +++ b/pppd/pppd.8 @@ -1856,6 +1856,15 @@ used for undoing the effects of the /etc/ppp/ip\-up and invoked in the same manner and with the same parameters as the ip\-up script. .TP +.B /etc/ppp/ipv6\-pre\-up +A program or script which is executed just before the ppp network +interface is brought up for IPv6. It is executed with the same parameters as +the ip\-up script (below). At this point the interface exists and has +IP addresses assigned but is still down. This can be used to +add firewall rules before any IP traffic can pass through the +interface. Pppd will wait for this script to finish before bringing +the interface up, so this script should run quickly. +.TP .B /etc/ppp/ipv6\-up Like /etc/ppp/ip\-up, except that it is executed when the link is available for sending and receiving IPv6 packets. It is executed with the parameters