static int tfw_bmb_connect(int tn, int cn) { int ret; struct sock *sk; TfwBmbConn *conn; conn = &bmb_task[tn].conn[cn]; ret = ss_sock_create(bmb_server_address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP, &sk); if (ret) { TFW_ERR("Unable to create kernel socket (%d)\n", ret); return ret; } ss_proto_init(&conn->proto, &bmb_hooks, tn * nconns + cn); rcu_assign_sk_user_data(sk, &conn->proto); ss_set_callbacks(sk); ret = ss_connect(sk, &bmb_server_address.sa, tfw_addr_sa_len(&bmb_server_address), 0); if (ret) { TFW_ERR("Connect error on server socket sk %p (%d)\n", sk, ret); tfw_connection_unlink_from_sk(sk); ss_close(sk); return ret; } conn->sk = sk; bmb_task[tn].conn_attempt++; return 0; }
static int kclient_connect(int descidx) { int ret; struct sock *sk; kclient_desc_t *desc = *(kclient_desc + descidx / KCLIENT_NCONNECTS) + descidx % KCLIENT_NCONNECTS; ret = ss_sock_create(kclient_server_address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP, &sk); if (ret) { SS_DBG("Unable to create kernel socket (%d)\n", ret); desc->flags |= KCLIENT_CONNECT_ERROR; atomic_inc(&kclient_connect_nerror); return ret; } ss_proto_init(&desc->proto, &kclient_hooks, descidx); rcu_assign_sk_user_data(sk, &desc->proto); ss_set_callbacks(sk); ret = ss_connect(sk, &kclient_server_address.sa, tfw_addr_sa_len(&kclient_server_address), 0); if (ret) { SS_DBG("Connect error on server socket sk %p (%d)\n", sk, ret); ss_release(sk); desc->flags |= KCLIENT_CONNECT_ERROR; atomic_inc(&kclient_connect_nerror); return ret; } desc->sk = sk; desc->flags |= KCLIENT_CONNECT_STARTED; atomic_inc(&kclient_connect_nattempt); return 0; }
void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock, struct udp_tunnel_sock_cfg *cfg) { struct sock *sk = sock->sk; /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; rcu_assign_sk_user_data(sk, cfg->sk_user_data); udp_sk(sk)->encap_type = cfg->encap_type; udp_sk(sk)->encap_rcv = cfg->encap_rcv; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) udp_sk(sk)->encap_destroy = cfg->encap_destroy; #endif udp_tunnel_encap_enable(sock); }
void setup_udp_tunnel_sock(struct net *net, struct socket *sock, struct udp_tunnel_sock_cfg *cfg) { struct sock *sk = sock->sk; /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; /* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */ udp_set_convert_csum(sk, true); rcu_assign_sk_user_data(sk, cfg->sk_user_data); udp_sk(sk)->encap_type = cfg->encap_type; udp_sk(sk)->encap_rcv = cfg->encap_rcv; udp_sk(sk)->encap_destroy = cfg->encap_destroy; udp_tunnel_encap_enable(sock); }
void rpl_udp_tunnel_sock_release(struct socket *sock) { rcu_assign_sk_user_data(sock->sk, NULL); kernel_sock_shutdown(sock, SHUT_RDWR); sock_release(sock); }
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); }