PPP, from PPPD upstream, separate IPv6 handling for sifup/sifdown

The current code is buggy regarding handling of link state when using
both IPCP and IPv6CP: if IPv6CP has been set up and if during IPCP
negociation, ipcp_up() fails, it will incorrectly take the interface
down. The simple solution here is to change the platform code to do the
same as on Solaris: separate IPv6CP up/down state handling with sif6up()
and sif6down(), so that we really know when the interface is allowed to
go down.

(Based from pppd commit b04d2dc6df5c6b5650fea44250d58757ee3dac4a)
This commit is contained in:
Sylvain Rochet 2014-12-24 23:01:06 +01:00
parent 7d077a2260
commit e39d012312
5 changed files with 77 additions and 21 deletions

View File

@ -379,6 +379,11 @@ struct ppp_pcb_s {
/* flags */ /* flags */
unsigned int if_up :1; /* True when the interface is up. */ unsigned int if_up :1; /* True when the interface is up. */
#if PPP_IPV6_SUPPORT
unsigned int if6_up :1; /* True when the IPv6 interface is up. */
#else
unsigned int :1; /* 1 bit of padding */
#endif /* PPP_IPV6_SUPPORT */
unsigned int pcomp :1; /* Does peer accept protocol compression? */ unsigned int pcomp :1; /* Does peer accept protocol compression? */
unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ unsigned int accomp :1; /* Does peer accept addr/ctl compression? */
unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ unsigned int proxy_arp_set :1; /* Have created proxy arp entry */
@ -396,7 +401,7 @@ struct ppp_pcb_s {
#else #else
unsigned int :1; /* 1 bit of padding */ unsigned int :1; /* 1 bit of padding */
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
unsigned int :6; /* 5 bits of padding to round out to 16 bits */ unsigned int :5; /* 5 bits of padding to round out to 16 bits */
#if PPPOS_SUPPORT #if PPPOS_SUPPORT
/* FIXME: there is probably one superfluous */ /* FIXME: there is probably one superfluous */

View File

@ -406,6 +406,11 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2);
int sifup(ppp_pcb *pcb); int sifup(ppp_pcb *pcb);
int sifdown (ppp_pcb *pcb); int sifdown (ppp_pcb *pcb);
#if PPP_IPV6_SUPPORT
int sif6up(ppp_pcb *pcb);
int sif6down (ppp_pcb *pcb);
#endif /* PPP_IPV6_SUPPORT */
int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode);
void netif_set_mtu(ppp_pcb *pcb, int mtu); void netif_set_mtu(ppp_pcb *pcb, int mtu);

View File

@ -312,3 +312,15 @@ Solaris port, don't care.
4043750fca36e7e0eb90d702e048ad1da4929418 4043750fca36e7e0eb90d702e048ad1da4929418
Just release stuff. Just release stuff.
2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits.
ad993a20ee485f0d0e2ac4105221641b200da6e2
Low level serial port, not in the port.
2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown
b04d2dc6df5c6b5650fea44250d58757ee3dac4a
Reimplemented.

View File

@ -1103,21 +1103,12 @@ static void ipv6_check_options() {
static int ipv6_demand_conf(int u) { static int ipv6_demand_conf(int u) {
ipv6cp_options *wo = &ipv6cp_wantoptions[u]; ipv6cp_options *wo = &ipv6cp_wantoptions[u];
#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
#if defined(SOL2)
if (!sif6up(u)) if (!sif6up(u))
return 0; return 0;
#else
if (!sifup(u))
return 0;
#endif /* defined(SOL2) */
#endif
if (!sif6addr(u, wo->ourid, wo->hisid)) if (!sif6addr(u, wo->ourid, wo->hisid))
return 0; return 0;
#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
if (!sifup(u))
return 0;
#endif
if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
return 0; return 0;
@ -1222,8 +1213,8 @@ static void ipv6cp_up(fsm *f) {
} }
/* bring the interface up for IPv6 */ /* bring the interface up for IPv6 */
if (!sifup(f->pcb)) { if (!sif6up(f->pcb)) {
PPPDEBUG(LOG_DEBUG, ("sifup failed (IPV6)")); PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)"));
ipv6cp_close(f->pcb, "Interface configuration failed"); ipv6cp_close(f->pcb, "Interface configuration failed");
return; return;
} }
@ -1286,7 +1277,7 @@ static void ipv6cp_down(fsm *f) {
ipv6cp_clear_addrs(f->pcb, ipv6cp_clear_addrs(f->pcb,
go->ourid, go->ourid,
ho->hisid); ho->hisid);
sifdown(f->pcb); sif6down(f->pcb);
} }
#if 0 /* UNUSED */ #if 0 /* UNUSED */

View File

@ -2196,10 +2196,6 @@ int sifup(ppp_pcb *pcb) {
netif_set_addr(&pcb->netif, &pcb->addrs.our_ipaddr, &pcb->addrs.netmask, netif_set_addr(&pcb->netif, &pcb->addrs.our_ipaddr, &pcb->addrs.netmask,
&pcb->addrs.his_ipaddr); &pcb->addrs.his_ipaddr);
#if PPP_IPV6_SUPPORT
ip6_addr_copy(pcb->netif.ip6_addr[0], pcb->addrs.our6_ipaddr);
netif_ip6_addr_set_state(&pcb->netif, 0, IP6_ADDR_PREFERRED);
#endif /* PPP_IPV6_SUPPORT */
netif_set_up(&pcb->netif); netif_set_up(&pcb->netif);
pcb->if_up = 1; pcb->if_up = 1;
@ -2221,12 +2217,59 @@ int sifdown(ppp_pcb *pcb) {
return 1; return 1;
pcb->if_up = 0; pcb->if_up = 0;
/* make sure the netif status callback is called */
netif_set_down(&pcb->netif); if (1
#if PPP_IPV6_SUPPORT
/* set the interface down if IPv6 is down as well */
&& !pcb->if6_up
#endif /* PPP_IPV6_SUPPORT */
) {
/* make sure the netif status callback is called */
netif_set_down(&pcb->netif);
}
PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: err_code=%d\n", pcb->num, pcb->err_code));
return 1; return 1;
} }
#if PPP_IPV6_SUPPORT
/*
* sif6up - Config the interface up and enable IPv6 packets to pass.
*/
int sif6up(ppp_pcb *pcb) {
ip6_addr_copy(pcb->netif.ip6_addr[0], pcb->addrs.our6_ipaddr);
netif_ip6_addr_set_state(&pcb->netif, 0, IP6_ADDR_PREFERRED);
netif_set_up(&pcb->netif);
pcb->if6_up = 1;
pcb->err_code = PPPERR_NONE;
PPPDEBUG(LOG_DEBUG, ("sif6up: unit %d: err_code=%d\n", pcb->num, pcb->err_code));
pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb);
return 1;
}
/********************************************************************
*
* sif6down - Disable the indicated protocol and config the interface
* down if there are no remaining protocols.
*/
int sif6down(ppp_pcb *pcb) {
if(!pcb->if6_up)
return 1;
pcb->if6_up = 0;
/* set the interface down if IPv4 is down as well */
if (!pcb->if_up) {
/* make sure the netif status callback is called */
netif_set_down(&pcb->netif);
}
PPPDEBUG(LOG_DEBUG, ("sif6down: unit %d: err_code=%d\n", pcb->num, pcb->err_code));
return 1;
}
#endif /* PPP_IPV6_SUPPORT */
/* /*
* sifnpmode - Set the mode for handling packets for a given NP. * sifnpmode - Set the mode for handling packets for a given NP.
*/ */