aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2006-08-26 23:06:05 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:18:21 -0400
commit25030a7f9eeab2dcefff036469e0e2b4f956198f (patch)
tree923030c42f1c2bf4aa9cd851df13b95bd0fe542b /net/ipv6/udp.c
parent6a28ec8cd0c6993a4ac0d52f4347f7ed077b5cac (diff)
[UDP]: Unify UDPv4 and UDPv6 ->get_port()
This patch creates one common function which is called by udp_v4_get_port() and udp_v6_get_port(). As a result, * duplicated code is removed * udp_port_rover and local port lookup can now be removed from udp.h * further savings follow since the same function will be used by UDP-Litev4 and UDP-Litev6 In contrast to the patch sent in response to Yoshifujis comments (fixed by this variant), the code below also removes the EXPORT_SYMBOL(udp_port_rover), since udp_port_rover can now remain local to net/ipv4/udp.c. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c76
1 files changed, 2 insertions, 74 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b9cc55ccb000..9662561701d1 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -61,81 +61,9 @@
61 61
62DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; 62DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
63 63
64/* Grrr, addr_type already calculated by caller, but I don't want 64static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
65 * to add some silly "cookie" argument to this method just for that.
66 */
67static int udp_v6_get_port(struct sock *sk, unsigned short snum)
68{ 65{
69 struct sock *sk2; 66 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
70 struct hlist_node *node;
71
72 write_lock_bh(&udp_hash_lock);
73 if (snum == 0) {
74 int best_size_so_far, best, result, i;
75
76 if (udp_port_rover > sysctl_local_port_range[1] ||
77 udp_port_rover < sysctl_local_port_range[0])
78 udp_port_rover = sysctl_local_port_range[0];
79 best_size_so_far = 32767;
80 best = result = udp_port_rover;
81 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
82 int size;
83 struct hlist_head *list;
84
85 list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
86 if (hlist_empty(list)) {
87 if (result > sysctl_local_port_range[1])
88 result = sysctl_local_port_range[0] +
89 ((result - sysctl_local_port_range[0]) &
90 (UDP_HTABLE_SIZE - 1));
91 goto gotit;
92 }
93 size = 0;
94 sk_for_each(sk2, node, list)
95 if (++size >= best_size_so_far)
96 goto next;
97 best_size_so_far = size;
98 best = result;
99 next:;
100 }
101 result = best;
102 for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
103 if (result > sysctl_local_port_range[1])
104 result = sysctl_local_port_range[0]
105 + ((result - sysctl_local_port_range[0]) &
106 (UDP_HTABLE_SIZE - 1));
107 if (!udp_lport_inuse(result))
108 break;
109 }
110 if (i >= (1 << 16) / UDP_HTABLE_SIZE)
111 goto fail;
112gotit:
113 udp_port_rover = snum = result;
114 } else {
115 sk_for_each(sk2, node,
116 &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
117 if (inet_sk(sk2)->num == snum &&
118 sk2 != sk &&
119 (!sk2->sk_bound_dev_if ||
120 !sk->sk_bound_dev_if ||
121 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
122 (!sk2->sk_reuse || !sk->sk_reuse) &&
123 ipv6_rcv_saddr_equal(sk, sk2))
124 goto fail;
125 }
126 }
127
128 inet_sk(sk)->num = snum;
129 if (sk_unhashed(sk)) {
130 sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]);
131 sock_prot_inc_use(sk->sk_prot);
132 }
133 write_unlock_bh(&udp_hash_lock);
134 return 0;
135
136fail:
137 write_unlock_bh(&udp_hash_lock);
138 return 1;
139} 67}
140 68
141static void udp_v6_hash(struct sock *sk) 69static void udp_v6_hash(struct sock *sk)