blob: 7fccf6c3417a16267f7849588219b6b2abf2f608 [file] [log] [blame]
Tom Herbert8024e022014-07-13 19:49:37 -07001#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/udp.h>
8#include <net/udp_tunnel.h>
9#include <net/net_namespace.h>
10
Andy Zhoufd384412014-09-16 17:31:16 -070011int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
12 struct socket **sockp)
Tom Herbert8024e022014-07-13 19:49:37 -070013{
14 int err = -EINVAL;
15 struct socket *sock = NULL;
Andy Zhoufd384412014-09-16 17:31:16 -070016 struct sockaddr_in udp_addr;
Tom Herbert8024e022014-07-13 19:49:37 -070017
Andy Zhoufd384412014-09-16 17:31:16 -070018 err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock);
19 if (err < 0)
20 goto error;
Tom Herbert8024e022014-07-13 19:49:37 -070021
Andy Zhoufd384412014-09-16 17:31:16 -070022 sk_change_net(sock->sk, net);
Tom Herbert8024e022014-07-13 19:49:37 -070023
Andy Zhoufd384412014-09-16 17:31:16 -070024 udp_addr.sin_family = AF_INET;
25 udp_addr.sin_addr = cfg->local_ip;
26 udp_addr.sin_port = cfg->local_udp_port;
27 err = kernel_bind(sock, (struct sockaddr *)&udp_addr,
28 sizeof(udp_addr));
29 if (err < 0)
30 goto error;
Tom Herbert8024e022014-07-13 19:49:37 -070031
Andy Zhoufd384412014-09-16 17:31:16 -070032 if (cfg->peer_udp_port) {
Tom Herbert8024e022014-07-13 19:49:37 -070033 udp_addr.sin_family = AF_INET;
Andy Zhoufd384412014-09-16 17:31:16 -070034 udp_addr.sin_addr = cfg->peer_ip;
35 udp_addr.sin_port = cfg->peer_udp_port;
36 err = kernel_connect(sock, (struct sockaddr *)&udp_addr,
37 sizeof(udp_addr), 0);
Tom Herbert8024e022014-07-13 19:49:37 -070038 if (err < 0)
39 goto error;
Tom Herbert8024e022014-07-13 19:49:37 -070040 }
41
Andy Zhoufd384412014-09-16 17:31:16 -070042 sock->sk->sk_no_check_tx = !cfg->use_udp_checksums;
Tom Herbert8024e022014-07-13 19:49:37 -070043
44 *sockp = sock;
Tom Herbert8024e022014-07-13 19:49:37 -070045 return 0;
46
47error:
48 if (sock) {
49 kernel_sock_shutdown(sock, SHUT_RDWR);
50 sk_release_kernel(sock->sk);
51 }
52 *sockp = NULL;
53 return err;
54}
Andy Zhoufd384412014-09-16 17:31:16 -070055EXPORT_SYMBOL(udp_sock_create4);
Tom Herbert8024e022014-07-13 19:49:37 -070056
57MODULE_LICENSE("GPL");