Exemplo n.º 1
0
/* associated socket ceases to exist */
static void pep_sock_close(struct sock *sk, long timeout)
{
	struct pep_sock *pn = pep_sk(sk);
	int ifindex = 0;

	sock_hold(sk); /* keep a reference after sk_common_release() */
	sk_common_release(sk);

	lock_sock(sk);
	if (sk->sk_state == TCP_LISTEN) {
		/* Destroy the listen queue */
		struct sock *sknode;
		struct hlist_node *p, *n;

		sk_for_each_safe(sknode, p, n, &pn->ackq)
			sk_del_node_init(sknode);
		sk->sk_state = TCP_CLOSE;
	}
	ifindex = pn->ifindex;
	pn->ifindex = 0;
	release_sock(sk);

	if (ifindex)
		gprs_detach(sk);
	sock_put(sk);
}
Exemplo n.º 2
0
/* associated socket ceases to exist */
static void pep_sock_close(struct sock *sk, long timeout)
{
	struct pep_sock *pn = pep_sk(sk);
	int ifindex = 0;

	sock_hold(sk); /* keep a reference after sk_common_release() */
	sk_common_release(sk);

	lock_sock(sk);
	if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) {
		if (sk->sk_backlog_rcv == pipe_do_rcv)
			/* Forcefully remove dangling Phonet pipe */
			pipe_do_remove(sk);
		else
			pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD,
						NULL, 0);
	}
	sk->sk_state = TCP_CLOSE;

	ifindex = pn->ifindex;
	pn->ifindex = 0;
	release_sock(sk);

	if (ifindex)
		gprs_detach(sk);
	sock_put(sk);
}
Exemplo n.º 3
0
static void raw_close(struct sock *sk, long timeout)
{
	/*
	 * Raw sockets may have direct kernel references. Kill them.
	 */
	ip_ra_control(sk, 0, NULL);

	sk_common_release(sk);
}
Exemplo n.º 4
0
static int serval_inet_connect(struct socket *sock, struct sockaddr *addr,
                               int alen, int flags)
{
        struct sockaddr_in *in = (struct sockaddr_in *)addr;
        struct sockaddr_sv sv;
        unsigned char localhost[4] = { 0x7f, 0x0, 0x0, 0x1 };
        struct sock *sk = sock->sk;
        
        if (alen < sizeof(addr->sa_family))
		return -EINVAL;

        if (addr->sa_family != AF_INET)
                return -EAFNOSUPPORT;

        if (memcmp(&in->sin_addr, &localhost, sizeof(in->sin_addr)) == 0) {
                /* Give back control to legacy TCP in case of localhost */
                LOG_DBG("Dest is localhost, giving back sock\n");
                sock->ops = &inet_stream_ops;
		sock->sk = serval_sk(sk)->old_sk;
                module_put(serval_inet_stream_ops.owner);
                sk_common_release(sk);
                sk = sock->sk;
                sock_put(sk);
                sk->sk_type = sock->type;
		sk->sk_wq = sock->wq;
                return inet_stream_ops.connect(sock, addr, alen, flags);
        }
        
        /* Release old TCP sock */
        module_put(inet_stream_ops.owner);
        sock_put(serval_sk(sk)->old_sk);
        sk_common_release(serval_sk(sk)->old_sk);
        serval_sk(sk)->old_sk = NULL;

        inet_addr_to_service(in, &sv);
        alen = sizeof(sv);

        return serval_stream_ops.connect(sock, (struct sockaddr *)&sv,
                                         alen, flags);
}
Exemplo n.º 5
0
/*
 * Create a socket. Initialise the socket, blank the addresses
 * set the state.
 */
static int ieee802154_create(struct net *net, struct socket *sock,
			     int protocol, int kern)
{
	struct sock *sk;
	int rc;
	struct proto *proto;
	const struct proto_ops *ops;

	if (net != &init_net)
		return -EAFNOSUPPORT;

	switch (sock->type) {
	case SOCK_RAW:
		proto = &ieee802154_raw_prot;
		ops = &ieee802154_raw_ops;
		break;
	case SOCK_DGRAM:
		proto = &ieee802154_dgram_prot;
		ops = &ieee802154_dgram_ops;
		break;
	default:
		rc = -ESOCKTNOSUPPORT;
		goto out;
	}

	rc = -ENOMEM;
	sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto);
	if (!sk)
		goto out;
	rc = 0;

	sock->ops = ops;

	sock_init_data(sock, sk);
	/* FIXME: sk->sk_destruct */
	sk->sk_family = PF_IEEE802154;

	/* Checksums on by default */
	sock_set_flag(sk, SOCK_ZAPPED);

	if (sk->sk_prot->hash)
		sk->sk_prot->hash(sk);

	if (sk->sk_prot->init) {
		rc = sk->sk_prot->init(sk);
		if (rc)
			sk_common_release(sk);
	}
