diff -rc2P linux-2.4.19ctx-14/include/net/sock.h linux-2.4.19ctx-15/include/net/sock.h
*** linux-2.4.19ctx-14/include/net/sock.h Sat Dec 7 09:56:40 2002
--- linux-2.4.19ctx-15/include/net/sock.h Sat Dec 7 01:19:32 2002
***************
*** 488,491 ****
--- 488,492 ----
struct sock {
+ /* See tcp.h comment on tcp_tw_bucket */
/* Socket demultiplex comparisons on incoming packets. */
__u32 daddr; /* Foreign IPv4 addr */
***************
*** 509,512 ****
--- 510,515 ----
unsigned char shutdown;
atomic_t refcnt; /* Reference count */
+ struct iproot_info *ip_info;
+ /* End of common section with tcp_tw_bucket */
socket_lock_t lock; /* Synchronizer... */
***************
*** 526,530 ****
unsigned int allocation; /* Allocation mode */
int sndbuf; /* Size of send buffer in bytes */
! __u32 bcast_addr; /* Local bcast addr, for ipv4root */
struct sock *prev;
--- 529,533 ----
unsigned int allocation; /* Allocation mode */
int sndbuf; /* Size of send buffer in bytes */
! __u32 rcv_saddr2; /* Second bound ipv4 addr, for ipv4root */
struct sock *prev;
diff -rc2P linux-2.4.19ctx-14/include/net/tcp.h linux-2.4.19ctx-15/include/net/tcp.h
*** linux-2.4.19ctx-14/include/net/tcp.h Sat Dec 7 09:56:40 2002
--- linux-2.4.19ctx-15/include/net/tcp.h Sat Dec 7 01:31:51 2002
***************
*** 173,176 ****
--- 173,177 ----
rcv_wscale; /* It is also TW bucket specific */
atomic_t refcnt;
+ struct ipv4_info *ip_info;
/* And these are ours. */
diff -rc2P linux-2.4.19ctx-14/kernel/exit.c linux-2.4.19ctx-15/kernel/exit.c
*** linux-2.4.19ctx-14/kernel/exit.c Sat Dec 7 09:56:40 2002
--- linux-2.4.19ctx-15/kernel/exit.c Wed Nov 20 14:48:07 2002
***************
*** 68,72 ****
current->counter = MAX_COUNTER;
sys_release_s_info(p);
! sys_release_ip_info(p);
p->pid = 0;
free_task_struct(p);
--- 68,72 ----
current->counter = MAX_COUNTER;
sys_release_s_info(p);
! sys_release_ip_info(p->ip_info);
p->pid = 0;
free_task_struct(p);
diff -rc2P linux-2.4.19ctx-14/kernel/fork.c linux-2.4.19ctx-15/kernel/fork.c
*** linux-2.4.19ctx-14/kernel/fork.c Sat Dec 7 09:56:40 2002
--- linux-2.4.19ctx-15/kernel/fork.c Thu Nov 28 00:07:02 2002
***************
*** 619,623 ****
/* If the socket has its own bind function then use it. (RAW) */
--- 483,491 ----
int chk_addr_ret;
int err;
! __u32 s_addr; /* Address used for validation */
! __u32 s_addr1;
! __u32 s_addr2 = 0xffffffffl; /* Optional address of the socket */
! /* bcast in ipv4root world */
! struct iproot_info *ip_info;
/* If the socket has its own bind function then use it. (RAW) */
***************
*** 491,518 ****
return -EINVAL;
! s_addr = addr->sin_addr.s_addr;
! ipv4root = current->ip_info != NULL ? current->ip_info->ipv4[0] : 0;
! if (ipv4root != 0){
// printk ("ipv4root0 %08lx %08x\n",ipv4root,s_addr);
- __u32 v4_bcast = current->ip_info->v4_bcast;
if (s_addr == 0){
s_addr = ipv4root;
! bcast_addr = v4_bcast;
}else if (s_addr == 0x0100007f){
! s_addr = ipv4root;
}else if (s_addr != v4_bcast
&& s_addr != ipv4root){
int i;
- int nbipv4 = current->ip_info->nbipv4;
for (i=0; i<nbipv4; i++){
! if (s_addr == current->ip_info->ipv4[i]){
break;
}
}
if (i == nbipv4) return -EADDRNOTAVAIL;
}
}
chk_addr_ret = inet_addr_type(s_addr);
- // printk ("ipv4root %08lx %08x %d\n",ipv4root,s_addr,chk_addr_ret);
/* Not specified by any standard per-se, however it breaks too
--- 496,533 ----
return -EINVAL;
+
+ /*
+ Check if an address is in the list
+ */
+ static inline int raw_addr_in_list (
+ u32 rcv_saddr1,
+ u32 rcv_saddr2,
+ u32 loc_addr,
+ struct iproot_info *ip_info)
+ {
+ int ret = 0;
+ if (loc_addr != 0
+ && (rcv_saddr1 == loc_addr || rcv_saddr2 == loc_addr)){
+ ret = 1;
+ }else if (rcv_saddr1 == 0){
+ /* Accept any address or only the one in the list */
+ if (ip_info == NULL){
+ ret = 1;
+ }else{
+ int n = ip_info->nbipv4;
+ int i;
+ for (i=0; i<n; i++){
+ if (ip_info->ipv4[i] == loc_addr){
+ ret = 1;
+ break;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
unsigned long raddr, unsigned long laddr,
***************
*** 102,110 ****
{
struct sock *s = sk;
-
for (s = sk; s; s = s->next) {
if (s->num == num &&
!(s->daddr && s->daddr != raddr) &&
! !(s->rcv_saddr && s->rcv_saddr != laddr) &&
!(s->bound_dev_if && s->bound_dev_if != dif))
break; /* gotcha */
--- 134,142 ----
{
struct sock *s = sk;
for (s = sk; s; s = s->next) {
if (s->num == num &&
!(s->daddr && s->daddr != raddr) &&
! raw_addr_in_list(s->rcv_saddr,s->rcv_saddr2,laddr,s->ip_info) &&
! // !(s->rcv_saddr && s->rcv_saddr != laddr) &&
!(s->bound_dev_if && s->bound_dev_if != dif))
break; /* gotcha */
diff -rc2P linux-2.4.19ctx-14/net/ipv4/tcp_ipv4.c linux-2.4.19ctx-15/net/ipv4/tcp_ipv4.c
*** linux-2.4.19ctx-14/net/ipv4/tcp_ipv4.c Sat Dec 7 09:56:40 2002
--- linux-2.4.19ctx-15/net/ipv4/tcp_ipv4.c Tue Nov 19 16:38:22 2002
***************
*** 175,178 ****
--- 175,228 ----
}
+ /*
+ Return 1 if addr match the socket IP list
+ or the socket is INADDR_ANY
+ */
+ static inline int tcp_in_list (struct sock *sk, u32 addr)
+ {
+ int ret = 0;
+ struct iproot_info *ip_info = sk->ip_info;
+ if (ip_info != NULL){
+ int n = ip_info->nbipv4;
+ int i;
+ for (i=0; i<n; i++){
+ if (ip_info->ipv4[i] == addr){
+ ret = 1;
+ break;
+ }
+ }
+ }else if (!sk->rcv_saddr || sk->rcv_saddr == addr){
+ ret = 1;
+ }
+ return ret;
+ }
+
+ /*
+ Check if the addresses in sk1 conflict with those in sk2
+ */
+ int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2)
+ {
+ int ret = 0;
+ if (sk1->rcv_saddr){
+ /* Bind to one address only */
+ ret = tcp_in_list (sk2,sk1->rcv_saddr);
+ }else if (sk1->ip_info != NULL){
+ /* A restricted bind(any) */
+ struct iproot_info *ip_info = sk1->ip_info;
+ int n = ip_info->nbipv4;
+ int i;
+ for (i=0; i<n; i++){
+ if (tcp_in_list (sk2,ip_info->ipv4[i])){
+ ret = 1;
+ break;
+ }
+ }
+ }else{
+ /* A bind(any) do not allow other bind on the same port */
+ ret = 1;
+ }
+ return ret;
+ }
+
static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
{
***************
*** 187,193 ****
!sk2->reuse ||
sk2->state == TCP_LISTEN) {
! if (!sk2->rcv_saddr ||
! !sk->rcv_saddr ||
! (sk2->rcv_saddr == sk->rcv_saddr))
break;
}
--- 237,241 ----
!sk2->reuse ||
sk2->state == TCP_LISTEN) {
! if (tcp_ipv4_addr_conflict(sk,sk2))
break;
}
***************
*** 408,411 ****
--- 456,490 ----
}
+ /*
+ Check if an address is in the list
+ */
+ static inline int tcp_addr_in_list (
+ u32 rcv_saddr,
+ u32 daddr,
+ struct iproot_info *ip_info)
+ {
+ int ret = 0;
+ if (rcv_saddr == daddr){
+ ret = 1;
+ }else if (rcv_saddr == 0){
+ /* Accept any address or only the one in the list */
+ if (ip_info == NULL){
+ ret = 1;
+ }else{
+ int n = ip_info->nbipv4;
+ int i;
+ for (i=0; i<n; i++){
+ if (ip_info->ipv4[i] == daddr){
+ ret = 1;
+ break;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+
+
/* Don't inline this cruft. Here are some nice properties to
* exploit here. The BSD API does not allow a listening TCP
***************
*** 425,432 ****