+/*
+ 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)
+{
+ struct nx_info *nxi = sk->sk_nx_info;
+
+ vxdprintk("tcp_in_list(%p) %p,%p;%lx\n",
+ sk, nxi, sk->sk_socket,
+ (sk->sk_socket?sk->sk_socket->flags:0));
+
+ if (nxi) {
+ int n = nxi->nbipv4;
+ int i;
+
+ for (i=0; i<n; i++)
+ if (nxi->ipv4[i] == addr)
+ return 1;
+ }
+ else if (!tcp_v4_rcv_saddr(sk) || tcp_v4_rcv_saddr(sk) == addr)
+ return 1;
+ return 0;
+}
+
+/*
+ Check if the addresses in sk1 conflict with those in sk2
+*/
+int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2)
+{
+ if (sk1 && sk2)
+ nxdprintk("inet_bind(%p,%p) %p,%p;%lx %p,%p;%lx\n",
+ sk1, sk2,
+ sk1->sk_nx_info, sk1->sk_socket,
+ (sk1->sk_socket?sk1->sk_socket->flags:0),
+ sk2->sk_nx_info, sk2->sk_socket,
+ (sk2->sk_socket?sk2->sk_socket->flags:0));
+
+ if (tcp_v4_rcv_saddr(sk1)) {
+ /* Bind to one address only */
+ return tcp_in_list (sk2, tcp_v4_rcv_saddr(sk1));
+ } else if (sk1->sk_nx_info) {
+ /* A restricted bind(any) */
+ struct nx_info *nxi = sk1->sk_nx_info;
+ int n = nxi->nbipv4;
+ int i;
+
+ for (i=0; i<n; i++)
+ if (tcp_in_list (sk2, nxi->ipv4[i]))
+ return 1;
+ } else /* A bind(any) do not allow other bind on the same port */
+ return 1;
+ return 0;
+}
+