out:
	return rc;
}
Exemplo n.º 6
0
/* associated socket ceases to exist */
static void pn_sock_close(struct sock *sk, long timeout)
{
	sk_common_release(sk);
}
Exemplo n.º 7
0
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
		       size_t len)
{
	struct inet_sock *inet = inet_sk(sk);
	struct ipcm_cookie ipc;
	struct rtable *rt = NULL;
	int free = 0;
	__be32 daddr;
	__be32 saddr;
	u8  tos;
	int err;

	err = -EMSGSIZE;
	if (len > 0xFFFF)
		goto out;

	/*
	 *	Check the flags.
	 */

	err = -EOPNOTSUPP;
	if (msg->msg_flags & MSG_OOB)	/* Mirror BSD error message */
		goto out;               /* compatibility */

	/*
	 *	Get and verify the address.
	 */

	if (msg->msg_namelen) {
		struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name;
		err = -EINVAL;
		if (msg->msg_namelen < sizeof(*usin))
			goto out;
		if (usin->sin_family != AF_INET) {
			static int complained;
			if (!complained++)
				printk(KERN_INFO "%s forgot to set AF_INET in "
						 "raw sendmsg. Fix it!\n",
						 current->comm);
			err = -EAFNOSUPPORT;
			if (usin->sin_family)
				goto out;
		}
		daddr = usin->sin_addr.s_addr;
		/* ANK: I did not forget to get protocol from port field.
		 * I just do not know, who uses this weirdness.
		 * IP_HDRINCL is much more convenient.
		 */
	} else {
		err = -EDESTADDRREQ;
		if (sk->sk_state != TCP_ESTABLISHED)
			goto out;
		daddr = inet->inet_daddr;
	}

	ipc.addr = inet->inet_saddr;
	ipc.opt = NULL;
	ipc.tx_flags = 0;
	ipc.oif = sk->sk_bound_dev_if;

	if (msg->msg_controllen) {
		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
		if (err)
			goto out;
		if (ipc.opt)
			free = 1;
	}

	saddr = ipc.addr;
	ipc.addr = daddr;

	if (!ipc.opt)
		ipc.opt = inet->opt;

	if (ipc.opt) {
		err = -EINVAL;
		/* Linux does not mangle headers on raw sockets,
		 * so that IP options + IP_HDRINCL is non-sense.
		 */
		if (inet->hdrincl)
			goto done;
		if (ipc.opt->srr) {
			if (!daddr)
				goto done;
			daddr = ipc.opt->faddr;
		}
	}
	tos = RT_CONN_FLAGS(sk);
	if (msg->msg_flags & MSG_DONTROUTE)
		tos |= RTO_ONLINK;

	if (ipv4_is_multicast(daddr)) {
		if (!ipc.oif)
			ipc.oif = inet->mc_index;
		if (!saddr)
			saddr = inet->mc_addr;
	}

	{
		struct flowi4 fl4 = {
			.flowi4_oif = ipc.oif,
			.flowi4_mark = sk->sk_mark,
			.daddr = daddr,
			.saddr = saddr,
			.flowi4_tos = tos,
			.flowi4_proto = (inet->hdrincl ?
					 IPPROTO_RAW :
					 sk->sk_protocol),
			.flowi4_flags = FLOWI_FLAG_CAN_SLEEP,
		};
		if (!inet->hdrincl) {
			err = raw_probe_proto_opt(&fl4, msg);
			if (err)
				goto done;
		}

		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
		rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
		if (IS_ERR(rt)) {
			err = PTR_ERR(rt);
			rt = NULL;
			goto done;
		}
	}

	err = -EACCES;
	if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST))
		goto done;

	if (msg->msg_flags & MSG_CONFIRM)
		goto do_confirm;
back_from_confirm:

	if (inet->hdrincl)
		err = raw_send_hdrinc(sk, msg->msg_iov, len,
					&rt, msg->msg_flags);

	 else {
		if (!ipc.addr)
			ipc.addr = rt->rt_dst;
		lock_sock(sk);
		err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0,
					&ipc, &rt, msg->msg_flags);
		if (err)
			ip_flush_pending_frames(sk);
		else if (!(msg->msg_flags & MSG_MORE)) {
			err = ip_push_pending_frames(sk);
			if (err == -ENOBUFS && !inet->recverr)
				err = 0;
		}
		release_sock(sk);
	}
done:
	if (free)
		kfree(ipc.opt);
	ip_rt_put(rt);

out:
	if (err < 0)
		return err;
	return len;

do_confirm:
	dst_confirm(&rt->dst);
	if (!(msg->msg_flags & MSG_PROBE) || len)
		goto back_from_confirm;
	err = 0;
	goto done;
}

