From 83c2de652b2b53a23b9e87d6eb3cb4085fe797c2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 3 Jan 2020 12:56:45 +0100 Subject: [PATCH 04/14] smarter killaddr --- pppd/options.c | 8 ++++++++ pppd/pppd.h | 3 +++ pppd/sys-linux.c | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/pppd/options.c b/pppd/options.c index f8d6c00..12d12fd 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -102,6 +102,9 @@ int maxconnect = 0; /* Maximum connect time */ char user[MAXNAMELEN]; /* Username for PAP */ char passwd[MAXSECRETLEN]; /* Password for PAP */ bool persist = 0; /* Reopen link after it goes down */ +bool killoldaddr = 0; /* If our IP is reassigned on + reconnect, kill active TCP + connections using the old IP. */ char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ bool demand = 0; /* do dial-on-demand */ char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ @@ -252,6 +255,11 @@ option_t general_options[] = { { "demand", o_bool, &demand, "Dial on demand", OPT_INITONLY | 1, &persist }, + { "killoldaddr", o_bool, &killoldaddr, + "Kill connections from an old source address", 1}, + { "nokilloldaddr", o_bool,&killoldaddr, + "Don't kill connections from an old source address" }, + { "--version", o_special_noarg, (void *)showversion, "Show version number" }, { "--help", o_special_noarg, (void *)showhelp, diff --git a/pppd/pppd.h b/pppd/pppd.h index 612902f..bdb8778 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -310,6 +310,9 @@ extern char our_name[MAXNAMELEN];/* Our name for authentication purposes */ extern char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ extern bool explicit_remote;/* remote_name specified with remotename opt */ extern bool demand; /* Do dial-on-demand */ +extern bool killoldaddr; /* If our IP is reassigned on + reconnect, kill active TCP + connections using the old IP. */ extern char *ipparam; /* Extra parameter for ip up/down scripts */ extern bool cryptpap; /* Others' PAP passwords are encrypted */ extern int idle_time_limit;/* Shut down link if idle for this long */ diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index 85b1512..95f5a72 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -172,6 +172,10 @@ struct in6_ifreq { static const eui64_t nulleui64; #endif /* INET6 */ +#ifndef SIOCKILLADDR +#define SIOCKILLADDR 0x8939 +#endif + /* We can get an EIO error on an ioctl if the modem has hung up */ #define ok_error(num) ((num)==EIO) @@ -220,6 +224,7 @@ static int default_rt_repl_rest; /* replace and restore old default rt */ static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ static char proxy_arp_dev[16]; /* Device for proxy arp entry */ static u_int32_t our_old_addr; /* for detecting address changes */ +static u_int32_t our_current_addr; static int dynaddr_set; /* 1 if ip_dynaddr set */ static int looped; /* 1 if using loop */ static int link_mtu; /* mtu for the link (not bundle) */ @@ -566,6 +571,27 @@ int generic_establish_ppp (int fd) return -1; } +static void do_killaddr(u_int32_t oldaddr) +{ + struct ifreq ifr; + + memset(&ifr,0,sizeof ifr); + + SET_SA_FAMILY (ifr.ifr_addr, AF_INET); + SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); + SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); + + SIN_ADDR(ifr.ifr_addr) = oldaddr; + + strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + + if(ioctl(sock_fd,SIOCKILLADDR,&ifr) < 0) { + if (!ok_error (errno)) + error("ioctl(SIOCKILLADDR): %m(%d)", errno); + return; + } +} + /******************************************************************** * * tty_disestablish_ppp - Restore the serial port to normal operation. @@ -2747,9 +2773,14 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, } } - /* set ip_dynaddr in demand mode if address changes */ - if (demand && tune_kernel && !dynaddr_set - && our_old_addr && our_old_addr != our_adr) { + if(persist && our_old_addr && our_old_addr != our_adr) { + + if(killoldaddr) + do_killaddr(our_old_addr); + + + /* set ip_dynaddr in demand mode if address changes */ + if (tune_kernel && !dynaddr_set) { /* set ip_dynaddr if possible */ char *path; int fd; @@ -2761,7 +2792,10 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, close(fd); } dynaddr_set = 1; /* only 1 attempt */ + } } + + our_current_addr = our_adr; our_old_addr = 0; return 1; @@ -2818,6 +2852,8 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr) our_old_addr = our_adr; + our_current_addr = 0; + return 1; } -- 2.30.0