Example #1
0
int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
                     struct socket **sockp)
{
    struct sockaddr_in6 udp6_addr;
    int err;
    struct socket *sock = NULL;

    err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock);
    if (err < 0)
        goto error;

    sk_change_net(sock->sk, net);

    udp6_addr.sin6_family = AF_INET6;
    memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
           sizeof(udp6_addr.sin6_addr));
    udp6_addr.sin6_port = cfg->local_udp_port;
    err = kernel_bind(sock, (struct sockaddr *)&udp6_addr,
                      sizeof(udp6_addr));
    if (err < 0)
        goto error;

    if (cfg->peer_udp_port) {
        udp6_addr.sin6_family = AF_INET6;
        memcpy(&udp6_addr.sin6_addr, &cfg->peer_ip6,
               sizeof(udp6_addr.sin6_addr));
        udp6_addr.sin6_port = cfg->peer_udp_port;
        err = kernel_connect(sock,
                             (struct sockaddr *)&udp6_addr,
                             sizeof(udp6_addr), 0);
    }
    if (err < 0)
        goto error;

    udp_set_no_check6_tx(sock->sk, !cfg->use_udp6_tx_checksums);
    udp_set_no_check6_rx(sock->sk, !cfg->use_udp6_rx_checksums);

    *sockp = sock;
    return 0;

error:
    if (sock) {
        kernel_sock_shutdown(sock, SHUT_RDWR);
        sk_release_kernel(sock->sk);
    }
    *sockp = NULL;
    return err;
}
Example #2
0
int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
                     struct socket **sockp)
{
    int err;
    struct socket *sock = NULL;
    struct sockaddr_in udp_addr;

    err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock);
    if (err < 0)
        goto error;

    sk_change_net(sock->sk, net);

    udp_addr.sin_family = AF_INET;
    udp_addr.sin_addr = cfg->local_ip;
    udp_addr.sin_port = cfg->local_udp_port;
    err = kernel_bind(sock, (struct sockaddr *)&udp_addr,
                      sizeof(udp_addr));
    if (err < 0)
        goto error;

    if (cfg->peer_udp_port) {
        udp_addr.sin_family = AF_INET;
        udp_addr.sin_addr = cfg->peer_ip;
        udp_addr.sin_port = cfg->peer_udp_port;
        err = kernel_connect(sock, (struct sockaddr *)&udp_addr,
                             sizeof(udp_addr), 0);
        if (err < 0)
            goto error;
    }

    sock->sk->sk_no_check_tx = !cfg->use_udp_checksums;

    *sockp = sock;
    return 0;

error:
    if (sock) {
        kernel_sock_shutdown(sock, SHUT_RDWR);
        sk_release_kernel(sock->sk);
    }
    *sockp = NULL;
    return err;
}
Example #3
0
int sclp_sock_create4(struct net *net, struct sclp_port_cfg *cfg, struct socket **sockp)
{
    int err;
    struct socket *sock = NULL;
    struct sockaddr_in sclp_addr;

    err = sock_create_kern(AF_INET, SOCK_SCLP, 0, &sock);
    if (err < 0)
        goto error;

    sk_change_net(sock->sk, net);

    sclp_addr.sin_family = AF_INET;
    sclp_addr.sin_addr = cfg->local_ip;
    sclp_addr.sin_port = cfg->local_sclp_port;

    err = kernel_bind(sock, (struct sockaddr*)&sclp_addr, sizeof(sclp_addr));
    if (err < 0)
        goto error;

    if (cfg->peer_sclp_port) {
        sclp_addr.sin_family = AF_INET;
        sclp_addr.sin_addr = cfg->peer_ip;
        sclp_addr.sin_port = cfg->peer_sclp_port;
        err = kernel_connect(sock, (struct sockaddr*)&sclp_addr, sizeof(sclp_addr), 0);
        if (err < 0)
            goto error;
    }

    *sockp = sock;
    return 0;

error:
    if (sock) {
        kernel_sock_shutdown(sock, SHUT_RDWR);
        sk_release_kernel(sock->sk);
    }
    *sockp = NULL;
    return err;
}
Example #4
0
static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
					      vxlan_rcv_t *rcv, void *data)
{
	struct vxlan_sock *vs;
	struct sock *sk;
	struct sockaddr_in vxlan_addr = {
		.sin_family = AF_INET,
		.sin_addr.s_addr = htonl(INADDR_ANY),
		.sin_port = port,
	};
	int rc;

	vs = kmalloc(sizeof(*vs), GFP_KERNEL);
	if (!vs) {
		pr_debug("memory alocation failure\n");
		return ERR_PTR(-ENOMEM);
	}

	INIT_WORK(&vs->del_work, vxlan_del_work);

	/* Create UDP socket for encapsulation receive. */
	rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vs->sock);
	if (rc < 0) {
		pr_debug("UDP socket create failed\n");
		kfree(vs);
		return ERR_PTR(rc);
	}

	/* Put in proper namespace */
	sk = vs->sock->sk;
	sk_change_net(sk, net);

	rc = kernel_bind(vs->sock, (struct sockaddr *) &vxlan_addr,
			sizeof(vxlan_addr));
	if (rc < 0) {
		pr_debug("bind for UDP socket %pI4:%u (%d)\n",
				&vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
		sk_release_kernel(sk);
		kfree(vs);
		return ERR_PTR(rc);
	}
	vs->rcv = rcv;
	vs->data = data;

	/* Disable multicast loopback */
	inet_sk(sk)->mc_loop = 0;
	rcu_assign_sk_user_data(vs->sock->sk, vs);

	/* Mark socket as an encapsulation socket. */
	udp_sk(sk)->encap_type = 1;
	udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
	udp_encap_enable();
	return vs;
}

struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
				  vxlan_rcv_t *rcv, void *data,
				  bool no_share, u32 flags)
{
	return vxlan_socket_create(net, port, rcv, data);
}

void vxlan_sock_release(struct vxlan_sock *vs)
{
	ASSERT_OVSL();
	rcu_assign_sk_user_data(vs->sock->sk, NULL);

	queue_work(system_wq, &vs->del_work);
}