mm: create the new vm_fault_t type
[linux-2.6-microblaze.git] / net / ipv4 / udp_tunnel.c
1 #include <linux/module.h>
2 #include <linux/errno.h>
3 #include <linux/socket.h>
4 #include <linux/udp.h>
5 #include <linux/types.h>
6 #include <linux/kernel.h>
7 #include <net/dst_metadata.h>
8 #include <net/net_namespace.h>
9 #include <net/udp.h>
10 #include <net/udp_tunnel.h>
11
12 int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
13                      struct socket **sockp)
14 {
15         int err;
16         struct socket *sock = NULL;
17         struct sockaddr_in udp_addr;
18
19         err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock);
20         if (err < 0)
21                 goto error;
22
23         if (cfg->bind_ifindex) {
24                 err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTOIFINDEX,
25                                         (void *)&cfg->bind_ifindex,
26                                         sizeof(cfg->bind_ifindex));
27                 if (err < 0)
28                         goto error;
29         }
30
31         udp_addr.sin_family = AF_INET;
32         udp_addr.sin_addr = cfg->local_ip;
33         udp_addr.sin_port = cfg->local_udp_port;
34         err = kernel_bind(sock, (struct sockaddr *)&udp_addr,
35                           sizeof(udp_addr));
36         if (err < 0)
37                 goto error;
38
39         if (cfg->peer_udp_port) {
40                 udp_addr.sin_family = AF_INET;
41                 udp_addr.sin_addr = cfg->peer_ip;
42                 udp_addr.sin_port = cfg->peer_udp_port;
43                 err = kernel_connect(sock, (struct sockaddr *)&udp_addr,
44                                      sizeof(udp_addr), 0);
45                 if (err < 0)
46                         goto error;
47         }
48
49         sock->sk->sk_no_check_tx = !cfg->use_udp_checksums;
50
51         *sockp = sock;
52         return 0;
53
54 error:
55         if (sock) {
56                 kernel_sock_shutdown(sock, SHUT_RDWR);
57                 sock_release(sock);
58         }
59         *sockp = NULL;
60         return err;
61 }
62 EXPORT_SYMBOL(udp_sock_create4);
63
64 void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
65                            struct udp_tunnel_sock_cfg *cfg)
66 {
67         struct sock *sk = sock->sk;
68
69         /* Disable multicast loopback */
70         inet_sk(sk)->mc_loop = 0;
71
72         /* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
73         inet_inc_convert_csum(sk);
74
75         rcu_assign_sk_user_data(sk, cfg->sk_user_data);
76
77         udp_sk(sk)->encap_type = cfg->encap_type;
78         udp_sk(sk)->encap_rcv = cfg->encap_rcv;
79         udp_sk(sk)->encap_err_lookup = cfg->encap_err_lookup;
80         udp_sk(sk)->encap_destroy = cfg->encap_destroy;
81         udp_sk(sk)->gro_receive = cfg->gro_receive;
82         udp_sk(sk)->gro_complete = cfg->gro_complete;
83
84         udp_tunnel_encap_enable(sock);
85 }
86 EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
87
88 void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock,
89                              unsigned short type)
90 {
91         struct sock *sk = sock->sk;
92         struct udp_tunnel_info ti;
93
94         if (!dev->netdev_ops->ndo_udp_tunnel_add ||
95             !(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
96                 return;
97
98         ti.type = type;
99         ti.sa_family = sk->sk_family;
100         ti.port = inet_sk(sk)->inet_sport;
101
102         dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
103 }
104 EXPORT_SYMBOL_GPL(udp_tunnel_push_rx_port);
105
106 void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock,
107                              unsigned short type)
108 {
109         struct sock *sk = sock->sk;
110         struct udp_tunnel_info ti;
111
112         if (!dev->netdev_ops->ndo_udp_tunnel_del ||
113             !(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
114                 return;
115
116         ti.type = type;
117         ti.sa_family = sk->sk_family;
118         ti.port = inet_sk(sk)->inet_sport;
119
120         dev->netdev_ops->ndo_udp_tunnel_del(dev, &ti);
121 }
122 EXPORT_SYMBOL_GPL(udp_tunnel_drop_rx_port);
123
124 /* Notify netdevs that UDP port started listening */
125 void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type)
126 {
127         struct sock *sk = sock->sk;
128         struct net *net = sock_net(sk);
129         struct udp_tunnel_info ti;
130         struct net_device *dev;
131
132         ti.type = type;
133         ti.sa_family = sk->sk_family;
134         ti.port = inet_sk(sk)->inet_sport;
135
136         rcu_read_lock();
137         for_each_netdev_rcu(net, dev) {
138                 if (!dev->netdev_ops->ndo_udp_tunnel_add)
139                         continue;
140                 if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
141                         continue;
142                 dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
143         }
144         rcu_read_unlock();
145 }
146 EXPORT_SYMBOL_GPL(udp_tunnel_notify_add_rx_port);
147
148 /* Notify netdevs that UDP port is no more listening */
149 void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type)
150 {
151         struct sock *sk = sock->sk;
152         struct net *net = sock_net(sk);
153         struct udp_tunnel_info ti;
154         struct net_device *dev;
155
156         ti.type = type;
157         ti.sa_family = sk->sk_family;
158         ti.port = inet_sk(sk)->inet_sport;
159
160         rcu_read_lock();
161         for_each_netdev_rcu(net, dev) {
162                 if (!dev->netdev_ops->ndo_udp_tunnel_del)
163                         continue;
164                 if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
165                         continue;
166                 dev->netdev_ops->ndo_udp_tunnel_del(dev, &ti);
167         }
168         rcu_read_unlock();
169 }
170 EXPORT_SYMBOL_GPL(udp_tunnel_notify_del_rx_port);
171
172 void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
173                          __be32 src, __be32 dst, __u8 tos, __u8 ttl,
174                          __be16 df, __be16 src_port, __be16 dst_port,
175                          bool xnet, bool nocheck)
176 {
177         struct udphdr *uh;
178
179         __skb_push(skb, sizeof(*uh));
180         skb_reset_transport_header(skb);
181         uh = udp_hdr(skb);
182
183         uh->dest = dst_port;
184         uh->source = src_port;
185         uh->len = htons(skb->len);
186
187         memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
188
189         udp_set_csum(nocheck, skb, src, dst, skb->len);
190
191         iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet);
192 }
193 EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
194
195 void udp_tunnel_sock_release(struct socket *sock)
196 {
197         rcu_assign_sk_user_data(sock->sk, NULL);
198         kernel_sock_shutdown(sock, SHUT_RDWR);
199         sock_release(sock);
200 }
201 EXPORT_SYMBOL_GPL(udp_tunnel_sock_release);
202
203 struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb,  unsigned short family,
204                                     __be16 flags, __be64 tunnel_id, int md_size)
205 {
206         struct metadata_dst *tun_dst;
207         struct ip_tunnel_info *info;
208
209         if (family == AF_INET)
210                 tun_dst = ip_tun_rx_dst(skb, flags, tunnel_id, md_size);
211         else
212                 tun_dst = ipv6_tun_rx_dst(skb, flags, tunnel_id, md_size);
213         if (!tun_dst)
214                 return NULL;
215
216         info = &tun_dst->u.tun_info;
217         info->key.tp_src = udp_hdr(skb)->source;
218         info->key.tp_dst = udp_hdr(skb)->dest;
219         if (udp_hdr(skb)->check)
220                 info->key.tun_flags |= TUNNEL_CSUM;
221         return tun_dst;
222 }
223 EXPORT_SYMBOL_GPL(udp_tun_rx_dst);
224
225 MODULE_LICENSE("GPL");