示例#1
0
文件: proto.c 项目: krzk/linux
int dccp_disconnect(struct sock *sk, int flags)
{
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct inet_sock *inet = inet_sk(sk);
	struct dccp_sock *dp = dccp_sk(sk);
	int err = 0;
	const int old_state = sk->sk_state;

	if (old_state != DCCP_CLOSED)
		dccp_set_state(sk, DCCP_CLOSED);

	/*
	 * This corresponds to the ABORT function of RFC793, sec. 3.8
	 * TCP uses a RST segment, DCCP a Reset packet with Code 2, "Aborted".
	 */
	if (old_state == DCCP_LISTEN) {
		inet_csk_listen_stop(sk);
	} else if (dccp_need_reset(old_state)) {
		dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
		sk->sk_err = ECONNRESET;
	} else if (old_state == DCCP_REQUESTING)
		sk->sk_err = ECONNRESET;

	dccp_clear_xmit_timers(sk);
	ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
	dp->dccps_hc_rx_ccid = NULL;

	__skb_queue_purge(&sk->sk_receive_queue);
	__skb_queue_purge(&sk->sk_write_queue);
	if (sk->sk_send_head != NULL) {
		__kfree_skb(sk->sk_send_head);
		sk->sk_send_head = NULL;
	}

	inet->inet_dport = 0;

	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
		inet_reset_saddr(sk);

	sk->sk_shutdown = 0;
	sock_reset_flag(sk, SOCK_DONE);

	icsk->icsk_backoff = 0;
	inet_csk_delack_init(sk);
	__sk_dst_reset(sk);

	WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);

	sk->sk_error_report(sk);
	return err;
}
示例#2
0
int dccp_disconnect(struct sock *sk, int flags)
{
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct inet_sock *inet = inet_sk(sk);
	int err = 0;
	const int old_state = sk->sk_state;

	if (old_state != DCCP_CLOSED)
		dccp_set_state(sk, DCCP_CLOSED);

	
	if (old_state == DCCP_LISTEN) {
		inet_csk_listen_stop(sk);
	} else if (dccp_need_reset(old_state)) {
		dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
		sk->sk_err = ECONNRESET;
	} else if (old_state == DCCP_REQUESTING)
		sk->sk_err = ECONNRESET;

	dccp_clear_xmit_timers(sk);

	__skb_queue_purge(&sk->sk_receive_queue);
	__skb_queue_purge(&sk->sk_write_queue);
	if (sk->sk_send_head != NULL) {
		__kfree_skb(sk->sk_send_head);
		sk->sk_send_head = NULL;
	}

	inet->dport = 0;

	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
		inet_reset_saddr(sk);

	sk->sk_shutdown = 0;
	sock_reset_flag(sk, SOCK_DONE);

	icsk->icsk_backoff = 0;
	inet_csk_delack_init(sk);
	__sk_dst_reset(sk);

	WARN_ON(inet->num && !icsk->icsk_bind_hash);

	sk->sk_error_report(sk);
	return err;
}
示例#3
0
int dccp_disconnect(struct sock *sk, int flags)
{
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct inet_sock *inet = inet_sk(sk);
	int err = 0;
	const int old_state = sk->sk_state;

	if (old_state != DCCP_CLOSED)
		dccp_set_state(sk, DCCP_CLOSED);

	/* ABORT function of RFC793 */
	if (old_state == DCCP_LISTEN) {
		inet_csk_listen_stop(sk);
	/* FIXME: do the active reset thing */
	} else if (old_state == DCCP_REQUESTING)
		sk->sk_err = ECONNRESET;

	dccp_clear_xmit_timers(sk);
	__skb_queue_purge(&sk->sk_receive_queue);
	if (sk->sk_send_head != NULL) {
		__kfree_skb(sk->sk_send_head);
		sk->sk_send_head = NULL;
	}

	inet->dport = 0;

	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
		inet_reset_saddr(sk);

	sk->sk_shutdown = 0;
	sock_reset_flag(sk, SOCK_DONE);

	icsk->icsk_backoff = 0;
	inet_csk_delack_init(sk);
	__sk_dst_reset(sk);

	BUG_TRAP(!inet->num || icsk->icsk_bind_hash);

	sk->sk_error_report(sk);
	return err;
}
示例#4
0
int mhost_bind(struct socket *sock, struct sockaddr *sa, int addr_len)
{
    int err = 0;
    unsigned short snum;
    struct sock *sk = sock->sk;
    struct inet_sock *inet = inet_sk(sk);
    struct ipv6_pinfo *np = inet6_sk(sk);

    /* mhost not used yet */
//    struct mhost_sock *mhost = mhost_sk(sk);
    struct sockaddr_mhost *sm;
    struct sockaddr_in6 addr;

    printk(KERN_INFO "mhost_bind called\n");
    sm = (struct sockaddr_mhost *)sa;

    addr.sin6_port = sm->port;
    addr.sin6_family = AF_INET6;
    addr.sin6_addr = in6_any;
    err = inet6_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6));

    if (!err) {
        udp_table_insert(sk, inet_sk(sk)->inet_num);
    }

    return err;

    /* If the socket has its own bind function then use it! (RAW) */
    if (sk->sk_prot->bind) {
        return sk->sk_prot->bind(sk, sa, addr_len);
    }

    if (addr_len < sizeof(struct sockaddr_mhost))
        return -EINVAL;

    /* how do i feel about different bindings/addressings? 
     * (need to decide how i want to handle these cases)
     */
    if (sa->sa_family != AF_MHOST) {
        /* here, we've specified an address family SO instead
         * of binding across all L3 addresses, we're ONLY going
         * to bind to the specific address family and address
         * specified. Not all L3 protocols may support this behavior
         * and that's okay! I'll add it back in later :-)
         */
        printk(KERN_INFO "error: family not af_mhost\n");
        return -EAFNOSUPPORT;
    }
    
    /* if we've got here, we're binding to AF_MHOST. the rest of
     * the content in the sockaddr is irrelevant (except for the port)
     * because it's meaningless! the goal now is to find an address 
     * that is acceptable across all the different L3 structures. For
     * now, this is all we support so I'm just storing it all in my
     * own UDP table and cross-checking it with the af_inet one!
     */
        
    /* check port validity */
    snum = ntohs(sm->port);
    if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) {
        printk(KERN_INFO "error: port not valid\n");
        return -EACCES;
    }

    lock_sock(sk);

    /* Check these errors (active socket, double bind). */
    if (sk->sk_state != TCP_CLOSE || inet->inet_num) {
        printk(KERN_INFO "error: active socket or double-bind\n");
        err = -EINVAL;
        goto out;
    }
        
    /* these settings are reminiscent to the inet6_bind 
     * case for INADDR_ANY. they correspond to just that! */
    inet->inet_rcv_saddr = 0;
    inet->inet_saddr = 0;
    ipv6_addr_copy(&np->rcv_saddr, &in6_any);
    ipv6_addr_copy(&np->saddr, &in6_any);

    /* inet transport layer binding here! */
    if (sk->sk_prot->get_port(sk, snum)) {
        printk(KERN_INFO "error: transport-layer bind failed\n");
        inet_reset_saddr(sk);
        err = -EADDRINUSE;
        goto out;
    }
    
    if (snum)
        sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
    inet->inet_sport = htons(inet->inet_num);
    inet->inet_dport = 0;
    inet->inet_daddr = 0;
    
out:
    release_sock(sk);
    return err;
};