diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 179 |
1 files changed, 143 insertions, 36 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 163ae4068b5f..bf147f8db399 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -99,6 +99,7 @@ | |||
99 | #include <net/arp.h> | 99 | #include <net/arp.h> |
100 | #include <net/route.h> | 100 | #include <net/route.h> |
101 | #include <net/ip_fib.h> | 101 | #include <net/ip_fib.h> |
102 | #include <net/inet_connection_sock.h> | ||
102 | #include <net/tcp.h> | 103 | #include <net/tcp.h> |
103 | #include <net/udp.h> | 104 | #include <net/udp.h> |
104 | #include <linux/skbuff.h> | 105 | #include <linux/skbuff.h> |
@@ -112,11 +113,7 @@ | |||
112 | #include <linux/mroute.h> | 113 | #include <linux/mroute.h> |
113 | #endif | 114 | #endif |
114 | 115 | ||
115 | DEFINE_SNMP_STAT(struct linux_mib, net_statistics); | 116 | DEFINE_SNMP_STAT(struct linux_mib, net_statistics) __read_mostly; |
116 | |||
117 | #ifdef INET_REFCNT_DEBUG | ||
118 | atomic_t inet_sock_nr; | ||
119 | #endif | ||
120 | 117 | ||
121 | extern void ip_mc_drop_socket(struct sock *sk); | 118 | extern void ip_mc_drop_socket(struct sock *sk); |
122 | 119 | ||
@@ -153,11 +150,7 @@ void inet_sock_destruct(struct sock *sk) | |||
153 | if (inet->opt) | 150 | if (inet->opt) |
154 | kfree(inet->opt); | 151 | kfree(inet->opt); |
155 | dst_release(sk->sk_dst_cache); | 152 | dst_release(sk->sk_dst_cache); |
156 | #ifdef INET_REFCNT_DEBUG | 153 | sk_refcnt_debug_dec(sk); |
157 | atomic_dec(&inet_sock_nr); | ||
158 | printk(KERN_DEBUG "INET socket %p released, %d are still alive\n", | ||
159 | sk, atomic_read(&inet_sock_nr)); | ||
160 | #endif | ||
161 | } | 154 | } |
162 | 155 | ||
163 | /* | 156 | /* |
@@ -210,7 +203,7 @@ int inet_listen(struct socket *sock, int backlog) | |||
210 | * we can only allow the backlog to be adjusted. | 203 | * we can only allow the backlog to be adjusted. |
211 | */ | 204 | */ |
212 | if (old_state != TCP_LISTEN) { | 205 | if (old_state != TCP_LISTEN) { |
213 | err = tcp_listen_start(sk); | 206 | err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); |
214 | if (err) | 207 | if (err) |
215 | goto out; | 208 | goto out; |
216 | } | 209 | } |
@@ -235,12 +228,14 @@ static int inet_create(struct socket *sock, int protocol) | |||
235 | struct proto *answer_prot; | 228 | struct proto *answer_prot; |
236 | unsigned char answer_flags; | 229 | unsigned char answer_flags; |
237 | char answer_no_check; | 230 | char answer_no_check; |
238 | int err; | 231 | int try_loading_module = 0; |
232 | int err = -ESOCKTNOSUPPORT; | ||
239 | 233 | ||
240 | sock->state = SS_UNCONNECTED; | 234 | sock->state = SS_UNCONNECTED; |
241 | 235 | ||
242 | /* Look for the requested type/protocol pair. */ | 236 | /* Look for the requested type/protocol pair. */ |
243 | answer = NULL; | 237 | answer = NULL; |
238 | lookup_protocol: | ||
244 | rcu_read_lock(); | 239 | rcu_read_lock(); |
245 | list_for_each_rcu(p, &inetsw[sock->type]) { | 240 | list_for_each_rcu(p, &inetsw[sock->type]) { |
246 | answer = list_entry(p, struct inet_protosw, list); | 241 | answer = list_entry(p, struct inet_protosw, list); |
@@ -261,9 +256,28 @@ static int inet_create(struct socket *sock, int protocol) | |||
261 | answer = NULL; | 256 | answer = NULL; |
262 | } | 257 | } |
263 | 258 | ||
264 | err = -ESOCKTNOSUPPORT; | 259 | if (unlikely(answer == NULL)) { |
265 | if (!answer) | 260 | if (try_loading_module < 2) { |
266 | goto out_rcu_unlock; | 261 | rcu_read_unlock(); |
262 | /* | ||
263 | * Be more specific, e.g. net-pf-2-proto-132-type-1 | ||
264 | * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM) | ||
265 | */ | ||
266 | if (++try_loading_module == 1) | ||
267 | request_module("net-pf-%d-proto-%d-type-%d", | ||
268 | PF_INET, protocol, sock->type); | ||
269 | /* | ||
270 | * Fall back to generic, e.g. net-pf-2-proto-132 | ||
271 | * (net-pf-PF_INET-proto-IPPROTO_SCTP) | ||
272 | */ | ||
273 | else | ||
274 | request_module("net-pf-%d-proto-%d", | ||
275 | PF_INET, protocol); | ||
276 | goto lookup_protocol; | ||
277 | } else | ||
278 | goto out_rcu_unlock; | ||
279 | } | ||
280 | |||
267 | err = -EPERM; | 281 | err = -EPERM; |
268 | if (answer->capability > 0 && !capable(answer->capability)) | 282 | if (answer->capability > 0 && !capable(answer->capability)) |
269 | goto out_rcu_unlock; | 283 | goto out_rcu_unlock; |
@@ -317,9 +331,7 @@ static int inet_create(struct socket *sock, int protocol) | |||
317 | inet->mc_index = 0; | 331 | inet->mc_index = 0; |
318 | inet->mc_list = NULL; | 332 | inet->mc_list = NULL; |
319 | 333 | ||
320 | #ifdef INET_REFCNT_DEBUG | 334 | sk_refcnt_debug_inc(sk); |
321 | atomic_inc(&inet_sock_nr); | ||
322 | #endif | ||
323 | 335 | ||
324 | if (inet->num) { | 336 | if (inet->num) { |
325 | /* It assumes that any protocol which allows | 337 | /* It assumes that any protocol which allows |
@@ -847,10 +859,6 @@ static struct net_proto_family inet_family_ops = { | |||
847 | .owner = THIS_MODULE, | 859 | .owner = THIS_MODULE, |
848 | }; | 860 | }; |
849 | 861 | ||
850 | |||
851 | extern void tcp_init(void); | ||
852 | extern void tcp_v4_init(struct net_proto_family *); | ||
853 | |||
854 | /* Upon startup we insert all the elements in inetsw_array[] into | 862 | /* Upon startup we insert all the elements in inetsw_array[] into |
855 | * the linked list inetsw. | 863 | * the linked list inetsw. |
856 | */ | 864 | */ |
@@ -961,6 +969,119 @@ void inet_unregister_protosw(struct inet_protosw *p) | |||
961 | } | 969 | } |
962 | } | 970 | } |
963 | 971 | ||
972 | /* | ||
973 | * Shall we try to damage output packets if routing dev changes? | ||
974 | */ | ||
975 | |||
976 | int sysctl_ip_dynaddr; | ||
977 | |||
978 | static int inet_sk_reselect_saddr(struct sock *sk) | ||
979 | { | ||
980 | struct inet_sock *inet = inet_sk(sk); | ||
981 | int err; | ||
982 | struct rtable *rt; | ||
983 | __u32 old_saddr = inet->saddr; | ||
984 | __u32 new_saddr; | ||
985 | __u32 daddr = inet->daddr; | ||
986 | |||
987 | if (inet->opt && inet->opt->srr) | ||
988 | daddr = inet->opt->faddr; | ||
989 | |||
990 | /* Query new route. */ | ||
991 | err = ip_route_connect(&rt, daddr, 0, | ||
992 | RT_CONN_FLAGS(sk), | ||
993 | sk->sk_bound_dev_if, | ||
994 | sk->sk_protocol, | ||
995 | inet->sport, inet->dport, sk); | ||
996 | if (err) | ||
997 | return err; | ||
998 | |||
999 | sk_setup_caps(sk, &rt->u.dst); | ||
1000 | |||
1001 | new_saddr = rt->rt_src; | ||
1002 | |||
1003 | if (new_saddr == old_saddr) | ||
1004 | return 0; | ||
1005 | |||
1006 | if (sysctl_ip_dynaddr > 1) { | ||
1007 | printk(KERN_INFO "%s(): shifting inet->" | ||
1008 | "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n", | ||
1009 | __FUNCTION__, | ||
1010 | NIPQUAD(old_saddr), | ||
1011 | NIPQUAD(new_saddr)); | ||
1012 | } | ||
1013 | |||
1014 | inet->saddr = inet->rcv_saddr = new_saddr; | ||
1015 | |||
1016 | /* | ||
1017 | * XXX The only one ugly spot where we need to | ||
1018 | * XXX really change the sockets identity after | ||
1019 | * XXX it has entered the hashes. -DaveM | ||
1020 | * | ||
1021 | * Besides that, it does not check for connection | ||
1022 | * uniqueness. Wait for troubles. | ||
1023 | */ | ||
1024 | __sk_prot_rehash(sk); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | int inet_sk_rebuild_header(struct sock *sk) | ||
1029 | { | ||
1030 | struct inet_sock *inet = inet_sk(sk); | ||
1031 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); | ||
1032 | u32 daddr; | ||
1033 | int err; | ||
1034 | |||
1035 | /* Route is OK, nothing to do. */ | ||
1036 | if (rt) | ||
1037 | return 0; | ||
1038 | |||
1039 | /* Reroute. */ | ||
1040 | daddr = inet->daddr; | ||
1041 | if (inet->opt && inet->opt->srr) | ||
1042 | daddr = inet->opt->faddr; | ||
1043 | { | ||
1044 | struct flowi fl = { | ||
1045 | .oif = sk->sk_bound_dev_if, | ||
1046 | .nl_u = { | ||
1047 | .ip4_u = { | ||
1048 | .daddr = daddr, | ||
1049 | .saddr = inet->saddr, | ||
1050 | .tos = RT_CONN_FLAGS(sk), | ||
1051 | }, | ||
1052 | }, | ||
1053 | .proto = sk->sk_protocol, | ||
1054 | .uli_u = { | ||
1055 | .ports = { | ||
1056 | .sport = inet->sport, | ||
1057 | .dport = inet->dport, | ||
1058 | }, | ||
1059 | }, | ||
1060 | }; | ||
1061 | |||
1062 | err = ip_route_output_flow(&rt, &fl, sk, 0); | ||
1063 | } | ||
1064 | if (!err) | ||
1065 | sk_setup_caps(sk, &rt->u.dst); | ||
1066 | else { | ||
1067 | /* Routing failed... */ | ||
1068 | sk->sk_route_caps = 0; | ||
1069 | /* | ||
1070 | * Other protocols have to map its equivalent state to TCP_SYN_SENT. | ||
1071 | * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme | ||
1072 | */ | ||
1073 | if (!sysctl_ip_dynaddr || | ||
1074 | sk->sk_state != TCP_SYN_SENT || | ||
1075 | (sk->sk_userlocks & SOCK_BINDADDR_LOCK) || | ||
1076 | (err = inet_sk_reselect_saddr(sk)) != 0) | ||
1077 | sk->sk_err_soft = -err; | ||
1078 | } | ||
1079 | |||
1080 | return err; | ||
1081 | } | ||
1082 | |||
1083 | EXPORT_SYMBOL(inet_sk_rebuild_header); | ||
1084 | |||
964 | #ifdef CONFIG_IP_MULTICAST | 1085 | #ifdef CONFIG_IP_MULTICAST |
965 | static struct net_protocol igmp_protocol = { | 1086 | static struct net_protocol igmp_protocol = { |
966 | .handler = igmp_rcv, | 1087 | .handler = igmp_rcv, |
@@ -1007,7 +1128,6 @@ static int __init init_ipv4_mibs(void) | |||
1007 | } | 1128 | } |
1008 | 1129 | ||
1009 | static int ipv4_proc_init(void); | 1130 | static int ipv4_proc_init(void); |
1010 | extern void ipfrag_init(void); | ||
1011 | 1131 | ||
1012 | /* | 1132 | /* |
1013 | * IP protocol layer initialiser | 1133 | * IP protocol layer initialiser |
@@ -1128,19 +1248,10 @@ module_init(inet_init); | |||
1128 | /* ------------------------------------------------------------------------ */ | 1248 | /* ------------------------------------------------------------------------ */ |
1129 | 1249 | ||
1130 | #ifdef CONFIG_PROC_FS | 1250 | #ifdef CONFIG_PROC_FS |
1131 | extern int fib_proc_init(void); | ||
1132 | extern void fib_proc_exit(void); | ||
1133 | #ifdef CONFIG_IP_FIB_TRIE | 1251 | #ifdef CONFIG_IP_FIB_TRIE |
1134 | extern int fib_stat_proc_init(void); | 1252 | extern int fib_stat_proc_init(void); |
1135 | extern void fib_stat_proc_exit(void); | 1253 | extern void fib_stat_proc_exit(void); |
1136 | #endif | 1254 | #endif |
1137 | extern int ip_misc_proc_init(void); | ||
1138 | extern int raw_proc_init(void); | ||
1139 | extern void raw_proc_exit(void); | ||
1140 | extern int tcp4_proc_init(void); | ||
1141 | extern void tcp4_proc_exit(void); | ||
1142 | extern int udp4_proc_init(void); | ||
1143 | extern void udp4_proc_exit(void); | ||
1144 | 1255 | ||
1145 | static int __init ipv4_proc_init(void) | 1256 | static int __init ipv4_proc_init(void) |
1146 | { | 1257 | { |
@@ -1205,7 +1316,3 @@ EXPORT_SYMBOL(inet_stream_ops); | |||
1205 | EXPORT_SYMBOL(inet_unregister_protosw); | 1316 | EXPORT_SYMBOL(inet_unregister_protosw); |
1206 | EXPORT_SYMBOL(net_statistics); | 1317 | EXPORT_SYMBOL(net_statistics); |
1207 | EXPORT_SYMBOL(sysctl_ip_nonlocal_bind); | 1318 | EXPORT_SYMBOL(sysctl_ip_nonlocal_bind); |
1208 | |||
1209 | #ifdef INET_REFCNT_DEBUG | ||
1210 | EXPORT_SYMBOL(inet_sock_nr); | ||
1211 | #endif | ||