static void raw_close(struct sock *sk, long timeout)
{
	/*
	 * Raw sockets may have direct kernel refereneces. Kill them.
	 */
	ip_ra_control(sk, 0, NULL);

	sk_common_release(sk);
}
Exemplo n.º 8
0
static void raw_close(struct sock *sk, long timeout)
{
	ip_ra_control(sk, 0, NULL);

	sk_common_release(sk);
}
Exemplo n.º 9
0
int mhost_create(struct net *net, struct socket *sock, int protocol, int kern)
{
	struct sock *sk;
    struct inet_sock *inet;
    struct ipv6_pinfo *np;
	struct inet_protosw *answer;
    int err;
    char answer_no_check;
    struct proto *answer_prot;
    unsigned char answer_flags;
    printk(KERN_INFO "mhost_create called\n");
    
	sock->state = SS_UNCONNECTED;
    
    /* we only support SOCK_DGRAM as of now... */
    answer = &mhost_dgram_protosw;
    protocol = IPPROTO_UDP;
    /* end "big answer/protocol code mess" here */
    
    err = -EPERM;
    if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW))
        goto out;

    sock->ops = answer->ops;
    answer_prot = answer->prot;
    answer_no_check = answer->no_check;
    answer_flags = answer->flags;

    WARN_ON(answer_prot->slab == NULL);

    err = -ENOBUFS,
    sk = sk_alloc(net, AF_MHOST, GFP_KERNEL, answer_prot);
    if (sk == NULL)
        goto out;
    
    sock_init_data(sock, sk);

    err = 0;
    sk->sk_no_check = answer_no_check;
    if (INET_PROTOSW_REUSE & answer_flags)
        sk->sk_reuse = 1;
    
    inet = inet_sk(sk);
    inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
    
    if (SOCK_RAW == sock->type) {
        inet->inet_num = protocol;
        if (IPPROTO_RAW == protocol)
            inet->hdrincl = 1;
    }

    sk->sk_destruct    = inet_sock_destruct;
    sk->sk_protocol    = protocol;
    sk->sk_family      = AF_INET6; /* HACK FOR RECEIVING UDP6!!! */
    sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;

    inet_sk(sk)->pinet6 = np = (struct ipv6_pinfo *) mhost_sk_generic(sk);

    
    /* HERE DO ALL MHOST-SPECIFIC INITS!!! */
    
    /* now backwards-compat for IPv6 */
    np->hop_limit   = -1;
    np->mcast_hops  = IPV6_DEFAULT_MCASTHOPS;
    np->mc_loop     = 1;
    np->pmtudisc    = IPV6_PMTUDISC_WANT;
    np->ipv6only    = net->ipv6.sysctl.bindv6only;

    /* now backwards-compat for IPv4 */
    inet->uc_ttl    = -1;
    
    inet->mc_loop   = 1;
    inet->mc_ttl    = 1;
    inet->mc_index  = 0;
    inet->mc_list   = NULL;

    sock_init_data(sock, sk);
            
    inet->uc_ttl    = -1;
    inet->mc_loop   = 1;
    inet->mc_ttl    = 1;
    inet->mc_all    = 1;
    inet->mc_index  = 0;
    inet->mc_list   = NULL;

    if (ipv4_config.no_pmtu_disc)
        inet->pmtudisc = IP_PMTUDISC_DONT;
    else
        inet->pmtudisc = IP_PMTUDISC_WANT;

    sk_refcnt_debug_inc(sk);
    
    if (inet->inet_num) {
        /* assumes that any protocol which allows
         * the user to assign a number at socket
         * creation time automatically shares.
         */
        inet->inet_sport = htons(inet->inet_num);
        sk->sk_prot->hash(sk);
    }

    if (sk->sk_prot->init) {
        int err = sk->sk_prot->init(sk);
        if (err)
            sk_common_release(sk);
    }
    
out:
    return err;
};
Exemplo n.º 10
0
static int serval_inet_tcp_init_sock(struct sock *sk)
{
        struct socket *sock = sk->sk_socket;
        struct sock *old_sk = sk;
        const struct proto_ops *old_ops = sock->ops;
        struct inet_sock *inet;
        int err = 0;

        LOG_DBG("init sock\n");

        /* First fully initialize the old sock. Otherwise, the release
           function will fail. */
        err = old_tcp_prot.init(sk);
        
        if (err)
                return err;
        
        sock->ops = &serval_inet_stream_ops;
        sk = serval_sk_alloc(sock_net(sk), sock,
                             GFP_KERNEL,
                             SERVAL_PROTO_TCP,
                             &serval_tcp_proto);
        
        if (!sk) {
                LOG_ERR("Fail alloc\n");
                goto out_fail_alloc;
        }
        /* Initialize serval sock part of socket */
        serval_sock_init(sk);

        /* Initialize inet part */
        inet = inet_sk(sk);
	inet->uc_ttl	= -1; /* Let IP decide TTL */
	inet->mc_loop	= 1;
	inet->mc_ttl	= 1;
	inet->mc_index	= 0;
	inet->mc_list	= NULL;

        if (sk->sk_prot->init) {
                /* Call protocol specific init */
                err = sk->sk_prot->init(sk);

		if (err < 0) {
                        LOG_ERR("Fail init\n");
                        goto out_fail_init;
                }
	}
 
        sock_hold(old_sk);
        serval_sk(sk)->old_sk = old_sk;

        LOG_DBG("Successfully hijacked sock\n");

        return 0;
        
 out_fail_init:
        sk_common_release(sk);
 out_fail_alloc:
        sock->ops = old_ops;
        sock->sk = old_sk;
        return 0;
}