diff -u --exclude *~ --recursive linux-2.4.0-orig/include/linux/sockios.h linux-hacked-dynip/include/linux/sockios.h --- linux-2.4.0-orig/include/linux/sockios.h Sat Dec 30 00:20:32 2000 +++ linux-hacked-dynip/include/linux/sockios.h Sat Jan 27 17:04:34 2001 @@ -65,6 +65,7 @@ #define SIOCDIFADDR 0x8936 /* delete PA address */ #define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ #define SIOCGIFCOUNT 0x8938 /* get number of devices */ +#define SIOCKILLADDR 0x8939 /* kill all connections with this local address */ #define SIOCGIFBR 0x8940 /* Bridging support */ #define SIOCSIFBR 0x8941 /* Set bridging options */ diff -u --exclude *~ --recursive linux-2.4.0-orig/include/net/tcp.h linux-hacked-dynip/include/net/tcp.h --- linux-2.4.0-orig/include/net/tcp.h Fri Jan 5 21:41:37 2001 +++ linux-hacked-dynip/include/net/tcp.h Sat Jan 27 18:02:21 2001 @@ -787,9 +787,8 @@ extern int tcp_disconnect(struct sock *sk, int flags); extern void tcp_unhash(struct sock *sk); - extern int tcp_v4_hash_connecting(struct sock *sk); - +extern void tcp_v4_zap_saddr(u32 saddr); /* From syncookies.c */ extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, diff -u --exclude *~ --recursive linux-2.4.0-orig/net/ipv4/af_inet.c linux-hacked-dynip/net/ipv4/af_inet.c --- linux-2.4.0-orig/net/ipv4/af_inet.c Tue Jan 2 09:26:19 2001 +++ linux-hacked-dynip/net/ipv4/af_inet.c Sat Jan 27 18:27:38 2001 @@ -854,6 +854,7 @@ case SIOCSIFPFLAGS: case SIOCGIFPFLAGS: case SIOCSIFFLAGS: + case SIOCKILLADDR: return(devinet_ioctl(cmd,(void *) arg)); case SIOCGIFBR: case SIOCSIFBR: diff -u --exclude *~ --recursive linux-2.4.0-orig/net/ipv4/devinet.c linux-hacked-dynip/net/ipv4/devinet.c --- linux-2.4.0-orig/net/ipv4/devinet.c Sat Dec 30 00:22:05 2000 +++ linux-hacked-dynip/net/ipv4/devinet.c Sat Jan 27 21:09:48 2001 @@ -510,6 +510,7 @@ case SIOCSIFBRDADDR: /* Set the broadcast address */ case SIOCSIFDSTADDR: /* Set the destination address */ case SIOCSIFNETMASK: /* Set the netmask for the interface */ + case SIOCKILLADDR: /* Kill all connections with this local address */ if (!capable(CAP_NET_ADMIN)) return -EACCES; if (sin->sin_family != AF_INET) @@ -536,7 +537,10 @@ break; } - if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) { + if (ifa == NULL + && cmd != SIOCSIFADDR + && cmd != SIOCSIFFLAGS + && cmd != SIOCKILLADDR) { ret = -EADDRNOTAVAIL; goto done; } @@ -646,6 +650,9 @@ ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); inet_insert_ifa(ifa); } + break; + case SIOCKILLADDR: /* Kill all connections with this local address */ + tcp_v4_zap_saddr(sin->sin_addr.s_addr); break; } done: diff -u --exclude *~ --recursive linux-2.4.0-orig/net/ipv4/tcp_ipv4.c linux-hacked-dynip/net/ipv4/tcp_ipv4.c --- linux-2.4.0-orig/net/ipv4/tcp_ipv4.c Fri Jan 5 21:17:42 2001 +++ linux-hacked-dynip/net/ipv4/tcp_ipv4.c Sat Jan 27 18:07:25 2001 @@ -390,6 +390,38 @@ wake_up(&tcp_lhash_wait); } +/* Terminate all active connections with a local address equal to + * SADDR. If sysctl_ip_dynaddr is set, connections in the SYN_SENT + * state are not closed, because their source address will presumably + * be rewritten. + */ +void tcp_v4_zap_saddr(u32 saddr) +{ + int i; + rwlock_t *lock; + struct sock *sk; + + for (i = 0; i < (tcp_ehash_size<<1); i++) { + lock = &tcp_ehash[i].lock; + + read_lock(lock); + + for(sk = tcp_ehash[i].chain; sk; sk = sk->next) + if(sk->rcv_saddr == saddr) + { + if(sysctl_ip_dynaddr && sk->state == TCP_SYN_SENT) + continue; + + sk->err = ENETRESET; + sk->error_report(sk); + + tcp_done(sk); + } + + read_unlock(lock); + } +} + /* Don't inline this cruft. Here are some nice properties to * exploit here. The BSD API does not allow a listening TCP * to specify the remote port nor the remote address for the