diff -rc2P linux-2.4.19ctx-14/Makefile linux-2.4.19ctx-15/Makefile *** linux-2.4.19ctx-14/Makefile Sat Dec 7 09:56:39 2002 --- linux-2.4.19ctx-15/Makefile Fri Nov 1 11:56:40 2002 *************** *** 2,6 **** PATCHLEVEL = 4 SUBLEVEL = 19 ! EXTRAVERSION =ctx-14 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) --- 2,6 ---- PATCHLEVEL = 4 SUBLEVEL = 19 ! EXTRAVERSION =ctx-15 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -rc2P linux-2.4.19ctx-14/fs/proc/array.c linux-2.4.19ctx-15/fs/proc/array.c *** linux-2.4.19ctx-14/fs/proc/array.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/fs/proc/array.c Tue Nov 19 15:38:19 2002 *************** *** 333,336 **** --- 333,338 ---- buffer += sprintf (buffer,"ipv4root_bcast: %08x\n" ,task->ip_info->v4_bcast); + buffer += sprintf (buffer,"ipv4root_refcnt: %d\n" + ,task->ip_info->refcount); }else{ buffer += sprintf (buffer,"ipv4root: 0\n"); diff -rc2P linux-2.4.19ctx-14/include/linux/sched.h linux-2.4.19ctx-15/include/linux/sched.h *** linux-2.4.19ctx-14/include/linux/sched.h Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/include/linux/sched.h Thu Nov 28 00:05:24 2002 *************** *** 1005,1010 **** void sys_assign_s_info (struct task_struct *); void sys_alloc_s_info (void); ! void sys_release_ip_info (struct task_struct *); ! void sys_assign_ip_info (struct task_struct *); void sys_alloc_ip_info (void); --- 1005,1010 ---- void sys_assign_s_info (struct task_struct *); void sys_alloc_s_info (void); ! void sys_release_ip_info (struct iproot_info *); ! void sys_assign_ip_info (struct iproot_info *); void sys_alloc_ip_info (void); 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 **** sys_assign_s_info (p); ! sys_assign_ip_info (p); atomic_inc(&p->user->__count); --- 619,623 ---- sys_assign_s_info (p); ! sys_assign_ip_info (p->ip_info); atomic_inc(&p->user->__count); diff -rc2P linux-2.4.19ctx-14/kernel/sys.c linux-2.4.19ctx-15/kernel/sys.c *** linux-2.4.19ctx-14/kernel/sys.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/kernel/sys.c Fri Dec 6 23:52:43 2002 *************** *** 1089,1117 **** } } /* ! Decrease the reference count on the ip_info member of a task Free the struct if the reference count reach 0. */ ! void sys_release_ip_info (struct task_struct *p) { ! down_write (&uts_sem); ! if (p->ip_info != NULL){ ! p->ip_info->refcount--; ! if (p->ip_info->refcount == 0){ // printk ("vfree s_info %d\n",p->pid); ! vfree (p->ip_info); ! p->ip_info = NULL; } } - up_write (&uts_sem); } /* Increase the reference count on the ip_info member of a task */ ! void sys_assign_ip_info (struct task_struct *p) { ! down_write (&uts_sem); ! if (p->ip_info != NULL) p->ip_info->refcount++; ! up_write (&uts_sem); } --- 1089,1119 ---- } } + /* ! Decrease the reference count on the ip_info struct Free the struct if the reference count reach 0. */ ! void sys_release_ip_info (struct iproot_info *ip_info) { ! if (ip_info != NULL){ ! down_write (&uts_sem); ! ip_info->refcount--; ! if (ip_info->refcount == 0){ // printk ("vfree s_info %d\n",p->pid); ! vfree (ip_info); } + up_write (&uts_sem); } } /* Increase the reference count on the ip_info member of a task */ ! void sys_assign_ip_info (struct iproot_info *ip_info) { ! if (ip_info != NULL){ ! down_write (&uts_sem); ! ip_info->refcount++; ! up_write (&uts_sem); ! } } *************** *** 1126,1130 **** memset (ip_info,0,sizeof(*ip_info)); ip_info->refcount = 1; ! sys_release_ip_info (current); current->ip_info = ip_info; } --- 1128,1132 ---- memset (ip_info,0,sizeof(*ip_info)); ip_info->refcount = 1; ! sys_release_ip_info (current->ip_info); current->ip_info = ip_info; } diff -rc2P linux-2.4.19ctx-14/net/ipv4/af_inet.c linux-2.4.19ctx-15/net/ipv4/af_inet.c *** linux-2.4.19ctx-14/net/ipv4/af_inet.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/net/ipv4/af_inet.c Thu Nov 28 00:04:52 2002 *************** *** 178,181 **** --- 178,183 ---- if (sk->protinfo.af_inet.opt) kfree(sk->protinfo.af_inet.opt); + sys_release_ip_info (sk->ip_info); + sk->ip_info = NULL; dst_release(sk->dst_cache); #ifdef INET_REFCNT_DEBUG *************** *** 395,398 **** --- 397,401 ---- sk->s_context = current->s_context; + sk->ip_info = NULL; #ifdef INET_REFCNT_DEBUG *************** *** 480,486 **** int chk_addr_ret; int err; ! __u32 s_addr; ! __u32 bcast_addr = 0xffffffffl; ! __u32 ipv4root; /* 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; iip_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; ! s_addr = s_addr1 = addr->sin_addr.s_addr; ! ip_info = current->ip_info; ! if (ip_info != NULL){ ! __u32 v4_bcast = ip_info->v4_bcast; ! __u32 ipv4root = ip_info->ipv4[0]; ! int nbipv4 = ip_info->nbipv4; // printk ("ipv4root0 %08lx %08x\n",ipv4root,s_addr); if (s_addr == 0){ s_addr = ipv4root; ! if (nbipv4 > 1){ ! s_addr1 = 0; ! }else{ ! s_addr1 = ipv4root; ! ip_info = NULL; ! } ! s_addr2 = v4_bcast; }else if (s_addr == 0x0100007f){ ! s_addr = s_addr1 = ipv4root; ! ip_info = NULL; }else if (s_addr != v4_bcast && s_addr != ipv4root){ int i; for (i=0; iipv4[i]){ break; } } if (i == nbipv4) return -EADDRNOTAVAIL; + ip_info = NULL; } + //printk ("bind: ip_info != NULL, s_addr %x, s_addr1 %x, s_addr2 %x\n" + // ,s_addr,s_addr1,s_addr2); } chk_addr_ret = inet_addr_type(s_addr); /* Not specified by any standard per-se, however it breaks too *************** *** 550,555 **** goto out; ! sk->rcv_saddr = sk->saddr = s_addr; ! sk->bcast_addr = bcast_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ --- 565,572 ---- goto out; ! sk->rcv_saddr = sk->saddr = s_addr1; ! sk->rcv_saddr2 = s_addr2; ! sk->ip_info = ip_info; ! if (ip_info != NULL) sys_assign_ip_info (ip_info); if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ *************** *** 558,561 **** --- 575,580 ---- if (sk->prot->get_port(sk, snum) != 0) { sk->saddr = sk->rcv_saddr = 0; + sk->ip_info = NULL; + sys_release_ip_info (ip_info); err = -EADDRINUSE; goto out; diff -rc2P linux-2.4.19ctx-14/net/ipv4/raw.c linux-2.4.19ctx-15/net/ipv4/raw.c *** linux-2.4.19ctx-14/net/ipv4/raw.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/net/ipv4/raw.c Wed Nov 27 23:33:36 2002 *************** *** 97,100 **** --- 97,132 ---- } + + /* + 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; iipv4[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; iipv4[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; iipv4[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; iipv4[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 **** score = 1; ! if(rcv_saddr) { ! if (rcv_saddr != daddr) ! continue; score++; } if (sk->bound_dev_if) { --- 504,511 ---- score = 1; ! if (tcp_addr_in_list(rcv_saddr,daddr,sk->ip_info)){ score++; + }else{ + continue; } if (sk->bound_dev_if) { *************** *** 456,460 **** if (sk->num == hnum && sk->next == NULL && ! (!sk->rcv_saddr || sk->rcv_saddr == daddr) && !sk->bound_dev_if) goto sherry_cache; --- 535,539 ---- if (sk->num == hnum && sk->next == NULL && ! tcp_addr_in_list(sk->rcv_saddr,daddr,sk->ip_info) && !sk->bound_dev_if) goto sherry_cache; diff -rc2P linux-2.4.19ctx-14/net/ipv4/tcp_minisocks.c linux-2.4.19ctx-15/net/ipv4/tcp_minisocks.c *** linux-2.4.19ctx-14/net/ipv4/tcp_minisocks.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/net/ipv4/tcp_minisocks.c Sat Dec 7 01:20:15 2002 *************** *** 382,385 **** --- 382,386 ---- tw->s_context = sk->s_context; + tw->ip_info = NULL; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) *************** *** 652,655 **** --- 653,657 ---- memcpy(newsk, sk, sizeof(*newsk)); + sys_assign_ip_info (newsk->ip_info); newsk->state = TCP_SYN_RECV; diff -rc2P linux-2.4.19ctx-14/net/ipv4/udp.c linux-2.4.19ctx-15/net/ipv4/udp.c *** linux-2.4.19ctx-14/net/ipv4/udp.c Sat Dec 7 09:56:40 2002 --- linux-2.4.19ctx-15/net/ipv4/udp.c Tue Nov 19 17:11:03 2002 *************** *** 107,110 **** --- 107,113 ---- int udp_port_rover; + int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2); + + static int udp_v4_get_port(struct sock *sk, unsigned short snum) { *************** *** 161,167 **** sk2 != sk && sk2->bound_dev_if == sk->bound_dev_if && ! (!sk2->rcv_saddr || ! !sk->rcv_saddr || ! sk2->rcv_saddr == sk->rcv_saddr) && (!sk2->reuse || !sk->reuse)) goto fail; --- 164,168 ---- sk2 != sk && sk2->bound_dev_if == sk->bound_dev_if && ! tcp_ipv4_addr_conflict (sk2,sk) && (!sk2->reuse || !sk->reuse)) goto fail; *************** *** 206,209 **** --- 207,224 ---- } + static int udp_in_list (struct iproot_info *ip_info, u32 addr) + { + int ret = 0; + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == addr){ + ret = 1; + break; + } + } + return ret; + } + /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM *************** *** 222,225 **** --- 237,246 ---- continue; score++; + }else if (sk->ip_info != NULL){ + if (udp_in_list (sk->ip_info,daddr)){ + score++; + }else{ + continue; + } } if(sk->daddr) { *************** *** 262,265 **** --- 283,287 ---- } + static inline struct sock *udp_v4_mcast_next(struct sock *sk, u16 loc_port, u32 loc_addr, *************** *** 273,277 **** (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || ! (s->rcv_saddr && s->rcv_saddr != loc_addr && s->bcast_addr != loc_addr) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; --- 295,299 ---- (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || ! (s->rcv_saddr && s->rcv_saddr != loc_addr && s->rcv_saddr2 != loc_addr) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; *************** *** 518,521 **** --- 540,561 ---- if (rt == NULL) { + struct iproot_info *ip_info = current->ip_info; + if (ip_info != NULL) { + __u32 ipv4root = ip_info->ipv4[0]; + if (ipv4root != 0){ + if (daddr == 0x0100007f && current->s_context != 0){ + daddr = ipv4root; + } + if (ufh.saddr == 0){ + ufh.saddr = ipv4root; + } + #if 0 + else if (!udp_in_list(ip_info,ufh.saddr)){ + err = EADDRNOTAVAIL; + goto out; + } + #endif + } + } err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif); if (err)