write_unlock_bh(&raw_v4_lock);
}
+
+/*
+ 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 nx_info *nx_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 (nx_info == NULL)
+ ret = 1;
+ else {
+ int n = nx_info->nbipv4;
+ int i;
+ for (i=0; i<n; i++) {
+ if (nx_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,
int dif)
if (inet->num == num &&
!(inet->daddr && inet->daddr != raddr) &&
- !(inet->rcv_saddr && inet->rcv_saddr != laddr) &&
+ raw_addr_in_list(inet->rcv_saddr, inet->rcv_saddr2,
+ laddr, sk->sk_nx_info) &&
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
goto found; /* gotcha */
}
struct hlist_node *node;
sk_for_each(sk, node, &raw_v4_htable[state->bucket])
- if (sk->sk_family == PF_INET)
+ if (sk->sk_family == PF_INET &&
+ vx_check(sk->sk_xid, VX_WATCH|VX_IDENT))
goto found;
}
sk = NULL;
sk = sk_next(sk);
try_again:
;
- } while (sk && sk->sk_family != PF_INET);
+ } while (sk && (sk->sk_family != PF_INET ||
+ !vx_check(sk->sk_xid, VX_WATCH|VX_IDENT)));
if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
sk = sk_head(&raw_v4_htable[state->bucket]);